| 
注册时间2006-10-1
阅读权限20
最后登录1970-1-1UID23416 以武会友  
 
 该用户从未签到 | 
 
| 加壳方式  Armadillo v4.40 使用工具  OllyDBG 汉化第二版,LordPE,ImportREC v1.6F,PEiD v0.94,PE Tools
 脱壳目标  看雪wangfanyc发的帖子,要求脱壳  Armadillo 2.51 - 3.xx DLL Stub -> Silicon Realms Toolworks
 脱壳平台  WINXP SP2
 脱壳作者  邪秀才
 
 
 经过看雪上的各位老大指点,终于能独自完成Armadillo DLL的壳了,正好有需求拿来试试手~!~!
 
 
 1 侦壳:用PEiD查壳 Armadillo 2.51 - 3.xx DLL Stub -> Silicon Realms Toolworks
 
 这里如何判断Arm的版本呢?记得FLY大狭说过Armadillo V4.0新增的反跟踪手段:
 
 OllyDbg在处理调式包含格式串的消息时存在问题,被跟踪的应用程序可以使OllyDbg崩溃,或可能以进程权限执行任意指令。OutputDebugString函数可发送字符串到调试器上,然后OllyDbg会在底端显示相关状态消息,但是如果包含格式串消息,就可能使OllyDbg崩溃。Armadillo以前的版本没有此种Anti,自V4.0始才有。
 
 有他这句话我们就可以做如下判断了:
 
 OD 载入
 
 下断点 HE OutputDebugStringA
 
 Shift+F9 运行,中断下来。看堆栈:
 
 0006EAB0   00B2580F  /CALL 到 OutputDebugStringA 来自 00B25809
 0006EAB4   0006F428  \String = "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
 
 出现这个说明这个DLL是经过Armadillo 4.X压缩过
 
 2 判断进程:DLL文件加壳应该是不可以双进程,所以这里是单进程方式。
 
 
 二 、脱壳
 
 1 寻找 Magic Jump
 
 先用LordPE看看加壳后的DLL信息:基址=00400000,入口点=0003FE97
 
 设置Ollydbg忽略所有的异常选项。老规矩:用IsDebug 1.4插件去掉Ollydbg的调试器标志
 
 清除断点后OD 重新载入
 
 停在这里
 
 
 00927E97 >/$  55            PUSH EBP
 00927E98  |.  8BEC          MOV EBP,ESP
 00927E9A  |.  53            PUSH EBX
 00927E9B  |.  8B5D 08       MOV EBX,DWORD PTR SS:[EBP+8]
 00927E9E  |.  56            PUSH ESI
 00927E9F  |.  8B75 0C       MOV ESI,DWORD PTR SS:[EBP+C]
 00927EA2  |.  57            PUSH EDI
 00927EA3  |.  8B7D 10       MOV EDI,DWORD PTR SS:[EBP+10]
 00927EA6  |.  85F6          TEST ESI,ESI
 
 
 
 下断点 BP GetModuleHandleA,Shift+F9 运行中断后,注意看堆栈:
 
 00069368   00B26DF3  /CALL 到 GetModuleHandleA 来自 00B26DED
 0006936C   00B3BC1C  \pModule = "kernel32.dll"
 00069370   00B3CEC4  ASCII "VirtualAlloc"
 00069374   00B3FA98
 00069378   7C9210ED  ntdll.RtlLeaveCriticalSection
 
 Shift+F9  继续,主要看堆栈,FLY大侠的教程很多,这里主要是找返回的时机
 
 
 00069368   00B26E10  /CALL 到 GetModuleHandleA 来自 00B26E0A
 0006936C   00B3BC1C  \pModule = "kernel32.dll"
 00069370   00B3CEB8  ASCII "VirtualFree"
 00069374   00B3FA98
 00069378   7C9210ED  ntdll.RtlLeaveCriticalSection
 
 
 Shift+F9  继续,呵呵,这里出现了,调试程序无法处理例外,我们被发现了 ,呵呵,再用到FLY大侠的方法,下断点 BP GetModuleHandleA+5
 
 
 
 清除断点后OD 重新载入
 
 
 00927E97 >/$  55            PUSH EBP
 00927E98  |.  8BEC          MOV EBP,ESP
 00927E9A  |.  53            PUSH EBX
 00927E9B  |.  8B5D 08       MOV EBX,DWORD PTR SS:[EBP+8]
 00927E9E  |.  56            PUSH ESI
 00927E9F  |.  8B75 0C       MOV ESI,DWORD PTR SS:[EBP+C]
 00927EA2  |.  57            PUSH EDI
 00927EA3  |.  8B7D 10       MOV EDI,DWORD PTR SS:[EBP+10]
 00927EA6  |.  85F6          TEST ESI,ESI
 00927EA8  |.  75 09         JNZ SHORT SystemMo.00927EB3
 00927EAA  |.  833D 28379400>CMP DWORD PTR DS:[943728],0
 00927EB1  |.  EB 26         JMP SHORT SystemMo.00927ED9
 
 
 下断点 BP GetModuleHandleA+5,Shift+F9 运行中断后,注意看堆栈:
 
 这里用 BP API+5 是为了多过壳检查是否下过 API 断点,相关资料看雪论坛上面可以找到。
 
 
 
 00069364  /0006EAAC
 00069368  |00B26DF3  返回到 00B26DF3 来自 kernel32.GetModuleHandleA
 0006936C  |00B3BC1C  ASCII "kernel32.dll"
 00069370  |00B3CEC4  ASCII "VirtualAlloc"
 00069374  |00B3FA98
 00069378  |7C9210ED  ntdll.RtlLeaveCriticalSection
 
 Shift+F9
 
 00069364  /0006EAAC
 00069368  |00B26E10  返回到 00B26E10 来自 kernel32.GetModuleHandleA
 0006936C  |00B3BC1C  ASCII "kernel32.dll"
 00069370  |00B3CEB8  ASCII "VirtualFree"
 00069374  |00B3FA98
 00069378  |7C9210ED  ntdll.RtlLeaveCriticalSection
 
 
 Shift+F9
 
 
 000690C8  /00069368
 000690CC  |00B15CE1  返回到 00B15CE1 来自 kernel32.GetModuleHandleA
 000690D0  |0006921C  ASCII "kernel32.dll"                               返回时机已到,
 
 
 ALT+F9   返回到这里
 
 
 00B15CE1    8B0D AC40B400   MOV ECX,DWORD PTR DS:[B440AC]
 00B15CE7    89040E          MOV DWORD PTR DS:[ESI+ECX],EAX
 00B15CEA    A1 AC40B400     MOV EAX,DWORD PTR DS:[B440AC]
 00B15CEF    391C06          CMP DWORD PTR DS:[ESI+EAX],EBX
 00B15CF2    75 16           JNZ SHORT 00B15D0A
 00B15CF4    8D85 B4FEFFFF   LEA EAX,DWORD PTR SS:[EBP-14C]
 00B15CFA    50              PUSH EAX
 00B15CFB    FF15 BC62B300   CALL DWORD PTR DS:[B362BC]               ; kernel32.LoadLibraryA
 00B15D01    8B0D AC40B400   MOV ECX,DWORD PTR DS:[B440AC]
 00B15D07    89040E          MOV DWORD PTR DS:[ESI+ECX],EAX
 00B15D0A    A1 AC40B400     MOV EAX,DWORD PTR DS:[B440AC]
 00B15D0F    391C06          CMP DWORD PTR DS:[ESI+EAX],EBX
 00B15D12    0F84 2F010000   JE 00B15E47                                Magic Jump 改 JE 为 JMP 避开 IAT 加密
 00B15D18    33C9            XOR ECX,ECX
 00B15D1A    8B07            MOV EAX,DWORD PTR DS:[EDI]
 00B15D1C    3918            CMP DWORD PTR DS:[EAX],EBX
 00B15D1E    74 06           JE SHORT 00B15D26
 00B15D20    41              INC ECX
 00B15D21    83C0 0C         ADD EAX,0C
 00B15D24  ^ EB F6           JMP SHORT 00B15D1C
 00B15D26    8BD9            MOV EBX,ECX
 00B15D28    C1E3 02         SHL EBX,2
 00B15D2B    53              PUSH EBX
 00B15D2C    E8 63F20100     CALL 00B34F94                            ; JMP 到 msvcrt.??2@YAPAXI@Z
 00B15D31    8B0D A440B400   MOV ECX,DWORD PTR DS:[B440A4]
 
 
 
 把 00B75D12 这句的 JE 00B75E47 改成 JMP 00B75E47
 
 2 获得重定位信息
 
 
 下断点 bp GetTickCount,Shift+F9 运行中断后,注意看堆栈:
 
 00069370   00B2C009  /CALL 到 GetTickCount 来自 00B2C003
 
 Shift+F9
 
 00069370   00B2C3C8  /CALL 到 GetTickCount 来自 00B2C3C2          在这里清除断点后Alt+F9返回程序
 
 
 00B2C3C8    2B85 A4D4FFFF   SUB EAX,DWORD PTR SS:[EBP-2B5C]            返回到这里
 00B2C3CE    8B8D A8D4FFFF   MOV ECX,DWORD PTR SS:[EBP-2B58]
 00B2C3D4    6BC9 32         IMUL ECX,ECX,32
 00B2C3D7    81C1 D0070000   ADD ECX,7D0
 00B2C3DD    3BC1            CMP EAX,ECX
 00B2C3DF    76 07           JBE SHORT 00B2C3E8
 00B2C3E1    C685 34D9FFFF 0>MOV BYTE PTR SS:[EBP-26CC],1
 00B2C3E8    83BD E4D7FFFF 0>CMP DWORD PTR SS:[EBP-281C],0
 00B2C3EF    0F85 8A000000   JNZ 00B2C47F
 00B2C3F5    0FB685 94D4FFFF MOVZX EAX,BYTE PTR SS:[EBP-2B6C]
 00B2C3FC    85C0            TEST EAX,EAX
 00B2C3FE    74 7F           JE SHORT 00B2C47F
 
 
 在 CPU 窗口按 Ctrl+S 查找如下代码
 
 PUSH EAX
 XCHG CX,CX
 POP EAX
 STC
 
 
 00B2CF54    50              PUSH EAX                       找到这里
 00B2CF55    66:87C9         XCHG CX,CX
 00B2CF58    58              POP EAX
 00B2CF59    F9              STC
 00B2CF5A    2D F1233E92     SUB EAX,923E23F1
 00B2CF5F    A2 B5419372     MOV BYTE PTR DS:[729341B5],AL
 00B2CF64    43              INC EBX
 00B2CF65    0F7421          PCMPEQB MM4,QWORD PTR DS:[ECX]
 00B2CF68    1947 C0         SBB DWORD PTR DS:[EDI-40],EAX
 00B2CF6B    60              PUSHAD
 00B2CF6C    C9              LEAVE
 00B2CF6D    92              XCHG EAX,EDX
 00B2CF6E    C9              LEAVE
 00B2CF6F    34 C9           XOR AL,0C9
 00B2CF71    99              CDQ
 00B2CF72    9B              WAIT
 00B2CF73    E6 2C           OUT 2C,AL                                ; I/O 命令
 00B2CF75    B7 25           MOV BH,25
 00B2CF77    3E:AE           SCAS BYTE PTR ES:[EDI]
 
 
 我们在 00B2CF54 行按 F2 设置断点,然后 F9 执行后取消断点到这里
 
 
 
 00B2CF54    50              PUSH EAX
 00B2CF55    66:87C9         XCHG CX,CX
 00B2CF58    58              POP EAX
 00B2CF59    C705 E0C0B300 6>MOV DWORD PTR DS:[B3C0E0],0B3CB60
 00B2CF63    A1 E49FB400     MOV EAX,DWORD PTR DS:[B49FE4]
 00B2CF68    8B00            MOV EAX,DWORD PTR DS:[EAX]                 注意这里,重定位表的RVA
 00B2CF6A    8985 3CD9FFFF   MOV DWORD PTR SS:[EBP-26C4],EAX
 00B2CF70    A1 E49FB400     MOV EAX,DWORD PTR DS:[B49FE4]
 00B2CF75    83C0 04         ADD EAX,4
 00B2CF78    A3 E49FB400     MOV DWORD PTR DS:[B49FE4],EAX
 00B2CF7D    A1 E49FB400     MOV EAX,DWORD PTR DS:[B49FE4]
 00B2CF82    8B00            MOV EAX,DWORD PTR DS:[EAX]                 注意这里,重定位表的大小
 00B2CF84    8985 78D9FFFF   MOV DWORD PTR SS:[EBP-2688],EAX
 00B2CF8A    A1 E49FB400     MOV EAX,DWORD PTR DS:[B49FE4]
 00B2CF8F    83C0 04         ADD EAX,4
 00B2CF92    A3 E49FB400     MOV DWORD PTR DS:[B49FE4],EAX
 00B2CF97    83BD 3CD9FFFF 0>CMP DWORD PTR SS:[EBP-26C4],0               重定位表的RVA为0吗?
 00B2CF9E    74 6F           JE SHORT 00B2D00F                           为0则重定位处理
 00B2CFA0    83BD 78D9FFFF 0>CMP DWORD PTR SS:[EBP-2688],0               重定位表的大小为0吗?
 00B2CFA7    74 66           JE SHORT 00B2D00F                           为0则重定位处理
 00B2CFA9    8B85 FCD7FFFF   MOV EAX,DWORD PTR SS:[EBP-2804]
 00B2CFAF    8B8D 0CD8FFFF   MOV ECX,DWORD PTR SS:[EBP-27F4]
 00B2CFB5    3B48 34         CMP ECX,DWORD PTR DS:[EAX+34]
 00B2CFB8    74 55           JE SHORT 00B2D00F                           如与映像基址不符则重定位处理!
 00B2CFBA    FFB5 78D9FFFF   PUSH DWORD PTR SS:[EBP-2688]
 00B2CFC0    8B85 0CD8FFFF   MOV EAX,DWORD PTR SS:[EBP-27F4]
 00B2CFC6    0385 3CD9FFFF   ADD EAX,DWORD PTR SS:[EBP-26C4]
 00B2CFCC    50              PUSH EAX
 00B2CFCD    8B85 FCD7FFFF   MOV EAX,DWORD PTR SS:[EBP-2804]
 00B2CFD3    FF70 34         PUSH DWORD PTR DS:[EAX+34]
 00B2CFD6    FFB5 0CD8FFFF   PUSH DWORD PTR SS:[EBP-27F4]
 00B2CFDC    E8 3C150000     CALL 00B2E51D                                重定位处理CALL
 00B2CFE1    83C4 10         ADD ESP,10
 00B2CFE4    0FB6C0          MOVZX EAX,AL
 00B2CFE7    85C0            TEST EAX,EAX
 00B2CFE9    75 24           JNZ SHORT 00B2D00F
 00B2CFEB    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
 00B2CFEE    8B00            MOV EAX,DWORD PTR DS:[EAX]
 00B2CFF0    C700 07000000   MOV DWORD PTR DS:[EAX],7
 00B2CFF6    68 50CBB300     PUSH 0B3CB50                             ; ASCII "Location CPG"
 00B2CFFB    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
 00B2CFFE    FF70 04         PUSH DWORD PTR DS:[EAX+4]
 00B2D001    E8 24800000     CALL 00B3502A                            ; JMP 到 msvcrt.strcpy
 00B2D006    59              POP ECX
 00B2D007    59              POP ECX
 00B2D008    33C0            XOR EAX,EAX
 
 F8走到00B2CF68处看到
 
 DS:[009C5DE0]=00077000      重定位的RVA
 EAX=009C5DE0 (SystemMo.009C5DE0)
 
 F8走到00B2CF82处看到
 
 DS:[009C5DE4]=0000755C       重定位的大小
 EAX=009C5DE4 (SystemMo.009C5DE4), ASCII "\u"
 
 
 我们把 00B2CFB8 的 JE 00B2D00F 改成 JMP 00B2D00F 跳过重定位处理,这样就不需要修改 DLL 的基址了,否则修改基址为OEP处看到的基址,如这里为00870000
 
 
 现在我们 Alt+M 打开内存查看窗口,看到这个DLL的给个区段
 
 内存映射
 地址       大小       属主       区段       包含          类型   访问      初始访问  已映射为
 0
 00400000   00001000   LOADDLL               PE 文件头        Imag   R         RWE
 00410000   00001000   LOADDLL    CODE       代码            Imag   R E       RWE
 00420000   00003000   LOADDLL    DATA       数据            Imag   RW        RWE
 00430000   00001000   LOADDLL    .idata     输入表           Imag   RW        RWE
 00440000   00001000   LOADDLL    .edata     输出表           Imag   R         RWE
 00450000   00001000   LOADDLL    .rsrc      资源            Imag   RW        RWE
 00460000   00103000                                       Map    R         R
 00570000   000B5000                                       Map    R E       R E
 00870000   00001000   SystemMo              PE 文件头        Imag   R         RWE
 00871000   00069000   SystemMo   CODE                     Imag   R         RWE
 008DA000   00004000   SystemMo   DATA                     Imag   R         RWE
 008DE000   00005000   SystemMo   BSS                      Imag   R         RWE
 008E3000   00003000   SystemMo   .idata                   Imag   R         RWE
 008E6000   00001000   SystemMo   .edata     输出表           Imag   R         RWE
 008E7000   00008000   SystemMo   .reloc                   Imag   R         RWE
 008EF000   00040000   SystemMo   .text      代码            Imag   R         RWE
 0092F000   00010000   SystemMo   .adata     代码            Imag   R         RWE
 0093F000   00010000   SystemMo   .data      数据            Imag   R         RWE
 0094F000   00010000   SystemMo   .reloc1    重定位           Imag   R         RWE
 0095F000   00070000   SystemMo   .pdata     输入表           Imag   R         RWE
 009CF000   00007000   SystemMo   .rsrc      资源            Imag   R         RWE
 009E0000   0000C000                                       Priv   RW        RW
 009F0000   00002000                                       Map    R         R
 00A00000   0001B000                                       Priv   RW        RW
 00A21000   000BF000                                       Priv   RW        RW
 00AE3000   00002000                                       Priv   RW        RW
 00B00000   00064000                                       Priv   RW        RW
 
 在00871000   00069000   SystemMo   CODE       这里设置内存访问断点 F9 运行,中断在OEP
 
 008D90B0    55              PUSH EBP
 008D90B1    8BEC            MOV EBP,ESP
 008D90B3    83C4 C4         ADD ESP,-3C
 008D90B6    B8 B88C8D00     MOV EAX,SystemMo.008D8CB8
 008D90BB    E8 C8D0F9FF     CALL SystemMo.00876188
 008D90C0    E8 D3AEF9FF     CALL SystemMo.00873F98
 008D90C5    8D40 00         LEA EAX,DWORD PTR DS:[EAX]
 008D90C8    0000            ADD BYTE PTR DS:[EAX],AL
 008D90CA    0000            ADD BYTE PTR DS:[EAX],AL
 008D90CC    0000            ADD BYTE PTR DS:[EAX],AL
 008D90CE    0000            ADD BYTE PTR DS:[EAX],AL
 008D90D0    0000            ADD BYTE PTR DS:[EAX],AL
 008D90D2    0000            ADD BYTE PTR DS:[EAX],AL
 008D90D4    0000            ADD BYTE PTR DS:[EAX],AL
 
 用LordPE选中Ollydbg的loaddll.exe的进程,在下面的列表里选择SystemMo.dll,然后完整脱壳,得到dumped.dll
 
 
 我们用 LordPE 打开 dumped.dll 到目录中修改 重定位:RVA=77000 大小=755C  然后保存修改
 
 
 3 搞定输入表
 
 Alt+M 打开内存查看窗口,看到这个DLL的给个区段
 
 
 内存映射, 条目 35
 地址=008E3000
 大小=00003000 (12288.)
 属主=SystemMo 00870000
 区段=.idata
 类型=Imag 01001002
 访问=R
 初始访问=RWE
 由于我们刚才已经跳过了重定位处理所以这里是未经过重定位处理的地址
 我们在命令行里输入 D 8E3000往下走会看到许多函数地址
 
 008E3140  7C93188A  ntdll.RtlDeleteCriticalSection
 008E3144  7C9210ED  ntdll.RtlLeaveCriticalSection
 008E3148  7C921005  ntdll.RtlEnterCriticalSection
 008E314C  7C809FA1  kernel32.InitializeCriticalSection
 008E3150  7C809B14  kernel32.VirtualFree
 008E3154  7C809A81  kernel32.VirtualAlloc
 008E3158  7C80995D  kernel32.LocalFree
 008E315C  7C8099BD  kernel32.LocalAlloc
 
 现在上下滚动窗口就可以很容易的找到IAT的开始和结束的地址
 
 
 开始地址=008e3140
 结束地址=008e3798
 
 大小=008e3798-008e3140=658
 
 但是现在直接用ImportREC选取SystemMo.dll,看到
 
 
 当前输入函数信息:
 0 (十进制:0)
 30D (十进制:781) 输入函数  增加: +30D
 (30D (十进制:781)  无效指针(s)  增加: +30D
 ->> 模块被选择! : d:\pj\systemmodule.dll
 映像基地址:00400000 大小:00166000
 
 原来ImportREC显示SystemMo.dll的基址还是00400000呀,
 
 填入RVA=004e3140、大小=658,可以得到输入表,却无法完成修复抓取文件。为什么呢?经过看雪的名位老大的帖子才发现都是重定位惹的祸。
 于是利用 FLY 大狭的移花接木的办法:再打开一个 Ollydbg,载入 Win98 的 NotePad.EXE,然后把 008e3140-008e3798  的数据复制、粘贴进NotePad.EXE 的 00405000-00405658,然后用 ImportREC 选择 NotePad.EXE 进程,填入 RVA=00005000、大小=658,得到输入表,CUT掉垃圾指针,改 OEP=000690b0,就可以 FixDump 了,经测试在本机上可以使用!
 
 [ 本帖最后由 下下雪 于 2006-12-17 22:23 编辑 ]
 | 
 |