脱壳笔记——精选推荐

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【脱壳一般流程】
查壳(PEID、FI、PE-SCAN)--->寻找OEP(OD)--->脱壳/Dump(LordPE、PeDumper、OD自带的脱壳插件、PETools)--->修复(Import REConstructor)
【工具介绍】
1、查壳
PEID--功能强大的侦壳工具,自带脱壳插件(但是,效果不怎么样)
工作原理:核心是userdb.txt(大家看看就完全明白了)[通过壳的入口特征码进行辨认]
使用方法:可以拖放、也可以把PEID添加到右键菜单里面去
FI--功能强大的侦壳工具,DOS界面。

使用方法:可以拖放、可以使用DO S命令行
2、寻找OEP
ollydbg的四个区域
左上角是cpu窗口,分别是地址,机器码,汇编代码,注释;注释添加方便,而且还能即时显示函数的调用结果,返回值.
右上角是寄存器窗口,但不仅仅反映寄存器的状况,还有好多东东;双击即可改变Ef lag的值,对于寄存器,指令执行后发生改变的寄存器会用红色突出显示.
cpu窗口下面还有一个小窗口,显示当前操作改变的寄存器状态.
左下角是内存窗口.可以ascii或者unicode两种方式显示内存信息.
右下角的是当前堆栈情况,还有注释啊.
几个经常使用的快捷键
F2:在需要的地方下断点(INT3型断点)
F3:选择打开程序
F4:运行到所选择的那一行
F7:单步进入
F8:单步跟踪
F9:执行程序(运行程序)
其中要特别讲一下3个F9的区别和作用:
根据Ollydbg.hlp的中文翻译
Shif t+F9 -与F9相同,但是如果被调试程序发生异常而中止,调试器会首先尝试执行被调试程序指定的异常处理(请参考忽略Kernel32中的内存非法访问)。

Ctrl+F9 - 执行直到返回,跟踪程序直到遇到返回,在此期间不进入子函数也不更新CPU数据。

因为程序是一条一条命令执行的,
所以速度可能会慢一些。

按Esc键,可以停止跟踪。

Alt+F9 - 执行直到返回到用户代码段,跟踪程序直到指令所属于的模块不在系统目录中,在此期间不进入子函数也不更新CPU 数据。

因为程序是一条一条执行的,所以速度可能会慢一些。

按Esc键,可以停止跟踪。

看这些中文介绍大家可能还不是很明白,用我们通俗的语句来说就是:
Ctrl+F9 运行至retn (一般到了retn之后接上F7返回)
Alt+F9 运行至上层调用的下句
Shif t+F9 忽略异常运行
文件:
1.其中包括该菜单的下部有上次打开的纪录,该纪录保存有上次未清除的断点.
2.附加.对付那些Anti-Debug程序.先运行程序,再运行od,文件-->附加.
查看:
1.执行模块(Alt+E),查看程序使用的动态链接库
2.查看断点.Alt+B
调试:
1.运行(F9)加载程序后,运行!
2.暂停(F12)
3.单步进入(F7)遇见CALL进入!进入该子程序.
4.单步跳过(F8)遇见CALL不进去!
5.执行到返回(AL T+F9)就是执行到该子程的返回语句
查看-->文件
二进制文件编辑功能.查看-->文件,打开的文件是二进制显示.选中要改变的机器指令,空格,修改,右击-->保存.
具体的用途在后面的几壳脱壳课程当中将会用到,大家现在理解就行。

在后面的操作中学会使用!
其他的一些具体的大家还是要看看OD的中文帮助的
3、Dump
OD自带的脱壳插件--到达OEP之后右键。

LordPE、PeDumper--选择所调试的进程--右键--完整脱壳
4、修复
Import REConstructor 1.6
【壳的介绍】
壳出于程序作者想对程序资源压缩、注册保护的目的,把壳分为压缩壳和加密壳两种
UPX ASPCAK TELOCK PELITE N SPACK ...
ARMADILLO ASPROTECT ACPRO TECT EPE SVK P ...
顾名思义,压缩壳只是为了减小程序体积对资源进行压缩,加密壳是程序输入表等等进行加密保护。

当然加密壳的保护能力要强得多!
【常见的脱壳方法】
预备知识
1.PUSHAD (压栈)代表程序的入口点,
2.POPAD(出栈)代表程序的出口点,与PU SHAD想对应,一般找到这个OEP就在附近
3.OEP:程序的入口点,软件加壳就是隐藏了OEP(或者用了假的OEP/FOEP),只要我们找到程序真正的OEP,就可以立刻脱壳。

方法一:单步跟踪法
1.用OD载入,点“不分析代码!”
2.单步向下跟踪F8,实现向下的跳。

也就是说向上的跳不让其实现!(通过F4)
3.遇到程序往回跳的(包括循环),我们在下一句代码处按F4(或者右健单击代码,选择断点——>运行到所选)
4.绿色线条表示跳转没实现,不用理会,红色线条表示跳转已经实现!
5.如果刚载入程序,在附近就有一个CALL的,我们就F7跟进去,不然程序很容易跑飞,这样很快就能到程序的OEP
6.在跟踪的时候,如果运行到某个CALL程序就运行的,就在这个CALL中F7进入
7.一般有很大的跳转(大跨段),比如jmp XXXXXX 或者JE XXXXXX 或者有RETN的一般很快就会到程序的OEP。

Btw:在有些壳无法向下跟踪的时候,我们可以在附近找到没有实现的大跳转,右键-->“跟随”,然后F2下断,Shif t+F9运行停在“跟随”的位置,再取消断点,继续F8单步跟踪。

一般情况下可以轻松到达OEP!
方法二:ESP定律法
ESP定理脱壳(ESP在OD的寄存器中,我们只要在命令行下ESP的硬件访问断点,就会一下来到程序的OEP了!)
1.开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色)。

(这只是一般情况下,更确切的说我们选择的ESP 值是关键句之后的第一个ESP值)
2.在命令行下:dd XXXXXXXX(指在当前代码中的ESP地址,或者是hr XXXXXXXX),按回车!
3.选中下断的地址,断点--->硬件访--->WORD断点。

4.按一下F9运行程序,直接来到了跳转处,按下F8,到达程序OEP。

方法三:内存镜像法
1:用OD打开软件!
2:点击选项——调试选项——异常,把里面的忽略全部√上!CTRL+F2重载下程序!
3:按ALT+M,打开内存镜象,找到程序的第一个.rsrc.按F2下断点,然后按SHIFT+F9运行到断点,接着再按ALT+M,打开内存镜象,找到程序的第一个.rsrc.上面的.CODE(也就是00401000处),按F2下断点!然后按SHIFT+F9(或者是在没异常情况下按F9),直接到达程序OEP!
注:.rsrc是资源,一般壳都对资源进行操作,所以上面的
方法四:一步到达OEP
1.开始按Ctrl+F,输入:popad(只适合少数壳,包括UPX,ASPACK壳),然后按下F2,F9运行到此处
2.来到大跳转处,点下F8,到达OEP!
这个定理是最有效的
方法五:最后一次异常法
1:用OD打开软件
2:点击选项——调试选项——异常,把里面的√全部去掉!CTRL+F2重载下程序
3:一开始程序就是一个跳转,在这里我们按SHIFT+F9,直到程序运行,记下从开始按SHIFT+F9到程序运行的次数m!4:CTRL+F2重载程序,按SHIFT+F9(这次按的次数为程序运行的次数m-1次)
5:在OD的右下角我们看见有一个"SE 句柄",这时我们按CTRL+G,输入SE 句柄前的地址!
6:按F2下断点!然后按SHIFT+F9来到断点处!
7:去掉断点,按F8慢慢向下走!
8:到达程序的OEP!
方法六:模拟跟踪法
1:先试运行,跟踪一下程序,看有没有SEH暗桩之类
2:ALT+M打开内存镜像,找到(包含=SFX,imports,relocations)
内存镜像,项目30
地址=0054B000
大小=00002000 (8192.)
Owner=check 00400000
区段=.aspack
包含=SFX,imports,relocations
类型=Imag 01001002
访问=R
初始访问=RWE
3:地址为0054B000,如是我们在命令行输入tc eip<0054B000,回车,正在跟踪ing。

Btw:大家在使用这个方法的时候,要理解他是要在怎么样的情况下才可以使用
方法七:“SFX”法
1:设置OD,忽略所有异常,也就是说异常选项卡里面都打上勾
2:切换到SFX选项卡,选择“字节模式跟踪实际入口(速度非常慢)”,确定。

3:重载程序(如果跳出是否“压缩代码?”选择“否”,OD直接到达OEP)
Btw:这种方法不要滥用得好,锻炼能力为妙。

【UXP练手】【附件upx.exe】
---------------------------------------------------------------------------------
黑鹰红客基地动画教程
黑鹰红客基地
专业的红客安全技术培训基地
多抽出一分钟时间学习.让你的生命更加精彩.
注:10元的动画免费对外公布.20.50.100.200元的动画只提供给本站的vip会员做为辅助教材.
---------------------------------------------------------------------------------
手脱UPX的四种方法
首先,查壳,使用PEID是UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo,使用FI为UPX v1.08 接下来用OD载入,提示为“压缩代码是否继续分析”,我们选择否
我在这里介绍几种方法,请看我的操作。

方法1:单步跟踪(最常见的方法)
0040E8C0 N> 60 pushad //停在这里了,我们F8单步
0040E8C1 BE 15B04000 mov esi,NO TEPAD.0040B015
0040E8C6 8DBE EB5FFFFF lea edi,dword ptr ds:[esi+FFFF>
0040E8CC 57 push edi
0040E8CD 83CD FF or ebp,FFFFFFFF
0040E8D0 EB 10 jmp short NOTEPAD.0040E8E2 //跳
》》》》
0040E8E2 8B1E mov ebx,dword ptr ds:[esi]//跳到这里
0040E8E4 83EE FC sub esi,-4
0040E8E7 11DB adc ebx,ebx
0040E8E9 ^ 72 ED jb short NOTEPAD.0040E8D8 //这里要往回跳了
0040E8EB B8 01000000 mov eax,1 //F4,然后继续F8
0040E8F0 01DB add ebx,ebx
0040E8F2 75 07 jnz short NOTEPAD.0040E8FB //跳
》》》》
0040E8FB 11C0 adc eax,eax //来到这里,F8继续
0040E8FD 01DB add ebx,ebx
0040E8FD 01DB add ebx,ebx
0040E8FF ^ 73 EF jnb short NOTEPAD.0040E8F0
0040E901 75 09 jnz short NO TEPAD.0040E90C //跳
》》》》
0040E90C 31C9 xor ecx,ecx //跳到这里,继续F8
0040E90E 83E8 03 sub eax,3
0040E90E 83E8 03 sub eax,3
0040E911 72 0D jb short NOTEPAD.0040E920 //跳
》》》》
0040E920 01DB add ebx,ebx //跳到这里,继续F8
0040E922 75 07 jnz short NO TEPAD.0040E92B //跳
》》》
0040E92B 11C9 adc ecx,ecx //跳到了这里,继续F8
0040E92D 01DB add ebx,ebx
0040E92F 75 07 jnz short NOTEPAD.0040E938 //跳
》》》
0040E938 11C9 adc ecx,ecx //跳到这里,继续F8
0040E93A75 20 jnz short NO TEPAD.0040E95C //跳
》》》》
0040E95C 81FD 00F3FFFF cmp ebp,-0D00 //来到这,继续F8 0040E962 83D1 01 adc ecx,1
0040E965 8D142F lea edx,dword ptr ds:[edi+ebp]
0040E968 83FD FC cmp ebp,-4
0040E96B 76 0F jbe short NOTEPAD.0040E97C
0040E96D 8A02 mov al,byte ptr ds:[edx]
0040E96F 42 inc edx
0040E970 8807 mov byte ptr ds:[edi],al
0040E972 47 inc edi
0040E973 49 dec ecx
0040E974 ^ 75 F7 jnz short NO TEPAD.0040E96D//要往回跳了0040E976 ^ E9 63FFFFFF jmp NOTEPAD.0040E8DE
0040E97B 90 nop
0040E97C 8B02 mov eax,dword ptr ds:[edx]// F4,继续F8 0040E97E 83C2 04 add edx,4
0040E981 8907 mov dword ptr ds:[edi],eax
0040E983 83C7 04 add edi,4
0040E986 83E9 04 sub ecx,4
0040E989 ^ 77 F1 ja short NO TEPAD.0040E97C
0040E98B 01CF add edi,ecx
0040E98D ^ E9 4CFFFFFF jmp NOTEPAD.0040E8DE //要往回跳了。

0040E992 5E pop esi //这里F4,继续F8
0040E993 89F7 mov edi,esi
0040E995 B9 DD000000 mov ecx,0DD
0040E99A8A07 mov al,byte ptr ds:[edi]
0040E99C 47 inc edi
0040E99D 2C E8 sub al,0E8
0040E99F 3C 01 cmp al,1
0040E9A1 ^ 77 F7 ja short NO TEPAD.0040E99A//要往回跳了0040E9A3 803F 00 cmp byte ptr ds:[edi],0 //这里F4,继续F8 0040E9A6 ^ 75 F2 jnz short NO TEPAD.0040E99A//要往回跳了0040E9A8 8B07 mov eax,dword ptr ds:[edi] // F4,继续F8 0040E9AA8A5F 04 mov bl,byte ptr ds:[edi+4]
0040E9AD 66:C1E8 08 shr ax,8
0040E9B1 C1C0 10 rol eax,10
0040E9B4 86C4 xchg ah,al
0040E9B6 29F8 sub eax,edi
0040E9B8 80EB E8 sub bl,0E8
0040E9BB 01F0 add eax,esi
0040E9BD 8907 mov dword ptr ds:[edi],eax
0040E9BF 83C7 05 add edi,5
0040E9C2 89D8 mov eax,ebx
0040E9C4 ^ E2 D9 loopd short NO TEPAD.0040E99F //要往回跳了0040E9C6 8DBE 00C00000 lea edi,dword ptr ds:[esi+C000> //F4继续F8
0040E9CC 8B07 mov eax,dword ptr ds:[edi]
0040E9CE 09C0 or eax,eax
0040E9D0 74 3C je short NO TEPAD.0040EA0E
0040E9D2 8B5F 04 mov ebx,dword ptr ds:[edi+4]
0040E9D5 8D8430 14EC00>lea eax,dword ptr ds:[eax+esi+>
0040E9DC 01F3 add ebx,esi
0040E9DE 50 push eax
0040E9DF 83C7 08 add edi,8
0040E9E2 FF96 A0EC0000 call dword ptr ds:[esi+ECA0]
0040E9E8 95 xchg eax,ebp
0040E9E9 8A07 mov al,byte ptr ds:[edi]
0040E9EB 47 inc edi
0040E9EC 08C0 or al,al
0040E9EE ^ 74 DC je short NOTEPAD.0040E9CC
0040E9F0 89F9 mov ecx,edi
0040E9F2 57 push edi
0040E9F3 48 dec eax
0040E9F4 F2:AE repne scas byte ptr es:[edi]
0040E9F6 55 push ebp
0040E9F7 FF96 A4EC0000 call dword ptr ds:[esi+ECA4]
0040E9FD 09C0 or eax,eax
0040E9FF 74 07 je short NOTEPAD.0040EA08
0040EA01 8903 mov dword ptr ds:[ebx],eax
0040EA03 83C3 04 add ebx,4
0040EA06 ^ EB E1 jmp short NO TEPAD.0040E9E9 //要往回跳了0040EA08 FF96 A8EC0000 call dword ptr ds:[esi+ECA8]
0040EA0E 61 popad //这里F4,继续F8 0040EA0F - E9 B826FFFF jmp NOTEPAD.004010CC //在这里直接跳到了OEP 》》》》
004010CC 55 push ebp //来到这里,在此dump
004010CD 8BEC mov ebp,esp
004010CF 83EC 44 sub esp,44
其他操作请看动画
方法2:ESP定律手动脱壳
0040E8C0 N> 60 pushad //停在这里了,我们F8单步
0040E8C1 BE 15B04000 mov esi,NO TEPAD.0040B015 //ESP突现,0012FFA4 dd 0012FFA4回车,断点--硬件访问--WORD,F9运行,直接来到这里
0040EA0F - E9 B826FFFF jmp NOTEPAD.004010CC //来到这单步就到了OEP
不详述,和方法一一样了
方法3:内存镜像法
(由于经过了方法2和方法3大家都熟悉了代码,我在这里就不写了)
ALT+M打开内存
找到.rsrc,F2下断,F9运行。

ALT+M打开内存
找到UPX0,F2下断,F9运行
0040EA01 8903 mov dword ptr ds:[ebx],eax//来到这,F8继续
0040EA03 83C3 04 add ebx,4
0040EA06 ^ EB E1 jmp short NO TEPAD.0040E9E9
0040EA08 FF96 A8EC0000 call dword ptr ds:[esi+ECA8]
0040EA0E 61 popad
0040EA0F - E9 B826FFFF jmp NOTEPAD.004010CC
其他的就不说了~请看动画。

方法4:捷径
直接CTRL+F,输入popad
0040EA0E 61 popad//F2下断,F9运行,F2取消断点,单步F8
0040EA0F - E9 B826FFFF jmp NOTEPAD.004010CC
---------------------------------------------------------------------------------
【aspack脱壳练手】
【AsPack-KillBox.exe】
【AsPack-登陆器.exe】
“KillBox”用PEID查得是ASPack 2.12 -> Alexey Solodovnikov
1、单步跟踪法
2、ESP定律法
00424001 K> 60 pushad //入口,看到关键提示大家就应该惊醒了,单步F8 00424002 E8 03000000 call KillBox.0042400A //到这里,注意寄存器提示ESP=0012FFA4 00424007 - E9 EB045D45 jmp 459F44F7
0042400C 55 push ebp
0042400D C3 retn
命令行下断hr 0012FFA4,F9运行!
3、内存镜像法
首先Alt+M打开内存镜像
找到.rsrc区段
内存映射,项目29
地址=004D3000
大小=00241000 (2363392.)
宿主=登陆器00400000
区段=.rsrc //F2下断,Shif t+F9运行!
包含=resources
类型=Imag 01001002
访问=R
初始访问=R WE
继续
内存映射,项目22
地址=00401000
大小=000BB000 (765952.)
宿主=登陆器00400000
区段=CODE //F2下断,Shif t+F9运行!直接到达OEP!
包含=code
类型=Imag 01001002
访问=R
初始访问=R WE
********************************************************************************************
"登陆器"其实是一个ASPack的变形壳
今天我们使用2种方法快速搞定它!
一、ESP定律法
二、内存断点法
****************************************************************************************************** 一、ESP定律法
OD载入程序
00717082 登陆> 60 pushad //入口,看到关键提示大家就应该惊醒了,单步F8
00717083 E8 00000000 call 登陆器.00717088 //到这里,注意寄存器提示ESP=0012FFA4
00717088 5D pop ebp
00717089 81ED B6A4450>sub ebp,登陆器.0045A4B6
0071708F 8D BD B0A4450>lea edi,dword ptr ss:[ebp+45A4B0]
00717095 81EF 8200000>sub edi,82
命令行下断hr 0012FFA4,F9运行!
00717374 - FFE0 jmp eax ; 登陆器.00714001 //到这里,单步F8
00717376 42 inc edx
00717377 4B dec ebx
00717378 2E:44 inc esp
0071737A41 inc ecx
00714001 60 pushad //来到这里,仍然是关键提示,单步F8
00714002 E8 03000000 call 登陆器.0071400A//到这里,ESP=0012FFA4(和上面的一样),由于上一个硬件断点没删除所以到这里我们直接F9就可以了!
00714007 - E9 EB045D45 jmp 45CE44F7
0071400C 55 push ebp
0071400D C3 retn
007143B0 /75 08 jnz short 登陆器.007143BA //到这里!删除断点,F8
007143B2 |B8 01000000 mov eax,1
007143B7 |C2 0C00 retn 0C
007143BA\68 D8BD4B00 push 登陆器.004BBDD8
007143BF C3 retn //返回到004BBDD8 (登陆器.004BBDD8),程序的OEP!
004BBDD8 55 push ebp //OEP,看入口代码特征就知道程序是Delphi写的
004BBDD9 8BEC mov ebp,esp
004BBDDB 83C4 F0 add esp,-10
004BBDDE B8 98B94B00 mov eax,登陆器.004BB998
004BBDE3 E8 BCA5F4FF call 登陆器.004063A4
004BBDE8 A1 7CE84B00 mov eax,dword ptr ds:[4BE87C]
004BBDED 8B00 mov eax,dword ptr ds:[eax]
004BBDEF E8 1073FAFF call 登陆器.00463104
在此LordPE完全Dump!请出Import来修复下!OEP处填BBDD8--自动搜索IA T--获取输入表(全部有效)--FixDump!
测试正常运行,用PEID查看是Borland Delphi 6.0 - 7.0写的
好了,ESP定律法就到这里,下面介绍的是内存断点法
******************************************************************************************************
二、内存断点法
重新载入下吧,来实行我们的内存断点法
首先Alt+M打开内存镜像
找到.rsrc区段
内存映射,项目29
地址=004D3000
大小=00241000 (2363392.)
宿主=登陆器00400000
区段=.rsrc //F2下断,Shif t+F9运行!
包含=resources
类型=Imag 01001002
访问=R
初始访问=R WE
77F764F3 66:8B50 0C mov dx,word ptr ds:[eax+C] //来到这里,我们不用管它
77F764F7 8995 6CFFFFF>mov dword ptr ss:[ebp-94],edx
77F764FD8D70 10 lea esi,dword ptr ds:[eax+10]
77F76500 89B5 68FFFFF>mov dword ptr ss:[ebp-98],esi
77F76506 66:F747 02 F>test word ptr ds:[edi+2],0FFFF
再次Alt+M打开内存镜像
找到.code区段或者是.text区段(因为编写语言不一样所以区段名称的一样的,一般是00401000段)
内存映射,项目22
地址=00401000
大小=000BB000 (765952.)
宿主=登陆器00400000
区段=CODE //F2下断,Shif t+F9运行!直接到达OEP!
包含=code
类型=Imag 01001002
访问=R
初始访问=R WE
004BBDD8 55 push ebp //OEP,看入口代码特征就知道程序是Delphi写的
004BBDD9 8BEC mov ebp,esp
004BBDDB 83C4 F0 add esp,-10
004BBDDE B8 98B94B00 mov eax,登陆器.004BB998
004BBDE3 E8 BCA5F4FF call 登陆器.004063A4
004BBDE8 A1 7CE84B00 mov eax,dword ptr ds:[4BE87C]
在此LordPE完全Dump!请出Import来修复下!OEP处填BBDD8--自动搜索IA T--获取输入表(全部有效)--FixDump!测试正常运行,用PEID查看是Borland Delphi 6.0 - 7.0写的
【f sg 脱壳练手】
【f sg 1.33.exe】
【FSG 1.33变形壳.exe】
【FSG 2.0】
【f sg 1.33.exe】
方法一:单步法(忽略所有异常)
方法二:ESP定律(忽略所有异常)
这里没有明显的pushad指令,但是还是满足ESP定理的,单步如下
004103ED 56 push esi
004103EE 96 xchg eax,esi ; f sg_1_33.004001B0
004103EF B2 80 mov dl,0x80
004103F1 A4 movs byte ptr es:[edi],byte ptr ds:[esi]
在xchg eax,esi 处,发现esp寄存器发生变化,这是通过代码变形,使得不用直接使用pushad。

对00112FFC0对应的数据下硬件断点,运行到达这里
0041045A AD lods dword ptr ds:[esi]
0041045B 48 dec eax
0041045C 74 0A je Xf sg_1_33.00410468
0041045E 79 02 jns Xf sg_1_33.00410462
00410460 AD lods dword ptr ds:[esi]
这里撤销硬件断点,单步,很快就可以到OEP了
00410480 /EB 09 jmp Xf sg_1_33.0041048B
00410482 |FE0E dec byte ptr ds:[esi]
00410484 -|0F84 420CFFFF je f sg_1_33.004010CC
0041048A|56 push esi
0041048B \55 push ebp
这里的判断ds:[esi]里面的值,如果等于0,就跳装到4010CC,这个就是OEP了,这是这个壳的一个特点,熟悉一下就行。

(dump的时候断点要取出,不然断点出dum p下来的是int 3)
方法三:模拟跟踪法(不忽略内存异常)[首先忽略所有异常,F9试运行一下,遇到异常,好我们现在试下不忽略内存异常,(这是一个自己尝试的过程目的就是是要找到好多调试设置!),再试运行,OK,程序运行了。

要的就是他,模拟跟踪法是需要在没有异常的情况下才能够完全运用的]
ALT+M,打开内存镜像,
内存镜像,项目15
地址=0040C000
大小=00005000 (20480.)
Owner=f sg_1_33 00400000
区段=
包含=SFX,imports,resources
类型=Imag 01001002
访问=R
初始访问=RWE
下命令行tc eip<0040c000,enter。

正在跟踪之中。

有时候需要点时间等~
【FSG 1.33变形壳.exe】
单步几步,ESP=0012FFC0的时候,跟随到数据窗口中,下硬件访问断点,在来到的地方单步到这里
这段循环跟踪一下,就知道是处理IA T表的00430801 /EB 09 jmp short 0043080C这句一直得不到运行,直接下断点让其运行,在单步几步,就运行到这里了
00402666 55 push ebp ; COMCTL32.#241
00402667 8BEC mov ebp, esp
00402669 6A FF push -1
0040266B 68 00674100 push 00416700
00402670 68 FC504000 push 004050FC
00402675 64:A1 00000000 mov eax, dword ptr f s:[0]
0040267B 50 push eax
0040267C 64:8925 0000000>mov dword ptr f s:[0], esp
00402683 83EC 58 sub esp, 58
00402686 53 push ebx
00402687 56 push esi
00402688 57 push edi
00402689 8965 E8 mov dword ptr [ebp-18], esp
0040268C FF15 14524100 call dword ptr [415214] ; kernel32.GetV ersion
很明显的VC入口特征。

这里就是OEP了
修复的时候发现有个指针是无效的,我们就剪切掉吧。

这时候还是不可以运行。

重新用od导入修复后的文件,发现有一个int 异常,直接nop掉
0040127E 90 nop
0040127F 90 nop
00401280 |> 8D4D E4 lea ecx, dword ptr [ebp-1C]
然后就可以运行了。

【FSG 2.0.exe】
直接用ESP定理,在入口出单步几步,直到
0040015D A4 movs byte ptr es:[edi], byte ptr [esi]
对esp跟踪到数据里面,对对应的数据设置内存断点。

004001C2 AD lods dword ptr [esi]
004001C3 97 xchg eax, edi
004001C4 AD lods dword ptr [esi]
到达这里之后,先删除断点,跟踪几步就到了。

在这个图里面,可以看到jmp dword ptr[ebx+C]一直没有被执行,对其F2,然后F9
可以看到ds:[004133A4]=00401000 (f sg_2_0.00401000),401000刚好是代码段附近的,这里就是OEP了,跟随进去。

00401000 2BDB sub ebx, ebx ; f sg_2_0.00413398 00401002 B8 4CA04000 mov eax, 0040A04C
00401007 C700 08000000 mov dword ptr [eax], 8
0040100D C740 04 FF00000>mov dword ptr [eax+4], 0FF
这时候用Import REC是无效的,f sg2.0对输入表加密了(或者有hook)
00401015 E8 DC620000 call 004072F6 ; jmp 到COMCTL32.InitCommonControlsEx
看这一句,跟随进去,马上看到HOOK表了
0040723C - FF25 54904000 jmp dword ptr [409054] ; kernel32.CreateFileMappingA 00407242 - FF25 50904000 jmp dword ptr [409050]; kernel32.CreateThread ……………………………..
004072F0 - FF25 08904000 jmp dword ptr [409008] ; GDI32.GetObjectA
004072F6 - FF25 00904000 jmp dword ptr [409000] ; COMCTL32.InitCommonControlsEx
跟随进入数据窗口,执行命令d 409060,进入数据窗口,上下翻动,可以看到转存的IA T表
00409000 77184088 園w COMCTL32.InitCommonControlsEx …………………………………………………………………………
0040908C 77D24A4E NJ襴USER32.EndDialog
00409090 7FFFFFFF •
00409094 7632309F ?2v comdlg32.GetOpenFileNameA
00409098 7FFFFFFF •
计算一下便宜,填进去就可以了,IA T RV A=9000,size=98
把无效指针剪切出来就行了
【PECompact 】
【PECompact 1.84.exe】一个ESP定理搞定
【PECompact 2.55.EXE】
这个壳一开始就给你弄了个SHE异常
FS寄存器指向当前活动线程的TEB结构(线程结构)
偏移说明
000 指向SEH链指针
004 线程堆栈顶部
008 线程堆栈底部
00C SubSystemTib
010 FiberData
014 ArbitraryUserPointer
018 FS段寄存器在内存中的镜像地址
020 进程PID
024 线程ID
02C 指向线程局部存储指针
030 PEB结构地址(进程结构)
034 上个错误号
参考</archive/index.php?t-100224.html>
所以这里ESP不好用了。

这里用了前人一个套路(最不喜欢套路了,没自己弄明白)
设置Ollydbg忽略所有的异常选项。

od载入
01001000 N> B8 90BA0101 mov eax,NOTEPAD.0101BA90
01001005 50 push eax ; NO TEPAD.0101BA90 01001006 64:FF35 0000000>push dword ptr f s:[0]
0100100D 64:8925 0000000>mov dword ptr f s:[0],esp
01001014 33C0 xor eax,eax
01001016 8908 mov dword ptr ds:[eax],ecx
01001018 50 push eax
下断点:BP V irtualFree。

中断后,取消断点,Alt+F9。

002F00C0 58 pop eax //返回到这
002F00C1 EB 03 jmp short 002F00C6
002F00C3 33C0 xor eax,eax
002F00C5 48 dec eax
002F00C6 5D pop ebp
002F00C7 5B pop ebx
然后,ctrl+F ,查找push 8000(特征码)。

002F093E 03C7 add eax,edi
002F0940 68 00800000 push 8000 //这里
002F0945 6A 00 push 0
002F0947 FFB5 951C0010 push dword ptr ss:[ebp+10001C95]
002F094D FF10 call dword ptr ds:[eax]
002F094F 8B46 0C mov eax,dword ptr ds:[esi+C]
002F0952 03C7 add eax,edi
002F0954 5D pop ebp
002F0955 5E pop esi
002F0956 5F pop edi
002F0957 5B pop ebx
002F0958 C3 retn //此处f2 ,下断
F9 ,运行,此时断了。

单步f8,来到
0101BB3D 8985 C8120010 mov dword ptr ss:[ebp+100012C8],eax ; NOTEPAD.0100739D 0101BB43 8BF0 mov esi,eax
0101BB45 59 pop ecx
0101BB46 5A pop edx
0101BB47 EB 0C jmp short NO TEPAD.0101BB55
0101BB49 03CA add ecx,edx
0101BB4B 68 00800000 push 8000
0101BB50 6A 00 push 0
0101BB52 57 push edi
0101BB53 FF11 call dword ptr ds:[ecx]
0101BB55 8BC6 mov eax,esi
0101BB57 5A pop edx
0101BB58 5E pop esi
0101BB59 5F pop edi
0101BB5A59 pop ecx
0101BB5B 5B pop ebx
0101BB5C 5D pop ebp
0101BB5D FFE0 jmp eax //跳到oep
0101BB5F 0000 add byte ptr ds:[eax],al
0101BB61 0000 add byte ptr ds:[eax],al
0100739D 6A 70 push 70 //OEP
0100739F 68 98180001 push PECompac.01001898
010073A4 E8 BF010000 call PECompac.01007568
010073A9 33DB xor ebx,ebx
010073AB 53 push ebx
010073AC 8B3D CC100001 mov edi,dword ptr ds:[10010CC]; kernel32.GetModuleHandleA 010073B2 FFD7 call edi
010073B4 66:8138 4D5A cmp word ptr ds:[eax],5A4D
010073B9 75 1F jnz short PECompac.010073DA
下面就是DUMP进程,ImportREC修复输入表了。

【北斗nspack】
【北斗1.4.exe】ESP定理直接搞定
【北斗 3.4.exe】ESP定理直接搞定
【PEncrypt 4.0】
【PEncrypt V4.0.EXE】最后一次异常法
这是一个比较少见的可,最后一次异常发搞定他
两次shif t + F9,到这里
0040CCD2 4B dec ebx
0040CCD3 6F outs dx,dword ptr es:[edi]
0040CCD4 6368 69 arpl word ptr ds:[eax+69],bp
0040CCD7 8B4424 04 mov eax,dword ptr ss:[esp+4]
0040CCDB 8B00 mov eax,dword ptr ds:[eax]
这时候看堆栈
在SE句柄上面下断点40CCD7,再次shif t+F9,这时候继续单步,很快就到OEP了。

用LoadPE脱壳,然后Import REC修复,这时候还是不可以运行,重新启动LoadPE,设置如下:
然后修复一下,就可以运行了。

这是一个比较陌生的壳,要多种方法不断尝试,特别是SHE是特别麻烦的事。

【SFX方法脱壳】
直接设置这里,可以对80%压缩壳起作用,部分加密壳也可以,不过对于acprotect ,asprotect等强壳无效【yoda's cryptor 1.2脱壳】
【Y oda's Crypter v1.2.98.E.exe】ESP无效了,两次内存断点可以搞定,先对资源段下断点,然后对代码段下断点,就可以到达OEP,IA T修复需要用Import REC的等级修复。

如图:
<注:尽量使用没有太多插件的od,不然有时候od会出现一些异常,如果用跟踪等级3,可以每次只选几个,反复进行,就不会死机了>
【tElock 脱壳】
【tElock.exe】
第一种方法:最后一次异常法
最后一次异常法,一共有21次异常(不断shif t+F9)知道运行起来,重新载入od,20次忽略异常,就可以到最后一次异常处
看堆栈里面的内容,到0040D7FB出下断点,shif t+F9,运行到这里,所有的SHE都跳过了,然后就一直单步,如果有pushad 或者popad这两个指令,特别关注一下,很快就可以到OEP。

一直运行到这里,跟随,到达OEP
0040D7AF 61 popad
0040D7B0 - FF6424 D0 jmp dword ptr [esp-30] ; tElock.004010CC
接着就是修复IA T了,tElock的IA T是比较恶心的,记得很多人说过Import REC在用lever 3的时候会死机,其实这个和od有关,这时候如果直接打开一个新的tElock.exe,然后Import REC载入的进程不要和OD公用一个,这个问题集就不存在了,如果还是会死,那么就几个几个修复,最后有四个无效的,直接剪切掉就行了。

【PETI TE脱壳】
【PETI TE.98.E.exe】
这个壳可以用ESP定理,但是这里有点不一样
pushf w
pushad
对应
popad
pushf w
运行到这里pushad的就结束了,查看ESP,下内存断点。

搞定
【PEtite 2.x.exe】同上ESP定理搞定。

【ESP定律OR 两次内存断点配合寻找OEP】
一.准备知识
在我们开始讨论ESP定律之前,我先给你讲解一下一些简单的汇编知识。

1.call
这个命令是访问子程序的一个汇编基本指令。

也许你说,这个我早就知道了!别急请继续看完。

call真正的意义是什么呢?我们可以这样来理解:
1.向堆栈中压入下一行程序的地址;
2.JMP到call的子程序地址处。

例如:
00401029.E8 DA240A00 call 004A3508
0040102E.5A pop edx
在执行了00401029以后,程序会将0040102E压入堆栈,然后JMP到004A3508地址处!
也就是压入下一个EIP的值
2.RETN
与call对应的就是RETN了。

对于RETN我们可以这样来理解:
1.将当前的ESP中指向的地址出栈;
2.JMP到这个地址。

这个就完成了一次调用子程序的过程。

在这里关键的地方是:如果我们要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RETN这条指令之前,ESP指向的是我们压入栈中的地址。

这也就是著名的“堆栈平衡”原理!
3.狭义ESP定律
ESP定律的原理就是“堆栈平衡”原理。

让我们来到程序的入口处看看吧!
1.这个是加了ASPACK壳的入口时各个寄存器的值!
EAX 00000000
ECX 0012FFB0
EDX 7FFE0304 //堆栈值
EBX 7FFD F000 //堆栈值
ESP 0012FFC4
EBP 0012FFF0
ESI 77F57D70 ntdll.77F57D70
EDI 77F944A8 ntdll.77F944A8
EIP 0040D000 ASPACK.<ModuleEntryPoint>
2.这个是ASPACK壳JMP到OEP后的寄存器的值!
EAX 004010CC ASPACK.004010CC
ECX 0012FFB0
EDX 7FFE0304 //堆栈值
EBX 7FFD F000 //堆栈值
ESP 0012FFC4
EBP 0012FFF0
ESI 77F57D70 ntdll.77F57D70
EDI 77F944A8 ntdll.77F944A8
EIP 004010CC ASPACK.004010CC
呵呵~是不是除了EIP不同以外,eax保存当前OEP值,其他都一模一样啊!
为什么会这样呢?我们来看看
0040D000 A> 60 pushad //注意这里ESP=0012FFC4
0040D001 E8 00000000 call ASPACK.0040D006 //ESP=0012FFA4
PUSHAD就是把所有寄存器压栈!我们在到壳的最后看看:
0040D558 61 popad //ESP=0012FFA4
0040D559 75 08 jnz short ASPACK.0040D563 //注意这里ESP=0012FFC4
也就是说当我们对ESP的0012FFA4下硬件访问断点之后。

当程序要通过堆栈访问这些值
,从而恢复原来寄存器的值,准备跳向苦苦寻觅的OEP的时候,OD帮助我们中断下来。

小结:我们可以把壳假设为一个子程序,当壳把代码解压前和解压后,他必须要做的是遵循堆栈平衡的原理。

因为大家对ESP理解各有异同,但是,大同小异!一般理解可以为:
1、在命令行下断hr esp-4(此时的ESP就是OD载入后当前显示的值)
2、hr ESP(关键标志下一行代码所指示的ESP值(单步通过))
5.总结
现在我们可以轻松的回答一些问题了。

1.ESP定律的原理是什么?
堆栈平衡原理。

2.ESP定律的适用范围是什么?
几乎全部的压缩壳,部分加密壳。

只要是在JMP到OEP后,ESP=0012FFC4的壳,理论上我们都可以使用。

但是在何时下断点避开校验,何时下断OD才能断下来,这还需要多多总结和多多积累。

3.是不是只能下断12FFA4的访问断点?
当然不是,那只是ESP定律的一个体现,我们运用的是ESP定律的原理,而不应该是他的具体数值,不能说12FFA4,或者12FFC0就是ESP定律,他们只是ESP定律的一个应用罢了!
二内存断点
1、要解决的问题是:
1.什么是内存断点?
2 .如何在寻找OEP时使用内存断点。

2、内存断点寻找OEP的原理
i.首先,在OD中内存断点和普通断点(F2下断)是有本质区别的。

内存断点等效于命令bpm,他的中断要用到DR0-DR7的调试寄存器,也就是说OD通过这些D R0-DR7的调试寄存器来判断是否断下普通断点(F2下断)等效于bpx,他是在所执行的代码的当前地址的一个字节修改为CC(int3)。

当程序运行到int3的时候就会产生一个异常,而这个异常将交给OD处理,把这个异常给EIP-1以后,就正好停在了需要的中断的地方(这个根据系统不同会不一样),同时OD在把上面的int3修改回原来的代码。

内存断点分为:内存访问断点,内存写入断点。

我们知道,在程序运行的时候会有3种基本的状态产生:读取-->写入-->执行。

004AE242 A1 00104000 mov eax,dword ptr ds:[004AE24C] //004AE24C处的内存读取
004AE247 A3 00104000 mov dword ptr ds:[004AE24C],eax //004AE24C处的内存写入
004AE24C 83C0 01 add eax,1 //004AE24C处的内存执行
1.当对004AE24C下内存访问断点的时候,可以中断在004AE242也可以中断在004AE247。

2.当对004AE24C下内存写入断点的时候,只能中断在004AE247。

3.当执行004AE24C的时候,只能中断在004AE24C
到这里你可能不明白了,为什么内存访问断点能中断在004AE247这一句对004AE24C的写入,而且还能中断在004AE24C的执行呢?其实很简单,我们只要仔细体会一下“内存访问”这四个字的含义遍可以知道,当我们对004AE24C进行读取的时候需要“访问”他吧,当我对004AE24C进行写入的时候也需要“访问”他吧!!当然我们要执行内存地址004AE24C的代码的时候也是还是要“访问”他的!
所以我们不难得出下面的结论:
1.内存写入中断的地方,一定是也可以用内存访问中断。

2.内存执行的地方,也可以用内存访问中断。

如果这时你认为,那么内存写入岂不是没用了。

呵呵~那我要告诉你当然不是,如果你想快速的准确的定位到004AE247这一行的时候,那么他就大有作用了!
总结一下:内存断点不修改原代码,不会像普通断点那样因为修改代码被程序校验而导致中断失败;对于区段的访问只是区域大了一点,其原理和上面分析的三行代码是一样的。

ii.如何使用内存断点来寻找OEP呢?
要回答这个问题首先要回答这一个问题:壳是如何解压代码的?
正如我们知道的,壳如果要把原来加密或压缩的代码运行起来就必须要解压和解密原来的代码。

而这一个过程我们难道不能将他看做是对代码段(code段)的写入吗?好了,解压完毕了。

我们要从壳代码的区段JMP到原来的代码段的时候,难道不正是对代码段(code段)的执行吗?。

相关文档
最新文档