-
-
[原创]第二阶段第一题分析(看雪金山2007逆向分析挑战赛)
-
发表于: 2007-8-30 12:16 6854
-
【原创】第二阶段第一题分析(看雪金山2007逆向分析挑战赛)
1.) OD 载入, 点 Exploit 按钮, 到下面的处理代码
004002F6 /$ 55 push ebp
004002F7 |. 8BEC mov ebp, esp
004002F9 |. 83EC 10 sub esp, 10
004002FC |. 56 push esi
004002FD |. 57 push edi
004002FE |. 33FF xor edi, edi
00400300 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00400303 |. 33F6 xor esi, esi
00400305 |. 897D FC mov dword ptr [ebp-4], edi
00400308 |. 897D F8 mov dword ptr [ebp-8], edi
0040030B |. E8 60010000 call 00400470
00400310 |. 68 6C024000 push 0040026C ; ASCII "test.txt"
00400315 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00400318 |. E8 63010000 call 00400480 ; 打开文件, 取得文件长度
0040031D |. 85C0 test eax, eax
0040031F |. 74 64 je short 00400385 ; 不存在, 跳去显示 Fail!
00400321 |. 8D45 FC lea eax, dword ptr [ebp-4]
00400324 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00400327 |. 50 push eax
00400328 |. E8 D3010000 call 00400500 ; 取文件长度
0040032D |. 85C0 test eax, eax
0040032F |. 74 54 je short 00400385
00400331 |. 8B4D FC mov ecx, dword ptr [ebp-4]
00400334 |. 83F9 08 cmp ecx, 8 ; 长度要大于8
00400337 |. 7E 4C jle short 00400385
00400339 |. B8 00100000 mov eax, 1000 ; 长度要小于0x1000
0040033E |. 3BC8 cmp ecx, eax
00400340 |. 7F 43 jg short 00400385
00400342 |. 6A 40 push 40 ; /Protect = PAGE_EXECUTE_READWRITE
00400344 |. 41 inc ecx ; |
00400345 |. 50 push eax ; |AllocationType => MEM_COMMIT
00400346 |. 51 push ecx ; |Size
00400347 |. 57 push edi ; |Address
00400348 |. FF15 24024000 call dword ptr [<&KERNEL32.VirtualAll>; \VirtualAlloc
0040034E |. 8BF0 mov esi, eax ; 设地址为XXXXXXXX
00400350 |. 3BF7 cmp esi, edi
00400352 |. 74 31 je short 00400385
00400354 |. 8D45 F8 lea eax, dword ptr [ebp-8]
00400357 |. 53 push ebx
00400358 |. 50 push eax
00400359 |. 56 push esi
0040035A |. FF75 FC push dword ptr [ebp-4]
0040035D |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00400360 |. E8 AB010000 call 00400510 ; ReadFile(...) to XXXXXXXX
00400365 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00400368 |. 8BD8 mov ebx, eax
0040036A |. E8 61010000 call 004004D0 ; CloseHandle(...)
0040036F |. 3BDF cmp ebx, edi
00400371 |. 5B pop ebx
00400372 |. 74 11 je short 00400385
00400374 |. 8B45 FC mov eax, dword ptr [ebp-4]
00400377 |. 3945 F8 cmp dword ptr [ebp-8], eax
0040037A |. 75 09 jnz short 00400385
0040037C |. 50 push eax ; 地址XXXXXXXX入栈
0040037D |. 56 push esi ; 长度入栈
0040037E |. E8 FDFEFFFF call 00400280 ; 文件数据处理, F7!!!!
00400383 |. 59 pop ecx ; 没有溢出返回这里
00400384 |. 59 pop ecx
00400385 |> 57 push edi ; /Style
00400386 |. 68 68024000 push 00400268 ; |Title = "Try"
0040038B |. 68 60024000 push 00400260 ; |Text = "Failed!"
00400390 |. 57 push edi ; |hOwner
00400391 |. FF15 4C024000 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00400397 |. 8D4D F0 lea ecx, dword ptr [ebp-10] ; 显示MessageBoxA后从这里继续执行
0040039A |. E8 31010000 call 004004D0
0040039F |. 3BF7 cmp esi, edi
004003A1 |. 74 0D je short 004003B0
004003A3 |. 68 00800000 push 8000 ; /FreeType = MEM_RELEASE
004003A8 |. 57 push edi ; |Size
004003A9 |. 56 push esi ; |Address
004003AA |. FF15 20024000 call dword ptr [<&KERNEL32.VirtualFre>; \VirtualFree
004003B0 |> 8D4D F0 lea ecx, dword ptr [ebp-10]
004003B3 |. E8 38010000 call 004004F0
004003B8 |. 6A 01 push 1
004003BA |. 58 pop eax
004003BB |. 5F pop edi
004003BC |. 5E pop esi
004003BD |. C9 leave
004003BE \. C3 retn
2.) 文件数据处理:
00400280 /$ 55 push ebp
00400281 |. 8BEC mov ebp, esp
00400283 |. 83EC 2C sub esp, 2C ; 局部变量大小 只有 0x2C
00400286 |. 8065 D4 00 and byte ptr [ebp-2C], 0
0040028A |. 56 push esi
0040028B |. 57 push edi
0040028C |. 6A 0A push 0A
0040028E |. 59 pop ecx
0040028F |. 33C0 xor eax, eax
00400291 |. 8D7D D5 lea edi, dword ptr [ebp-2B]
00400294 |. 837D 0C 00 cmp dword ptr [ebp+C], 0
00400298 |. F3:AB rep stos dword ptr es:[edi]
0040029A |. 66:AB stos word ptr es:[edi]
0040029C |. AA stos byte ptr es:[edi]
0040029D |. 7C 51 jl short 004002F0
0040029F |. 8B75 08 mov esi, dword ptr [ebp+8]
004002A2 |. 68 A802CC78 push 78CC02A8
004002A7 |. 68 1B8F9469 push 69948F1B
004002AC |. FF76 04 push dword ptr [esi+4] ; 文件的4,5,6,7 BYTE
004002AF |. FF36 push dword ptr [esi] ; 文件的0,1,2,3 BYTE
004002B1 |. E8 0A030000 call 004005C0 ; U64 整数 的 乘法
// 即 HHHHHHHHLLLLLLLL = b7b6b5b4b3b2b1b0 * 0x78CC02A869948F1B
004002B6 |. 68 82FFE65B push 5BE6FF82
004002BB |. 68 854716A5 push A5164785
004002C0 |. 52 push edx
004002C1 |. 50 push eax
004002C2 |. E8 79020000 call 00400540 ; U64 整数 的 取模
// 即 MMMMMMMMmmmmmmmm = HHHHHHHHLLLLLLLL % 0x5BE6FF82A5164785
004002C7 |. 6A 04 push 4
004002C9 |. 8BCE mov ecx, esi
004002CB |. 5F pop edi
004002CC |> 8031 1C /xor byte ptr [ecx], 1C ; 前 8 Byte 变换
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
// 相当于如下C代码
for (i=0;i<8;i+=2)
{
buffer[i] ^= 0x1C;
buffer[i+1] ^= buffer[i];
}
004002D9 |. 6A 1A push 1A
004002DB |. 59 pop ecx ; ECX = 1A
004002DC |. 2BC8 sub ecx, eax ; EAX 为整数取模后的低 32bit
004002DE |. 0FAFC8 imul ecx, eax
004002E1 |. 81E9 9C000000 sub ecx, 9C
// 即 ECX = (0x0000001A - mmmmmmmm) * mmmmmmmm - 0x0000009C
004002E7 |. 85C9 test ecx, ecx ; 得到一值ECX
004002E9 |. 7E 05 jle short 004002F0
004002EB |. 8D7D D4 lea edi, dword ptr [ebp-2C]
004002EE |. F3:A5 rep movs dword ptr es:[edi], dword ptr [esi] ; 溢出点, ECX>=0D 时, 返回地址会被覆盖
004002F0 |> 5F pop edi
004002F1 |. 33C0 xor eax, eax
004002F3 |. 5E pop esi
004002F4 |. C9 leave
004002F5 \. C3 retn ; 正常返回0x00400383, 溢出返回其它地址
3.) 在004002EE时的堆栈如下:
0012FC50 00000000 // saved_old_edi
0012FC54 008E0000 // saved_old_esi
0012FC58 00000000 // 局部变量, 从XXXXXXXX COPY ECX 个 DWORD 到这
0012FC5C 00000000 // 局部变量
0012FC60 00000000 // 局部变量
0012FC64 00000000 // 局部变量
0012FC68 00000000 // 局部变量
0012FC6C 00000000 // 局部变量
0012FC70 00000000 // 局部变量
0012FC74 00000000 // 局部变量
0012FC78 00000000 // 局部变量
0012FC7C 00000000 // 局部变量
0012FC80 00000000 // 局部变量
0012FC84 /0012FCAC // saved_old_ebp
0012FC88 |00400383 // 返回地址
0012FC8C |008E0000 // parameter1, 即动态分配的地址XXXXXXXX
0012FC90 |00000033 // parameter2, 文件长度
0012FC94 |00000111 // 调用程序的栈
4.) 要溢出成功, 可把返回地址覆盖成004002F5, 这样, 就会返回004002F5, 再执行004002F5的retn 就回到动态分配的地址XXXXXXXX执行
先解如下方程:
ECX = (0x0000001A - mmmmmmmm) * mmmmmmmm - 0x0000009C
0x0000000D <= ECX <= 0x0000000F
用如下C程序计算:
unsigned int i, c;
for(i=0;i!=0xffffffff;i++) {
c = (0x1A - i) * i - 0x9C;
if (c>=0x0D && C<= 0x0F) {
printf("mmmmmmmm=%08X ECX=%08X\n", i, c);
}
}
结果ECX=0000000D, mmmmmmmm=????000D
即mmmmmmmm 高16bit可任意, 低16bit为000D, 结果总是0000000D
5.) 再解如下方程:
HHHHHHHHLLLLLLLL = b7b6b5b4b3b2b1b0 * 0x78CC02A869948F1B // (a)
HHHHHHHHLLLLLLLL % 0x5BE6FF82A5164785 = MMMMMMMM????000D // (b)
当 HHHHHHHHHLLLLLLLL
为 从 0x0000000000000000 到 0x5BE6FF82A5164784 时, 模 = HHHHHHHHLLLLLLLL, 即 LLLLLLLL = ????000D
为 从 0x5BE6FF82A5164785 到 0xB7CDFF054A2C8F09 时, 模 = HHHHHHHHLLLLLLLL - 0x5BE6FF82A5164785, 即 LLLLLLLL = ????4792
为 从 0xB7CDFF054A2C8F0A 到 0xFFFFFFFFFFFFFFFF 时, 模 = HHHHHHHHLLLLLLLL - 0xB7CDFF054A2C8F0A, 即 LLLLLLLL = ????8F17
结果: LLLLLLLL的低16bit 只能是 0x000D, 0x4792, 或 0x8F17
用如下C程序计算解方程(a):
unsigned int i, l;
for(i=0;i!=0xffffffff;i++) {
l = (i * 0x69948F1B) & 0xFFFF;
if (l==0x0D || l==0x4792 || l== 0x8F17) {
printf("b3b2b1b0=%08X,LLLLLLLL=%08X\n", i, l);
}
}
结果:
b3b2b1b0=????97F7,LLLLLLLL=????000D
b3b2b1b0=????65D6,LLLLLLLL=????4792
b3b2b1b0=????33B5,LLLLLLLL=????8F17
即b0, b1 只能是如下三组中的数据之一: {F7, 97}, {D6, 65}, {B5, 33},
5.) 将三组数据进行如下变换:
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
再用OD看反汇编结果, 如下:
// F7, 97 ==> EB, 7C // JMP short $+80
// D6, 65 ==> CA, AF // retf xxxxxxxx
// B5, 33 ==> A9, 9A // test eax, xxxxxxxx
EB, 7C 将使file长度至少为128 byte, 现在只讨论决定A9, 9A, 使文件最小
6.) 设变换后的代码为
008E0000 A9 9Axxyyzz test eax, zzyyxx9A
008E0005 90 nop
008E0006 EB 04 jmp short $+06
先将zz定为90, 这样由变换规则可确定d0-d7如下:
{B5, 33, ??, ??, 8C, 00, F7, EF}
只有16bit未知, 编一小程序, 循环65536次, 使 等式(a), (b) 成立, 有一组解就行
7.) 然后就是写代码, 显示 OK!, 返回, 还能正确执行, 代码如下:
008E0000 A9 9A4C4C90 test eax, 904C4C9A
008E0005 90 nop
008E0006 EB 04 jmp short 008E000C
008E0008 4F 4B 21 00 ; "OK!"
008E000C E8 00000000 call 008E0011
008E0011 5D pop ebp
008E0012 8BC5 mov eax, ebp
008E0014 83E8 09 sub eax, 9
008E0017 6A 00 push 0
008E0019 50 push eax
008E001A 50 push eax
008E001B 6A 00 push 0
008E001D FF15 4C024000 call dword ptr [<&USER32.MessageBoxA>] ; USER32.MessageBoxA
008E0023 8BEC mov ebp, esp
008E0025 C745 00 9703400>mov dword ptr [ebp], 400397
008E002C 83C5 1C add ebp, 1C
008E002F C3 retn
008E0030 F5 02 40 00 ; DWORD 004002F5
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课