CTF逆向
本帖最后由 muyilin 于 2022-3-9 11:09 编辑## 2018年九月份安恒杯月赛之NewDriver
由于该题附件和相关知识有从吾爱破解中获得,所以也把该篇发在吾爱破解中,作为自己加入吾爱破解的第一篇文章^~^。(PS:附件在文末)
**这题是复现的,用于研究 RC4 加密,首先拿到附件:**
![在这里插入图片描述](https://img-blog.csdnimg.cn/68c32755243041a5a763e0905d583816.png)
.
.
**照例扔入 exeinfope 中查看信息:**
![在这里插入图片描述](https://img-blog.csdnimg.cn/25c9c80bdde448b68f4834c67d1fd879.png?)
.
.
**32 位无壳,照例扔入 IDA32 中查看信息,有 main 函数看 main 函数:**(这次就用老版7.0 IDA 来分析算了)
![在这里插入图片描述](https://img-blog.csdnimg.cn/c4fc31c49eaf45f082716bd4bb260268.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/80772cbf5e0e43e392176cab50e95def.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ea56e9b274cb4455b3af340f052928c1.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/589b9608dd4f41129ecdf5ea373166c4.png?)
.
.
**分析第一个自定义函数:**
![在这里插入图片描述](https://img-blog.csdnimg.cn/c162e4209fed4e15b079a37b05099054.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/be4367d2b47e4a57ac3c78e625f65acc.png)
.
.
**分析第二个自定义函数:**
![在这里插入图片描述](https://img-blog.csdnimg.cn/0eb1f0d1b12f43a3935263cc2ec48836.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a479353fb2404d239131b7e5f74e1ec5.png?)
.
.
**分析第三个自定义函数:**
![在这里插入图片描述](https://img-blog.csdnimg.cn/e9c6619680da48ba8bcb521d7ad9e5e3.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/9e74a3f204a3491fa360101d5d546657.png?)
.
.
所以总的流程是,用户输入------>base64加密------>RC4数据初始化并且加密-------->进行比较
.
**第一个解法,RC4解密后,Base64变表解密:**
这里`替换`了密文和密钥,需要注意的是密钥哪里由于C语言的字符串末尾`补0`特性,导致key多了一个`0x00`,结果就大不同了,所以我们只能用16进制的`没有`补齐0x00的数据才行。
```c
#include <stdio.h>
typedef struct _RC4INFO
{
unsigned char s_box;
unsigned char t_box;
}RC4_INFO,*PRC4_INFO;
void rc4_init(PRC4_INFO prc4,unsigned char key[], unsigned int keylen)
{
int i = 0;
int j = 0;
unsigned char tmp;
if (prc4 == NULL)
{
return;
}
//init sbox an KeyBox(Tbox)
for (i = 0; i < 256; i++)
{
prc4->s_box = i;
prc4->t_box = key;
}
//swap sbox
for (i = 0; i < 256; i++)
{
j = (j + prc4->s_box + prc4->t_box) % 256;
tmp = prc4->s_box;
prc4->s_box = prc4->s_box;
prc4->s_box = tmp;
}
}
void rc4_crypt(
unsigned char data[], //要加密的数据
unsigned int datalen, //要加密的数据长度
unsigned char key[], //加密数据所用的Key
unsigned int keylen) //加密数据所用的key长度
{
int dn = 0;//data的意思
int i = 0;
int j = 0; // i j 分别用于交换sbox 和 sbox
int t = 0; //t = s + s
unsigned char tmp;
RC4_INFO rc4;
rc4_init(&rc4, key, keylen);
for (dn = 0; dn < datalen; dn++)
{
i = (i + 1) % 256;
j = (j + rc4.s_box) % 256;
//swap
tmp = rc4.s_box;
rc4.s_box = rc4.s_box;
rc4.s_box = tmp;
//得到T下标用于交换
t = (rc4.s_box + rc4.s_box) % 256;
data ^= rc4.s_box;
}
}
void EntryBuffer(unsigned char data[],unsigned int datalen)
{/*
unsigned char key[] = {
0x66, 0x6C, 0x61, 0x67, 0x7B, 0x74, 0x68, 0x69, 0x73, 0x5F,
0x69, 0x73, 0x5F, 0x6E, 0x6F, 0x74, 0x5F, 0x74, 0x68, 0x65,
0x5F, 0x66, 0x6C, 0x61, 0x67, 0x5F, 0x68, 0x61, 0x68, 0x61,
0x68, 0x61, 0x7D,0x00
};
*/
//unsigned char key[] ="flag{this_is_not_the_flag_hahaha}";
unsigned char key[] = {
0x66, 0x6C, 0x61, 0x67, 0x7B, 0x74, 0x68, 0x69, 0x73, 0x5F,
0x69, 0x73, 0x5F, 0x6E, 0x6F, 0x74, 0x5F, 0x74, 0x68, 0x65,
0x5F, 0x66, 0x6C, 0x61, 0x67, 0x5F, 0x68, 0x61, 0x68, 0x61,
0x68, 0x61, 0x7D
};
printf("\n\n%x\n\n",key);
rc4_crypt(data, datalen, key, sizeof(key) / sizeof(key));
printf("\n%d\n",sizeof(key) / sizeof(key));
}
int main()
{
unsigned char Hell[] = {
0x20, 0xC3, 0x1A, 0xAE, 0x97, 0x3C, 0x7A, 0x41, 0xDE, 0xF6,
0x78, 0x15, 0xCB, 0x4B, 0x4C, 0xDC, 0x26, 0x55, 0x8B, 0x55,
0xE5, 0xE9, 0x55, 0x75, 0x40, 0x3D, 0x82, 0x13, 0xA5, 0x60,
0x13, 0x3B, 0xF5, 0xD8, 0x19, 0x0E, 0x47, 0xCF, 0x5F, 0x5E,
0xDE, 0x9D, 0x14, 0xBD
};
printf("pData=%s\n\n", Hell);
//EntryBuffer((unsigned char*)Hell,sizeof(Hell)/sizeof(Hell)); //加密
//printf("pData=%s\n\n", Hell);
EntryBuffer((unsigned char*)Hell,sizeof(Hell)/sizeof(Hell)); //在调用一次就是解密了
printf("pData=%s\n\n", Hell);
return 0;
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/6727672c201d4b509b58a74bade671f2.png?)
.
.
**第二种解法,由于RC4末尾是异或操作,所以可以直接抽出内存中初始化后的数据来重新加密即可:**
在RC4的异或运算对合性中,RC4加密解密使用同一套算法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/47175726643a42d0afa7da8108a889e2.png?)
![在这里插入图片描述](https://img-blog.csdnimg.cn/317b22efc0b44695b18018317e09c9d5.png?)
```python
key=
key2=
key3=[]
v3=0
v4=0
v6=0
s=""
#这里直接仿写IDA中第三个加密函数逻辑即可
for v3 in range(44):
v3+=1
v6=key
v4=(v6+v4)%256
key=key
key=v6
key3.append(key[(key+v6)%256])
for i in range(44):
key2^=key3
for i in key2:
s+=chr(i)
print s
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/4f6b2e92a6fe4057975a484e7e8e23f6.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/6727672c201d4b509b58a74bade671f2.png?) 优秀,学习下 kole 发表于 2022-3-9 14:50
我发现可以直接的F5(使用的是IDA7.6),不用修复堆栈,你修复完传上来的吗
没有,IDA7.5及以上的的确可以一键F5,但是考虑到时2018年的题,所以我还是老老实实用IDA7.0来分析了:lol 跑来学习了 思路很清晰,学到了 支持,希望能学到第二篇知识!(麻烦附件也一同上传下){:1_919:} kole 发表于 2022-3-9 10:53
支持,希望能学到第二篇知识!(麻烦附件也一同上传下)
附件删了。。。。{:1_907:} muyilin 发表于 2022-3-9 10:58
附件删了。。。。
啊这,在哪里还可以下载呢 kole 发表于 2022-3-9 11:01
啊这,在哪里还可以下载呢
附件我重新下载放文末了 muyilin 发表于 2022-3-9 11:09
附件我重新下载放文末了
我发现可以直接的F5(使用的是IDA7.6),不用修复堆栈,你修复完传上来的吗 感谢分享