muyilin 发表于 2022-3-8 21:05

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?)

iloveasdl 发表于 2022-3-9 08:36

优秀,学习下

muyilin 发表于 2022-3-10 09:13

kole 发表于 2022-3-9 14:50
我发现可以直接的F5(使用的是IDA7.6),不用修复堆栈,你修复完传上来的吗

没有,IDA7.5及以上的的确可以一键F5,但是考虑到时2018年的题,所以我还是老老实实用IDA7.0来分析了:lol

timeni 发表于 2022-3-9 09:51

跑来学习了

Panel 发表于 2022-3-9 10:34

思路很清晰,学到了

kole 发表于 2022-3-9 10:53

支持,希望能学到第二篇知识!(麻烦附件也一同上传下){:1_919:}

muyilin 发表于 2022-3-9 10:58

kole 发表于 2022-3-9 10:53
支持,希望能学到第二篇知识!(麻烦附件也一同上传下)

附件删了。。。。{:1_907:}

kole 发表于 2022-3-9 11:01

muyilin 发表于 2022-3-9 10:58
附件删了。。。。

啊这,在哪里还可以下载呢

muyilin 发表于 2022-3-9 11:09

kole 发表于 2022-3-9 11:01
啊这,在哪里还可以下载呢

附件我重新下载放文末了

kole 发表于 2022-3-9 14:50

muyilin 发表于 2022-3-9 11:09
附件我重新下载放文末了

我发现可以直接的F5(使用的是IDA7.6),不用修复堆栈,你修复完传上来的吗

aonima 发表于 2022-3-9 18:13

感谢分享
页: [1] 2 3
查看完整版本: CTF逆向