看雪论坛.珠海金山2007逆向分析挑战赛――“金山杯”
第二阶段比赛 第1题
无壳,直接OD载入,可以看到:
00400310 |. 68 6C024000 PUSH 0040026C ; ASCII "test.txt"
00400315 |. 8D4D F0 LEA ECX, DWORD PTR [EBP-10]
00400318 |. E8 63010000 CALL 00400480 ; CreateFileA
很明显test.txt就是keyfile,文件大小必须在8到1k之间。
接下来读取文件的内容,对其进行变化
0040037E |. E8 FDFEFFFF CALL 00400280 ; 这里就是变化的函数
跟进函数,首先放出一块堆栈给溢出数据做准备
004002A2 |. 68 A802CC78 PUSH 78CC02A8
004002A7 |. 68 1B8F9469 PUSH 69948F1B
004002AC |. FF76 04 PUSH DWORD PTR [ESI+4]
004002AF |. FF36 PUSH DWORD PTR [ESI]
004002B1 |. E8 0A030000 CALL 004005C0 ; 文件的头8个字节做乘法
004002B6 |. 68 82FFE65B PUSH 5BE6FF82
004002BB |. 68 854716A5 PUSH A5164785
004002C0 |. 52 PUSH EDX
004002C1 |. 50 PUSH EAX
004002C2 |. E8 79020000 CALL 00400540 ; 结果进行位移计算变化
再对头8个字节进行简单的xor运算。
004002C7 |. 6A 04 PUSH 4
004002C9 |. 8BCE MOV ECX, ESI
004002CB |. 5F POP EDI
004002CC |> 8031 1C /XOR BYTE PTR [ECX], 1C
004002CF |. 8A11 |MOV DL, BYTE PTR [ECX]
004002D1 |. 3051 01 |XOR BYTE PTR [ECX+1], DL
004002D4 |. 41 |INC ECX
004002D5 |. 41 |INC ECX
004002D6 |. 4F |DEC EDI
004002D7 |.^ 75 F3 \JNZ SHORT 004002CC
运算结果变化一下得到溢出代码的大小。
004002D9 |. 6A 1A PUSH 1A
004002DB |. 59 POP ECX
004002DC |. 2BC8 SUB ECX, EAX
004002DE |. 0FAFC8 IMUL ECX, EAX
004002E1 |. 81E9 9C000000 SUB ECX, 9C
004002E7 |. 85C9 TEST ECX, ECX
最后复制到堆栈检测能否实现功能。
004002EB |. 8D7D D4 LEA EDI, DWORD PTR [EBP-2C]
004002EE |. F3:A5 REP MOVS DWORD PTR ES:[EDI], DWORD PTR [ESI]
按照要求和提示,我们只需要修改消息文字即可,函数的调用完全使用已有的代码,即改成下面的模样:
00400385 |> \57 PUSH EDI ; /Style
00400386 |. 68 68024000 PUSH 00400268 ; |Title = "OK!"
0040038B |. 68 60024000 PUSH 00400260 ; |Text = "OK!"
00400390 |. 57 PUSH EDI ; |hOwner
00400391 |. FF15 4C024000 CALL NEAR DWORD PTR [<&USER32.MessageBoxA>] ; \MessageBoxA
/*
在EBP=12FBC4的前提下构造代码:
JMP 12FB78
DB 00, 00, 00, 00, 00, 00 ; 预留给校验值
MOV DWORD PTR [400268], 214B4F ; "OK!"
MOV DWORD PTR [400260], 214B4F
MOV DWORD PTR [400264], 0
MOV EBP,12FBC4
JMP 400383
DD 12FB70
经过asm以后其大小恰好填充堆栈到溢出点,代码段大小是0D个DD,根据这个结果反推前面一步也是0D,然后计算一个辗转相除的结果等于
7590C53F 8AD397F7
填入文件头,即可得到keyfile了。
经过本机器(xp+sp2)的测试成功
*/
以下是修改过的思路:
由于ebp是和系统相关的,溢出点不能以它为标准,观察堆栈
0012FBA0 00400383 RETURN to ExploitM.00400383 from ExploitM.00400280;溢出点
0012FBA4 00AE0000 ;分配的内存位置
0012FBA8 00000080 ;内存大小
所以可以让溢出点返回4002F5处,让程序再次pop一个dword,这样流程返回到了分配的内存地址处,
而此处的开始代码恰好是合法的,于是构造下面的代码:
00AE0000 /EB 7C JMP SHORT 00AE007E ; code begin
00AE0002 |CF IRETD
00AE0003 |45 INC EBP
00AE0004 |23E6 AND ESP, ESI
00AE0006 |8CF9 MOV CX, SEG? ; Undefined segment register
00AE0008 |C705 68024000 4>MOV DWORD PTR [400268], 214B4F ; modify title string
00AE0012 |C705 60024000 4>MOV DWORD PTR [400260], 214B4F ; modify text string
00AE001C |C705 64024000 0>MOV DWORD PTR [400264], 0
00AE0026 |8BEC MOV EBP, ESP
00AE0028 |83C5 1C ADD EBP, 1C ; correct value of EBP
00AE002B |E8 04000000 CALL 00AE0034 ; push esp to modify it
00AE0030 |F5 CMC
00AE0031 |0240 00 ADD AL, BYTE PTR [EAX] ; this is the exploit address
00AE0034 |832C24 30 SUB DWORD PTR [ESP], 30 ; correct value of ESP
00AE0038 |83EC 04 SUB ESP, 4 ; correct value of EIP
00AE003B |C70424 83034000 MOV DWORD PTR [ESP], 400383 ; correct ret address
00AE0042 |C3 RET ; back to main route
...
00AE007E ^\EB 88 JMP SHORT 00AE0008
这里没有使用到硬编码,都是固定地址和相对计算,在xp+sp2和2003下测试过,2000应该也跑不掉的
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)