刚好在学逆向,突然想着可以看一下还在比赛的看雪ctf

流浪者

win32 gui 输入注册码,错误会有提示

od 打开,搜索字符串,找到判断结果的函数位置;

ida 打开,找到od确定的函数位置,根据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
sub_401770      proc near               ; CODE XREF: sub_4017F0+83↓p

BOOL __cdecl sub_4017F0(int a1)
{
BOOL result; // eax
char Str1[28]; // [esp+D8h] [ebp-24h]
int v3; // [esp+F4h] [ebp-8h]
int v4; // [esp+F8h] [ebp-4h]

v4 = 0;
v3 = 0;
while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )
{
Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
++v4;
}
Str1[v4] = 0;
if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
result = sub_401770();
else
result = sub_4017B0();
return result;
}


aAbcdefghiabcde db 'abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ',0

可以看到就是字符串对应,直接写脚本
中间卡了一下就是得到的是数字位置,如19,42什么的,但是输入没法这样,出去溜了个弯,回去在od strcmp之前下了个断点,查看对输入字符串的处理,之后突然意识到可能是 0-9 a-z A-Z 对应,尝试了一下,bingo

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
a = 'abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ'

b = 'KanXueCTF2019JustForhappy'
array = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

c = ''

for i in range(len(b)):
for j in range(len(a)):
if b[i]== a[j]:
c += array[j]
print c

Repwn

中间卡住了。。好在后面还是把解出来了哈哈哈哈,先说下目前的思路

还是先拖进od然后搜索出现的字符串,不记得是用ida还是od找到了判断入口,下断点,同时在ida中找到函数位置,反汇编,可以看到层层嵌套的判断

第一次 判断了13位,也可以因此确定其中的13位:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
v1 = 8;
v2 = 0;
v8 = 'ruoY';
v9 = 'pnI_';
v10 = 'I_tu';
v11 = 'rW_s';
v12 = 'gno';
v4 = '0Y1X';
v5 = 't3Nu';
v6 = 'd00G';
v7 = 0;
while ( *((_BYTE *)&v4 + v2) == *(_BYTE *)(v1 + key) )
{
++v2;
++v1;
if ( v2 > 11 )
{
result = 1;
if ( *(_BYTE *)(key + 20) == 'H' )
return result;
return 0;
}
}
return 0;

第二次,确定了序列长度,同时在检查第三步回来之后还会对最后四位处理,最后会将其覆盖到返回地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if ( strlen(Str) == 24 )
{
if ( check3((int)Str) )
{
Str[20] -= 88;
Str[21] -= 70;
Str[22] -= 3;
Str[23] -= 107;
strcpy(&Dest, Str);
}
}
else
{
printf("String Length is Wrong");
}

第三次,也就是最后一次,,deal_8对前八位全部减0x30, 第三次通过计算可以确定第五到八位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 deal_8(a1);
v1 = no_4 + 1000 * fl[0] + 100 * no_2 + 10 * no_3;
v2 = no_6 + 10 * no_5;
v3 = no_8 + 10 * no_7;

if ( 2 * (v1 + v2) != 4040 || 3 * v2 / 2 + 100 * v3 != 115 )// v1+v2 = 0x7e4
goto LABEL_2;
result = 1;


if ( v1 - 110 * v3 != 1900 )
{
printf("Key_Is_Wrong,Please_Input_Again!");
LABEL_2:
result = 0;
}

经过不断的尝试+猜测,终于试出了flag

1
20101001X1Y0uN3tG00dHaCk