首页 电脑 电脑学堂 查看内容

逆向追踪+TC(模拟跟踪)方法寻找暗桩--解除脱UPX后的校验

2005-2-27 07:49 1026 0

摘要: 来源:http://www.asmcc.com【脱文标题】 逆向追踪+TC(模拟跟踪)方法寻找暗桩--解除脱UPX后的校验【脱文作者】 Lenus  【作者邮箱】 Lenus_M@...
关键词: nbsp 脱壳 程序 0040 push CALL 09 77 dword 一个

来源:http://www.asmcc.com【脱文标题】 逆向追踪+TC(模拟跟踪)方法寻找暗桩--解除脱UPX后的校验【脱文作者】 Lenus  【作者邮箱】 [email protected]  【作者主页】 www.popbase.net & bbs.asmcc.com【使用工具】 Ollydbg,Loadpe,PEID,Import_Rec 1.6【破解平台】 WinXp(SP2)【软件名称】 在DFCG上逛的时候找到的一个小外挂,好象是玩升级游戏可以看其他人的牌的工具。       【加壳方式】 UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]【脱壳声明】 我是一个考古人,在软件的土地上,发掘未知的宝藏!----------------------------------------------------------------------  【脱壳内容】 1.寻找OEP+dump+修复IAT。UPX的壳,脱壳过程我就不再重复。用ESP定律可以马上找到,或者直接往下找到0000000前面的JMP。用LORDPE dump下来,用Import_Rec修复。注意到这个壳有OVERLAY,所以脱壳修复后,不求他马上能运行(如果马上就能运行那这篇文章就太垃圾了^^)本来这个壳不想写什么的,但是看到论坛上很多人在问,对于UPX脱壳后的修复问题。所以在这里我打算整理一次一些基本的方法。供大家参考,当然还有很多修复的方法,在这里不可能全讲完。而且随着自己的脱壳经验的增长慢慢的也会懂一些技巧!2.修复暗桩I.逆向跟踪法  运行修复好了IAT的程序,发现什么反应都没有!  从这里我们可以有两个结论:  1.壳的不能正常运行不是关于overlay的。因为,如果是因为没读到附加的数据应该有非法操作和警告的对话窗弹出。  2.壳应该是有校验的地方发现壳被脱掉了就直接退出了程序。  得到上面的结论我们不难得出我们的下一步是什么:找校验的地方。  但是代码茫茫我们该如何去寻找呢?我用我的逆向追踪法!  因为程序的退出一般用的是这个API:ExitProcess  于是我们从最后的函数开始向前追踪程序!  用OD载入脱壳后的代码我的是DUMP_.EXE,来到这里0040F765 d>  55                  push ebp                 //这里是OEP0040F766     8BEC                mov ebp,esp0040F768     6A FF               push -10040F76A     68 903A4100         push dumped_.00413A90  在命令行下断BP ExitProcess ,F9运行,断下7C81CAA2 k>  8BFF                mov edi,edi                               ; ntdll.7C930738       //停在这里7C81CAA4     55                  push ebp7C81CAA5     8BEC                mov ebp,esp7C81CAA7     6A FF               push -17C81CAA9     68 B0F3E877         push 77E8F3B0这里是系统领空,看看堆栈。0012FF04    77C09D45  /CALL 到 ExitProcess 来自 msvcrt.77C09D3F     //还记得我写的ESP定律的预备知识吗?(没看过的去补补课^^)0012FF08    00000000  \ExitCode = 0很明显77C09D45是call ExitProcess的时候,压入堆栈的地址。好了我们到77C09D45处去看看,ctrl+g 输入77C09D45,来到77C09D45处。77C09D3F     FF15 1C12BE77       call dword ptr ds:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess  //这里call ExitProcess77C09D45     CC                  int3                                                             //这里是返回地址                这里还是系统的领空,向上面找找是什么地方call到这里来的?77C09D11     CC                  int377C09D12     CC                  int377C09D13     8BFF                mov edi,edi                       //上面是int 3 估计这个系统函数的入口是这里,F2下断。77C09D15     55                  push ebp77C09D16     8BEC                mov ebp,esp77C09D18     68 A440BE77         push msvcrt.77BE40A4                      ; ASCII "mscoree.dll"77C09D1D     FF15 E810BE77       call dword ptr ds:[<&KERNEL32.GetModuleHa>; kernel32.GetModuleHandleA找到了新的入口,那就从来一遍ctrl+F2 ,F9 , 断下!看堆栈!0012FF10    77C09E78  返回到 msvcrt.77C09E78 来自 msvcrt.77C09D130012FF14    00000000继续找,到77C09E78处!!77C09E73     E8 9BFEFFFF         call msvcrt.77C09D13   //这里是call向77C09D13的地方77C09E78     CC                  int3  再想上找入口77C09E54     E8 0EFFFFFF         call msvcrt._initterm77C09E59     59                  pop ecx77C09E5A     59                  pop ecx77C09E5B     85DB                test ebx,ebx77C09E5D     74 0B               je short msvcrt.77C09E6A                //第3处77C09E5F     6A 08               push 877C09E61     E8 B3060000         call msvcrt._unlock77C09E66     59                  pop ecx77C09E67     5E                  pop esi77C09E68     5D                  pop ebp77C09E69     C3                  retn                                 //第2处77C09E6A     FF75 08             push dword ptr ss:[ebp+8]           // 第1处77C09E6D     8935 541AC377       mov dword ptr ds:[77C31A54],esi77C09E73     E8 9BFEFFFF         call msvcrt.77C09D13看到前面有个RETN 第一个可能的入口是77C09E6A,可能有一个call从什么地方call过来;然而我们知道有些RETN也可能是变形JMP(不过这个不太可能,但我们对他也不可掉以轻心);第3个地方是77C09E5D他JMP过了RETN。所以为了保险我们3个一起下断!!好了重来一次!F9,断在了77C09E5D 处,果然是JMP过了RETN好了继续向上找吧!77C09DD8     CC                  int377C09DD9     CC                  int377C09DDA     CC                  int377C09DDB     8BFF                mov edi,edi        //找到这里,估计有是一个call吧!下断,重来!77C09DDD     55                  push ebp重来后断在这里看堆栈:0012FF20    77C09E90  返回到 msvcrt.77C09E90 来自 msvcrt.77C09DDB  //还没回到程序领空(真累,但是一路能断下来说明我们的方向是正确的!!)0012FF24    00000000继续来到77C09E90向上找77C09E7C     CC                  int377C09E7D     CC                  int377C09E7E m>  8BFF                mov edi,edi    //是这里 下断,重来77C09E80     55                  push ebpF9 后断到这里,看堆栈!0012FF34    0040F8A3  /CALL 到 exit 来自 dumped_.0040F89D   //终于回到程序领空了!庆祝一下吧!0012FF38    00000000  \status = 0好了,到程序领空去吧!0040F884   ^\EB F5               jmp short dumped_.0040F87B0040F886     6A 0A               push 0A0040F888     58                  pop eax0040F889     50                  push eax0040F88A     56                  push esi0040F88B     53                  push ebx0040F88C     53                  push ebx0040F88D     FF15 F4804200       call dword ptr ds:[<&kernel32.#374>]      ; kernel32.GetModuleHandleA0040F893     50                  push eax0040F894     E8 17040000         call dumped_.0040FCB00040F899     8945 98             mov dword ptr ss:[ebp-68],eax0040F89C     50                  push eax0040F89D     FF15 BC864200       call dword ptr ds:[<&msvcrt.#657>]        ; msvcrt.exit    //从这里开始call向ExitProcess逆向追踪现在全部完毕了,呵呵,很累是吗?其实做一个好的crack,想不累是不可能的,关键是这一路下来我们在系统的领空玩得挺高兴的,而且多学会了一种方法,呵呵,值了!!II.TC模拟跟踪法下面我们的工作就是什么地方是校验了(一般的程序在exitprocess的前面不远就会有一个关键比较可以跳过,但是这个程序却没有。)于是我们在这里先停一停。来看看原未脱壳的程序它在这里是怎么运行的。呵呵我们发现原来这个地址离OEP还不是很远!于是,我们用OD载入未脱壳的程序,用ESP定律来到OEP处!(这里请格外注意一下,一定要关掉原来的程序,因为这个程序会检查在内存中是否还有另一个同样的进程,如果有就直接退出,这个也是我后来才知道的,但是这个东西却不是校验,所以,曾经影响了我的判断!)向下找到0040F89D地址,在他的前面的JMP和CALL全部下断(不要太多了^^)我们会发现程序在(用F8)步过0040F894这里的时候,程序就运行了。所以我们又得到了以下的结论: 1.程序的校验一定在0040F894里面的某个地方。因为我们的脱壳后的程序也步过了这一句但是什么都没反映就出来了!2.程序0040F89D是正个程序的终点。上面的call里面一定有个校验比较。如果发现程序被脱壳就直接跳出来结束。(难怪我们运行程序的时候什么反应都没有)知道上面的结论我们就再来一次。F7进入0040F894 的call0040FCB0     FF7424 10           push dword ptr ss:[esp+10]                   //到这里0040FCB4     FF7424 10           push dword ptr ss:[esp+10]                   0040FCB8     FF7424 10           push dword ptr ss:[esp+10]0040FCBC     FF7424 10           push dword ptr ss:[esp+10]0040FCC0     E8 43000000         call                      //这个call没什么东西啊,F7继续跟进!0040FCC5     C2 1000             retn 10                                     //返回就挂了0040FD08   - FF25 28864200       jmp dword ptr ds:[<&mfc42.#1576>]         ; mfc42.#1576  //到这里,啊跳转表,原来这个是一个api啊!0040FD0E     CC                  int3跳到这里:73D3CF2B m>  8BFF                mov edi,edi                               ; ntdll.7C930738   //到这里了73D3CF2D     53                  push ebx73D3CF2E     56                  push esi哎,又是系统领空了!真是累,如果各位还想在里面玩玩我可不想在奉陪了,这里祭出OD强大的模拟跟踪命令TC,在命令行键入 TC EIP<7000000(只要不在系统领空的时候就断下来!)回车后,马上到了这里:0040F062   - FF25 98814200       jmp dword ptr ds:[<&mfc42.#3922>]         ; mfc42.#3922   //又是一个api  -_-!0040F068   - FF25 9C814200       jmp dword ptr ds:[<&mfc42.#1089>]         ; mfc42.#1089到这里73DC9FED m>  8B15 9404E173       mov edx,dword ptr ds:[73E10494]   //又来到系统领空。73DC9FF3     85D2                test edx,edx73DC9FF5     74 14               je short mfc42.73DCA00B再来TC EIP<7000000,回车后到这里00402300     64:A1 00000000      mov eax,dword ptr fs:[0]             //哈哈,终于找到了。小样,别以为用了api我就认不出你了。00402306     6A FF               push -100402308     68 38FF4000         push dumped_.0040FF380040230D     50                  push eax0040230E     64:8925 00000000    mov dword ptr fs:[0],esp00402315     81EC 30020000       sub esp,2300040231B     53                  push ebx0040231C     56                  push esi0040231D     57                  push edi0040231E     68 FC714100         push dumped_.004171FC                     ; ASCII "OLDWORM_GLUPGRADE_HELPER_APP"00402323     6A 00               push 000402325     8BF1                mov esi,ecx00402327     68 01001F00         push 1F00010040232C     FF15 CC804200       call dword ptr ds:[<&kernel32.#627>]      ; kernel32.OpenMutexA00402332     85C0                test eax,eax00402334     8986 C4000000       mov dword ptr ds:[esi+C4],eax0040233A     75 56               jnz short dumped_.004023920040233C     68 FC714100         push dumped_.004171FC                     ; ASCII "OLDWORM_GLUPGRADE_HELPER_APP"00402341     6A 01               push 100402343     50                  push eax00402344     FF15 D0804200       call dword ptr ds:[<&kernel32.#93>]       ; kernel32.CreateMutexA上面的0040233A有一个跳转,但是这个不是的哦,看到前面的OpenMutexA了吗?这个估计是判断内存里面还有同样的进程,然后决定新建一个新的进程CreateMutexA(如果哪位兄弟觉得这个功能很多余也可以暴掉,不过我还算是比较尊重原创的^-^)向下面找0040236F     E8 ACD60000         call dumped_.0040FA2000402374     83C4 04             add esp,400402377     85C0                test eax,eax00402379     74 17               je short dumped_.00402392                 //可疑目标10040237B     E8 80A40000         call dumped_.0040C80000402380     85C0                test eax,eax00402382     74 28               je short dumped_.004023AC                //可以目标200402384     6A FF               push -1上面的两个都是可能关键跳转,为了确定我们在这里分别下断,考察未脱壳程序在这里是否跳转。考察结果:未脱壳程序:目标1没跳,目标2跳了。脱壳后的程序:目标1跳了,直接跳过了目标2。所以只要把00402379 nop掉就可以了。再次友情提醒,如果那位兄弟没有修改上面的判断进程的跳转的话,那么在考察两个程序关键跳的时候,一定要一个一个的看,不能开两个OD!!OK,暴掉后程序正常运行。----------------------------------------------------------------------  【脱壳总结】            1.如果说逆向跟踪是大概确定校验地址的办法,那么正向跟踪(TC法)就是进一步确定精确校验的地址的办法。           2.找校验的时候,多次用到CTRL+F2&F9的办法,这是一个cracker的必修课,你如果觉得我上面写的CTRL+F2&F9已经很多了,那么我可以告诉你,我在调试的时候,比这里用到的CTRL+F2&F9多了10倍!           3.耐性很重要,一定要坚持----------------------------------------------------------------------【后话】             关于寻找校验的办法还有很多,有些我也不是很懂。但是,我们可以慢慢的积累经验,以后就会好了。谢谢你能看完。          如果有什么不足欢迎指出,如果要转载请保持文章的完整!
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部