跳转至

  • 压缩壳
  • 加密壳

UPX壳

壳的加载

  1. 保存入口点的参数
    1. 加载程序初始化时保存各个寄存器的值
    2. 外壳程序执行完毕后, 恢复寄存器的值
    3. 跳到源程序执行
  2. 获取所需的函数API
    1. 一般壳的导入表中只有GetProcAddress, GetModuleHandleLoadLibrary
    2. 如果需要其他的API函数, 则通过LoadLibraryA(w)或者是LoadLibraryExA(w)将dll文件映射到调用进程的地址空间中
    3. 如果DLL文件已经映射到调用进程的地址空间中, 就可以调用GetModleHandleA(w)函数获得DLL模块的句柄
    4. 一旦DLL模块被加载, 就可以调用GetProcAddress获得输入函数的地址
  3. 解密各区块的数据
  4. 跳回原程序的入口点
    1. 先恢复原PE文件的IAT,处理重定位项
    2. 加壳的时候, 外壳自己构造了一个输入表, 重新对每一个dll引入的函数获取地址, 填写到IAT表中

脱壳

  • 自动脱壳
    • 正常脱
    • 改待修改字如CTF...为UPX\
      • 可以通过DIE等工具看一下哪些被修改了, imhex有文件对功能, 也可以使用
      • imhex双击修改字节
  • 手脱
    1. 查壳
    2. 寻找OEP
    3. Dump内存
    4. 输入表重建(IAT)
    5. 关闭程序重定位

寻找OEP

单步跟踪

  • F8单步向下
  • 大循环使用F4来跳过
  • 壳代码的入口点是一个近call, 不要跳过, 跟入
  • 大幅度跳转的jmp指令, 都有可能跳到了原程序的入口点

ESP定律

通过堆栈平衡来快速的找到OEP 1. 程序刚开始push 2. 将寄存器压栈后就在rsp/esp寄存器所在处设置硬件访问断点 3. 运行程序, 触发断点

修复IAT

X64的自带插件

去重定位

  • File Header的Charateristics
  • Optional Header的DllCharateristics
  • 去掉Relocation info