参考: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;
}