作者: ljttt
写作日期:2000-07-25
目标程序:PECompact.exe 35,840 v1.34 脱壳
程序下载:http://www.cnvnet.com/download/d/pecsetup.exe
使用工具:SoftICE 4.00; ProcDump 1.6.2; IceDump 6.0.1.5; HexWorkShop;
(补充一句:以下Import table我称作输入表,可能说法不规范,不过我打习惯了,大家原谅一下)
(注:以下文中数字为十六进制)
分析:
运行ProcDump,点击Pe-Editor按钮,选中PECompact.exe,得到程序内存映象大小:Size of Image为 00031000和基地址Image
Base为0040000。然后点击Sections,没有发现.idata这样容易识别的输入表Section,
看来找输入表的地址和大小也将成为重点了。
首先我们来抓取Import table
1、先装载IceDump。到IceDump目录中运行相应SoftICE版本的icedump.exe。(比如我用的SoftICE版本为4.00就到win9x/400目录下运行icedump.exe)
2、运行SoftICE的Loader,加载PECompact.exe。
3、Ctrl-D进行SoftICE,如下设置断点
bpx loadlibrarya do "dd esp->4"
(注:在没有明确的输入表地址的情况下,这不失为找输入表地址的一种好办法)
4、按F5回到Windows中,单击Loader中的Load按钮。程序中断在第一条指令处。进入了SoftICE。
(看来PECompact.exe不象受Asprotect保护的程序那样。无法用SoftICE自动中断在第一条指令处)
5、按F5运行程序。又中断在我们设下的中断Loadlibrarya处。看看数据窗口。显示如下:
0030:004171AE 4E52454B 32334C45 4C4C442E 4C000000
KERNEL32.DLL...L
0030:004171BE 4C64616F 61726269 00417972 65470000
oadLibraryA...Ge
0030:004171CE 6F725074 64644163 73736572 56000000
tProcAddress...V
0030:004171DE 75747269 6C416C61 00636F6C 69560000
irtualAlloc...Vi
0030:004171EE 61757472 6572466C 00000065 74697845
rtualFree...Exit
0030:004171FE 636F7250 00737365 72460000 694C6565
Process...FreeLi
0030:0041720E 72617262 00000079 4D746547 6C75646F
brary...GetModul
0030:0041721E 6E614865 41656C64 47000000 6F4D7465
eHandleA...GetMo
0030:0041722E 656C7564 656C6946 656D614E 9D8B0041
duleFileNameA...
0030:0041723E 004020A6 20AA9D3B 01750040 0CB58BC3
. @.;.. @.u.....
6、根据经验,一般第一次是脱壳代码自己的函数库的加载。并不是我们需要的输入表。因此,按F5继续执行程序。程序又一次中断,这一次数据窗口显示如下:
0030:0040D4A0 4E52454B 32334C45 6C6C642E 49444700
KERNEL32.dll.GDI
0030:0040D4B0 642E3233 55006C6C 33524553 6C642E32
32.dll.USER32.dl
0030:0040D4C0 4441006C 49504156 642E3233 49006C6C
l.ADVAPI32.dll.I
0030:0040D4D0 4547414D 2E504C48 006C6C64 646D6F63
MAGEHLP.dll.comd
0030:0040D4E0 3233676C 6C6C642E 45485300 32334C4C
lg32.dll.SHELL32
0030:0040D4F0 6C6C642E 41434A00 2E31474C 006C6C64
.dll.JCALG1.dll.
0030:0040D500 696C7061 6C642E62 00F4006C 4C746547
aplib.dll...GetL
0030:0040D510 45747361 726F7272 01A70000 65766F4D
astError....Move
0030:0040D520 656C6946 01160041 50746547 41636F72
FileA...GetProcA
0030:0040D530 65726464 00007373 655201CB 6F436461
ddress....ReadCo
可以看到偏移地址为40D4A0,根据我们对输入表的知识,(具体原理说明可以看看雪教学中的"脱壳高级篇"中的文章,那里面比我说得清楚多了)我们可以搜索内存映象中的字节A0,D4,00,00。(即00D4A0=40D4A0-400000)来确定输入表的位置。下指令
s 30:400000 l ffffffff A0,D4,00,00
7、搜索的结果显示
Pattern found at 0030:0040D00C (0000D00C)
我们用如下指令来定位到输入表的起始位置(当然目前还不能确定就是输入表)
dd 0040D00C-C
如下为数据窗口的显示结果。
0030:0040D000 0000D0C8 00000000 00000000 0000D4A0
................
0030:0040D010 0000D2B4 0000D1A0 00000000 00000000
................
0030:0040D020 0000D4AD 0000D38C 0000D1CC 00000000
................
0030:0040D030 00000000 0000D4B7 0000D3B8 0000D260
............`...
现在我们来看看到底是否我们要找的输入表。下指令
dd 40D0C8
显示结果如下:
0030:0040D0C8 0000D50A 0000D51A 0000D526 0000D538
........&...8...
0030:0040D0D8 0000D548 0000D556 0000D564 0000D57A
H...V...d...z...
0030:0040D0E8 0000D58C 0000D59E 0000D5B4 0000D5C2
................
0030:0040D0F8 0000D5D2 0000D5DE 0000D5F4 0000D5FE
................
继续追踪,下指令
db 40D50A
显示结果如下:
0030:0040D50A F4 00 47 65 74 4C 61 73-74 45 72 72 6F 72 00 00 ..GetLastError..
0030:0040D51A A7 01 4D 6F 76 65 46 69-6C 65 41 00 16 01 47 65 ..MoveFileA...Ge
0030:0040D52A 74 50 72 6F 63 41 64 64-72 65 73 73 00 00 CB 01 tProcAddress....
0030:0040D53A 52 65 61 64 43 6F 6E 73-6F 6C 65 41 00 00 31 00 ReadConsoleA..1.
(以上说这么多,只是为了说明找输入表的方法的具体实现过程,原理在各位高手的"脱壳高级篇"已经说得很详细了)
OK,符合输入表的规范。看来这就是我们要找的输入表了。我们还要确定一下输入表的长度,在数据窗口中向下翻页。直到发现大量的0x00字节。确定一下长度为C40字节。(这次就不Dump窗口看了,写到这里我开始怀疑我这篇又臭又长的文章不知道要写多长,大家还没有看着看着睡着了吧
:-) )
现在我们来保存输入表,下指令
PAGEIN D 40D000 C40 C:\TEMP\DUMP.BIN
现在再来确定程序真正的Entry Point
1、这里我为了省事,干脆
BD *
禁止所有中断,然后按F5运行程序,重新在SoftICE的Loader中单击Load按钮运行程序,(当然这种方法在对PECompact.exe的脱壳中可以用,其他的就不一定了)又中断在第一条指令。窗口显示如下:
015F:0041E800 EB06
JMP 0041E808
(JUMP )
015F:0041E802 6800E00100 PUSH
0001E000
015F:0041E807 C3
RET
==> 0041E808 9C
PUSHFD
015F:0041E809 60
PUSHAD
015F:0041E80A E802000000 CALL
0041E811 (注意了,这里可不是什么过程调用,只是JMP的变形而已)
015F:0041E80F 33C0
XOR EAX,EAX
015F:0041E811 8BC4
MOV EAX,ESP
015F:0041E813 83C004 ADD
EAX,04
注意,在Call 0041E811语句处我们要按F8键继续,不然就Over了。这里的Call语句可不是什么真正的过程调用。无非是变相的一种Jmp跳转语句而已。要识别它也不难。看看它跳转的地址是否就在附近。如果是就小心了。按F8键不要按F10键。
好了,转过了一道小小的弯,一路F10下来,还顺风顺水。直到如下
015F:0041E860 5F
POP EDI
015F:0041E861 8DB570804000 LEA
ESI,[EBP+00408070]
015F:0041E867 B99F030000 MOV
ECX,0000039F
015F:0041E86C F3A5
REPZ MOVSD
015F:0041E86E 5F
POP EDI
015F:0041E86F C3
RET
到了第一个ret。看!它要跳转了。又一段旅程开始。按F8继续,这一段就要小心一点,直到。
015F:00420121 8BB53E854000 MOV
ESI,[EBP+0040853E]
015F:00420127 8BBD42854000 MOV
EDI,[EBP+00408542]
015F:0042012D E82E0A0000 CALL
00420B60
015F:00420132 61
POPAD
015F:00420133 9D
POPFD
015F:00420134 50
PUSH EAX
015F:00420135 6800E04100 PUSH
0041E000
015F:0042013A C20400 RET
0004
又要跳转到41E000了。瞧这里,又要小心了。不要在Call 0041E009语句处按F10哦
015F:0041E000 9C
PUSHFD
015F:0041E001 60
PUSHAD
015F:0041E002 E802000000 CALL
0041E009
015F:0041E007 33C0
XOR EAX,EAX
015F:0041E009 8BC4
MOV EAX,ESP
015F:0041E00B 83C004 ADD
EAX,04
一路下来到
015F:0041E092 FFD0
CALL EAX
015F:0041E094 FFA59A214000 JMP
[EBP+0040219A]
015F:0041E09A 61
POPAD
015F:0041E09B 9D
POPFD
015F:0041E09C 6800704100 PUSH
00417000
015F:0041E0A1 C3
RET
又要跳到417000了。这里又要小心Call 00417009语句了。
015F:00417000 9C
PUSHFD
015F:00417001 60
PUSHAD
015F:00417002 E802000000 CALL
00417009
015F:00417007 33C0
XOR EAX,EAX
015F:00417009 8BC4
MOV EAX,ESP
015F:0041700B 83C004 ADD
EAX,04
一路下来,终于到终点站了。万岁!
015F:00417090 6A00
PUSH 00
015F:00417092 FFD0
CALL EAX
015F:00417094 FFA59A214000 JMP
[EBP+0040219A]
015F:0041709A 61
POPAD
015F:0041709B 9D
POPFD
015F:0041709C 6800104000 PUSH
00401000
015F:004170A1 C3
RET
程序真正的入口到了。在ret指令处我们下指令:
PAGEIN D 400000 31000 C:\TEMP\DUMP.EXE
第三步。开始我们的后期修补工作。(Zzzzzz.....Zzzzzz......什么,大家都睡着了,没办法我总不能就此结束吧。咬牙继续写下去。)
1、启动HexWorkShop,打开Dump.exe。用菜单中的Go命令定位到0000D000处。用Select Block命令选择C40个字节,按Del键删除。
然后打到Dump.bin文件,用菜单中的Select Block命令选择C40个字节(用Select All一样)。用Copy命令复制到剪贴板。切换到Dump.exe窗口用菜单中的Paste命令粘贴过来。(注意当前位置是从D000开始的,不要贴错位置哦)
2、启动ProcDump。单击PE Editor打开Dump.exe文件。然后单击Sections,把每个Section中
PSize改成和VSize同样大小,Offset改成和RVA同样大小。按OK确定。
3、然后修改Entry Point为00001000。单击Directory按钮修改其中的Import Table的RVA为0000D000,Size为00000C40,然后保存。
4、该收工吧。看看成果。运行Dump.exe。屏幕显示 "找不到所需的.Dll文件 - JCALG1.DLL"不存在。 (险些晕倒)。
5、再看看,回到HexWorkShop窗口。用菜单中的Go命令定位到00D000处,找到如下位置:
0000D000 0000D0C8 00000000 00000000 0000D4A0
................
0000D010 0000D2B4 0000D1A0 00000000 00000000
................
0000D020 0000D4AD 0000D38C 0000D1CC 00000000
................
0000D030 00000000 0000D4B7 0000D3B8 0000D260
............`...
0000D040 00000000 00000000 0000D4C2 0000D44C
............L...
0000D050 0000D284 00000000 00000000 0000D4CF
................
0000D060 0000D470 0000D28C 00000000 00000000
p...............
0000D070 0000D4DC 0000D478 0000D294 00000000
....x...........
0000D080 00000000 0000D4E9 0000D480 0000D2A4
................
0000D090 00000000 00000000 0000D4F5 0000D490
................
0000D0A0 0000D2AC 00000000 00000000 0000D500
................
0000D0B0 0000D498 00000000 00000000 00000000
................
0000D0C0 00000000 00000000 0000D50A 0000D51A
................
0000D0D0 0000D526 0000D538 0000D548 0000D556
&...8...H...V...
6、把从0000D08C开始到0000D0B2之间的字节全部改为00。保存。为什么这样改?因为
这之间的字节分成两段,分别对应着输入表中对JCALG1.DLL和aplib.dll的引入。
0000D2A4 00000000 00000000 0000D4F5 0000D490
0000D2AC 00000000 00000000 0000D500 0000D498
7、运行,Ok!
附:
我写了个ProcDump的Script如下,可以省略大部分步骤。现在简要说明一下。
运行ProcDump。用Script脱壳出文件Dump.exe,然后按修补工作中的第3-5步修改即可。不过第5步时定位到0000C600字节处。因为ProcDump脱壳出的Dump.exe文件头只有600个字节,而内存中文件头要占1000个字节。所以可以得到VA=D000-1000-600=C600字节。
[5'My ONE PECompact v1.34]
L1=OBJR
L2=LOOK 60
L3=BP
L4=OBJR
L5=LOOK C3
L6=BP
L7=WALK
L8=OBJR
L9=LOOK EB,14
LA=BP
LB=WALK
LC=OBJR
LD=LOOK C2,04,00
LE=BP
LF=WALK
L10=OBJR
L11=LOOK C3
L12=BP
L13=WALK
L14=OBJR
L15=LOOK 68,??,??,??,??,C3
L16=BP
L17=STEP
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001
OPTL4=00030000
OPTL5=00000000
脱壳时间没花多少时间,写这篇又臭又长的文章花了俺3个多小时。俺文字功底不好。该文章的结构参照看雪兄的"脱壳高级篇"中一文。俺实在写累了。睡觉去罗!
最后,还有一个问题问问各位,TRW中如何保存当前屏幕?(写作 用)还请赐教。
- 标 题:对PECompact.exe v1.34的手动脱壳 -----俺写的一篇臭文 (10千字)
- 作 者:ljttt
- 时 间:2000-7-26 7:16:08
- 链 接:http://bbs.pediy.com