脱壳技术2——原理及实战
壳的加载过程:
- 保存入口参数
- 加壳程序初始化时保存各寄存器的值
- 外壳执行完毕,恢复各寄存器值
- 最后在跳到源程序执行
- 获取所需函数API
- 一般壳的输入表中只有GetProcAdress、GetModuleHandle和LoadLibrary这几个API函数
- 如果需要其他API函数,则通过LoadLibraryA(w)或LoadLibraryExA(w)将DLL文件映射到调用进程的地址空间中
- 如果DLL文件已经被映射到调用进程的地址空间里了,就可以调用GetModuleHandleA(w)函数获得DLL模块句柄
- 一旦DLL模块被加载,就可以调用GetProcAddress函数获取输入函数的地址
- 解密各区块数据
- 出于保护源程序代码和数据的目的,一般会加密源程序文件的各个区块。在程序执行时外壳将这些区块数据解密,以让程序正常运行
- 外壳一般会按照区块加密,按区块解密,并将解密后的数据放在合适的内存位置
- 跳转回原程序入口点
- 在跳转回入口点之前,一般会恢复填写原PE文件输入表(IAT),并处理好重定位项(主要是DLL文件)
- 因为加壳时外壳自己构造了一个输入表,因此在这里需要重新对每一个DLL引入的所有函数重新获取地址,并填写到IAT表中
- 做完上述工作后,会将控制权移交源程序,并继续执行
接下来我们将要使用单步跟踪法进行脱壳:
原理:
通过ollydbg的步过(f8),步入(f7),和运行到(f4)功能,完整走过程序的脱壳过程,跳过一些循环恢复代码的片段,并用单步进入确保程序不会略过OEP,这样可以在软件自动脱壳运行完毕后,到达OEP,并dump程序
要点:
- 打开程序按f8单步向下,尽量实现向下的jmp跳转
- 会经常遇到大循环,这时要多用f4来跳过循环
- 如果函数载入时不远处就是一个call(近call),那么我们尽量不要直接跳过,而是进入这个call
- 一般跳转幅度大的指令,都极有可能是跳转到了原程序入口点(OEP)
由于这个方法比较简单就不做实战研究了
ESP定律法:
esp定律法是脱壳的利器,是应用频率最高的脱壳方法之一
要点:
esp定律的原理在于利用程序中堆栈平衡来快速找到OEP
由于在程序自解密或者自解压过程中,不少壳会先将当前寄存器状态压栈,如使用pushad,在解压结束后,会将之前的寄存器值出栈,如使用popad,因此在寄存器出栈时,往往程序代码被恢复,此时硬件断点触发,然后在程序当前位置,只需要少许单步操作,就很容易到达正确的OEP位置
- 程序刚载入开始pushad/pushfd
- 将全部寄存器压栈之后就对esp寄存器设硬件断点
- 运行程序,触发断点
- 删除硬件断点开始分析
一步到达OEP法:
要点:
- ctrl+f查找popad
- ctrl+i跳转到下一匹配处
- 找到匹配处,确认是壳加载完毕即将跳转到OEP部分,则设下断点运行到该处
- 只适用于极少数压缩壳
内存镜像法:
内存镜像法是在加壳程序被加载时,通过OD的ALT+M快捷键,进入到程序虚拟内存区段,然后通过加两次内存一次性断点,到达程序正确的OEP
原理:
内存镜像法的原理在于对于程序资源段和代码段下断点,一般程序自解压或者自解密时,会首先访问资源段获取所需资源,然后再自动脱壳完成后,转会程序代码段,这时候下内存一次性断点,程序就会停在OEP处.
最后一次异常法
程序在自解压或者自揭密过程中,可能会触发无数次的异常,如果能定位到最后一次异常的位置,可能就会很接近自动脱壳完成位置,现在最后一次异常法脱壳可以利用od的异常计数器插件,先记录异常数目,然后重新载入,自动停在最后一次异常处.
要点:
- 点击选项-调试选项-异常,把里面的√全部去掉!按ctrl+f2重新加载程序
- 开始程序就是一个跳转,在这里我们按SHIFT+f9,直到程序运行,记下从开始按HSIFT+f9到程序运行的次数m!
- ctrl+f2重新加载程序,继续按SHIFT+f9,这次按的次数为,m-1次
- 在od的右下角我们看见一个SE句柄,这时我们按ctrl+G,输入SE句柄前的地址
- 按F2下断点!然后按SHIFT+f9来到断点处,,按f8跟踪.
SFX法
sfx法利用了od自带的OEP寻找功能,可以选择直接让程序停在OD找到的OEP处,此时壳的解压过程已经完毕,可以直接dump程序。
要点:
- 设置OD,忽略所有异常,也就是说异常选项里都打上勾
- 切换到SFX选项卡,选择“字节模式跟踪实际入口(速度非常慢)",确定
- 重载程序(如果跳出是否压缩代码,选择”否“,OD直接到达oep
DUMP及IAT重建
找到程序OEP后,我们需要将程序dump出来,并重建IAT,IAT全名是Import address Table,表项指向函数实际地址
当我们找到了程序入口地址之后就需要将程序dump出来,但是有一个问题,就是dump出来的程序无法正常运行,大概率就是程序的IAT出现了问题,此时就需要重键IAT
我们需要用到ImportREc,选择一个正在运行的进程,Import REC修复输入表入口点需要直到OEP。
手动查找IAT并使用Import REC重建
首先使用esp定律,可以很快的跳转到OEP
右键od查找-所有模块间的调用后
显示出调用的函数列表,我们双击其中的某个函数
我们来到了函数调用处
进入函数
右键数据窗口中跟随——内存地址

浙公网安备 33010602011771号