Armadillo3.60 CopyMem-ll +Debug-Blocker脱壳―――补充改进归纳总结
magicjump是有规律的,
在3.6中,形式是这样的:
00F31349 FF15 C480F300 CALL NEAR DWORD PTR DS:[F380C4] ; kernel32.GetModuleHandleA
00F3134F 3985 BCE8FFFF CMP DWORD PTR SS:[EBP-1744],EAX
00F31355 75 0F JNZ SHORT 00F31366
00F31357 C785 B8E8FFFF 3>MOV DWORD PTR SS:[EBP-1748],0F3C530
00F31361 E9 C4000000 JMP 00F3142A
00F31366 83A5 94E6FFFF 0>AND DWORD PTR SS:[EBP-196C],0
00F3136D C785 90E6FFFF 4>MOV DWORD PTR SS:[EBP-1970],0F3CB48
00F31377 EB 1C JMP SHORT 00F31395
00F31379 8B85 90E6FFFF MOV EAX,DWORD PTR SS:[EBP-1970]
00F3137F 83C0 0C ADD EAX,0C
00F31382 8985 90E6FFFF MOV DWORD PTR SS:[EBP-1970],EAX
00F31388 8B85 94E6FFFF MOV EAX,DWORD PTR SS:[EBP-196C]
00F3138E 40 INC EAX
00F3138F 8985 94E6FFFF MOV DWORD PTR SS:[EBP-196C],EAX
00F31395 8B85 90E6FFFF MOV EAX,DWORD PTR SS:[EBP-1970]
00F3139B 8338 00 CMP DWORD PTR DS:[EAX],0―――――
00F3139E 0F84 86000000 JE 00F3142A ――――――――――重点
看到了吧,而且在3.6中这个跳转地址总是XXXX139E――――开场白
大家好,今天小妹将对Armadillo3.60 CopyMem-ll +Debug-Blocker脱壳的脱壳方法进行补充改进归纳总结,如果你看过我上一篇的话,你会觉得看不懂,或者很复杂,呵呵,相信看完这篇之后,你会有收获的,你会觉得脱掉AM的壳是件非常简单的事。
感谢jwh51提供的在标准双进程中的方法,我知道这一方法引自于mysqladm的一篇文章,所以我现在研究了这篇他的文章,感谢他优秀的文章,还要感谢Ricardo Narvaja的经典文章,他的文章可以说是开山作品,现在所以的方法都是从他的方法中改进出来的,呵呵。现在我将上面的内容结合自己的方法研究,摸索出一些方法和经验,希望对你有帮助。
找出OEP,我不多说了,感觉这里面没有捷径,都一样,可以参考我前面的文章作者其它的都可以,一样的。
DUMP出程序,目前两种方法,一种是Ricardo Narvaja的,不过他的有些方法不适合新版本3.6,我已做了修正改进,完全可行的,(详见文章)。一种是mysqladm的,感觉原理也一样,不过实现的途径不同,但两种方法复杂度都差不多,至于选哪一种,随你喜欢吧。
下面要谈的是重点:IAT的修复。
先找出IAT的起始地址和大小,这个不是难点,方法很多,如果你不会可以看我的文章。下面的是要找出magicjump,并修改再修复。以前用的是Ricardo Narvaja的方法,原理如下:
找出一个错误的指针,然后借助PUPE查看进程中的值,找到时机,再杀掉父进程,然后绑定子进程,再调试直至完成。Mysqladm的则是分离出子进程,然后直接调试子进程,注意这时是头开始的,并且通过中断禁止再产生子进程,这种方法可以说是上面的方法的改进,这种方法速度快,可行性也非常好,推荐使用这种方法,(感谢jwh51)我用这种方法对ultraedit重新做了一下,非常好的。很快,错误率也低。
下面我就把这一过程做一次给大家,希望你能够学会。限于时间,我不再介绍理论知识,要看这些内容原由请看文章。
现在我们假设已DUMP出程序,并且找到了OEP,IAT的起始和大小。(详见文章)。
我们用OD载入加壳程序,忽略所有异常,bp DebugActiveProcess,F9断下。看堆栈窗口:
0012DA9C 005D0BDB /CALL 到 DebugActiveProcess 来自 Uedit32.005D0BD5
0012DAA0 00000584 \ProcessId = 7F4 ―――>子进程句柄
打开另一个OD绑定7F4这个子进程。
然后ALT+F9,还原代码,不然是死循环,还原开头两行二进制:
60
E8 00000000
OK,BP OpenMutexA,F9后中断,不要清除断点,留意一下堆栈:
0012F574 005C25F1 /CALL 到 OpenMutexA 来自 Uedit32.005C25EB
0012F578 001F0001 |Access = 1F0001
0012F57C 00000000 |Inheritable = FALSE
0012F580 0012FBB4 \MutexName = "7F4::DAB78A59F5" 注意这里,
0012F584 0012FF04
0012F588 00000000
0012F58C 005E0999 Uedit32.005E0999
0012F590 003D003C
现在我们直接跳到00401000在这里新建EIP,(为什么是这里,自己看吧,呵呵)然后修改如下:
00401000 60 PUSHAD
00401001 9C PUSHFD
00401002 68 B4FB1200 PUSH 12FBB4 ――――>这里和上面那个地方一致
00401007 33C0 XOR EAX,EAX
00401009 50 PUSH EAX
0040100A 50 PUSH EAX
0040100B E8 E694A677 CALL KERNEL32.CreateMutexA
00401010 9D POPFD
00401011 61 POPAD
00401012 - E9 8F9FA777 JMP KERNEL32.OpenMutexA
继续F9,又会中断。清除断点。其实上面的步骤可以禁止再产生子进程。
bp VirtualProtect 几次中断,注意的这里的几次是多少次是有规律的,最好事先要忽略所有异常,然后会来到弹出一个异常框,(具体参考我的前一篇文章),好的再次越过,留意一下堆栈:
0012BEF0 00F3077C /CALL 到 VirtualProtect 来自 00F30776
0012BEF4 00401000 |Address = Uedit32.00401000
0012BEF8 0014C000 |Size = 14C000 (1359872.)
0012BEFC 00000004 |NewProtect = PAGE_READWRITE
0012BF00 0012D71C \pOldProtect = 0012D71C
一般情况下来到这里是6次。3.4也这样。
现在有两种方法 一种看上面的 00F30776 呵呵,根据我发现的规律你直接跳到00F3139E吧,如果00F3139E还没解压出来,请再按两次F9,再G过去就可以。
第二种下断bp GetModuleHandleA 直接过来了。
好的,来到
00F3139B 8338 00 CMP DWORD PTR DS:[EAX],0
00F3139E 0F84 86000000 JE 00F3142A
00F313A4 8B85 90E6FFFF MOV EAX,DWORD PTR SS:[EBP-1970]
00F313AA 8B40 08 MOV EAX,DWORD PTR DS:[EAX+8]
00F313AD 83E0 01 AND EAX,1
00F313B0 85C0 TEST EAX,EAX
00F313B2 74 25 JE SHORT 00F313D9
00F313B4 A1 9455F400 MOV EAX,DWORD PTR DS:[F45594]
00F313B9 8B0D 9455F400 MOV ECX,DWORD PTR DS:[F45594] ; Uedit32.005FB260
00F313BF 8B40 58 MOV EAX,DWORD PTR DS:[EAX+58]
在00F3139E处下断,每次中断改Z=1,由于走不到OEP,所以最后一次F9,会提示无法处理异常了,这时拿出IMPORT就可以,你不放心的话可以先前在内存窗口中G到0054D000也就是IAT处,最后中断时,你会发现这里正确还原了。好了,现在我们就成功了。
