首页
社区
课程
招聘
[原创]一点脱壳的笔记
发表于: 2012-5-3 01:21 16646

[原创]一点脱壳的笔记

2012-5-3 01:21
16646
笔记.rar

练过手的,常见壳脱壳步骤都做了记录(极大部分百度和一些视频教程),其中以壳脱壳的一些理论有点意思,逆向的学习要停一段时间了,最近人工智能什么的开始期末复习了,忙一下课内。这份东西待续吧。还是有很多壳的,每种壳又N多种anti,幸运的是大部分都有教程,通过模拟重现,再总结为什么这样做,比如为什么ESP定理有效,为什么最后一次异常法可以发挥作用,stolen code怎么跟踪,为什么两次内存断点可以发挥作用,这些东西里面都有提及,不光是模拟前人。估计不是对每个人有用,觉得有用的就扫一眼吧。

对应的练手的程序。


115 下载:http://115.com/file/c2ev3mxh#脱壳笔记.rar

【脱壳一般流程】

查壳(PEID、FI、PE-SCAN)--->寻找OEP(OD)--->脱壳/Dump(LordPE、PeDumper、OD自带的脱壳插件、PETools)--->修复(Import REConstructor)

【工具介绍】

1、查壳
   PEID--功能强大的侦壳工具,自带脱壳插件(但是,效果不怎么样)
   工作原理:核心是userdb.txt(大家看看就完全明白了)[通过壳的入口特征码进行辨认]
   使用方法:可以拖放、也可以把PEID添加到右键菜单里面去

   FI--功能强大的侦壳工具,DOS界面。
   使用方法:可以拖放、可以使用DOS命令行

2、寻找OEP

ollydbg的四个区域

左上角是cpu窗口,分别是地址,机器码,汇编代码,注释;注释添加方便,而且还能即时显示函数的调用结果,返回值.
右上角是寄存器窗口,但不仅仅反映寄存器的状况,还有好多东东;双击即可改变Eflag的值,对于寄存器,指令执行后发生改变的寄存器会用红色突出显示.
cpu窗口下面还有一个小窗口,显示当前操作改变的寄存器状态.
左下角是内存窗口.可以ascii或者unicode两种方式显示内存信息.
右下角的是当前堆栈情况,还有注释啊.

几个经常使用的快捷键

F2:在需要的地方下断点(INT3型断点)
F3:选择打开程序
F4:运行到所选择的那一行
F7:单步进入
F8:单步跟踪
F9:执行程序(运行程序)

其中要特别讲一下3个F9的区别和作用:

根据Ollydbg.hlp的中文翻译

Shift+F9 - 与F9相同,但是如果被调试程序发生异常而中止,调试器会首先尝试执行被调试程序指定的异常处理(请参考忽略Kernel32中的内存非法访问)。

Ctrl+F9 - 执行直到返回,跟踪程序直到遇到返回,在此期间不进入子函数也不更新CPU数据。因为程序是一条一条命令执行的,所以速度可能会慢一些。按Esc键,可以停止跟踪。

Alt+F9 - 执行直到返回到用户代码段,跟踪程序直到指令所属于的模块不在系统目录中,在此期间不进入子函数也不更新CPU数据。因为程序是一条一条执行的,所以速度可能会慢一些。按Esc键,可以停止跟踪。

看这些中文介绍大家可能还不是很明白,用我们通俗的语句来说就是:
Ctrl+F9    运行至retn (一般到了retn之后接上F7返回)
Alt+F9     运行至上层调用的下句
Shift+F9   忽略异常运行

文件:
    1.其中包括该菜单的下部有上次打开的纪录,该纪录保存有上次未清除的断点.
    2.附加.对付那些Anti-Debug程序.先运行程序,再运行od,文件-->附加.

查看:
    1.执行模块(Alt+E),查看程序使用的动态链接库
    2.查看断点.Alt+B

调试:
    1.运行(F9)加载程序后,运行!
    2.暂停(F12)
    3.单步进入(F7)遇见CALL进入!进入该子程序.
    4.单步跳过(F8)遇见CALL不进去!
    5.执行到返回(ALT+F9)就是执行到该子程的返回语句

查看-->文件

二进制文件编辑功能.查看-->文件,打开的文件是二进制显示.选中要改变的机器指令,空格,修改,右击-->保存.

具体的用途在后面的几壳脱壳课程当中将会用到,大家现在理解就行。在后面的操作中学会使用!

其他的一些具体的大家还是要看看OD的中文帮助的

3、Dump
OD自带的脱壳插件--到达OEP之后右键。。。
LordPE、PeDumper--选择所调试的进程--右键--完整脱壳

4、修复
Import REConstructor 1.6

【壳的介绍】

壳出于程序作者想对程序资源压缩、注册保护的目的,把壳分为压缩壳和加密壳两种
UPX ASPCAK TELOCK PELITE NSPACK ...
ARMADILLO ASPROTECT ACPROTECT EPE SVKP ...
顾名思义,压缩壳只是为了减小程序体积对资源进行压缩,加密壳是程序输入表等等进行加密保护。当然加密壳的保护能力要强得多!

【常见的脱壳方法】
  
预备知识

1.PUSHAD (压栈) 代表程序的入口点,
2.POPAD (出栈) 代表程序的出口点,与PUSHAD想对应,一般找到这个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下断,Shift+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】
---------------------------------------------------------------------------------
黑鹰红客基地动画教程
黑鹰红客基地www.3800cc.com
专业的红客安全技术培训基地
多抽出一分钟时间学习.让你的生命更加精彩.
注: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,NOTEPAD.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 NOTEPAD.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 NOTEPAD.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
0040E93A     75 20         jnz short NOTEPAD.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 NOTEPAD.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 NOTEPAD.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
0040E99A     8A07          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 NOTEPAD.0040E99A   //要往回跳了
0040E9A3     803F 00       cmp byte ptr ds:[edi],0   //这里F4,继续F8
0040E9A6   ^ 75 F2         jnz short NOTEPAD.0040E99A   //要往回跳了
0040E9A8     8B07          mov eax,dword ptr ds:[edi]  // F4,继续F8
0040E9AA     8A5F 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 NOTEPAD.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 NOTEPAD.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 NOTEPAD.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,NOTEPAD.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 NOTEPAD.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下断,Shift+F9运行!
包含=resources
类型=Imag 01001002
访问=R
初始访问=RWE

继续

内存映射,项目 22
地址=00401000
大小=000BB000 (765952.)
宿主=登陆器   00400000
区段=CODE //F2下断,Shift+F9运行!直接到达OEP!
包含=code
类型=Imag 01001002
访问=R
初始访问=RWE
********************************************************************************************
"登陆器"其实是一个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      8DBD 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
0071737A      41           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--自动搜索IAT--获取输入表(全部有效)--FixDump!

测试正常运行,用PEID查看是Borland Delphi 6.0 - 7.0写的

好了,ESP定律法就到这里,下面介绍的是内存断点法
******************************************************************************************************
二、内存断点法

重新载入下吧,来实行我们的内存断点法

首先Alt+M打开内存镜像
找到.rsrc区段

内存映射,项目 29
地址=004D3000
大小=00241000 (2363392.)
宿主=登陆器   00400000
区段=.rsrc   //F2下断,Shift+F9运行!
包含=resources
类型=Imag 01001002
访问=R
初始访问=RWE

77F764F3      66:8B50 0C   mov dx,word ptr ds:[eax+C]  //来到这里,我们不用管它
77F764F7      8995 6CFFFFF>mov dword ptr ss:[ebp-94],edx
77F764FD      8D70 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下断,Shift+F9运行!直接到达OEP!
包含=code
类型=Imag 01001002
访问=R
初始访问=RWE

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--自动搜索IAT--获取输入表(全部有效)--FixDump!

测试正常运行,用PEID查看是Borland Delphi 6.0 - 7.0写的

【fsg 脱壳练手】
【fsg 1.33.exe】
【FSG 1.33变形壳.exe】
【FSG 2.0】

【fsg 1.33.exe】

方法一:单步法(忽略所有异常)

方法二:ESP定律(忽略所有异常)
这里没有明显的pushad指令,但是还是满足ESP定理的,单步如下

004103ED    56              push esi
004103EE    96              xchg eax,esi                             ; fsg_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 Xfsg_1_33.00410468
0041045E    79 02           jns Xfsg_1_33.00410462
00410460    AD              lods dword ptr ds:[esi]

这里撤销硬件断点,单步,很快就可以到OEP了
00410480   /EB 09           jmp Xfsg_1_33.0041048B
00410482   |FE0E            dec byte ptr ds:[esi]
00410484  -|0F84 420CFFFF   je fsg_1_33.004010CC
0041048A   |56              push esi
0041048B   \55              push ebp

这里的判断ds:[esi]里面的值,如果等于0,就跳装到4010CC,这个就是OEP了,这是这个壳的一个特点,熟悉一下就行。
(dump的时候断点要取出,不然断点出dump下来的是int 3)

方法三:模拟跟踪法(不忽略内存异常)[首先忽略所有异常,F9试运行一下,遇到异常,好我们现在试下不忽略内存异常,(这是一个自己尝试的过程目的就是是要找到好多调试设置!),再试运行,OK,程序运行了。。要的就是他,模拟跟踪法是需要在没有异常的情况下才能够完全运用的]

ALT+M,打开内存镜像,
内存镜像,项目 15
地址=0040C000
大小=00005000 (20480.)
Owner=fsg_1_33 00400000
区段=
包含=SFX,imports,resources
类型=Imag 01001002
访问=R
初始访问=RWE

下命令行tc eip<0040c000,enter。正在跟踪之中。。。。有时候需要点时间等~

【FSG 1.33变形壳.exe】
单步几步,ESP=0012FFC0的时候,跟随到数据窗口中,下硬件访问断点,在来到的地方单步到这里

这段循环跟踪一下,就知道是处理IAT表的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 fs:[0]
0040267B    50              push    eax
0040267C    64:8925 0000000>mov     dword ptr fs:[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.GetVersion

很明显的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 (fsg_2_0.00401000),401000刚好是代码段附近的,这里就是OEP了,跟随进去。
00401000    2BDB            sub     ebx, ebx                               ; fsg_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是无效的,fsg2.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,进入数据窗口,上下翻动,可以看到转存的IAT表
00409000  77184088  園w   COMCTL32.InitCommonControlsEx
…………………………………………………………………………
0040908C  77D24A4E  NJ襴   USER32.EndDialog
00409090  7FFFFFFF  
00409094  7632309F  ?2v   comdlg32.GetOpenFileNameA
00409098  7FFFFFFF  

计算一下便宜,填进去就可以了,IAT RVA=9000,size=98

把无效指针剪切出来就行了

【PECompact 】
【PECompact 1.84.exe】一个ESP定理搞定
【PECompact 2.55.EXE】

这个壳一开始就给你弄了个SHE异常
FS寄存器指向当前活动线程的TEB结构(线程结构)偏移 说明000 指向SEH链指针004 线程堆栈顶部008 线程堆栈底部00C SubSystemTib010 FiberData014 ArbitraryUserPointer018 FS段寄存器在内存中的镜像地址020 进程PID024 线程ID02C 指向线程局部存储指针030 PEB结构地址(进程结构)034 上个错误号
参考< http://bbs.pediy.com/archive/index.php?t-100224.html>

所以这里ESP不好用了。

这里用了前人一个套路(最不喜欢套路了,没自己弄明白)

设置Ollydbg忽略所有的异常选项。
od载入

01001000 N>  B8 90BA0101     mov eax,NOTEPAD.0101BA90
01001005     50              push eax                               ; NOTEPAD.0101BA90
01001006     64:FF35 0000000>push dword ptr fs:[0]
0100100D     64:8925 0000000>mov dword ptr fs:[0],esp
01001014     33C0            xor eax,eax
01001016     8908            mov dword ptr ds:[eax],ecx
01001018     50              push eax

下断点:BP VirtualFree。中断后,取消断点,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 NOTEPAD.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
0101BB5A     59              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】最后一次异常法
这是一个比较少见的可,最后一次异常发搞定他
两次shift + 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,再次shift+F9,这时候继续单步,很快就到OEP了。
用LoadPE脱壳,然后Import REC修复,这时候还是不可以运行,重新启动LoadPE,设置如下:
然后修复一下,就可以运行了。

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

【SFX 方法脱壳】

直接设置这里,可以对80%压缩壳起作用,部分加密壳也可以,不过对于acprotect ,asprotect等强壳无效

【yoda's cryptor 1.2脱壳】

【Yoda's Crypter v1.2.98.E.exe】ESP无效了,两次内存断点可以搞定,先对资源段下断点,然后对代码段下断点,就可以到达OEP,IAT修复需要用Import REC的等级修复。
如图:

<注:尽量使用没有太多插件的od,不然有时候od会出现一些异常,如果用跟踪等级3,可以每次只选几个,反复进行,就不会死机了>

【tElock 脱壳】
【tElock.exe】

第一种方法:最后一次异常法

最后一次异常法,一共有21次异常(不断shift+F9)知道运行起来,重新载入od,20次忽略异常,就可以到最后一次异常处

看堆栈里面的内容,到0040D7FB出下断点,shift+F9,运行到这里,所有的SHE都跳过了,然后就一直单步,如果有pushad或者popad这两个指令,特别关注一下,很快就可以到OEP。
一直运行到这里,跟随,到达OEP

0040D7AF    61              popad
0040D7B0  - FF6424 D0       jmp     dword ptr [esp-30]               ; tElock.004010CC

接着就是修复IAT了,tElock的IAT是比较恶心的,记得很多人说过Import REC在用lever 3的时候会死机,其实这个和od有关,这时候如果直接打开一个新的tElock.exe,然后Import REC载入的进程不要和OD公用一个,这个问题集就不存在了,如果还是会死,那么就几个几个修复,最后有四个无效的,直接剪切掉就行了。

【PETITE脱壳】
【PETITE.98.E.exe】
这个壳可以用ESP定理,但是这里有点不一样

pushfw
pushad
对应
popad
pushfw

运行到这里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 7FFDF000  //堆栈值
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 7FFDF000  //堆栈值
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的原理
首先,在OD中内存断点和普通断点(F2下断)是有本质区别的。

内存断点等效于命令bpm,他的中断要用到DR0-DR7的调试寄存器,也就是说OD通过这些DR0-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段)的执行吗?

理清了上面的关系就好办了,那么如果载入OD后,我们直接对code段下内存访问断点的时候,一定会中断在壳对code段的写入的代码的上面,就像上面的004AE247的这一行。而如果当他把code段的代码全部解压解密完毕了以后,JMP到OEP的时候,我们是不是还可以停在OEP的代码上面呢?而且每按下F9都会中断,因为这时code段在执行中哦!

而如果你还要继续问我为什么一定要到那个地方才可以下断呢?我难道不可以一开始就下断吗?

正入我上面所说的,如果你在前面下断很可能壳对code段还没解压完毕呢,这时如果你不停的按F9,你将会看到OD的下方不断的在提示你,“对401000写入中断”“对401002写入中断”“对401004写入中断”.......如果你不介意按F9到他把正个code段写完的话,我除了同情你的“F9”以外,没什么其他的意见!

  那么我们就没有别更快一点的办法了吗?
  有的!那就是我们呼之欲出的两次内存断点办法。
  怎么理解两次内存断点呢?

让我来做一个假设吧,假设我是一个壳的作者。一个EXE文件的有code段,data段,rsrc段.....依次排列在你的内存空间中,那么我会怎么解码呢?呵呵~我比较笨一点,我会先将code段解码,然后再将data段解压,接着是rsrc段......那么你不难发现,只要你在data断或者rsrc段下内存访问断点,那么中断的时候code段就已经解压完毕了。这时我们再对code段下内存访问断点,不就可以到达OEP了吗?

  这里注意上面虽然下了两次内存访问断点,但是本质是不一样的,目的也是不一样的。

1.对data段下内存访问断点而中断是因为内存写入中断,目的是断在对对data段的解压时,这时壳要对data段写数据,但是code段已经解压 完毕。
2.对code段下内存访问断点而中断是因为内存执行中断,目的当然就是寻找OEP了。

总结一下:如果我们知道壳在什么地方对code段解压完毕我们就可以使用内存断点,找到OEP。如果不知道,那么我们就依靠2次内存断点去找,如果还不行就用多次内存断点。总之明白了原理在多次的内存断点其实都一样。从这个过程中我们了解的是壳在对区段解码的顺序!

【附加数据处理方法】
【Overlay.exe】
ESP定理马上可以找到OEP
资源需要修复

算出文件的结尾开始地址:00000400+0000C600=0000CA00,把后面的数据完全复制黏贴在新的文件上面就行了。

【自校验的去除】脱壳之后启动之后会自动退出,重新载入分析一下就可以了,技巧是createfile下断点。

【EncryptPE】【反外挂服务器.exe】
忽略所有异常,ESP定理,不过异常的种类比OD配置的多一些,前人的经验,多了如下异常:

这些异常还不是很清楚ANTI是如何触发的,不过忽略之后确实有用。OEP一下子就找到了,然后修复一下数据,搞定。

【Armadillo 1.xx - 2.xx 单线程】
【XDeskWeather】
*******************************************************************************************
1、1.xx--2.xx&单线程&标准方式==========》目标程序“XDeskWeather 3.6(桌面天气秀)”

现在任务管理器中查看是否双进程
*******************************************************************************************
方法:2次断点法,即是:
      bp GetModuleHandleA/he GetModuleHandleA/bp GetModuleHandleA+5/he GetModuleHandleA+5
      bp GetCurrentThreadId
这种断点是为了解决IAT加密,是一种通用技巧。
*******************************************************************************************
OD,载入。。。。。
004FD379 X>/$  55              push ebp  //程序入口
004FD37A   |.  8BEC            mov ebp,esp
004FD37C   |.  6A FF           push -1

下断he GetModuleHandleA,F9运行,注意看堆栈!

7C80B529 k>  8BFF              mov edi,edi     ;ntdll.7C930738 //停在这里
7C80B52B     55                push ebp
7C80B52C     8BEC              mov ebp,esp
7C80B52E     837D 08 00        cmp dword ptr ss:[ebp+8],0

***********************************
每一次F9运行时候,所出现的堆栈情况!
***********************************
0012FF38    004FD441  /CALL 到 GetModuleHandleA 来自 XDeskWea.004FD43B
0012FF3C    00000000  \pModule = NULL
0012FF40    00000000

0012ED48    77F45BB0  /CALL 到 GetModuleHandleA 来自 SHLWAPI.77F45BAA
0012ED4C    77F44FF4  \pModule = "KERNEL32.DLL"
0012ED50    00000001

0012EC88    5D175334  /CALL 到 GetModuleHandleA 来自 COMCTL32.5D17532E
0012EC8C    5D175380  \pModule = "kernel32.dll"
0012EC90    5D1E3AB8  COMCTL32.5D1E3AB8

0012F55C    004F3073  /CALL 到 GetModuleHandleA 来自 XDeskWea.004F306D
0012F560    00000000  \pModule = NULL
0012F564    7C939BA0  返回到 ntdll.7C939BA0 来自 ntdll.7C9399B5

0012C280    00C15331  /CALL 到 GetModuleHandleA 来自 00C1532B  //到这一次的时间缓冲有点大
0012C284    0012C3BC  \pModule = "kernel32.dll"
0012C288    00000002

此时,取消断点,Alt+F9返回!

00C15331     8B0D 60D8C300     mov ecx,dword ptr ds:[C3D860]   //返回到这里
00C15337     89040E            mov dword ptr ds:[esi+ecx],eax
00C1533A     A1 60D8C300       mov eax,dword ptr ds:[C3D860]
00C1533F     393C06            cmp dword ptr ds:[esi+eax],edi
00C15342     75 16             jnz short 00C1535A
00C15344     8D85 B4FEFFFF     lea eax,dword ptr ss:[ebp-14C]
00C1534A     50                push eax
00C1534B     FF15 B850C300     call dword ptr ds:[C350B8]      ; kernel32.LoadLibraryA
00C15351     8B0D 60D8C300     mov ecx,dword ptr ds:[C3D860]
00C15357     89040E            mov dword ptr ds:[esi+ecx],eax
00C1535A     A1 60D8C300       mov eax,dword ptr ds:[C3D860]
00C1535F     393C06            cmp dword ptr ds:[esi+eax],edi
00C15362     0F84 AD000000     je 00C15415                      //Magic Jump,改jmp!
00C15368     33C9              xor ecx,ecx
00C1536A     8B03              mov eax,dword ptr ds:[ebx]
00C1536C     3938              cmp dword ptr ds:[eax],edi
00C1536E     74 06             je short 00C15376

此时第一个断点的任务完成!

********************************************************************************************

下断bp GetCurrentThreadId,F9,注意观察堆栈!

7C809737 k>  64:A1 18000000    mov eax,dword ptr fs:[18]   //停在这里
7C80973D     8B40 24           mov eax,dword ptr ds:[eax+24]
7C809740     C3                retn

*************
0012BB40    73391E36  /CALL 到 GetCurrentThreadId 来自 73391E30
0012BB44    00000001
0012BB48    73391C1A  返回到 73391C1A 来自 73391DE2
0012BB4C    73391B60  返回到 73391B60 来自 73391B8C

0012BB20    7339353F  /CALL 到 GetCurrentThreadId 来自 73393539
0012BB24    00000000
0012BB28    734A0470

0012F5A8    00C2CF2D  /CALL 到 GetCurrentThreadId 来自 00C2CF27   //到这一次的时间缓冲有点大
0012F5AC    0012FF2C
0012F5B0    00000000

此时,取消断点,Alt+F9返回!

00C2CF2D     A3 F018C400       mov dword ptr ds:[C418F0],eax   //返回到了这里!
00C2CF32     E8 2487FEFF       call 00C1565B
00C2CF37     6A 00             push 0
00C2CF39     E8 4BD9FEFF       call 00C1A889
00C2CF3E     59                pop ecx
00C2CF3F     E8 7D39FFFF       call 00C208C1
00C2CF44     8BF8              mov edi,eax
00C2CF46     A1 E018C400       mov eax,dword ptr ds:[C418E0]
00C2CF4B     8B48 74           mov ecx,dword ptr ds:[eax+74]
00C2CF4E     3348 5C           xor ecx,dword ptr ds:[eax+5C]
00C2CF51     3308              xor ecx,dword ptr ds:[eax]
00C2CF53     03F9              add edi,ecx
00C2CF55     8B0E              mov ecx,dword ptr ds:[esi]
00C2CF57     85C9              test ecx,ecx
00C2CF59     75 2E             jnz short 00C2CF89
00C2CF5B     8B78 5C           mov edi,dword ptr ds:[eax+5C]
00C2CF5E     E8 5E39FFFF       call 00C208C1
00C2CF63     8B0D E018C400     mov ecx,dword ptr ds:[C418E0]    ; XDeskWea.0051F258
00C2CF69     FF76 14           push dword ptr ds:[esi+14]
00C2CF6C     8B51 74           mov edx,dword ptr ds:[ecx+74]
00C2CF6F     FF76 10           push dword ptr ds:[esi+10]
00C2CF72     33D7              xor edx,edi
00C2CF74     3311              xor edx,dword ptr ds:[ecx]
00C2CF76     FF76 0C           push dword ptr ds:[esi+C]
00C2CF79     03C2              add eax,edx
00C2CF7B     8B51 78           mov edx,dword ptr ds:[ecx+78]
00C2CF7E     3351 14           xor edx,dword ptr ds:[ecx+14]
00C2CF81     33D7              xor edx,edi
00C2CF83     2BC2              sub eax,edx
00C2CF85     FFD0              call eax
00C2CF87     EB 25             jmp short 00C2CFAE
00C2CF89     83F9 01           cmp ecx,1
00C2CF8C     75 22             jnz short 00C2CFB0
00C2CF8E     FF76 04           push dword ptr ds:[esi+4]
00C2CF91     FF76 08           push dword ptr ds:[esi+8]
00C2CF94     6A 00             push 0
00C2CF96     E8 2639FFFF       call 00C208C1
00C2CF9B     50                push eax
00C2CF9C     A1 E018C400       mov eax,dword ptr ds:[C418E0]
00C2CFA1     8B48 78           mov ecx,dword ptr ds:[eax+78]
00C2CFA4     3348 5C           xor ecx,dword ptr ds:[eax+5C]
00C2CFA7     3348 14           xor ecx,dword ptr ds:[eax+14]
00C2CFAA     2BF9              sub edi,ecx
00C2CFAC     FFD7              call edi   //直接到这下“硬件执行”断点,F9,取消断点,F7进入

004D12D4     55                push ebp   //到这里了,OEP!LordPE-纠正映像-Dump!
004D12D5     8BEC              mov ebp,esp
004D12D7     83C4 F0           add esp,-10
004D12DA     B8 0C0E4D00       mov eax,XDeskWea.004D0E0C
004D12DF     E8 004EF3FF       call XDeskWea.004060E4
004D12E4     A1 B06E4D00       mov eax,dword ptr ds:[4D6EB0]
004D12E9     8B00              mov eax,dword ptr ds:[eax]
004D12EB     E8 08C0F9FF       call XDeskWea.0046D2F8
004D12F0     E8 D7E5FFFF       call XDeskWea.004CF8CC
004D12F5     A1 B06E4D00       mov eax,dword ptr ds:[4D6EB0]
004D12FA     8B00              mov eax,dword ptr ds:[eax]

OD,不要关!打开import--选择进程--OEP输入D12D4--自动搜索IAT--获取输入表--显示无效函数--CUT!

这个技巧使用大部分Armadillo版本

【Armadillo 3.78 - 4.xx】
【Jxt】
【ArmaG3ddon v1.9】支持3.78~ 7.7
任务管理器一看,双进程。

遇到过Armadillo的朋友应该知道,它是有点变态的。。中文意思“穿山甲”,可想而知,是很难脱的。

首先介绍一下Armadillo的一些版本以及保护方式、线程情况吧

A:版本
   1.xx--2.xx
   3.0a--3.61
   3.75
   3.78
   4.x

B:保护方式
   标准方式
   非标准方式======>Armadillo CopyMem-ll +Debug-Blocker

C:线程
   单线程
   双线程

上面三种特征都可以两两组合,或者是三三组合。。变化方式之多,可见一斑!下面我将做下总结!希望能够起到抛砖引玉的作用!
*******************************************************************************************
保护方式判断:如果你用脱标准壳的方法去脱不行的话,那么就很有可能是非标准版啦。
线程的判断:方法1、运行程序,打开系统的任务管理器,看看有几个同名进程咯。
方法2、运行程序,打开LordPE,同样是看看有几个同名进程。一个的话就是单进程,两个就是双进程。
*******************************************************************************************
脱壳前的准备:(*****为了节约时间,我在后面将不做说明了,大家要记住!*****)
1、OD设置忽略所有的异常,用隐藏插件隐藏OD!
2、思想准备:Armadillo对断点的检测非常严格,所以我们在设置断点的时候要尽量去使用“硬件执行”
3、概念准备:使用PEID的Armadillo的版本检测一般没那么准确,我倒是发现fi的版本检测还是要强一些
4、Magic Jump:跳转的跨越段一般比较大!(返回时机一定要对!)
5:返回的时机:1、返回的地址是系统领空
2、Shift+F9过程当中,时间缓冲比较大才停下(得自己体会一下)
*******************************************************************************************
吉祥天传世外挂 1.0.0.1

首先PEID查壳是Armadillo 3.78 -> Silicon Realms Toolworks,其实是4.X的版本,而且是个双线程的标准壳!

下面具体的步骤就不写了,就写一些重点吧!

我是在2000下操作的,不知道在XP下是不是好搞点,呵呵

忽略所有异常,手动添加C000001E,E06D7363异常。隐藏OD!

一、双变单(使程序把自己当成子进程运行)

bp OpenMutexA

Ctrl+G:00401000

00401000      60               pushad
00401001      9C               pushfd
00401002      68 A0FD1200      push 12FDA0                        ; ASCII "44C::DA47D45903"
00401007      33C0             xor eax,eax
00401009      50               push eax
0040100A      50               push eax
0040100B      E8 E694A677      call KERNEL32.CreateMutexA
00401010      9D               popfd
00401011      61               popad
00401012    - E9 8F9FA777      jmp KERNEL32.OpenMutexA

60 9C 68 A0 FD 12 00 33 C0 50 50 E8 71 8D A8 77 9D 61 E9 74 8E A8 77

二、避开Anti

he OutputDebugStringA
中断2次!
选中%s%之类的字符,点右键->二进制->使用00填充

删除此断点!

三、Magic Jump,避开IAT加密

PS:很奇怪的就是用he GetModuleHandleA+5,却找不到Magic Jump!

bp GetModuleHandleA/he GetModuleHandleA

77E80B1A KE>  55               push ebp  //断下,取消这个断点
77E80B1B      8BEC             mov ebp,esp
77E80B1D      837D 08 00       cmp dword ptr ss:[ebp+8],0
77E80B21      75 0E            jnz short KERNEL32.77E80B31  //F2下断,Shift+F9,断下!注意堆栈!
77E80B23      64:A1 18000000   mov eax,dword ptr fs:[18]
77E80B29      8B40 30          mov eax,dword ptr ds:[eax+30]
77E80B2C      8B40 08          mov eax,dword ptr ds:[eax+8]

001292A4    /0012EBB0
001292A8    |01066AC2    返回到 01066AC2 来自 KERNEL32.GetModuleHandleA
001292AC    |0107BD6C    ASCII "kernel32.dll"
001292B0    |0107DDAC    ASCII "VirtualAlloc"

001292A4    /0012EBB0
001292A8    |01066ADF    返回到 01066ADF 来自 KERNEL32.GetModuleHandleA
001292AC    |0107BD6C    ASCII "kernel32.dll"
001292B0    |0107DDA0    ASCII "VirtualFree"

00129008    /001292A8
0012900C    |01055A99    返回到 01055A99 来自 KERNEL32.GetModuleHandleA
00129010    |0012915C    ASCII "kernel32.dll"  //取消断点,返回!

01055A99      8B0D 6C500801    mov ecx,dword ptr ds:[108506C]  //返回到这里!
01055A9F      89040E           mov dword ptr ds:[esi+ecx],eax
01055AA2      A1 6C500801      mov eax,dword ptr ds:[108506C]
01055AA7      391C06           cmp dword ptr ds:[esi+eax],ebx
01055AAA      75 16            jnz short 01055AC2
01055AAC      8D85 B4FEFFFF    lea eax,dword ptr ss:[ebp-14C]
01055AB2      50               push eax
01055AB3      FF15 B8620701    call dword ptr ds:[10762B8]        ; KERNEL32.LoadLibraryA
01055AB9      8B0D 6C500801    mov ecx,dword ptr ds:[108506C]
01055ABF      89040E           mov dword ptr ds:[esi+ecx],eax
01055AC2      A1 6C500801      mov eax,dword ptr ds:[108506C]
01055AC7      391C06           cmp dword ptr ds:[esi+eax],ebx
01055ACA      0F84 2F010000    je 01055BFF //Magic Jump,改jmp!
01055AD0      33C9             xor ecx,ecx
01055AD2      8B07             mov eax,dword ptr ds:[edi]
01055AD4      3918             cmp dword ptr ds:[eax],ebx
01055AD6      74 06            je short 01055ADE
01055AD8      41               inc ecx
01055AD9      83C0 0C          add eax,0C

往下拉,找如此类似的序列(一个jnz,一个jmp,两个salc/Magic Jump)
也可以这样做:Ctrl+F在当前位置查找命令: salc

01055C0E    ^\0F85 49FEFFFF    jnz 01055A5D
01055C14      EB 03            jmp short 01055C19  //F2下断,Shift+F9,断下!取消断点!
01055C16      D6               salc
01055C17      D6               salc

重要:断下后,记得要撤消Magic Jump处的修改!

为何要这样做?我发现程序在下面会依据原先的代码进行解码,
以前下 硬件断点 操作没有修改原代码,所以解码正确。
而直接修改Magic Jump后改变了原先的代码,导致解码不正确而异常出错!
现在我们在解码以前恢复原先的代码,因此就不会再出错了!

此时,打开内存镜像,在00401000段下断,Shift+F9直达OEP!

01070324      8B0C3A       mov ecx,dword ptr ds:[edx+edi]  //来到这里,F8
01070327      5B           pop ebx
01070328      03D7         add edx,edi
0107032A      A1 A4100801  mov eax,dword ptr ds:[10810A4]
0107032F      3148 70      xor dword ptr ds:[eax+70],ecx
01070332      A1 A4100801  mov eax,dword ptr ds:[10810A4]
01070337      3148 70      xor dword ptr ds:[eax+70],ecx
0107033A      A1 A4100801  mov eax,dword ptr ds:[10810A4]
0107033F      8B16         mov edx,dword ptr ds:[esi]
01070341      8B88 8400000>mov ecx,dword ptr ds:[eax+84]
01070347      3348 60      xor ecx,dword ptr ds:[eax+60]
0107034A      3348 34      xor ecx,dword ptr ds:[eax+34]
0107034D      030D BC10080>add ecx,dword ptr ds:[10810BC]     ; FlyWoool.00400000
01070353      85D2         test edx,edx
01070355      75 1E        jnz short 01070375
01070357      8B90 8800000>mov edx,dword ptr ds:[eax+88]
0107035D      FF76 18      push dword ptr ds:[esi+18]
01070360      3390 8400000>xor edx,dword ptr ds:[eax+84]
01070366      FF76 14      push dword ptr ds:[esi+14]
01070369      3350 40      xor edx,dword ptr ds:[eax+40]
0107036C      FF76 10      push dword ptr ds:[esi+10]
0107036F      2BCA         sub ecx,edx
01070371      FFD1         call ecx  
01070373     /EB 23        jmp short 01070398
01070375     |83FA 01      cmp edx,1
01070378     |75 21        jnz short 0107039B
0107037A     |FF76 04      push dword ptr ds:[esi+4]
0107037D     |8B90 8800000>mov edx,dword ptr ds:[eax+88]
01070383     |3390 8400000>xor edx,dword ptr ds:[eax+84]
01070389     |FF76 08      push dword ptr ds:[esi+8]
0107038C     |3350 40      xor edx,dword ptr ds:[eax+40]
0107038F     |6A 00        push 0
01070391     |FF76 0C      push dword ptr ds:[esi+C]
01070394     |2BCA         sub ecx,edx
01070396     |FFD1         call ecx      ; FlyWoool.004B79A6   //F7进去!直接到达OEP!

004B79A6      6A 60            push 60  //OEP!
004B79A8      68 00235D00      push FlyWoool.005D2300
004B79AD      E8 26070000      call FlyWoool.004B80D8
004B79B2      BF 94000000      mov edi,94
004B79B7      8BC7             mov eax,edi
004B79B9      E8 E2D1FFFF      call FlyWoool.004B4BA0
004B79BE      8965 E8          mov dword ptr ss:[ebp-18],esp
004B79C1      8BF4             mov esi,esp
004B79C3      893E             mov dword ptr ds:[esi],edi
004B79C5      56               push esi
004B79C6      FF15 A4445B00    call dword ptr ds:[5B44A4]         ; KERNEL32.GetVersionExA
004B79CC      8B4E 10          mov ecx,dword ptr ds:[esi+10]
004B79CF      890D A4367C00    mov dword ptr ds:[7C36A4],ecx
004B79D5      8B46 04          mov eax,dword ptr ds:[esi+4]

LordPE纠正大小Dump!打开Import 1.6,OEP填B79A6,有14个无效指针,全部CUT,正常运行!

【AcProtect】
【AcProtect 123.exe】

本例不处理stolen code ,相对简单

---------------------------------------------------------------------------------
Acprotect1.X之VB程序的处理(高一点的版本。。。。。)

目标程序:估计是个游戏外挂登陆器(网上别人求脱的^_^)
********************************************************************************************
首先Peid查壳,Nothing found *!再看EP区段.perplex,原来是Acprotect1.X版加的壳。

因为是VB程序(跟踪过程中很容易看出来的)

Stolen Code很简单,没有必要苦苦跟踪,VB的IAT加密目前大部分加密软件都是有心无力的。

OD异常设置不忽略内存异常,隐藏OD(估计是高一点版本的Acprotect,因为我有几次隐藏了OD还退出)
这时候反复重新载入几次之后就行了
********************************************************************************************
OD载入程序

00422000 123.<Mod>  55                 push ebp  //入口
00422001            50                 push eax
00422002            E8 01000000        call 123.00422008
00422007          - 7D 83              jge short 123.00421F8C
00422009            C40458             les eax,fword ptr ds:[eax+ebx*2]
0042200C            F8                 clc
0042200D            66:81E6 4858       and si,5848

F9一下,到最后一次典型异常!

0043374D            CD 01              int 1 //最后一次典型异常!注意堆栈!
0043374F            40                 inc eax
00433750            40                 inc eax
00433751            0BC0               or eax,eax
00433753            75 05              jnz short 123.0043375A
00433755            90                 nop

***********************************************
堆栈提示:

0012FF84   0012FFE0     指针到下一个 SEH 记录
0012FF88   00433731     SE 句柄   //右键--转存中跟随--下内存访问断点
0012FF8C   00948A20
***********************************************

下好断点后,Shift+F9运行!

00433731            8B5C24 0C          mov ebx,dword ptr ss:[esp+C] //运行到这里,F2下断,Shift+F9运行
00433735            8383 B8000000 02   add dword ptr ds:[ebx+B8],2
0043373C            33C0               xor eax,eax
0043373E            C3                 retn

00433781            8B048E             mov eax,dword ptr ds:[esi+ecx*4]  //运行到这里,F2下断,Shift+F9运行
00433784            8B5C8E 04          mov ebx,dword ptr ds:[esi+ecx*4+4>
00433788            2BC3               sub eax,ebx
0043378A            C1C8 05            ror eax,5
0043378D            2BC2               sub eax,edx
0043378F            81C2 43A18EAB      add edx,AB8EA143
00433795            89048E             mov dword ptr ds:[esi+ecx*4],eax  //Shift+F9运行后就跳到这里
00433798            49                 dec ecx
00433799          ^ EB E1              jmp short 123.0043377C
0043379B            61                 popad
0043379C            61                 popad
0043379D            C3                 retn  //取消所有的断点[2次F2(INT3断点),1次内存访问断点],F4下来!

************************************************
因为是VB程序,Stolen Code很简单,没必要苦苦跟踪
VB的IAT加密目前大部分加密软件都是有心无力的。
************************************************
鉴于这样。。

打开内存镜像

内存镜像,项目 21
地址=00401000 //F2下断,Shift+F9运行
大小=0001D000 (118784.)
Owner=123      00400000
区段=.text
包含=code
类型=Imag 01001002
访问=R
初始访问=RWE

00401B44          - FF25 9C114000      jmp dword ptr ds:[40119C] ; MSVBVM60.SetMemEvent
00401B4A          - FF25 7C114000      jmp dword ptr ds:[40117C] ; MSVBVM60.ThunRTMain //运行到这注意堆栈!
00401B50            47                 inc edi
00401B51            6B2B 2E            imul ebp,dword ptr ds:[ebx],2E
00401B54            36:E6 96           out 96,al
00401B57            09E5               or ebp,esp
00401B59            73 00              jnb short 123.00401B5B

**********************************************************************
堆栈提示:

0012FFD8   00438CC9     返回到 123.00438CC9 来自 123.00401B4A
0012FFDC   00402C98     ASCII "VB5!6&vb6chs.dll"  //要00402C98这个地址
0012FFE0   FFFFFFFF     SEH 链尾部

**********************************************************************

现在开始简单处理了。。。

汇编下

00401B4A          - FF25 7C114000      jmp dword ptr ds:[40117C] ; MSVBVM60.ThunRTMain
00401B50            68 982C4000        push 123.00402C98         ; ASCII "VB5!6&vb6chs.dll"
00401B55            E8 F0FFFFFF        call 123.00401B4A       ; jmp to MSVBVM60.ThunRTMain
00401B5A            90                 nop
00401B5B            0000               add byte ptr ds:[eax],al

FF 25 7C 11 40 00 68 98 2C 40 00 E8 F0 FF FF FF 90

用OD插件脱壳(纠正OEP为1B50),不用修复直接就可以运行了!

Microsoft Visual Basic 5.0 / 6.0

********************************************************************************************
后记:对Acprotect壳的处理套路大概就是这样了,对这个程序我们没有去处理stolen Code。。。所以显得简单了一些!

【AsProtect 】
【AsProtect emailcaster.exe】

ASProtect 1.23 RC1 -> Alexey Solodovnikov

没有注册的时候有试用提示!

1、OD载入之后忽略除了内存访问之外的所有异常,隐藏OD!Shift+F9,注意堆栈!

0012FF54   018032F0
0012FF58   01811810   ASCII "6uob9ACQoUA="  //硬盘指纹

当第2次出现硬盘指纹的时候,在00401000下F2断点,Shift+F9!

00480650     55              push ebp
00480651     8BEC            mov ebp,esp
00480653     8B45 08         mov eax,dword ptr ss:[ebp+8]
00480656     A3 EC7E4800     mov dword ptr ds:[487EEC],eax  //487EEC就是保存注册名的位置
0048065B     5D              pop ebp
0048065C     C2 0400         retn 4

继续Shift+F9运行来到最后一次异常!

01802CD1     3100            xor dword ptr ds:[eax],eax //最后一次异常
01802CD3     64:8F05 0000000>pop dword ptr fs:[0]
01802CDA     58              pop eax
01802CDB     833D 7C6D8001 0>cmp dword ptr ds:[1806D7C],0
01802CE2     74 14           je short 01802CF8
01802CE4     6A 0C           push 0C
01802CE6     B9 7C6D8001     mov ecx,1806D7C
01802CEB     8D45 F8         lea eax,dword ptr ss:[ebp-8]
01802CEE     BA 04000000     mov edx,4
01802CF3     E8 54E1FFFF     call 01800E4C
01802CF8     FF75 FC         push dword ptr ss:[ebp-4]
01802CFB     FF75 F8         push dword ptr ss:[ebp-8]
01802CFE     8B45 F4         mov eax,dword ptr ss:[ebp-C]
01802D01     8338 00         cmp dword ptr ds:[eax],0
01802D04     74 02           je short 01802D08
01802D06     FF30            push dword ptr ds:[eax]
01802D08     FF75 F0         push dword ptr ss:[ebp-10]
01802D0B     FF75 EC         push dword ptr ss:[ebp-14]
01802D0E     C3              retn  //F2下断,Shift+F9运行,注意堆栈

0012FF5C   018148AC
0012FF60   00400000   ASCII "MZP"
0012FF64   C9F5F162
0012FF68   0012FFA4   //要的就是0012FF68 SHE的地址。

hr 0012FF68,F9运行

01815082     03C3            add eax,ebx   ; emailcas.00400000  //来到这里,F8
01815084     894424 1C       mov dword ptr ss:[esp+1C],eax
01815088     61              popad
01815089     FFE0            jmp eax  //跳到OEP

00486718     55              push ebp  //OEP
00486719     8BEC            mov ebp,esp
0048671B     83C4 F4         add esp,-0C
0048671E     B8 18654800     mov eax,emailcas.00486518
00486723     E8 5401F8FF     call emailcas.0040687C
00486728     A1 BC814800     mov eax,dword ptr ds:[4881BC]
0048672D     8B00            mov eax,dword ptr ds:[eax]

以下就是脱壳修复了!

用Import REC等级1修复,然后利用插件修复。这时候程序还是未注册版本

最后是以自己的名字注册了!

还记得487EEC就是保存注册名的位置

在数据段00488360写入 注册名字

载入脱壳后修复的文件

命令行DD 487EEC
24894800

00487EEC  017F3861
00487EF0  0000001E
00487EF4  0000001E

修改成

00487EEC  00488360  ASCII "hack by zhxfl"
00487EF0  FFFFFFFF ;记录注册日期
00487EF4  FFFFFFFF;使用日期之类的。
**************
找块空地
00488FE0  63617243
00488FE4  7942206B
00488FE8  C8FDC820
00488FEC  00D0D0CB  shell32.00D0D0CB

另外程序有暗桩,怎么去掉见操作!
载入dump_.exe,然后触发安装,直接跳过异常语句即可。

【AcProtect】
【UltraProtect 1.x.EXE】

这里对stolen code的处理比较特别,不是把stolen code寻找出来,而是找另外一个OEP,保留部分壳的信息。

我们脱壳必须知道一些程序的入口特征,关于这个我会做一个专题的(一般是5种程序),下面就介绍一种:

Visual C++的入口特征

push ebp
mov ebp,esp
sub esp,44
push esi
call dword ptr ds:[<&KERNEL32.GetCommandLineA>]   ; [GetCommandLineA
mov esi,eax
mov al,byte ptr ds:[eax]

二进制代码

55 8B EC 83 EC 44 56 FF 15 E0 63 40 00 8B F0 8A 00

此例作为脱壳示例,只是想起到抛砖引玉的作用!
********************************************************************************************带发修行ACProtect v1.21=========>UltraProtect 1.x -> RISCO Software Inc.
********************************************************************************************Od设置不忽略内存异常,其余异常全部忽略

载入,隐藏!

0040D000 U>  60                   pushad  //入口,F8一下!
0040D001     70 02                jo short UltraPro.0040D005  //注意ESP值(0012FFA4)
0040D003     D3FE                 sar esi,cl
0040D005     C1D6 12              rcl esi,12
0040D008     FC                   cld
0040D009     F9                   stc

我们下断hr 0012FFA4,F9运行,这里ESP定律要分7对中断

0041E6FF     61                   popad   //1
0041E700     56                   push esi                                          ; ntdll.77F57D70
0041E701     BE A3DE4000          mov esi,UltraPro.0040DEA3

0041E750     60                   pushad
0041E751     E8 0ABDFFFF          call UltraPro.0041A460
0041E756     E8 00000000          call UltraPro.0041E75B

0041E768     899D AAD24000        mov dword ptr ss:[ebp+40D2AA],ebx
0041E76E     61                   popad   //2
0041E76F     890F                 mov dword ptr ds:[edi],ecx

0041E7BF     60                   pushad
0041E7C0     E8 9BBCFFFF          call UltraPro.0041A460
0041E7C5     E8 34BAFFFF          call UltraPro.0041A1FE

0041E7D0     61                   popad  //3
0041E7D1     8B0B                 mov ecx,dword ptr ds:[ebx]
0041E7D3     8F05 93DE4000        pop dword ptr ds:[40DE93]

0041E821     60                   pushad
0041E822     E8 39BCFFFF          call UltraPro.0041A460
0041E827     C685 D0D14000 00     mov byte ptr ss:[ebp+40D1D0],0

0041E82E     61                   popad  //4
0041E82F     FF35 EBDE4000        push dword ptr ds:[40DEEB]
0041E835     57                   push edi

0041E87F     60                   pushad
0041E880     E8 15DEFFFF          call UltraPro.0041C69A

0041E885     61                   popad  //5
0041E886     8F05 B7DE4000        pop dword ptr ds:[40DEB7]                         ; UltraPro.0040DF0B
0041E88C     FF35 B7DE4000        push dword ptr ds:[40DEB7]

0041E8D6     60                   pushad
0041E8D7     E8 5BDBFFFF          call UltraPro.0041C437

0041E8DC     61                   popad  //6
0041E8DD     FF35 CFDE4000        push dword ptr ds:[40DECF]
0041E8E3     56                   push esi

0041E92D     60                   pushad
0041E92E     E8 86FDFFFF          call UltraPro.0041E6B9

0041E933     61                   popad  //7
0041E934     8F05 73DE4000        pop dword ptr ds:[40DE73]   ; ntdll.77F944A8  //这里就是代发修行的最佳脱壳地点,此时对资源和代码已经完全解压。OD插件,DUMP!

大家可以看出 +++++++以上对应7句保护Call,为什么要算清楚是7句呢?,到伪造入口就明白。+++++++

另外怎么去知道那里才是带发修行的好地方呢?其实很简单~等下你就明白了!(嘿嘿~知道了吧~就是相当于最后一次ESP
分段了!)

F9继续运行!

0041BAAD     CD 01                int 1  //中断在这里,取消硬件断点!
0041BAAF     40                   inc eax
0041BAB0     40                   inc eax
0041BAB1     0BC0                 or eax,eax
0041BAB3     75 05                jnz short UltraPro.0041BABA
0041BAB5     90                   nop
0041BAB6     90                   nop

我们ALT+M 打开内存镜像,在00401000(Code)段F2下断,Shift+F9运行!

004010DD     3C 22                cmp al,22  //到这里了,伪OEP!
004010DF     75 1B                jnz short UltraPro.004010FC
004010E1     56                   push esi
004010E2     FF15 F4644000        call dword ptr ds:[4064F4]  ; UltraPro.0040D4D6
004010E8     8BF0                 mov esi,eax

我们按住Crtl+向上箭头,往上翻看(防止代码混乱-找真OEP!)

004010CC     95                   xchg eax,ebp  //真OEP,但是代码被抽取了!
004010CD     61                   popad
004010CE     2E:EF                out dx,eax
004010D0     D1AD 26477503        shr dword ptr ss:[ebp+3754726],1
004010D6     8730                 xchg dword ptr ds:[eax],esi
004010D8     3C A2                cmp al,0A2
004010DA   ^ 78 84                js short UltraPro.00401060
004010DC     7F 3C                jg short UltraPro.0040111A

现在就是还原代码了~

55 8B EC 83 EC 44 56 FF 15 E0 63 40 00 8B F0 8A 00

二进制粘帖!(其实这一步不用这么做的^_^,呵呵~如果用其他方法就得这么做了!)

这里,我们获取真、伪OEP只是方便修复IAT,其实壳早就在0041E934处解码完毕了!

关掉OD,打开加壳程序(因为我们使用跟踪等级3修复的时候,如果开着OD,ImportREC会死掉的!)

运行ImportREC,选择这个进程。把OEP改为000010CC,点IT AutoSearch,点“Get Import”,指针部分有效,用跟踪等级3全部修复,把OEP改为1E934(0041E934-00400000),修复程序,正常运行。

PS:如果还是死掉的话~我们就分段修复吧~一回少修复一点!

脱壳文件显示Nothing found *呵呵~其实壳已经脱掉了,这样的显示是因为加壳的缘故了~很正常!!

【ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov 以壳脱壳】

【以壳脱壳原理】
1.以壳解壳的原理I.什么是stolen code。===================== 关于stolen bytes ===================== 稍微说明一下: 每一种编译工具例如 : VC++ , Delphi , Borland , etc.. 在OEP有一个唯一的/相同的PE头 其中的一些是这样的:
Push EBP MOV Ebp,Esp Add ESP , -010 Mov EAX, SOME_VALUE
(共11bytes) 或者:
Push EBP MOV Ebp,Esp          ;* Add ESP , -010       ;**Push EBX             ;***Push ESi Push EDi Mov EAX, SOME_VALUE  ;****
(共14 bytes)
1.对于*的部分原程序的OEP,通常是一开始以 Push EBP 和MOV Ebp,Esp这两句开始的,不用我多说大家也知道这两句的意思是以EBP代替ESP,作为访问堆栈的指针。为什么要这样呢?为什么几乎每个程序都是的开头能?因为如果我们写过C等函数的时候就应该清楚,程序的开始是以一个主函数main()为开始的,而函数在访问的过程中最重要的事情就是要确保堆栈的平衡,而在win32的环境下保持平衡的办法是这样的:1.让EBP保存ESP的值;2.在结束的时候调用mov esp,ebp pop ebp retn或者是leaveretn两个形式是一个意思。这样做的好处是不用考虑ESP等于多少,PUSH了多少次,要POP多少次了,因为我们知道EBP里面放的是开始时候的ESP值。
2.对于**的部分Add ESP , -010这种代码的意思是在堆栈区域开辟一块区域保存和使用局部变量,用EBP-XX来调用。
3.对于***的部分
在下来就是保存寄存器的初始值。
4.对于****的部分
初始化寄存器。
小节:我们知道了这就是程序在编译后程序OEP的一般形式,而某些壳在处理OEP的代码时,把这些固定的代码nop掉,然后把他们放到壳代码的空间里面(而且还常伴随着花指令)!使原程序的开始从壳空间开始,然后再JMP回程序空间。如果我们脱掉壳了以后,这一部分就会遗失,也就达到了反脱壳的目的。这就是stolen code技术,或者更确切的说是stolen OEP code技术。
II.Replace Code
这是一种将原程序代码抽出,放到壳代码中执行的技术。应该就是一般说的SDK(Software Development Kit)技术。(其实我也不是很懂^^)
怎么实现的不清楚,但是他是如何体现出来的呢?
当你脱完壳了以后,运行发现提示“XXXXXX处不易读取”十有八九就是因为采用了SDK技术。因为当我们脱壳后这部分代码都没有了,我们怎么能读取呢?
总之我把replace code看成是又一种形式的stolen code,他偷掉的是程序中的的code。
  III.以壳解壳的提出  上面的两种反脱壳的技术是横在我们面前的拦路虎,我们如何解决他呢?
办法有2个:
1.跟踪并且分析代码然后自己补充完整。
2.用以壳解壳的办法。
对于一些stolen OEP code我们好象还可以接受(还不太多嘛),但是如果SDK把成段成段的抽调代码,那我估计你能把那些代码补全了还不如自己去去把这个程序写出来^-^。而我们知道这些被偷掉的代码全在壳里面,只不过他不属于程序的空间,所以我们不能把他dump下来。那么我们想:如果我们把他们全都dump下来以后,那不就不用自己去补了。在这种想法的促使下,以壳解壳的方法诞生了。
接下来的问题便是:我们怎么dump下来呢?
但是在这个问题的前面应该是dump什么部分?按照前面所说的,如果我们在dump下程序了以后运行发现程序在读某一块内存区域,但是那一块区域却什么都没有,这时你便应该知道要dump什么区域了吧!
那么如何dump呢?
使用LordPE的 dump region...(区域dump)功能就可以了,选种自己想要的区域就可以直接dump下来了!
在接下来是该如何装入原来的文件呢?
先给大概的出步骤:
1.使用PE Editor的Load section from disk...(从硬盘载入区段头)功能增加一个区域,放入壳代码;
2.修改那个新区段的RVA;3.重建PE文件(在重建选项一般保留“验正PE”就可以了)
对于1没什么好说的,我们来解释一下为什么要修改这个RVA。
   代码在文件中有他们自己的位置,我们称为文件地址。而当他映射到内存的时候并不是像文件中的地址那样排列。他是按照RVA(相对虚拟地址)的地址+基址 来确定自己在内存中的位置的。所以我们要将原来壳代码所在的位置减掉基址添入就可以了。编辑使用edit section head....的功能。最后因为实际的PE文件和PE头里面的信息有写不一样(你都添加了一个区段当然不一样了),那么需要修复PE头,所以只选用验正PE,不建议在这个时候优化程序,因为我们一般的步骤是先添加区段壳代码,然后修复IAT,这个也是是要添加一个区段的哦!
----------------------------------------------------------------3.总结     现在我们来回答开始提出的三个问题:
1.什么是以壳解壳?  以壳解壳是针对主程序的部分代码被偷,进而提出来的一种解决办法。采用添加原壳代码的的手段,达到使程序运行时仍能像未脱壳以前那样正确的访问到壳代码空间。可以说是一种“懒”办法,但是对于某些程序被偷得太多的时候却是一种无奈之举!
2.什么时候要以壳解壳?  当你发现被偷掉的代码很多,自己不能手动补充完整的时候。
3.如何以壳解壳?
  上面给出了一个以壳解壳的实例。下面也是一个(明天再帖^^)
4.以壳解壳有什么不足?
  因为以壳解壳采用了壳中的代码,那么如果在壳中代码中有部分是校验,或者是一些检验脱壳的代码,那么我们无异于是引狼入室。而且保留了壳代码,不仅增加了文件大小而且留下了原程序本来就没有的东西,总让人心理不是很爽。所以我的向来主张是以壳解壳的办法是最后的救命稻草,不要太过于依赖。
5.什么时候不能使用以壳解壳的办法?
  当壳代码的RVA小于基址的时候!上面的方法将不在适用。
  例如:壳代码的RVA=300000 而程序的基址=400000。
  那时我们怎么修改这个RVA呢?我还没有找到合适的办法,期待那位能告诉我 ^-^。
问题在这个帖子里面解决了:
【以壳脱壳 实例 ASProtect 1.23】

OD设置忽略除了内存访问之外的所有异常!

00401000 cry>  68 01009000     push crysb.00900001  //入口!
00401005       E8 01000000     call crysb.0040100B
0040100A       C3              retn
0040100B       C3              retn
0040100C       EB 6E           jmp short crysb.0040107C
0040100E       C2 6873         retn 7368

Shift+F9走!第23次的时候第2次看到硬盘指纹。。。

016D46A5       3100            xor dword ptr ds:[eax],eax  //第23次
016D46A7       EB 01           jmp short 016D46AA
016D46A9       68 648F0500     push 58F64
016D46AE       0000            add byte ptr ds:[eax],al
016D46B0       00EB            add bl,ch

堆栈提示:
0012FF50     016C0000
0012FF54     016A0000
0012FF58     016D4138
0012FF5C     016E94E4    ASCII "6uob9ACQoUA="
0012FF60     016D3616    返回到 016D3616 来自 016C2524
0012FF64     016A0000

在CODE段下断,Shift+F9运行!

004085E0       8B4424 04       mov eax,dword ptr ss:[esp+4]  //到这里!
004085E4       A3 98324C00     mov dword ptr ds:[4C3298],eax  //[4C3298]是保存注册地址的
004085E9       C2 0400         retn 4

继续Shift+F9运行,第26次到达最后一次异常!

016D39EC       3100            xor dword ptr ds:[eax],eax  //最后一次异常
016D39EE       64:8F05 0000000>pop dword ptr fs:[0]
016D39F5       58              pop eax
016D39F6       833D B07E6D01 0>cmp dword ptr ds:[16D7EB0],0
016D39FD       74 14           je short 016D3A13
016D39FF       6A 0C           push 0C
016D3A01       B9 B07E6D01     mov ecx,16D7EB0
016D3A06       8D45 F8         lea eax,dword ptr ss:[ebp-8]
016D3A09       BA 04000000     mov edx,4
016D3A0E       E8 2DD1FFFF     call 016D0B40
016D3A13       FF75 FC         push dword ptr ss:[ebp-4]
016D3A16       FF75 F8         push dword ptr ss:[ebp-8]
016D3A19       8B45 F4         mov eax,dword ptr ss:[ebp-C]
016D3A1C       8338 00         cmp dword ptr ds:[eax],0
016D3A1F       74 02           je short 016D3A23
016D3A21       FF30            push dword ptr ds:[eax]
016D3A23       FF75 F0         push dword ptr ss:[ebp-10]
016D3A26       FF75 EC         push dword ptr ss:[ebp-14]
016D3A29       C3              retn //F2断下来,注意堆栈!

堆栈提示:
0012FF5C     016E7E9C
0012FF60     00400000    crysb.00400000
0012FF64     574F42C8
0012FF68     0012FFA4 =======>0012FF68
0012FF6C     016C0000

hr 0012FF68,F9运行!

016E8019      /EB 44           jmp short 016E805F  //到这里,删除断点,F7一下!
016E801B      |EB 01           jmp short 016E801E
016E801D      |9A 51579CFC BF0>call far 00BF:FC9C5751
016E8024      |0000            add byte ptr ds:[eax],al
016E8026      |00B9 00000000   add byte ptr ds:[ecx],bh
016E802C      |F3:AA           rep stos byte ptr es:[edi]

016E805F       03C3            add eax,ebx  //到这里,F8一下!
016E8061       BB C4000000     mov ebx,0C4  //这里就是我们以壳解壳的OEP=012E8061
016E8066       0BDB            or ebx,ebx
016E8068       75 07           jnz short 016E8071
016E806A       894424 1C       mov dword ptr ss:[esp+1C],eax
016E806E       61              popad

打开LordPE,完全DUMP这个进程!再区域脱壳Region00E50000-00E5C000.dmp(016E0000-00400000=012E0000)
(dump下来的区块必须包含以壳脱壳的OEP的低值范围)
组装Unpack.exe
按PE编辑器,导入dump.exe,按区段编辑,右键,导入dump下来的区段。这时候还需要编辑区段头OEP在这个区段里面,这个区块的基地址必须减去原来的40000,然后这个基地址就作为新的OEP基地址。参考Region00E50000-00E5C000.dmp看到新的基地址就是E50000-40000=E10000,改好之后保存,然后重建PE,选中dump PE。

请出AsprDbgr 修复输入表!

AsprDbgr v1.0beta (:P) Made by me... Manko.

  iEP=401000 (C:\Program Files\CrystalButton2\crysb.exe)

    IAT Start: 492000
          End: 492730
       Length: 730
      IATentry 492208 = 16D1CD8 resolved as GetCommandLineA
      IATentry 492224 = 16D1C64 resolved as GetModuleHandleA
      IATentry 492244 = 16D17A4 resolved as GetProcAddress
      IATentry 492288 = 16D1CC8 resolved as LockResource
      IATentry 492298 = 16D1C8C resolved as GetVersion
      IATentry 492320 = 16D1CB8 resolved as GetCurrentProcess
    12 invalid entries erased.
  Dip-Table at adress: 16D7AB4
    0 4085E0 0 0 0 0 0 0 0 0 0 0 0 0
  Last SEH passed. (16D39EE) Searching for signatures. Singlestepping to OEP!
    Call + OEP-jump-setup at: 16E6049 ( Code: E8000000 5D81ED )
    Mutated, stolen bytes at: 16E6095 ( Code: EB02CD20 EB02CD20 )
    Erase of stolen bytes at: 16E5FF8 ( Code: 9CFCBF37 606E01B9 )
      Repz ... found. Skipping erase of stolen bytes. ;)
  possible (temp)OEP: 4364B6 (Reached from preOEP: 16E6009)

打开IR1.6,在OEP处添0364B6,获取输入表全部有效--再把OEP改成以壳脱壳的OEP--修复抓取文件!

呵呵~可以运行,,现在我们来Pre-Dip注册一下~~

OD载入Unpack_.exe

还记得4C3298?

DD 4C3298

004C3298  016C3861  Unpack_.016C3861
004C329C  6D6F6F7A
004C32A0  00000000
004C32A4  00007963

找块空地。。我找004DFFF4写入******

现在修改成

004C3298  004DFFF4  ASCII "******"
004C329C  6D6F6F7A
004C32A0  00000000
004C32A4  00007963

因为没有试用标志。。。就不用改了

现在复制可执行文本--覆盖保存!

运行看看。。。呵呵已经注册给******了。。

抓个图留恋吧。。。到此为止。。。

***********
这里演示如何跟踪 stolen code。
Stolen Code

push ebp
mov ebp,esp
push -1
push 49A4A8
push 4363B8
mov eax,dword ptr fs:[0]
push eax
mov dword ptr fs:[0],esp
sub esp,58
push ebx
push esi
push edi           
mov dword ptr ss:[ebp-18],esp

55 8B EC 6A FF 68 A8 A4 49 00 68 B8 63 43 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58
53 56 57 89 65 E8

【UltraProtect 1.x -> RISCO Software Inc.】
【stolen code 的寻找】
【必须声明的是这个版本的壳有好几种保护方法,每种都需要不同的技巧。】
【完美卸载XP V9.14】
******************************************************************
Od设置不忽略INT3中断,其余异常全部忽略。隐藏!

OD载入
004AC000 N>  60                   pushad  //记下004AC000,这个后面要用到的!
004AC001     4E                   dec esi
004AC002     D3D6                 rcl esi,cl
004AC004     4E                   dec esi
004AC005     66:D3E8              shr ax,cl

F9运行。

004BAB23    90              NOP    //第一次也是最后一次INT3异常。
004BAB24    64:67:8F06 0000 POP DWORD PTR FS:[0]
004BAB2A    83C4 04         ADD ESP,4
004BAB2D    60              PUSHAD
004BAB2E    E8 00000000     CALL NetClean.004BAB33
004BAB33    5E              POP ESI
004BAB34    83EE 06         SUB ESI,6
004BAB37    B9 5B000000     MOV ECX,5B
004BAB3C    29CE            SUB ESI,ECX
004BAB3E    BA 09E5B87E     MOV EDX,7EB8E509
004BAB43    C1E9 02         SHR ECX,2
004BAB46    83E9 02         SUB ECX,2
004BAB49    83F9 00         CMP ECX,0
004BAB4C    7C 1A           JL SHORT NetClean.004BAB68

.................................................

堆栈内容

0012FF58   0012FFE0  指针到下一个 SEH 记录
0012FF5C   004BAAF0  SE 句柄    //右键对004BAAF0转存中跟随,下内存访问断点,Shift+F9!
0012FF60   F9E1E5CE

004BAAF0    8B4424 04       MOV EAX,DWORD PTR SS:[ESP+4]  //下断点Shift+F9中断1
004BAAF4    8B4C24 0C       MOV ECX,DWORD PTR SS:[ESP+C]
004BAAF8    FF81 B8000000   INC DWORD PTR DS:[ECX+B8]
004BAAFE    8B00            MOV EAX,DWORD PTR DS:[EAX]
004BAB00    2D 03000080     SUB EAX,80000003
004BAB05    75 12           JNZ SHORT NetClean.004BAB19
004BAB07    90              NOP
004BAB08    90              NOP
004BAB09    90              NOP
004BAB0A    90              NOP
004BAB0B    33C0            XOR EAX,EAX
004BAB0D    8941 04         MOV DWORD PTR DS:[ECX+4],EAX
004BAB10    8941 08         MOV DWORD PTR DS:[ECX+8],EAX
004BAB13    8941 0C         MOV DWORD PTR DS:[ECX+C],EAX
004BAB16    8941 10         MOV DWORD PTR DS:[ECX+10],EAX
004BAB19    C3              RETN

.................................................

004BAB4E    8B048E          MOV EAX,DWORD PTR DS:[ESI+ECX*4] //下断点Shift+F9中断2,清除内存断点
004BAB51    8B5C8E 04       MOV EBX,DWORD PTR DS:[ESI+ECX*4+4]
004BAB55    03C3            ADD EAX,EBX
004BAB57    C1C8 0E         ROR EAX,0E
004BAB5A    2BC2            SUB EAX,EDX
004BAB5C    81EA D41CF55C   SUB EDX,5CF51CD4
004BAB62    89048E          MOV DWORD PTR DS:[ESI+ECX*4],EAX
004BAB65    49              DEC ECX
004BAB66  ^ EB E1           JMP SHORT NetClean.004BAB49
004BAB68    61              POPAD
004BAB69    61              POPAD
004BAB6A    C3              RETN //F4直接下来,这时是寻找Stolen Code时候了。

.................................................

再次点它的死穴。

命令行  d 12ffc0。
右键下硬件访问dword断点!

004C9B31    55              PUSH EBP         //Stolen Code
004C9B32    8BEC            MOV EBP,ESP     //Stolen Code
004C9B34    6A FF           PUSH -1        //Stolen Code
004C9B36    90              NOP
004C9B37    60              PUSHAD
004C9B38    60              PUSHAD
这个程序抽了5个字节。
........................................................................

ALT+M 打开内存镜像断点,对准它的第二个死穴点。  

内存镜像, 项目 12
地址=00401000     //Code段下内存访问断点
大小=00047000 (290816.)
Owner=NetClean 00400000
区段=.text
Contains=code
类型=Imag 01001002
访问=R
初始访问=RWE

F9运行

004431F9    68 D8B24400     PUSH NetClean.0044B2D8  //临时Oep,滚动条向上看,如何判断抽掉多少字节,用滚动条是代码会混乱,右键分析代码,如我现在调整的样式,标签1
004431FE    68 B4334400     PUSH NetClean.004433B4                   ; JMP to MSVCRT._except_handler3
00443203    64:A1 00000000  MOV EAX,DWORD PTR FS:[0]
00443209    50              PUSH EAX
0044320A    64:8925 0000000>MOV DWORD PTR FS:[0],ESP
00443211    83EC 68         SUB ESP,68
00443214    53              PUSH EBX
00443215    56              PUSH ESI
00443216    57              PUSH EDI

.............................................................................
标签1

004431F4      8C            DB 8C   //真Oep
004431F5   .  C3            RETN
004431F6      49            DB 49                                    ;  CHAR 'I'
004431F7      2E            DB 2E                                    ;  CHAR '.'
004431F8      79            DB 79                                    ;  CHAR 'y'
004431F9   .  68 D8B24400   PUSH NetClean.0044B2D8
004431FE   .  68 B4334400   PUSH NetClean.004433B4                   ;  JMP to MSVCRT._except_handler3; SE handler installation
00443203   .  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00443209   .  50            PUSH EAX
0044320A   .  64:8925 00000>MOV DWORD PTR FS:[0],ESP
00443211   .  83EC 68       SUB ESP,68
00443214   .  53            PUSH EBX
00443215   .  56            PUSH ESI
00443216   .  57            PUSH EDI
00443217   .  8965 E8       MOV DWORD PTR SS:[EBP-18],ESP
0044321A   .  33DB          XOR EBX,EBX
0044321C   .  895D FC       MOV DWORD PTR SS:[EBP-4],EBX
0044321F   .  6A 02         PUSH 2
00443221   .  FF15 70874400 CALL DWORD PTR DS:[448770]               ;  MSVCRT.__set_app_type

.............................................................................

还原代码!

55 8B EC 6A FF

004431F4      55            PUSH EBP //用Od插件修正入口为431F4直接脱壳吧,重建输入表的勾去掉
004431F5      8BEC          MOV EBP,ESP
004431F7      6A FF         PUSH -1
004431F9   .  68 D8B24400   PUSH NetClean.0044B2D8
004431FE   .  68 B4334400   PUSH NetClean.004433B4                   ;  JMP to MSVCRT._except_handler3; SE handler installation
00443203   .  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00443209   .  50            PUSH EAX
0044320A   .  64:8925 00000>MOV DWORD PTR FS:[0],ESP
00443211   .  83EC 68       SUB ESP,68
00443214   .  53            PUSH EBX
00443215   .  56            PUSH ESI
00443216   .  57            PUSH EDI
00443217   .  8965 E8       MOV DWORD PTR SS:[EBP-18],ESP
0044321A   .  33DB          XOR EBX,EBX
0044321C   .  895D FC       MOV DWORD PTR SS:[EBP-4],EBX
0044321F   .  6A 02         PUSH 2
00443221   .  FF15 70874400 CALL DWORD PTR DS:[448770]               ;  MSVCRT.__set_app_type

........................................................................

修复IAT必须关闭OD单独开加壳程序修复,不然ImportREC停止响应,最后用ImportREC Oep填431F4,跟踪等级三轻松修复,有10个指针提示无法修复,你可以验证一下,经过验证全部是垃圾指针,通常ImportREC可全部修复指针,如有没有一般都是垃圾,拿剪刀全部Cut掉,修复后无法运行。

寻找出错原因。

004431C4  |.  68 00404500   PUSH 2_.00454000
004431C9  |.  E8 DC000000   CALL <JMP.&msvcrt._initterm>  //这个Call可能是新版Acprotect的解码技术,进这个Call里面,循环解码,没解完程序就崩溃。
004431CE  |.  83C4 24       ADD ESP,24  //这里类似代码,我没有再次跟踪。
其实本版本Acprotect嵌有Oep处代码检验程序,发现Oep处代码被替换,立即拒绝解码,你失去了关键的代码当然程序无法运行,还要承认N次错误确定按钮。

004C9B31    55              PUSH EBP         //Stolen Code
004C9B32    8BEC            MOV EBP,ESP     //Stolen Code
004C9B34    6A FF           PUSH -1        //Stolen Code

我们已经掌握。

004431F9   .  68 D8B24400   PUSH NetClean.0044B2D8    //临时Oep也知道。

现在做什么,让程序认为你没有脱壳,将perplex段里面有用的内容全部解码。

方法

PUSH EBP        //Stolen Code   
MOV EBP,ESP    //Stolen Code   
PUSH -1       //Stolen Code

jmp 004431F9

Od载入脱壳修复后的程序,Ctrl+G 004AC000,右键清除分析。

004AC000    60              PUSHAD  //4AC000是原来壳的入口点,将Oep入口代码复制到这里。
004AC001    4E              DEC ESI
004AC002    D3D6            RCL ESI,CL
004AC004    4E              DEC ESI
004AC005    66:D3E8         SHR AX,CL
004AC008    4E              DEC ESI
004AC009    8BC3            MOV EAX,EBX
004AC00B    48              DEC EAX
004AC00C    7A 03           JPE SHORT Unpack_.004AC011
004AC00E    7B 01           JPO SHORT Unpack_.004AC011
004AC010    7A C1           JPE SHORT Unpack_.004ABFD3
004AC012    EF              OUT DX,EAX                               ; I/O 命令
004AC013    F0:50           LOCK PUSH EAX                            ; 锁定前缀是不允许的
004AC015    E8 01000000     CALL Unpack_.004AC01B

.........................................................

55 8B EC 6A FF
jmp 004431F9

004AC000     55               push ebp
004AC001     8BEC             mov ebp,esp
004AC003     6A FF            push -1
004AC005   - E9 EF71F9FF      jmp dump1_.004431F9
004AC00A     C3               retn
004AC00B     48               dec eax
004AC00C     7A 03            jpe short dump1_.004AC011
004AC00E     7B 01            jpo short dump1_.004AC011
004AC010     7A C1            jpe short dump1_.004ABFD3
004AC012     EF               out dx,eax
004AC013     F0:50            lock push eax                   ; 不允许锁定前缀

...........................................................

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
2
沙发前排站位!
2012-5-3 08:16
0
雪    币: 297
活跃值: (235)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
3
天草早期教程的东东吧,总结的不错顶一个
2012-5-3 08:17
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
最怕那些比我勤奋,并且不比我笨的人
2012-5-3 08:17
0
雪    币: 319
活跃值: (49)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
好,很实用的东西……。
2012-5-3 09:45
0
雪    币: 106
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
顶了再看。话说除了看雪外还有那些好学习的网站吗
2012-5-3 09:47
0
雪    币: 20557
活跃值: (3780)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
Nice material !
Thank you very much
2012-5-3 12:51
0
游客
登录 | 注册 方可回帖
返回
//