ASProtect v0.94b保护
英文原作:r!sc
《Almost Manual Unpacking (using Softice and Icedump)》
原作日期:6th febuary 2000
教程翻译: 看雪
翻译日期:2000年5月26日
声 明: 本文以r!sc的教程为基础,以自己的观点补充调整。
目标程序:aspack.exe
. 231,424 . v 2.001
程序下载:AsPack
使用工具:Softice 4.05; ProcDump 1.6.2 Final; FrogsICE v0.43;Icedump 6.016
part1 . 理论知识
part2 . 分析原文件的PE头
part3 . 抓取import table
part4 . Dump整个程序并修正文件头
=part1===part1===part1===part1===part1===part1===part1===part1===part1===part1=
理论知识
这种被压缩或加密的PE文件,执行时,在内存中将会完全解压。其中import表在装载中也会被完全解压或解密(—攻击点)。其中抓取import表就很关键了,其具体位置,可用
Procdump分析文件头得到。然后,要跟踪程序完全解压后的跳到程序处的入口点,然后在内存里dump取程序的整个部分。将刚dump取的正确import表用十六进制工具粘贴到完全dump的程序,再
修正文件头,这样程序就可正常运行。
=part2===part2===part2===part2===part2===part2===part2===part2===part2===part2=
分析原文件的PE头
运行 Procdump,点击pe-editor按钮,选中ASPack.exe文件,我们想要得到程序解压后的尺寸,import表的地址和大小...幸运的是这个文件的每个块(section )都存在。
Size of image : 00079000 ; 这个PE文件执行时分配的内存空间。
image Base : 00400000 ; 基址
.idata ;.idata包含其他外来DLL的函数及数据信息
Virtual Size : 00002000 ; idata在内存的尺寸
Virtual Offset : 00046000 ; idata的地址(+imagebase
== 00446000)
.rdata
Virtual Size : 00001000
Virtual Offset : 00049000
import表有可能在idata块或rdata块,到底在哪部分?看看它们的尺寸,我将马压在.idata ...
=part3===part3===part3===part3===part3===part3===part3===part3===part3===part3=
抓取import table
1、先装载Icedump
在这用Icedump
6.016版本,其命令操作形式完全和以前的版本不同。先在Icedump目录里运行相应SOFTICE版本的icedump.exe(我用的SOFTICE是4.05版,因此在win9x/405目录下运行icedump.exe),如Icedump装载成功,Icedump会返回如下信息:
icedump v6.0.1.6 for winice v4.05
loader icedump unloaded icedump loaded ←出现这句话表示Icedump装载成功 C:> |
2、再装载FrogsICE
由于aspack能检测到SOFTICE的存在,因此装载Frogsice就可躲过。在我机子里:FrogsICE 1.00
Final和Icedump不能很好兼容工作,因此我将FrogsICE换成版本v0.43,hehe..它们配合的很好。双击FPloader.exe文件即可装载成功。
OK,到此你的SOFTICE的功能己大大加强里。
这时试试运行aspack,这时屏幕将蓝屏给你一菜单选项,告知aspack发现了SOFTICE,是否欺骗它,这时你按ESC按钮,程序即可正常运行。
3、 记住我们的第一步是抓取import table,它在内存的446000到449000处,因此程序运行时注意这段内存代码的解压情况。
由于SOFTICE不能LOAD aspack.exe,我们用:bpx loadlibrarya命令来拦断。
loadlibrarya命令解释:如果import表没在内存中就使用LoadLibraryA
API调用装入该模块,因此我们可以拦截此函数来观察import表。
:bpx loadlibrarya
然后运行aspack将中断如下:
Break due to BPX KERNEL32!LoadLibraryA
:dd 446000 l 40
(下此命令观察内存446000到449000处的数据)
.
-------SPACK!.idata--------------------dword----------ROT--?(0)--
0030:00446000 ???????? ???????? ???????? ???????? ................
0030:00446010
???????? ???????? ???????? ???????? ................
0030:00446020 ????????
???????? ???????? ???????? ................
0030:00446030 ???????? ????????
???????? ???????? ................
上图是SOFTICE的数据窗口,显示
??...说明import表在内存中没解压。
再按F5一下,程序将中断如下:(记着:在这例中只能要按一下F5,否则将不能抓取正确的import表)
0030:00446000 00000000 00000000 00000000 0004669C .............f..
0030:00446010 0004612C 00000000 00000000 00000000 ,a..............
0030:00446020
000468B6 000461AC 00000000 00000000 .h...a..........
0030:00446030 00000000
000468D0 000461B4 00000000 .....h...a......
这时446000处不是?? ?? ?? ??,意味着import表己被解压了。
.import表以一个IMAGE_IMPORT_DESCRIPTOR数组开始。
image_import_descriptors数据有5组dwords组成。
image_import_descriptors结构:
①dd offset original_first_thunk
②dd timedatestamp 时间及日期标志
③dd forwardchain
正向链结索引
④dd offset library name以NULL结尾的ASCII字符的RVA地址,该字符串包含输入的DLL名,
比如"Kernel32.dll"或"USER32.DLL"。
⑤dd offset first_thunk 该字段是在image_thunk_data联合结构中的RVA偏移
其中timedatestamp和forwardchain通常设置为00000000, original first thunk 选项不是必须的.
:dd 446000 l 40
0030:00446000 00000000 00000000 00000000 0004669C .............f..
0030:00446010
0004612C 00000000 00000000 00000000 ,a..............
地址4669c 指向 LibraryName (RVA, 你需要加上基址imagebase+400000)
:db
44669c l 10
0030:0044669C 4B 45 52 4E 45 4C 33 32-2E 44 4C 4C 00 00 00 00
KERNEL32.DLL....
地址612c指向 first_thunk 库。
:dd
44612c l 10
0030:0044612C 000466AA 000466C2 000466DA 000466F2 .f...f...f...f..
这些是以NULL结尾的ASCII字符的RVA地址,
. . 466aa 是第一个API函数的地址,466c2是第二个API函数地址...它们以以NULL结尾。
:db
0004466aa l 20
0030:004466AA 00 00 44 65 6C 65 74 65-43 72 69 74 69 63 61
6C ..DeleteCritical
0030:004466BA 53 65 63 74 69 6F 6E 00-00 00 4C 65 61 76
65 43 Section...LeaveC
通过上面的分析可知,这就是原始的.import表,快dump it!!(看看上文的image_import_descriptors地址)
:/dump
446000 2000 c:\aspack.idata.bin
(如你是用Icedump 6.016以前版本用此命令:pagein d 446000
2000 c:\aspack.idata.bin)
为了方便大家对比,特将dump正确的import表放在此下载。
=part4===part4===part4===part4===part4===part4===part4===part4===part4===part4=
Dump整个程序并修正文件头
1、现在我们要找程序的入口点,下命令:bpx loadlibrarya ,然后按14下F5,然后按F10一步一步跟踪来到如下代码:
0137:00C1150E 8B4508
MOV EAX,[EBP+08]
0137:00C11511 8B10 MOV EDX,[EAX] DS:004664FC=00400000 0137:00C11513 8B4508 MOV EAX,[EBP+08] 0137:00C11516 035018 ADD EDX,[EAX+18] 0137:00C11519 8B4508 MOV EAX,[EBP+08] 0137:00C1151C 8B401C MOV EAX,[EAX+1C] 0137:00C1151F E874F9FFFF CALL 00C10E98 ←在此按F8进入 0137:00C11524 5F POP EDI 0137:00C11525 5E POP ESI 0137:00C11526 5B POP EBX 0137:00C11527 59 POP ECX 0137:00C11528 59 POP ECX 0137:00C11529 5D POP EBP 0137:00C1152A C20400 RET 0004 |
F8进入后来到如下:
0137:00C10E96 8BC0
MOV EAX,EAX
0137:00C10E98 89C4 MOV ESP,EAX 0137:00C10E9A 89D0 MOV EAX,EDX 0137:00C10E9C 8B1D6C66C100 MOV EBX,[00C1666C] 0137:00C10EA2 89041C MOV [EBX+ESP],EAX 0137:00C10EA5 61 POPAD 0137:00C10EA6 50 PUSH EAX ;push 442b98 即为入口点 0137:00C10EA7 C3 RET ;返回到己完全解压的代码处,即入口点处。 0137:00C10EA8 C3 RET |
来到入口点:
0167:00442B98 55 PUSH EBP ←此处为入口点 0167:00442B99 8BEC MOV EBP,ESP 0167:00442B9B 83C4F4 ADD ESP,-0C |
在0167:00442B98 处就可dump整个内存数据了,此时程序己完全解压准备运行了。记下程序入口点:00442B98
在dump前,清除所有的断点:bc *.
./dump
400000 79000 c:\aspack.dumped.exe
(如你是用Icedump
6.016以前版本用此命令:pagein d 400000 79000 c:\aspack.dumped.exe)
2、替换正确的import表
用Hexworkshop打开aspack.dumped.exe和aspack.idata.bin. Goto到exe文件的46000偏移处,Select Block大小为2000. 拷贝aspack.idata.bin文件的同样大小(2000)的Block,粘贴到exe文件中以替换掉不正确的.idata section,然后存盘。(注意:以上所有数据都是十六进制)
3、修正PE文件头
用 Procdump打开刚建好的
aspack.dumped.exe文件,点击pe-editor按钮,然后再点击SECTIONS按钮,在每个section点击右键,选中Edit
section,把所有的 section 的PSize = VSize offset = RVA 。
如:CODE 的PSize=0001E000;
VSize=00042000;offset =00000400;RVA=00001000;
改成:PSize = VSize= 00042000;offset
= RVA =00001000;
在改完所有的sections后,按OK,存盘后,你在资源管理器中刷新一下,就会发现aspack.dumped.exe的图标回来了,但还不能运行,你还要修正入口点和import表。
将入口点(Entry Point)改为:00042B98(记着:00442B98-imagebase=42B98)
再点击Directory按钮,将Import Table改为 RVA (46000 );而其选项Size只要比0大就可;
然后点击OK,退出Procdump,再运行 aspack.dumped.exe ,程序运行的很甜美!
这时你用W32DASM不能反汇编,你可用 Procdump编辑第一个section characteristics:
将其 c0000060 (data, writable)改为: 60000040 (code, executable)或 e0000060 (code, data, etc etc)
注:大家抓取屏幕可在Icedump 6.016中,用:/Screendump抓取。
不加参数命令:/Screendump 选取模式,重复执行,会在0、1、2、3、4五种模式下转换。
模式1(默认)是以文本方式存盘,模式2是以HTML文件存盘。其它的请参考其readme.
模式选好后,就可用命令: /SCREENDUMP [