tElock脱壳笔记

tElock介绍
tElock是一款免费的加密保护程序。压缩引擎使用UPX内核,可压缩保护32位可执行文件EXE、DLL和OCX。它使用了各种Anti-Debug技术、SMC技术、重整覆盖、重整Reloc、自建输入表和产生任意区块名等保护技术。

OEP查找

(1)工具查找:peid的插件Generic OEP Finder,AsprLoader,oepfinder

(2)手动查找:二次内存断点法,最后一次异常法,单步跟踪



IAT修复

(1)解密被外壳加密了的IAT

IAT修复可以使用Import_REC插件、OD脚本,或者手动修复。
对于tElock 0.98加壳的程序,通过跟踪代码,很容易发现:真正的API地址在一个DWORD数组里面,在OD的数据窗口中使用二进制复制这个DWORD数组(注意要复制最后一个为0的DWORD),再二进制粘贴到IAT相应的位置。


对于tElock 0.99加壳的程序,虽然也可以跟踪代码,找到API真正的地址,但是其加密方式不再像tElock 0.98那样简单。如果有很多地址需要修复,最好使用插件或者脚本。(参考老外的一个视频)

(2)跳过外壳对IAT的加密

直接在VirtualAlloc的末尾F2下int 3断点(不要在函数的开始部分下断点,也不要下硬件断点) ,或者在过了一段利用S.E.H清除硬件断点的代码后,再对VirtualAlloc下硬件执行断点(过了这段代码后就可以下硬件断点了)。
断下后,执行到返回。将条件跳转指令修改为无条件跳转,这样就跳过了IAT加密。


(3)跳过外壳对原输入表的处理

外壳先将各个区段解压还原(此时内存中有完整的输入表),再加密IAT, 同时破坏IID数组。IAT的加密方式是,将IAT中的指针指向外壳代码空间(这段空间是由外壳动态申请的,抓取内存映像时不会被保存下来),由外壳调用相应的API。

由于tElock 0.98没有破坏原输入表,如果跳过外壳处理原输入表的代码,在到达OEP时抓取内存映像,那么只要修改PE头的几个数据就可以了,不需要再使用Import_REC重建输入表。

具体步骤:
将OD的异常选项设置为“忽略所有异常”。对GetProcAddress F2下断,断下来后取消int 3断点。

返回程序领空,向下查找指令add esi, 14。在下面的JMP指令上按ENTER键。

外壳在0042F21E处,判断原程序是否有输入表。如果有输入表,则ESI中放的是IID数组的RVA,否则,ESI = 0,外壳就不填充输入表。因此,在0042F21E处强行跳转,就可以得到包含原程序完整输入表的映像文件。

并且,同版本的tElock外壳此处的地址与外壳入口点的差值是定值。tElock 0.98是0x9B8。
0002FBD6  9B8 + 00401000 = 0042F21E
据此,可以得到如下脱壳方法:

计算出关键跳转的VA = 0042F21E。
OD设置为忽略除了除零异常外的全部异常。Shift + F9运行,到达除零异常。


在下一条指令上F2下断。Shift + F9运行。停在0042E0A9处。F2取消int 3断点。设置OD异常选项为忽略所有异常。Ctrl+G 来到0042F21E,下硬件执行断点。Shift + F9运行,断在0042F21E处,取消硬件执行断点。记下此时ESI的值00028000,然后在寄存器面板中双击ZF使其为1。Ctrl+G来到OEP=00403B70,下硬件执行断点,或者在内存映像中对代码段F2下断。Shift + F9运行。程序就会停在OEP了。此时抓取内存映像为dumpd.exe(注意correct image size)。使用LordPE修改dumpd.exe的入口点为3B70,输入表为28000。

tElock 0.99 与 0.98 的区别

(1)tElock 0.99 破坏了原输入表,所以无法采用方法3完美脱壳。
(2)tElock 0.99 增加了通过枚举窗口来反调试,而0.98只有代码自校验、检测一些API是否被下CC断点等反调试手段 (OD会被关闭SendMessage WM_CLOSE)。

下面是我脱吾爱破解脱壳练习第6期 tElock 0.99的步骤(使用原版OD,不加载任何插件)。

OD设置为忽略除了除零异常外的全部异常。Shift + F9运行,到达除零异常。

 

在下一条指令处F2下断,Shift + F9运行,停在004681D2处。F2取消断点。
设置OD为忽略所有异常。单步跟踪程序(注意变形JMP,不要跑飞了)。

 

直到如下地址,

 

EDI=00468613指向一个结构体,

 
其中第一个DWORD存放的是缓冲区指针。
相关API的资料:

BOOL EnumWindows(
    WNDENUMPROC lpEnumFunc,
    LPARAM lParam
);

Parameters

lpEnumFunc
[in] Pointer to an application-defined callback function. 
lParam
[in] Specifies an application-defined value to be passed to the callback function. 

Return Value

If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
If EnumWindowsProc returns zero, the return value is also zero. In this case, the callback function should call SetLastError to obtain a meaningful error code to be returned to the caller of EnumWindows.


BOOL CALLBACK EnumWindowsProc(
    HWND hwnd,
    LPARAM lParam
);

Parameters

hwnd
[in] Handle to a top-level window. 
lParam
[in] Specifies the application-defined value given in EnumWindows or EnumDesktopWindows. 

Return Value

To continue enumeration, the callback function must return TRUE; to stop enumeration, it must return FALSE.
这段代码的功能是:枚举系统中所有的窗口,如果发现某个窗口的类名为OLLY、OWL_ 、FileMOnC中的一个,则向该窗口发送WM_CLOSE消息。
过这段代码的方法:在0046865E处F2下断,Shift + F9运行。F2取消断点,在00468671处新建EIP(右键---> new origin here)。这样OD就不会被关闭了。
(使用修改版的OD或者使用插件隐藏OD,OD不会被关闭)

过了这段代码,Ctrl+G来到VirtualAlloc,下硬件执行断点。Shift + F9若干次,执行到返回,

 

取消硬件断点。将00469817处的指令用NOP填充。打开内存映像,对代码段F2下断。Shift + F9运行,直接到达OEP。并且IAT没有被加密。然后,用Lord_PE抓取内存映像(注意correct image size),用Import_REC重建输入表。

参考
<<加密与解密 第二版>>
http://bbs.pediy.com/showthread.php?t=97661   【转帖】Unpacking tElock 1.0 by HellSpider   
http://bbs.pediy.com/showthread.php?t=63158   【原创】单步跟踪tElock v 0.98             
http://bbs.pediy.com/showthread.php?t=86036   【原创】手脱tElock 0.98
http://bbs.chinapyg.com/viewthread.php?tid=50769 图文并茂_手脱tElock


说明:
(1)这里文章没有图。大家可以看附件里面的Word文档。
(2)我是一个菜鸟。笔记中如有什么不妥的地方,希望各位高手指出。
(3)参考了看雪很多文章,没有全部列出。

by asdfslw [www.pediy.com]
2009.12.31

【版权声明】本文由asdfslw原创于看雪软件安全论坛,转载请注明出处,并保留版权声明。