love

其实是比较简单的逆向,但是毕竟上手时间短,写一写顺便把思路缕清

题目

打开是dos窗口,等待输入flag,随便输入后直接退出

拖入IDA,重点函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
__int64 main_0()
{
int len; // eax
const char *v1; // eax
size_t real_len; // eax
int v3; // edx
__int64 v4; // ST08_8
signed int j; // [esp-B0h] [ebp-B0h]
signed int i; // [esp-A4h] [ebp-A4h]
signed int v8; // [esp-A4h] [ebp-A4h]
int v9; // [esp-98h] [ebp-98h]
int flag; // [esp-2Ch] [ebp-2Ch]
int v11; // [esp-10h] [ebp-10h]
int v12; // [esp-4h] [ebp-4h]

for ( i = 0; i < 100; ++i )
{
if ( (unsigned int)i >= 0x64 )
j____report_rangecheckfailure();
*((_BYTE *)&v12 + i - 0x94) = 0;
}
puts_("please enter the flag:");
scanf("%20s", &flag);
len = j_strlen((const char *)&flag);
v1 = (const char *)deal((int)&flag, len, (int)&v11);
strncpy((char *)&v9, v1, 40u);
v8 = j_strlen((const char *)&v9);
for ( j = 0; j < v8; ++j )
*((_BYTE *)&v12 + j - 0x94) += j;


real_len = j_strlen((const char *)&v9);
if ( !strncmp((const char *)&v9, Str2, real_len) )
puts_("rigth flag!\n");
else
puts_("wrong flag!\n");
HIDWORD(v4) = v3;
LODWORD(v4) = 0;
return v4;
}


Str2 db 'e3nifIH9b_C@n@dH',0

分析

程序流程也比较清晰,初始时将一段栈内存置为0,可以看到是在v9处,之后请求输入flag,然后对输入的flag deal加密处理
然后处理得到的字符串再次每位加i,相当于第二次加密,之后将其与一段字符串相比,相等的话就输出right flag

所以问题的重点其实是第一次加密是怎样处理的,ida中看到一堆abcdef…,想着可能是base64,但是不确定。

将文件拖入x32dbg 先运行起来,然后搜索字符串,找到主函数的位置,根据ida可以知道在第一次加密之后调用了strncpy,所以我们在搜索到wrong flag地址,往上翻,可以大概确定加密的地址,在其之后下断点,运行程序输入任意flag,因为约定函数返回值是存在eax中的,查看此时的eax,发现其值就是输入flag的base64,接下来写脚本就完事了

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
import base64

string='e3nifIH9b_C@n@dH'
unstring = ''
for i in range(len(string)):
unstring += chr(ord(string[i])-i)

flag = base64.b64decode(unstring)
print flag


$ python lovewp.py
{i_l0ve_you}