飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3120|回复: 0

[原创] 手脱Armadillo双进程3.00a - 3.61

[复制链接]

该用户从未签到

发表于 2009-1-30 00:27:33 | 显示全部楼层 |阅读模式
【破文标题】【原创】手脱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    0012D4E8  ASCII "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 [B550A4]               ; kernel32.GetModuleHandleA
00B35B68    3945 08         cmp     dword ptr [ebp+8], 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 [B579E0], edi
00B35B7A    B9 E079B500     mov     ecx, 0B579E0
00B35B7F    0F84 93000000   je      00B35C18                         ; Magic Jump, 将je改成jmp
00B35B85    8B35 60D8B500   mov     esi, dword ptr [B5D860]
00B35B8B    A1 E018B600     mov     eax, dword ptr [B618E0]
00B35B90    F641 08 01      test    byte ptr [ecx+8], 1
00B35B94    74 0E           je      short 00B35BA4
00B35B96    8B50 5C         mov     edx, dword ptr [eax+5C]
00B35B99    3350 48         xor     edx, dword ptr [eax+48]
00B35B9C    3350 1C         xor     edx, dword ptr [eax+1C]
00B35B9F    F6C2 80         test    dl, 80
00B35BA2    75 13           jnz     short 00B35BB7
00B35BA4    8B50 5C         mov     edx, dword ptr [eax+5C]
有人说还需要Ctrl+F在当前位置查找命令: salc,当看到jmp、salc、salc代码连在一起时,呵呵,恭喜,找到地方了,在salc上面的jmp处下断!
00C9C594     FF75 F4             push dword ptr ss:[ebp-C]
00C9C597     E8 A7540000         call 00CA1A43
00C9C59C     FF75 BC             push dword ptr ss:[ebp-44]
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 [ebp-18], esp
0041DE1F    8BF4            mov     esi, esp
0041DE21    893E            mov     dword ptr [esi], edi
0041DE23    56              push    esi
0041DE24    FF15 E8E24300   call    dword ptr [43E2E8]               ; kernel32.GetVersionExA
0041DE2A    8B4E 10         mov     ecx, dword ptr [esi+10]
使用LoedPE dump下完整的镜像,然后运行ImportREC 1.7,选择这个进程。把OEP改为0001DE04,点IT AutoSearch,CUT掉无效函数。FixDump,正常运行!
------------------------------------------------------------------------
【破解总结】壳虽然脱掉了,但是作者的加密方法仍然比较复杂。花了3个小时没有找到相应的破解方法,欢迎有兴趣的朋友共同探讨。
------------------------------------------------------------------------
【版权声明】

[ 本帖最后由 天琴空唱 于 2009-1-30 00:34 编辑 ]

评分

参与人数 2威望 +40 飘云币 +60 收起 理由
hyperchem + 40 + 40 原创内容,鼓励一下!
千里之外 + 20 多多思考 鼓励下

查看全部评分

PYG19周年生日快乐!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表