天琴空唱 发表于 2009-1-30 00:27:33

手脱Armadillo双进程3.00a - 3.61

【破文标题】【原创】手脱Armadillo双进程
【破文作者】天琴空唱
【作者邮箱】
【作者主页】
【破解工具】OD,PEID,FI
【破解平台】xp
【软件名称】俄罗斯方块外挂终结者 2.1++
【软件大小】
【原版下载】http://www.skycn.com/soft/19491.html
【保护方式】Armadillo
【软件简介】完全自动玩俄罗斯方块游戏,支持QQ火拼俄罗斯、联众。支持自动开始,自动发道具。速度快,可达到几近疯狂的速度。效率高,联众单机上测试可以几万行不死。是一款用来练习提高的好工具。
使用说明:
 使用方法简单明了,您只要选择相应的俄罗斯方块类型(目前支持:QQ火拼俄罗斯、联众俄罗斯单机版和网络版)
 然后按“开始”键就可以了。窗口上的小鱼图标如果变成彩色就说明开始工作,如果是灰色的说明暂停状态。
【破解声明】本文是对网上脱穿山甲壳方法的一些补充。这是我写的第一个破文,简单了些,希望大家不要见笑。
------------------------------------------------------------------------
【破解过程】用PEID查壳发现是Armadillo 3.00a - 3.61 -> Silicon Realms Toolworks。
用FI查显示为Armadillo 3.05
脱壳之前在网上参考了一些文章,按照他们做最后总是出现问题。后来自己摸索了一下终于脱壳成功
运行程序,打开任务管理器发现有2个进程,所以是双进程的壳。用AMD探测软件得到如下信息:
<------- 28-01-2009 14:45:10 ------->
D:\Program Files\方块终结者\TetrisTerminator.exe
!- Protected Armadillo
Protection system (Basic)
!- <Protection Options>
Standard protection or Minimum protection
!- <Backup Key Options>
No Registry Keys at All
!- <Compression Options>
Best/Slowest Compression
!- <Other Options>
Store Environment Vars Externally
Disable Monitoring Thread
!- Child detach
Child process ID: 00000A6C
Entry point: 00476000
Original bytes: 60E8
!- Elapsed Time 00h 00m 00s 438ms
************************************************
用OD载入,忽略所有异常,并且忽略C000001E异常,
一开始按照常规方法BP OpenMutexA, F9看堆栈
0012F588   0045ADA6/CALL 到 OpenMutexA 来自 TetrisTe.0045ADA0
0012F58C   001F0001|Access = 1F0001
0012F590   00000000|Inheritable = FALSE
0012F594   0012FBC8\MutexName = "1064::DA07E2D882" ★ 记住0012FBC8 这个地址
此处0012FBC8和其它破文的地址不一样,切记不可照搬。
然后Ctrl+G:401000键入以下代码
00401000   60                  pushad
00401001   9C                  pushfd
00401002   68 B4FB1200         push 0012FBC8 ★ 堆栈里看到的值
00401007   33C0                xor eax,eax
00401009   50                  push eax
0040100A   50                  push eax
0040100B   E8 B4B2A577         call kernel32.CreateMutexA
00401010   9D                  popfd
00401011   61                  popad
00401012   E9 33F7A577         jmp kernel32.OpenMutexA
在401000处新建起源,F9运行,再次中断在OpenMutexA处。
返回401000,撤销修改。这一步在一些教程里被忽略掉了,但是很重要,不然后面恢复后的代码都是错的。
取消以前断点,下断:HE GetModuleHandleA。 我试过bp GetModuleHandleA+5和he GetModuleHandleA+5, 但是发现只能中断下来一次。所以保险起见不用+5,另外,如果用bp有时也拦截不下来,所以保险起见用he。具体原因不明。
取消先前的 OpenMutexA断点后F9运行。这里我发现我的堆栈并不像教程里的那样有很多个GetModuleHandleA, 而是只有1个。后来发现我理解错了。应该是按F9,会发现程序不断的调用GetModuleHandleA。我们要注意堆栈的变化,当出现
0012D3AC    00C86622返回到 00C86622 来自 kernel32.GetModuleHandleA
0012D3B0    0012D4E8ASCII "advapi32.dll"
时,再一次按F9,取消所有断点,按alt+f9 返回。(一共按了10次)
有人说按shift+f9运行,当经过一个call缓冲有点大时,一般是在堆栈窗口出现ASCII "kernel32.dll"和ASCII "VirtualFree“后,再运行一次,出现"kernel32.dll",就是返回时机,取消断点,按alt+f9执行到返回。但是我没有发现有"VirtualFree。
00B35B62    FF15 A450B500   call    dword ptr                ; kernel32.GetModuleHandleA
00B35B68    3945 08         cmp   dword ptr , eax         ; 返回到这里
00B35B6B    75 07         jnz   short 00B35B74
00B35B6D    B9 E873B500   mov   ecx, 0B573E8
00B35B72    EB 52         jmp   short 00B35BC6
00B35B74    393D E079B500   cmp   dword ptr , edi
00B35B7A    B9 E079B500   mov   ecx, 0B579E0
00B35B7F    0F84 93000000   je      00B35C18                         ; Magic Jump, 将je改成jmp
00B35B85    8B35 60D8B500   mov   esi, dword ptr
00B35B8B    A1 E018B600   mov   eax, dword ptr
00B35B90    F641 08 01      test    byte ptr , 1
00B35B94    74 0E         je      short 00B35BA4
00B35B96    8B50 5C         mov   edx, dword ptr
00B35B99    3350 48         xor   edx, dword ptr
00B35B9C    3350 1C         xor   edx, dword ptr
00B35B9F    F6C2 80         test    dl, 80
00B35BA2    75 13         jnz   short 00B35BB7
00B35BA4    8B50 5C         mov   edx, dword ptr
有人说还需要Ctrl+F在当前位置查找命令: salc,当看到jmp、salc、salc代码连在一起时,呵呵,恭喜,找到地方了,在salc上面的jmp处下断!
00C9C594   FF75 F4             push dword ptr ss:
00C9C597   E8 A7540000         call 00CA1A43
00C9C59C   FF75 BC             push dword ptr ss:
00C9C59F   E8 8E430000         call 00CA0932
00C9C5A4   59                  pop ecx
00C9C5A5   59                  pop ecx
00C9C5A6   EB 03               jmp short 00C9C5AB//此处下断
00C9C5A8   D6                  salc
00C9C5A9   D6                  salc

F9运行,断在00C9C5A6处。当然,由于是动态解码,每次调试看到的地址可能是不同的,但代码是相同的!其实断在00C9C5A6处时,IAT解密已经完成了。现在我们返回Magic Jump 处,改回原先修改的代码,在00C9C24F处点右键->“撤销选择”即可。 为何要这样做?原作者说他发现程序在下面会依据原先的代码进行解码,以前下 硬件断点 操作没有修改原代码,所以解码正确。而直接修改Magic Jump后改变了原先的代码,导致解码不正确而异常出错!现在在解码以前恢复原先的代码,因此就不会再出错了!

经过多次实验发现这种说法并非完全正确,只有当AMD的版本大于3.6时才需要这么做。在这里如果断在jump处后将magic jump 改回je是不行的,因为只有程序还会运行到magic jump处,不像上面所说的断在00C9C5A6处时,IAT解密已经完成了。所以这里不需要改回去,也不需要找salc。
***********************************************************
Alt+M 查看内存,在401000开始的段上下 内存访问断点,F9运行,直接中断在OEP处
0041DE04    6A 60         push    60
0041DE06    68 20344400   push    00443420
0041DE0B    E8 BC120000   call    0041F0CC
0041DE10    BF 94000000   mov   edi, 94
0041DE15    8BC7            mov   eax, edi
0041DE17    E8 44E7FFFF   call    0041C560
0041DE1C    8965 E8         mov   dword ptr , esp
0041DE1F    8BF4            mov   esi, esp
0041DE21    893E            mov   dword ptr , edi
0041DE23    56            push    esi
0041DE24    FF15 E8E24300   call    dword ptr                ; kernel32.GetVersionExA
0041DE2A    8B4E 10         mov   ecx, dword ptr
使用LoedPE dump下完整的镜像,然后运行ImportREC 1.7,选择这个进程。把OEP改为0001DE04,点IT AutoSearch,CUT掉无效函数。FixDump,正常运行!
------------------------------------------------------------------------
【破解总结】壳虽然脱掉了,但是作者的加密方法仍然比较复杂。花了3个小时没有找到相应的破解方法,欢迎有兴趣的朋友共同探讨。
------------------------------------------------------------------------
【版权声明】

[ 本帖最后由 天琴空唱 于 2009-1-30 00:34 编辑 ]
页: [1]
查看完整版本: 手脱Armadillo双进程3.00a - 3.61