-
-
[原创] 看雪 ctf 攻防战 2018 - 追凶者也
-
2018-12-12 21:36 2497
-
一个 32位的 exe
自己电脑跑不起来,上班摸鱼又不敢花时间搞个win7,只能静态看了..
逻辑分析
ida 打开首先可以看到 WinMain 函数,进去看看
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { sub_401280(); return 0; } .text:00401280 sub_401280 proc near ; CODE XREF: WinMain(x,x,x,x)+5↑p .text:00401280 ; DATA XREF: .data:off_414018↓o .text:00401280 push ebp .text:00401281 mov ebp, esp .text:00401283 push eax .text:00401284 mov eax, ebx .text:00401286 pop eax .text:00401287 cmp ebp, esp .text:00401289 call __RTC_CheckEsp .text:0040128E pop ebp .text:0040128F retn .text:0040128F sub_401280 endp
WinMain 调了一个 函数,sub_401280 ,这个函数 call 了一个 CheckEsp 函数, 看 WinMain 的 xref 貌似 还加了反调试,应该是检查内存镜像完整性什么什么的
还好这个程序比较小,函数不多,乱点一下就可以找到关键逻辑
先看 DialogFunc 调用了下面这个函数
int __cdecl sub_401040(HWND hDlg) { ...... strcpy(Text, "try again!"); strcpy(Caption, "fail"); String = 0; v6 = 0; v7 = 0; v8 = 0; v9 = 0; v10 = 0; v11 = 0; GetDlgItemTextA(hDlg, 1001, &String, 20); v4 = 0; for ( i = 0; i < 20; ++i ) v4 += *(&String + i); if ( v4 > 0 && v4 < 0x1024 ) { v1 = malloc(v4); sub_401020(); j___free_base(v1); } return MessageBoxA(0, Text, Caption, 0); }
主要是
- 获取输入
- 每个byte的hex 相加 <0x1024
分配内存
然后调用了一个函数.text:00401020 sub_401020 proc near ; CODE XREF: sub_401040+E9↓p .text:00401020 .text:00401020 var_4 = dword ptr -4 .text:00401020 .text:00401020 push ebp .text:00401021 mov ebp, esp .text:00401023 push ecx .text:00401024 mov [ebp+var_4], 0CCCCCCCCh .text:0040102B mov [ebp+var_4], offset loc_40D180 .text:00401032 mov esp, ebp .text:00401034 pop ebp .text:00401035 retn .text:00401035 sub_401020 endp
这函数就是跳到了 loc_40D180 这个地址,这里是再 rdata 段
ida p 一下就可以 f5 看了,开头像下面.rdata:0040D180 push ebp .rdata:0040D181 mov ebp, esp .rdata:0040D183 sub esp, 100h .rdata:0040D189 mov [ebp+var_40], 'K' .rdata:0040D18D mov [ebp+var_3F], 'e' .rdata:0040D191 mov [ebp+var_3E], 'r' .rdata:0040D195 mov [ebp+var_3D], 'n' .rdata:0040D199 mov [ebp+var_3C], 'e' .rdata:0040D19D mov [ebp+var_3B], 6Ch .rdata:0040D1A1 mov [ebp+var_3A], '3' .rdata:0040D1A5 mov [ebp+var_39], '2' .rdata:0040D1A9 mov [ebp+var_38], '.' .rdata:0040D1AD mov [ebp+var_37], 'd' .rdata:0040D1B1 mov [ebp+var_36], 'l' .rdata:0040D1B5 mov [ebp+var_35], 'l' .rdata:0040D1B9 mov [ebp+var_34], 0 .rdata:0040D1BD mov [ebp+var_50], 'G' .rdata:0040D1C1 mov [ebp+var_4F], 'e' .rdata:0040D1C5 mov [ebp+var_4E], 't' .rdata:0040D1C9 mov [ebp+var_4D], 'P' .rdata:0040D1CD mov [ebp+var_4C], 'r' .rdata:0040D1D1 mov [ebp+var_4B], 'o' .rdata:0040D1D5 mov [ebp+var_4A], 'c' .rdata:0040D1D9 mov [ebp+var_49], 'A' .rdata:0040D1DD mov [ebp+var_48], 'd' .rdata:0040D1E1 mov [ebp+var_47], 'd' .rdata:0040D1E5 mov [ebp+var_46], 'r' .rdata:0040D1E9 mov [ebp+var_45], 'e' .... .rdata:0040D285 mov [ebp+var_15], 0 .rdata:0040D289 mov [ebp+var_8], 's' .rdata:0040D28D mov [ebp+var_7], 'u' .rdata:0040D291 mov [ebp+var_6], 'c' .rdata:0040D295 mov [ebp+var_5], 'c' .rdata:0040D299 mov [ebp+var_4], 'e' .rdata:0040D29D mov [ebp+var_3], 's' .rdata:0040D2A1 mov [ebp+var_2], 's'
写了一堆字符,最后可以看到 MessageBox , success 等, 这里应该是 loadlibary 然后调里面的 MessageBox 什么的吧,好像没有什么逻辑处理的东西???
乱点函数看到了一个可疑的逻辑bool __cdecl sub_401290(int a1, int a2) { byte_4147D0[0] = 4; byte_4147D0[1] = 1; byte_4147D0[2] = 3; byte_4147D0[3] = 7; byte_4147D0[4] = 2; byte_4147D0[5] = 5; byte_4147D0[6] = 8; byte_4147D0[7] = 6; byte_4147D0[8] = 0; return sub_4015B0(a1, a2); } bool __cdecl sub_4015B0(int a1, int a2) { int i; // [esp+0h] [ebp-Ch] int v4; // [esp+8h] [ebp-4h] v4 = -858993460; if ( a2 % 2 ) return 0; for ( i = 0; i < a2; i += 2 ) { if ( *(_BYTE *)(i + a1) == 'w' ) v4 = 0; if ( *(_BYTE *)(i + a1) == 'd' ) v4 = 1; if ( *(_BYTE *)(i + a1) == 's' ) v4 = 2; if ( *(_BYTE *)(i + a1) == 'a' ) v4 = 3; if ( !sub_401380(v4, *(char *)(i + a1 + 1) - 48) ) return 0; } return byte_4147D0[0] == 1 && byte_4147D0[1] == 2 && byte_4147D0[2] == 3 && byte_4147D0[3] == 4 && byte_4147D0[4] == 5 && byte_4147D0[5] == 6 && byte_4147D0[6] == 7 && byte_4147D0[7] == 8 && !byte_4147D0[8]; }
看到 wdsa 基本上就可以确定关键逻辑在这里了,这是要玩游戏??
注意到 rdata 是不可执行的,可能这里有什么SEH的处理逻辑在里面,木有时间,就先不管了,反正逻辑找到了
看看上面两个函数的 xref 什么的,wdsa 比较的应该就是 输入的每个byte
,输入的格式是
wXdXSXaXaX 类似这样,X是数字 0-9
每次获取两个byte 然后进入 sub_401380
最后要求byte_4147D0 这个表里面的内容是 1,2,...,8,0 这样,这个有9个项, 会不会是 3x3 的迷宫什么什么的
进 sub_401380 看看if ( !a2 ) return 0; v4 = 0; LABEL_4: if ( v4 >= 3 ) return 0; for ( i = 0; ; ++i ) { if ( i >= 3 ) { ++v4; goto LABEL_4; } if ( byte_4147D0[3 * v4 + i] == a2 ) break; LABEL_6: ; }
一开头的逻辑,可以确定这是进行 一个 3x3 的表的操作了,这里是根据 我们输入的 wX 的 X 定位一个项, 后面 根据 wdsa switch 处理
wdsa 一般想到的是 方向键,还原一下 这个表初始化的时候4 1 3 7 2 5 8 6 0
这不会是拼图游戏吧,类似这样?
4 1 3 4 1 3 7 2 5 => d6 => 7 2 5 8 6 0 8 0 6
看一下后面 switch 的处理逻辑也基本可以确定了,那么就是要把初始化的表变成
1 2 3 4 5 6 7 8 0
玩了一下,结果是
d6d8s7s4a1w2a5
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。