- UID
- 23416
注册时间2006-10-1
阅读权限20
最后登录1970-1-1
以武会友
该用户从未签到
|
加壳方式 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 编辑 ] |
|