首页
社区
课程
招聘
[原创][原创]脱壳系列1
2020-10-18 18:41 15464

[原创][原创]脱壳系列1

2020-10-18 18:41
15464

     



首先了解一下壳的种类:压缩壳,加密壳,虚拟机壳

加壳的原理:加壳的原理通常是加密,压缩源程序的各个区段,并给源程序添加一个或者多个区段作为源程序的引导代码,然后将源程序的入口点修改为外壳程序的入口点。

(注意:通常而言,一些简单的壳,壳代码在原程序之前运行,当然,现在很多强壳已经达到了肉中有壳,壳中有肉的局面)

壳的解密例程负责解密,然后跳转至OEP处开始执行。

研究壳有一段时间了,打算发一些脱壳系列的文章,总结一下脱壳技巧,本篇为脱壳第一篇,后续将会发一些进阶系列的文章。

一般而言,脱壳的基本步骤如下:


1:寻找OEP(注意:OEP指的是程序原始入口点,不是壳的入口点,英文全称是(original entry point)

2:转储,也就是dump

3:  修复IAT(导入地址表,英文全称:import address table )

4:检查目标程序是否存在AntiDump等阻止程序被转储的保护措施,并修复


注:遇到一些外文名词,可以尝试找到其英文全称,这样更加有助于理解


常用的脱壳方法(此处介绍一些常见脱壳方法,若要提高自己的能力,务必动手多练)

1 一步直达法,搜索JMP(0E9)或者CALL(0E8)指令的机器码

   对于一些简单的壳有效,例如UPX,ASPACK,原理:一般情况下,壳在解密完区段后会通过一个长跳转或者CALL跳转到OEP处。

   下面举一个简单的例子:

    一步直达法脱UPX壳:

   首先,OD加载,断在了程序的入口点

    

 ctrl+b

     

           

  多按几次ctrl+l

       直到出现如下界面,跳往第一区段

      

除了搜索jmp call 的机器码之外,还可以搜索call eax,jmp eax等指令的机器码,很多时候壳会将OEP的值存放在寄存器中,然后通过CALL/JMP 寄存器 跳到OEP.可以通过右键,search for-> all commands来搜索.



2  堆栈平衡法,也即ESP定律法

  类似于函数的开头会保存寄存器,函数结束会释放.(因为函数过程会用到一些寄存器),某些壳会使用pushad指令保存寄存器环境,解密各个区段完毕后,跳往OEP之前,会使用popad指令恢复寄存器环境.

    这里还是用上一个例子(见上图),开头是pushad

   注意:有些情况下,壳的第一条指令可能不是pushad,但是,有时候会在开头附近,还有时候,不用pushad,而是一个一个的push各个寄存器,例如: push eax,push ebx等等,这些都不是重点,关键在于壳在跳往OEP之前会恢复寄存器环境.

  

   

   

如上图所示,各个寄存器的值被压入了堆栈中,对这些值设置内存断点或者硬件断点(有些壳会检测硬件断点,初学者暂且不谈),当解密例程读取这些值得时候就会中断下来,此时OEP应该就在附近了

在esp上选则follow indump

   

选中四字节右键->breakpoint->hardwareonaccess->dword

我们断在了popad得下一行

这里要说明一下,现在的壳有很多保护机制,检测机制,有些壳会检测到这种方法,所以大家在脱壳得时候要尝试多种不同的方法


3 使用OD自带得SFX定位OEP

如下,打开debug option


一个是inaccurate,(这个是快的)一个是very slow(慢).

注意:只有当ollydbg发现入口点位于代码段之外时才会起作用,程序得入口点位于代码段中时该选项就不起作用了,壳得入口点位于代码段中得情况还是比较少见得.


这里我选的是inaccurate然后重启OD(重启才有作用),这里我选的是ASpack壳

然后断在了OEP,如下

  

4最后一次异常法

这个方法比较实用

首先,将exception菜单项中的忽略异常选项都选上,然后运行起来,然后打开日志窗口,如下


注意红线上面的部分,我们可以看到好多异常,但是都不是位于第一区段的,这说明了什么问题那?(此处思考两秒钟)

这说明产生的这些异常不是在源程序运行期间产生的,而是在壳的解密例程执行期间产生的异常,最后一次异常是在红线处,

好了,现在重启OD,将exception中的忽略异常的选项都去掉

然后运行,产生异常断了下来,直接shift+F9忽略定位到最后一次异常,(这里指的是壳的解密例程的最后一次异常,接着就跳转到OEP了)如图


接着对代码段设置内存访问断点(OD上方的M按钮打开内存映射)

右键,set breakpoint on access

定位到OEP如下

5  内存映像法

    对OD来讲,正常的内存访问断点读取,写入,执行的时候都会断下来,这里用一个打过补丁的OD,内存访问断点仅当执行的时候才会断下来

首先看下区段列表

本文开头已经提到,壳的解密例程会解密源程序的各个区段并写回原处,这里,只有当执行的时候才会断下来,所以,当其断下来的时候(第一个区段设置内存执行断点)才会断下来,所以,当它断下来时候,基本是有很大概率就是OEP了.

6 利用壳最常用的API来定位OEP

大部分的壳都会用到GetProcAddress,LoadLibrary这两个API,因为可以自己编程实现函数的加载,

断了下来,因为我们想要知道哪些地方调用了该函数,设置条件记录断点.记录的表达式设置为esp,也就是返回地址,快捷键shift+,

运行,查看日志

因为428C2B位于第一区段,即第一区段调用的,我们应该关注428C2B上面这一处.

好了,下面我们重新设置条件,运行起来.

断了下来,这里要注意,条件断点断下来是粉红色的,这是和普通断点的区别.

好了我们现在已经在OEP附近了.接着给代码段设置内存访问断点,很快就定位到OEP了.

此外,除了GetProcAddress之外,我们还可以尝试其他API函数,比如LoadLibrary,ExitThread等等.


7 利用应用程序调用的第一个API函数来定位OEP


这种方法和上面的方法很类似,就是给应用程序的第一个API设置断点,比如GetModuleHandleA,GetDesktopWindow,MessageBox,GetVersion等等.

这里我们用第一个例子的程序,很快就定位到了OEP

好了,最后要提醒一下,只看不练一点用都没有,脱壳是一门艺术,没有固定的方法,其实还有其他的方法,个人感觉脱壳最重要的还是手感,不练哪来的手感,对程序的逆向分析也是,都需要感觉

后续会讲一下IAT重定向以及antidump等进阶的东西.




[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2020-11-9 11:20 被Golden_Boy编辑 ,原因:
收藏
点赞8
打赏
分享
最新回复 (6)
雪    币: 86
活跃值: (903)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
luzhmu 2020-10-18 19:00
2
1
支持一下,虽然是入门级的东西
雪    币: 5180
活跃值: (2122)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lucktiger 2020-10-20 09:38
3
0
总结的不错,谢谢。
雪    币: 6437
活跃值: (2315)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shuyangzjg 2020-10-20 10:17
4
0
期待楼主后续系列
雪    币: 52
活跃值: (2206)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
实都 2020-10-21 09:46
5
0
感谢楼主,现在关注windows脱壳的不多了。。。
雪    币: 1918
活跃值: (313)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wangez8 2020-10-23 08:48
6
0
感谢楼主
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 2020-10-25 14:04
7
0
mark
游客
登录 | 注册 方可回帖
返回