学破解第105天,《攻防世界reverse练习区Mysterious》分析
前言:
一直对黑客充满了好奇,觉得黑客神秘,强大,无所不能,来论坛两年多了,天天看各位大佬发帖,自己只能做一个伸手党。也看了官方的入门视频教程,奈何自己基础太差,看不懂。自我反思之下,决定从今天(2019年6月17日)开始定下心来,从简单的基础教程开始学习,希望能从照抄照搬,到能独立分析,能独立破解。
不知不觉学习了好几个月,发现自己离了教程什么都不会,不懂算法,不懂编程。随着破解学习的深入,楼主这个半吊子迷失了自我,日渐沉迷水贴装X,不能自拔。
==========申明:从第71天楼主开始水贴装X,帖子不再具有连续性,仅供参考,后续帖子为楼主YY专用贴!!!==========
立帖为证!--------记录学习的点点滴滴
0x1上OD
1.把这个程序下载下来,直接跑起来,摸清敌情,看图就知道了,要我输入正确的password,试着点击一下,发现没有弹窗,也就意味着我不能使用messageBOX断点了
2.这个网站的程序一般不加壳,所以直接丢进OD,搜索字符串,看到了flag字样,走,回车过去看看
0040118A . E8 C1040000 call caddc1a7.00401650
0040118F . 83C4 04 add esp,0x4
00401192 . 8985 F8FEFFFF mov dword ptr ss:[ebp-0x108],eax
00401198 . 8B95 F8FEFFFF mov edx,dword ptr ss:[ebp-0x108]
0040119E . 83C2 01 add edx,0x1
004011A1 . 8995 F8FEFFFF mov dword ptr ss:[ebp-0x108],edx
004011A7 . 83BD F8FEFFFF>cmp dword ptr ss:[ebp-0x108],0x7B
004011AE . 0F85 F6000000 jnz caddc1a7.004012AA
004011B4 . 0FBE85 FFFEFF>movsx eax,byte ptr ss:[ebp-0x101]
004011BB . 83F8 78 cmp eax,0x78
004011BE . 0F85 E6000000 jnz caddc1a7.004012AA
004011C4 . 0FBE8D 01FFFF>movsx ecx,byte ptr ss:[ebp-0xFF]
004011CB . 83F9 7A cmp ecx,0x7A
004011CE . 0F85 D6000000 jnz caddc1a7.004012AA
004011D4 . 0FBE95 00FFFF>movsx edx,byte ptr ss:[ebp-0x100]
004011DB . 83FA 79 cmp edx,0x79
004011DE . 0F85 C6000000 jnz caddc1a7.004012AA
004011E4 . A1 A02F4200 mov eax,dword ptr ds:[0x422FA0] ; flag
3.好家伙,这么大一段都要跳过输出flag的地方,上面那个妥妥的关键call啊,F2下断点,运行起来,输入abcdef,然后愉快的断了下来,F7进去
00401650 /$ 55 push ebp
00401651 |. 8BEC mov ebp,esp
00401653 |. 8B45 08 mov eax,[arg.1]
00401656 |. 50 push eax
00401657 |. E8 F4FEFFFF call caddc1a7.00401550
0040165C |. 83C4 04 add esp,0x4
0040165F |. 5D pop ebp
00401660 \. C3 retn
4.继续跟下去,硬着头皮对着汇编刚一波,分析完后,还是有点迷
00401550 /$ 55 push ebp
00401551 |. 8BEC mov ebp,esp
00401553 |. 83EC 14 sub esp,0x14 ; 这是干啥子?分配14个字符空间
00401556 |> 833D 6C4C4200>/cmp dword ptr ds:[0x424C6C],0x1 ; 直接寻址,这是常量1?
0040155D |. 7E 17 |jle short caddc1a7.00401576 ; 这里跳了
0040155F |. 6A 08 |push 0x8
00401561 |. 8B45 08 |mov eax,[arg.1]
00401564 |. 33C9 |xor ecx,ecx ; caddc1a7.00424A6A
00401566 |. 8A08 |mov cl,byte ptr ds:[eax]
00401568 |. 51 |push ecx ; caddc1a7.00424A6A
00401569 |. E8 820C0000 |call caddc1a7.004021F0
0040156E |. 83C4 08 |add esp,0x8
00401571 |. 8945 F0 |mov [local.4],eax
00401574 |. EB 19 |jmp short caddc1a7.0040158F
00401576 |> 8B55 08 |mov edx,[arg.1] ; 输入的字符串abcdef
00401579 |. 33C0 |xor eax,eax ; 清空eax
0040157B |. 8A02 |mov al,byte ptr ds:[edx] ; 取字母a
0040157D |. 8B0D 604A4200 |mov ecx,dword ptr ds:[0x424A60] ; 把这个地址给ecx
00401583 |. 33D2 |xor edx,edx ; 清空edx
00401585 |. 66:8B1441 |mov dx,word ptr ds:[ecx+eax*2] ; 0x424B2C,值82
00401589 |. 83E2 08 |and edx,0x8 ; 又变成0了?
0040158C |. 8955 F0 |mov [local.4],edx
0040158F |> 837D F0 00 |cmp [local.4],0x0 ; 等于0,跳了
00401593 |. 74 0B |je short caddc1a7.004015A0
00401595 |. 8B45 08 |mov eax,[arg.1]
00401598 |. 83C0 01 |add eax,0x1
0040159B |. 8945 08 |mov [arg.1],eax
0040159E |.^ EB B6 \jmp short caddc1a7.00401556
004015A0 |> 8B4D 08 mov ecx,[arg.1] ; 输入的字符串abcdef
004015A3 |. 33D2 xor edx,edx ; 清空edx
004015A5 |. 8A11 mov dl,byte ptr ds:[ecx] ; 取字母a
004015A7 |. 8955 FC mov [local.1],edx
004015AA |. 8B45 08 mov eax,[arg.1] ; eax又是我输入的abcdef了
004015AD |. 83C0 01 add eax,0x1 ; eax地址加1
004015B0 |. 8945 08 mov [arg.1],eax ; bcdef
004015B3 |. 8B4D FC mov ecx,[local.1]
004015B6 |. 894D F4 mov [local.3],ecx ; 字母a,值61
004015B9 |. 837D FC 2D cmp [local.1],0x2D ; 0x2D对应-
004015BD |. 74 06 je short caddc1a7.004015C5 ; 不跳
004015BF |. 837D FC 2B cmp [local.1],0x2B ; 0x2B对应+
004015C3 |. 75 13 jnz short caddc1a7.004015D8 ; 跳
004015C5 |> 8B55 08 mov edx,[arg.1]
004015C8 |. 33C0 xor eax,eax
004015CA |. 8A02 mov al,byte ptr ds:[edx]
004015CC |. 8945 FC mov [local.1],eax
004015CF |. 8B4D 08 mov ecx,[arg.1]
004015D2 |. 83C1 01 add ecx,0x1
004015D5 |. 894D 08 mov [arg.1],ecx ; caddc1a7.00424A6A
004015D8 |> C745 F8 00000>mov [local.2],0x0 ; 局部变量2的值为0
004015DF |> 833D 6C4C4200>/cmp dword ptr ds:[0x424C6C],0x1 ; 跳
004015E6 |. 7E 13 |jle short caddc1a7.004015FB
004015E8 |. 6A 04 |push 0x4
004015EA |. 8B55 FC |mov edx,[local.1]
004015ED |. 52 |push edx
004015EE |. E8 FD0B0000 |call caddc1a7.004021F0
004015F3 |. 83C4 08 |add esp,0x8
004015F6 |. 8945 EC |mov [local.5],eax
004015F9 |. EB 15 |jmp short caddc1a7.00401610
004015FB |> 8B45 FC |mov eax,[local.1] ; a,值61
004015FE |. 8B0D 604A4200 |mov ecx,dword ptr ds:[0x424A60] ; 把这个地址给ecx
00401604 |. 33D2 |xor edx,edx ; 清空edx
00401606 |. 66:8B1441 |mov dx,word ptr ds:[ecx+eax*2] ; 0x424B2C,值82
0040160A |. 83E2 04 |and edx,0x4 ; edx又变0了,0x4是0100
0040160D |. 8955 EC |mov [local.5],edx
00401610 |> 837D EC 00 |cmp [local.5],0x0 ; 等于0,跳
00401614 |. 74 25 |je short caddc1a7.0040163B
00401616 |. 8B45 F8 |mov eax,[local.2] ; caddc1a7.0040165C
00401619 |. 6BC0 0A |imul eax,eax,0xA
0040161C |. 8B4D FC |mov ecx,[local.1]
0040161F |. 8D5408 D0 |lea edx,dword ptr ds:[eax+ecx-0x30]
00401623 |. 8955 F8 |mov [local.2],edx
00401626 |. 8B45 08 |mov eax,[arg.1]
00401629 |. 33C9 |xor ecx,ecx ; caddc1a7.00424A6A
0040162B |. 8A08 |mov cl,byte ptr ds:[eax]
0040162D |. 894D FC |mov [local.1],ecx ; caddc1a7.00424A6A
00401630 |. 8B55 08 |mov edx,[arg.1]
00401633 |. 83C2 01 |add edx,0x1
00401636 |. 8955 08 |mov [arg.1],edx
00401639 |.^ EB A4 \jmp short caddc1a7.004015DF
0040163B |> 837D F4 2D cmp [local.3],0x2D ; 0x2D对应-
0040163F |. 75 07 jnz short caddc1a7.00401648 ; 跳
00401641 |. 8B45 F8 mov eax,[local.2] ; caddc1a7.0040165C
00401644 |. F7D8 neg eax
00401646 |. EB 03 jmp short caddc1a7.0040164B
00401648 |> 8B45 F8 mov eax,[local.2] ; eax变成0了
0040164B |> 8BE5 mov esp,ebp
0040164D |. 5D pop ebp ; caddc1a7.0040165C
0040164E \. C3 retn
5.出call后,就是最开始找到的比较的地方,应该是在对密码格式进行判断
004011A1 . 8995 F8FEFFFF mov dword ptr ss:[ebp-0x108],edx
004011A7 . 83BD F8FEFFFF>cmp dword ptr ss:[ebp-0x108],0x7B ; edx = 1,0x7B是{
004011AE . 0F85 F6000000 jnz caddc1a7.004012AA ; 手动修改标志位让它不跳
004011B4 . 0FBE85 FFFEFF>movsx eax,byte ptr ss:[ebp-0x101] ; d
004011BB . 83F8 78 cmp eax,0x78 ; 0x78是x
004011BE . 0F85 E6000000 jnz caddc1a7.004012AA
004011C4 . 0FBE8D 01FFFF>movsx ecx,byte ptr ss:[ebp-0xFF] ; f
004011CB . 83F9 7A cmp ecx,0x7A ; 0x7A是z
004011CE . 0F85 D6000000 jnz caddc1a7.004012AA
004011D4 . 0FBE95 00FFFF>movsx edx,byte ptr ss:[ebp-0x100] ; e
004011DB . 83FA 79 cmp edx,0x79 ; 0x79是y
004011DE . 0F85 C6000000 jnz caddc1a7.004012AA
004011E4 . A1 A02F4200 mov eax,dword ptr ds:[0x422FA0] ; flag
6.一直跟,在内存中看到eax=0018F760, (ASCII "flag{1_Buff3r_0v3rf|0w}"),然而并不对,OD分析就到这里了,对程序大概摸清楚了,接下来就使用IDA吧。
0x2上IDA
1.直接把程序拖进IDA,带着在OD中的疑问,来找到我的答案吧!
if ( v10 == 123 && v12 == 120 && v14 == 122 && v13 == 121 )
{
strcpy(Text, "flag");
memset(&v7, 0, 0xFCu);
v8 = 0;
v9 = 0;
_itoa(v10, &v5, 10);
strcat(Text, "{");
strcat(Text, &v5);
strcat(Text, "_");
strcat(Text, "Buff3r_0v3rf|0w");
strcat(Text, "}");
MessageBoxA(0, Text, "well done", 0);
}
SetTimer(hWnd, 1u, 0x3E8u, TimerFunc);
2.看了这段代码后,就可以看到爆破来的flag不行的原因了,TEXT中保存的是flag,再看看flag,调用strcat进行连接,它是由flag{v5_Buff3r_0v3rf|0w}}组成的,而v5在_itoa(v10, &v5, 10);这里进行了赋值!
3.那我们显然就需要跟进_itoa这个函数了,看看里面的代码:
char *__cdecl _itoa(int a1, char *a2, int a3)
{
if ( a3 != 10 || a1 >= 0 )
xtoa(a1, a2, a3, 0);
else
xtoa(a1, a2, 10, 1);
return a2;
}
咋越看越糊涂了,里面咋还有函数......,去百度下这个函数
简介
整形转换为字符串 int--->char
char_itoa(int value,char* string,int radix);
参数说明
value-----要转换的整形值
string-----转换后的字符串
radix------表示基数(2, 8, 10, 16)等进制基数
4.看了函数声明,就说明V5就是v10的十进制字符串表示,v5的值是123,再看前面v10 == 123才会执行这个if语句。
5.继续反向推导,可知输入的字符串应该为122。
GetDlgItemTextA(hWnd, 1002, &String, 260);//获取文本框输入的内容
v10 = atoi(&String) + 1;//文本框里面输入的应该是123-1
flag显然是flag{123_Buff3r_0v3rf|0w},提交,完全正确,但是这个程序的密码我们还没分析完。
0x3追溯密码
1.我们输入122,然而并没有弹出正确的flag,程序一目了然,就是读取字符串转换为整数,为什么会不会呢?v12,v13,v14是个局部变量,但是通过IDA F5分析的代码看不到在哪赋值的!
2.这段if语句在OD中对应的就是在OD中最后分析的那片代码,回过头来再看一看,他比较的是
004011A1 . 8995 F8FEFFFF mov dword ptr ss:[ebp-0x108],edx
004011A7 . 83BD F8FEFFFF>cmp dword ptr ss:[ebp-0x108],0x7B ; edx = 1,0x7B是{
004011AE . 0F85 F6000000 jnz caddc1a7.004012AA ; 手动修改标志位让它不跳
004011B4 . 0FBE85 FFFEFF>movsx eax,byte ptr ss:[ebp-0x101] ; d
004011BB . 83F8 78 cmp eax,0x78 ; 0x78是x
004011BE . 0F85 E6000000 jnz caddc1a7.004012AA
004011C4 . 0FBE8D 01FFFF>movsx ecx,byte ptr ss:[ebp-0xFF] ; f
004011CB . 83F9 7A cmp ecx,0x7A ; 0x7A是z
004011CE . 0F85 D6000000 jnz caddc1a7.004012AA
004011D4 . 0FBE95 00FFFF>movsx edx,byte ptr ss:[ebp-0x100] ; e
004011DB . 83FA 79 cmp edx,0x79 ; 0x79是y
004011DE . 0F85 C6000000 jnz caddc1a7.004012AA
004011E4 . A1 A02F4200 mov eax,dword ptr ds:[0x422FA0] ; flag
3.我输入的是abcdef,首先比较0x7B,转换为10进制正是123,和IDA中的V10对上,后面依次用d,f,e比较0x78,0x7A,0x79,可以看到取我输入的后三位进行比较,和IDA中的if语句完全对上,替换后正确的密码应该是就是122xzy!
0x4总结
1.这题如果单用OD,我可能流程都搞不清楚。
2.这题如果只用IDA,我可能只猜得到flag,却得不到正确的password
3.看了IDA才知道开头的是数字,结合OD知道我输入的字符串后三位分别对应哪一个值。