脱壳技术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程序。

要点:

  1. 设置OD,忽略所有异常,也就是说异常选项里都打上勾
  2. 切换到SFX选项卡,选择“字节模式跟踪实际入口(速度非常慢)",确定
  3. 重载程序(如果跳出是否压缩代码,选择”否“,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查找-所有模块间的调用后

显示出调用的函数列表,我们双击其中的某个函数

我们来到了函数调用处

进入函数

右键数据窗口中跟随——内存地址

 

posted @ 2024-05-05 19:51  robot__i  阅读(108)  评论(0)    收藏  举报