好友
阅读权限10
听众
最后登录1970-1-1
|
一、静态分析
之前一直在做pwn题,抓耳挠腮,做不出来,今天看了看reverse题目,感觉有意思的题目,写上来。另外上一篇有朋友反应不够细,导致有些操作不了解,这篇写详细点。
用IDA打开程序后发现程序主函数并不明显,因此shift+F12,打开字符串窗口,发现输入flag的字段
点进去,按x,查看有什么地方调用的这个字符串,随后就能找到主函数位置了。
进入这个函数,按F5可以查看这个函数的逻辑了。
看到这里就很简单了,代码逻辑就是输入的字符串flag通过异或0x22等于一个常量,那想求这个flag,只需要将常量异或0x22即可。
右击鼠标,选择array,将其转为数组,随后点击左上角Edit->Export Data,将数据导出来。(IDA导出数据的操作)
使用如下代码:
[Python] 纯文本查看 复制代码 [/size][/font]
[font=宋体][size=3]a=[0x64, 0x63, 0x69, 0x67, 0x59, 0x6A, 0x63, 0x6A, 0x63, 0x03,[/size][/font][font=宋体][size=3]0x03, 0x6B, 0x05, 0x4F, 0x02, 0x4C, 0x4D, 0x56, 0x02, 0x4A,
0x47, 0x50, 0x47, 0x5F]
b=''
for i in a:
b+=(chr(i^0x22&0xff))
[/size][/font]
[font=宋体][size=3]print(b)[/size][/font]
[font=宋体][size=3]
执行后发现结果不对,是个假flag
二、动态调试
拉进x32dbg,断点下到0x401FB8处,也就是调用函数位置。
随便输入点东西,然后长度保持24,断到了0x401FB8。
进入这个函数看看,发生了什么
根据静态分析,这里应该跳转到0x401FE0,但是实际执行的时候,他跳转到了0x00402090.IDA查看一下这块儿代码是什么?
被加密了。。。只能动态给他脱出来了。
但是要给他粘贴到源程序中,该怎么粘贴。先复制源程序,不影响源程序,随后用010editor打开
在IDApro中,查看2090那个位置的机器码,复制出来,到010editor去搜索
经过对比,确定该位置是正确的,因此可以直接将x32dbg代码中复制出来的二进制代码粘贴到该位置,复制方式Edit->Paste from->Paste from Hex Text
然后保存即可
随后将修改过的程序拉到IDApro中,就可以看到2090这个位置的代码了。
三、最终题解
通过分析,主要的处理函数,是个rc4加密算法,而其需要两个输入,一个是用户输入的flag、另一个是key,通过动态分析,可以得到key
接下来是代码
[C++] 纯文本查看 复制代码 #include<cstdio>
#include<cstdint>
#include <string.h>
// 对应sub_402500 - RC4 KSA(密钥调度算法)
int rc4_ksa(uint8_t* S, const uint8_t* key, int key_len)
{
int result;
int j = 0;
int i;
uint8_t temp;
// 初始化S盒:S[i] = i
for (i = 0; i < 256; ++i)
{
S[i] = (uint8_t)i;
result = i + 1;
}
// 用密钥打乱S盒
for (i = 0; i < 256; ++i)
{
// j = (j + key[i % key_len] + S[i]) % 256
j = ((uint8_t)key[i % key_len] + j + S[i]) % 256;
// 交换S[i]和S[j]
temp = S[i];
S[i] = S[j];
S[j] = temp;
result = i + 1;
}
return result;
}
// 对应sub_4023A0 - RC4 PRGA(伪随机数生成+加解密)
int rc4_crypt(uint8_t* data, int data_len, const uint8_t* key, int key_len)
{
int result;
uint8_t S[256]; // 对应v9
int i = 0; // PRGA的i指针,对应v7
int j = 0; // PRGA的j指针,对应v5
int idx; // 循环变量,对应原代码的i
uint8_t temp; // 对应v8
// 第一步:初始化S盒(调用KSA)
rc4_ksa(S, key, key_len);
// 第二步:PRGA生成密钥流并异或加解密
for (idx = 0; idx < data_len; ++idx)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
// 交换S[i]和S[j]
temp = S[i];
S[i] = S[j];
S[j] = temp;
// 生成密钥流字节并异或数据
uint8_t t = (S[i] + S[j]) % 256;
data[idx] ^= S[t];
result = idx + 1;
}
return result;
}
int main() {
unsigned char plaintext[] =
{
0xEA, 0x64, 0x65, 0x15, 0xFF, 0x0A, 0xAD, 0x41, 0x6F, 0x81,
0xA1, 0x7B, 0xA8, 0xD0, 0x5E, 0x69, 0x74, 0x92, 0x6A, 0xE3,
0xBD, 0x6B, 0x33, 0x97, 0x2D, 0xC2, 0xB5, 0xFA, 0xD0, 0x8F,
0x6D, 0x3F, 0xAD, 0x00, 0xD0, 0x91
};
uint8_t key[] = {
0xE7,0xDA,0x07,0xAE,0xE5,0xFB,0xC3,0x0F,0x31,0xD8,0xDF,0x1B,0x3B,0x2E,0x5B,0x02,0x24
};
int data_len = 0x24;
int key_len = 16;
rc4_crypt(plaintext, data_len, key, key_len);
printf("解密后数据: %s\n", plaintext);
return 0;
}
运行结果如下
|
免费评分
-
查看全部评分
|