0%

脱壳对抗

不要慌, 壳一般都是有对抗的. 先干对抗. 注意混淆代码的call 不能步过.

脱壳对抗

不要慌, 壳一般都是有对抗的. 先干对抗.

1. IAT表的混淆

混淆代码的call 不能步过

  1. 生成混淆代码
  2. 将IAT中原API地址放入混淆代码中, 以ret或其他特征jmp到原API地址
  3. 将混淆代码的地址, 覆盖原IAT项

2. 脚本

  1. x64dbg 安装脚本(x64dbgpy)

    • 环境: python 2.7
    • API:
      • ~/x64dbgpy/pluginsdk/_scriptapi
  2. 思路

    • 遍历混淆后的IAT
      • 逐项查找混淆代码的特征, 提取原API地址
      • 逐项恢复IAT
  3. 实现

    1. 默认不支持中文注释

      • # -*- coding:utf-8 -*-
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      # -*- coding:utf-8 -*-

      from x64dbgpy.pluginsdk._scriptapi import *

      dwIatbase = 0x00475000 #iat表的首地址
      dwIatCount = 0x48 #iat表中的个数

      #循环取出iat表中的地址, 然后设为新eip,单步到ret
      for i in range(0, dwIatCount+1):
      #读取IAT表中的地址
      dwAddr = ReadDword(dwIatbase + i*4)

      #排除0
      if(dwAddr == 0):
      continue

      #以此地址为新eip
      SetEIP(dwAddr)

      #单步执行
      while True:
      StepIn()

      # 判断是否是ret
      if(ReadByte(GetEIP()) == 0xC3):
      #从栈顶取出真正的API地址,存入IAT表中对 应的位置
      WriteDword(dwIatbase + i*4, ReadDword(GetESP()))
      break #退出循环

      3. 打补丁

有时还会需要写一段shellcode, 调用壳函数得到API地址

  1. 思路
    • 混淆IAT, 要用混淆后的代码地址覆盖原API地址
      • 打补丁:
        • 使IAT填入正确的API地址.
      • 核心:
        1. 拿到真正API的地方
        2. 往IAT填入混淆代码地址的地方
    • 拿到真正API地址的时候, 临时存一下
    • 往IAT填入混淆代码地址时, 将真正的API写入IAT
  2. 混淆的关键流程
    • 申请堆
    • 拿到API地址
    • 写入混淆代码
    • 混淆代码中写入API地址
    • 混淆代码地址写入IAT
  3. 切入点
    • 申请堆
      • 对申请的堆设置写入断点
      • 观察栈和寄存器的情况, 写入实际API肯定会通过栈或寄存器传递.

扩展

  1. VMP 壳, 带VMP字样的一般以月为单位.
  2. python目录尽量不用中文.