参考:CTFSHOW re2
本文:跟着大佬的博客一步一步做CTFShow re2的记录
IDA分析
有个比较函数
re一下
s = "DH~mqqvqxB^||zll@Jq~jkwpmvez{"
s1 = ''
for i in s:s1 += chr(ord(i) ^ 0x1f)
print(s1)
得到
再四处看看
跟进sub_401028
四个sub点进去看看,感觉最后一个比较重要(因为它的参数有stream?
像RC4算法
我不知道啊
大概就是要%256,要打乱,要交换,要按字节运算,吧?
之后去找到RC4算法,用上面得到的[Warnning]Access_Unauthorized作为key,附件里打开是乱码的enflag.txt里的数据作为要加密的数据,改一通
因为RC4是对称加密,加密解密可以用同一个算法
enflag.txt数据怎么来的?

明显不能直接复制 (我就复制了当然是不行啦 ,猜想是二进制数据
那二进制数据怎么读取呢
折腾一会儿之后找到了在linux中用hexdump读取二进制数据的方法(直接使用是以十六进制显示的
参考:Linux下查看二进制文件
看看别人的代码,发现pData的数据是以十六进制形式,每两位一存,并且上图中的四位里前两位和后两位要交换顺序 (这是什么意思啊小端序吗(混乱
也就是要改成0xc3, 0x82, 0xa3, 0x25, 0xf6, 0x4c, 0x36, 0x3b, 0x59, 0xcc, 0xc4, 0xe9, 0xf1, 0xb5, 0x32, 0x18, 0xb1, 0x96, 0xae, 0xbf, 0x08, 0x35
(亲测不换顺序不行
但至少数据能对上(我太菜了呜呜呜
十六进制两位也就是二进制八位,一个字节,对应unsigned char的size,还有一定要注意char转unsigned char
来自RC4算法C语言实现:
1、明文密文还有状态数组S[i](0~255)类型应该选择为unsigned char 类型,因为其取值范围为0~255,且子长为一字节。
2、明文密文以及状态数组S[i]的类型应该全部一样,这样做异或运算时就不会发生内存溢出的问题。
最后代码是这样的
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;void rc4_init(unsigned char *s, unsigned char *key, unsigned long len)
{char k[256] = {0};unsigned char tmp = 0;for (int i = 0; i < 256; i++){s[i] = i;k[i] = key[i % len];}int j = 0;for (int i = 0; i < 256; i++){j = (j + s[i] + k[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;}
}void rc4_crypt(unsigned char *s, unsigned char *data, unsigned long len)
{unsigned char tmp;unsigned long k = 0;int i = 0, j = 0, t = 0;for (k = 0; k < len; k++){i = (i + 1) % 256;j = (j + s[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;t = (s[i] + s[j]) % 256;data[k] ^= s[t] ;}}int main()
{unsigned char s[256] = {0}, s2[256] = {0};char key[256] = {"[Warnning]Access_Unauthorized"};char pData[512] = {0xc3, 0x82, 0xa3, 0x25, 0xf6, 0x4c, 0x36, 0x3b, 0x59, 0xcc, 0xc4, 0xe9, 0xf1, 0xb5,
0x32, 0x18, 0xb1, 0x96, 0xae, 0xbf, 0x08, 0x35};rc4_init(s, (unsigned char*)key, strlen(key));for (int i = 0; i < 256; i++)s2[i] = s[i];unsigned long len = strlen(pData);rc4_crypt(s, (unsigned char*)pData, strlen(pData));printf("%s\n", pData);rc4_crypt(s2, (unsigned char*)pData, strlen(pData));printf("%s\n", pData);return 0;}

















