# 那些年我们一起脱过的衣裳－脱壳(中)

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2015-10-29T02:42:00Z
Canonical: https://wepostx.com/topics/1142

> 乌云历史资料归档
>
> **原始作者：** 珈蓝夜宇
> **原始编号：** superkieran-wooyundrops:856
> **原始发布时间：** 2015-10-29 10:42
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

# 0x01 我能在万花从中脱去壳的衣裳!（续）

## 3.3ESP定律法

### 3.3.1ESP定律介绍
ESP定律法是脱壳的利器，是国外友人发现的。有了ESP定律，可以方便我们脱掉大多数的压缩壳。可谓是本世纪破解界中最伟大的发现之一。这里只简单的看一下狭义ESP定律的原理。
当我们用OD载入之后开始就是 pushad 基本上就可以使用ESP定律脱壳了

### 3.3.2以老版菜刀为例:
首先查壳,还是UPX的壳

![原文图片](/media/2016/06/d195ce8147385ae41d2cbcfca1400b16)

1.使用OD载入之后开头是pushad,那么我们可以初步判断可以使用ESP进行脱壳

![原文图片](/media/2016/06/51c4ee8518f27bc8a338b5142f085433)

那么,我们该怎么判断到底能不能用ESP定律脱壳呢?
按下F8(单步步过),既然叫做ESP定律,那么肯定跟右上角寄存器窗口,中的ESP有必然的联系的

![原文图片](/media/2016/06/ad4fb3ad33918fe9e3cee365207af1c7)

2.可以看到到了这一步,只有ESP是红色的(不用管EIP),那就可以使用ESP定律。
选择ESP---||->右键---||->数据窗口中跟随

![原文图片](/media/2016/06/c2c824054fe8944b199ba4ccacde039b)

这时我们可以看到数据窗口,变成了下图所示

![原文图片](/media/2016/06/1dd8b783733d114130bea8e89a03fa19)

3.在HEX数据中选择任意一段(网上总有人说选一个字节,选两个字节,选四个字节),其实实际上选多少个都可以,但是只要从第一个开始选起。然后右键---||>断点---||>硬件访问---||>在Byte,Word,Dword选择任意一个都可以。

![原文图片](/media/2016/06/737a8311ff3c1525bf2c56b33d568dfd)

可以在调试中的硬件断点查看自己的断点

![原文图片](/media/2016/06/e2bf6b9ebafe07cebbb9c3a3b597348b)

4.然后按下F9运行程序,程序会自己断下来。断下来之后就会很快到达OEP,然后单步跟踪法一步一步向下
遇到向上跳转则在它的下一行按F4(运行到此处)

![原文图片](/media/2016/06/e64642de5de52989e3f7427caba3737c)

下面看到一个大跳转,跳转过去就是OEP了

```text
004AE9C4 - E9 DF6FFBFF jmp caidao.004659A8
```
5.到达OEP之后就可以开心的脱壳啦~(和单步跟踪法脱壳操作相同)

![原文图片](/media/2016/06/8cd41abd9517d47a75367bfef7ea420f)

再介绍一种非常简单的方法,用插件下硬件断点
在ESP右键选择 HW break [ESP] 她会自动下下硬件断点,之后直接按下F9运行程序再F8就到达OEP了

![原文图片](/media/2016/06/9fe79cdecd271cfbb54e68c8a617539d)

## 3.4两次断点法
还是以菜刀为例吧,我保证是最后一次了%>.<%
1.选项---||>调试设置---||>异常 全部打上√,也就是忽略所有的异常

![原文图片](/media/2016/06/db95aee986d07bb9f93f8a8e39651caf)

2.按键盘上的“ALT+M”组合键打开OD的内存窗口

![原文图片](/media/2016/06/98bb697c4c3ee533ebb96d95941e9adb)

3.如图,我们首先找到自己程序名的 .rsrc区段 按F2下断点 然后 Shift+F9 就会回到反汇编窗口
然后再按"ALT+M" 然后找到程序的第一个.rsrc.上面的.CODE（也 就是00401000处）,按F2下断点。
然后按SHIFT+F9就到达OEP或者到达了OEP的附近了,然后再用单步跟踪法就可以到达OEP了

![原文图片](/media/2016/06/8cd41abd9517d47a75367bfef7ea420f)

然后怎么脱壳我就不说了。我用了三种方法脱下UPX,只是想证明脱壳是可以用很多种方法脱壳的。而不是总是看到xxx壳用什么方法去脱啊?这些问题。。。。。。

## 3.5一步到达OEP
1.首先必备的就是查壳嘛~ ASPack的壳

![原文图片](/media/2016/06/4ca085bde2cbe3c76cd9b5023bb7e43f)

2.首先将程序加载进OD 按F9开始执行
在堆栈窗口可以看到 拖到最下边

![原文图片](/media/2016/06/ac8189dc579eb583eb6e7b80be948842)

3.然后慢慢向上找,因为我们的程序名称就叫ASPack,所以我们在向上找的第一个程序名称中,选中它,然后右键---||-->反汇编窗口中跟随

![原文图片](/media/2016/06/5041fe049ebb8f9656042ab0c2e0ab46)

在反汇编窗口中按Ctrl+A(分析代码)

![原文图片](/media/2016/06/fa2678ff0fa3306628ce32f5ef1097ae)

然后呢就能在堆栈窗口中可以看到一个括号将程序名称括起来了,这是一个段.

![原文图片](/media/2016/06/42a549378c0db3c805a803d3d80e0e26)

4.然后需要在段中找到段首,也就是这个括号的开头.找到返回到xxx(代表程序名称)这一行,选择反汇编窗口中跟随.

![原文图片](/media/2016/06/05ba2b122f27aabe1ee7b7d09003125b)

5.然后我们在反汇编窗口中向上找,肯定就在这附近,找了一下发现了OEP

![原文图片](/media/2016/06/3f83061253df9acb6423fee6493b6e93)

6.那么问题来了,我们程序都还没有开始调试,所以我们要怎么样才能将程序段在这里,然后进行脱壳呢?
选中OEP 的第一行,右键---||-->数据窗口中跟随---||-->选择

![原文图片](/media/2016/06/6b57914af2ac0d0f99b1e987a2bf8d4d)

7.然后在数据窗口中可以看到前面两个HEX数据已经被选中了,然后
右键---||-->断点---||-->硬件执行

![原文图片](/media/2016/06/29e038ca6f909573d840169ef6dbb31e)

然后查看一下硬件断点下好了没有,ok

![原文图片](/media/2016/06/6222763047c250d476d7943d04a40c11)

8.然后重新运行,按下F9执行程序,然后就直接在OEP断下来了,然后使用ollyDump脱壳进程进行脱壳.这个上面已经说了,现在我就不多说了

![原文图片](/media/2016/06/ab372b33a00cdffd1b78af5b2f21f26c)

## 3.6最后一次异常法
在脱壳方法中，最后一次异常法，这是最基础的脱壳技术之一。

![原文图片](/media/2016/06/6129c25adae1c97ab960aab141f849be)

1.将待脱壳程序载入到OD中，单击OD的“选项”菜单，在弹出的菜单中单击“调试设置”命令，在随后弹出的“调试选项”对话框中切换到“异常”选项卡，清除该选项卡下所有复选框，也就是不忽略任何异常。

![原文图片](/media/2016/06/5889b5153d7e3a59c183555549b1e67d)

2.按Shift+F9让程序运行起来，记录按键的次数。记录为x。我这里是两次就让程序运行起来了,但是你有可能需要十次或者二十次才能运行起来。
3.然后回到OD中，按Ctrl+F2(重新载入程序)，按1次Shift+F9。那么为什么按1次呢?上面让记录为x,所以这里需要按x-1次。例:如果让一个步骤按了10次运行起来了,我们在这里就要按9次Shift+F9。

![原文图片](/media/2016/06/8bc020174820661c7292c12933f430e5)

4.在OD右下角窗口中找到“SE句柄”或是“SE处理程序”，右键---||-->反汇编窗口中跟随(如果没有反汇编窗口中跟随,可以在反汇编窗口按Ctrl+G 输入"SE处理程序"前面的地址)。

![原文图片](/media/2016/06/d32c2ca7cee6a638256652582394b491)

5.在OD的反汇编窗口中跟随到上一步记录下的内存地址，并在此内存地址处下一个断点。

![原文图片](/media/2016/06/036631f496771c9327fe629b2064e6ac)

6.按键盘上的“Shift+F9”组合键让程序运行到上一步下的断点处，按键盘上的“F2”键取消此处的断点。
7.使用单步跟踪法追踪(一直按F8,遇到向上的跳转在下面那行按F4(运行到此处))直到到达OEP

![原文图片](/media/2016/06/feb89da2ea8f3c18974a1aa78fb38f64)

然后到了OEP怎么脱壳,在这里我就不说了

## 3.7模拟跟踪法
不管要怎样先查壳再说 nPack的壳

![原文图片](/media/2016/06/e282aed43db5df68e173ba88f3bec01e)

在讲到的众多脱壳方法中，我们首先讲了单步跟踪法脱壳，因为单步跟踪脱壳法是脱壳技术中最基础的方法，在后面其它的一些脱壳方法中总会或多或少的配合单步跟踪法才能顺利完成脱壳工作。便是始终是一次次的按“F8”键来单步跟踪程序，偶尔遇到回跳就跳过执行，这样机械性的操作很是烦人，那么能不能让机器来代替人力，让工具帮我们单步跟踪呢？答案是肯定的，这也就是这节讲的内容——模拟跟踪法。模拟脱壳法就是模拟单步跟踪来进行查找OEP。
网上的大部分模拟跟踪法的常见步骤是这样的：
1、将待脱壳程序载入OD中，先简单的跟踪一下程序，看看有没有SEH暗桩；
2、按键盘上的“ALT+F9”打开OD的内存窗口，找到“SFX，输入表，资源”的行，并记录此行的内存地址；
3、在OD的命令行窗口执行命令“tc eip<上一步中记录下的地址”，命令执行后就会跟踪到OEP。
然而这种方法可以是可以,但是可能从早上开始跟踪,一直跟踪到晚上都没有跟踪完成。网上那些人拿着文章转来转去,也没见得谁真的去试验过...效率实在太慢了,那不如我们来帮机器一把?
首先,需要用到的是上面所讲到的两次断点法,使用两次断点法,按照两次断点法的最后一次Shift+F9之后
然后ALT+M回到内存窗口,然后选中程序名称的SFX,输入表.

![原文图片](/media/2016/06/0403c212c54c2082d82c8339e718ce02)

然后在OD的命令执行窗口执行命令"tc eip<SFX,输入表这一行的地址"然后回车,执行命令,然后OD就能迅速的到达OEP了。

![原文图片](/media/2016/06/bed1dba63cf38980941c25531082ecf2)

当这里的跟踪变为暂停的时候,说明OEP已经到达了。

![原文图片](/media/2016/06/01ed0dcdacac7ef9b7b03826b8ec264e)

那么,这样就有人说了,如果这样我都能用两次断点法了,我为什么还要用模拟跟踪法,这样还有什么存在的意义?
如程序出错了,或者当你找不到OEP的时候就能使用此方法找到OEP。
到了OEP然后改怎样脱壳我就不说了,上面都写了好几次了~

## 3.8“SFX”法
查壳 0xpack的壳

![原文图片](/media/2016/06/16cbd9c95cfc69ee4ddabcba5c4e5d3e)

在OD中，不但可以利用模拟跟踪来代替单步跟踪进行脱壳，从而节省劳动力，还有一种SFX自动脱壳的方法也可以节省劳动力，并能快速有效的将程序的壳脱掉。
使用SFX自动脱壳法脱壳的常见步骤：
1、将OD设置为忽略所有异常；

![原文图片](/media/2016/06/1672e8184b58c3c52cc427b3cc73f416)

2、在OD的“调试选项”对话框的“SFX”选项卡中选择“字节模式跟踪实际入口”选项并确定；

![原文图片](/media/2016/06/5f7af5ec6997cea7640bae2ba98a169b)

3、将程序重新载入OD，然后左下角就会开始跟踪了,然后过一会儿就会自动断在OEP了!

![原文图片](/media/2016/06/bcf1b31e818b4864f3c8e4baf813e47a)

![原文图片](/media/2016/06/c1f372de7ee4cb0e052dc8ed90be55bb)

## 3.9出口标志法
前面几个脱壳方法中有一个共同点，就是在单步跟踪到popad指令后面不远处的jmp指令的时候，就可以大胆的判断这个jmp指令的目的地址就是OEP。
原因很简单，popad指令用于将壳运行之前保存的环境恢复，使原程序能正常运行。有些壳的popad指令很少，我们就可以查看被这种壳加壳的程序的所有popad指令，找到后面存在jmp指令的popad指令，然后来到其后的jmp指令的目的地址，这很可能就是OEP，然后就可以进行脱壳了。
1.将待脱壳程序载入OD中，在OD的反汇编客人口中单击鼠标右键，在弹出的右键菜单中单击“查找”→“所有命令”，在弹出的输入框中输入“popad”并按“查找”按钮,记得去掉整个块前面的勾啊!!!!

![原文图片](/media/2016/06/5523e22fcfbf2f7463d93178941aefb1)

2.当遇到第一个popad的时候按下F4(运行到此处),在这里,我的示例程序已经运行起来了,这就是我上面所说的"跑飞了",然后重新载入重新按照步骤1.查找popad,因为我们的第一个popad已经跑飞了,所以我们不理它。哼!然后按Ctrl+L查找下一个。
然后第二个popad又跑飞了,哼!重新开始,第一个和第二个我都不理你们了!
然后开始第三个popad,依然是跑飞。重来,第一.二.三我都不理你们了,直接按查找4次popad,执行这里,没有"跑飞"其实如果经验丰富的已经看出来马上就到达OEP了。而我还在假装不知道,然后F8单步跟踪。

![原文图片](/media/2016/06/29f695dda41cb977460bed03e628926d)

直到到达OEP

![原文图片](/media/2016/06/48f1960a1e440cc3705c8c322f635397)

然后在这里说一下LordPE+ImpREC脱壳吧,其实我在实战中很少用OD自带的插件脱壳的,因为,不是特别好用。
1.首先记住不要关闭OD,然后打开LoadPE,在最下面选择程序右键---||-->修正镜像大小

![原文图片](/media/2016/06/7a3ce0582c0ec86202a068ae546f0a14)

2.然后选择程序右键---||-->完整转存

![原文图片](/media/2016/06/3e6014f02e042e3d09a7d690c4ef35bc)

3.打开ImpRec在下拉框中选中程序

![原文图片](/media/2016/06/a2afe7da6fd902c4dae63cd793bc842b)

4.然后在OD中将下面箭头所指处复制下来

![原文图片](/media/2016/06/54ee6477c19edd43bc94c3c7b157671c)

5.然后在下面OEP处填写刚才复制的---||-->点击自动查找TAT---||-->获取输入表---||-->点击无效函数,这里没有

![原文图片](/media/2016/06/bb6e1db631f909573eb22ec5968d90a7)

(如果有,在输入表函数信息框内选中,然后删除指针!)

![原文图片](/media/2016/06/3be21c0fa49336f8f9a62412256b5faf)

然后点击右下角的转储到文件!需要选中那个刚才使用LoadPE完整转存的文件名,然后就脱壳完成!!!

# 0x02 后续章节

以上很多注意的点是我刚学脱壳时遇到的一系列的问题,我希望大家不要再误入网上那些随意转载的文章的那些不明白的东西.下节教大家如何编写自动化脱壳插件.
如果有什么不明白欢迎提问

## Replies
