Skip to content

动态 API 解析链还原 ​

1. 入口信号 ​

text
Import Table 很少或为空
字符串里没有 WinAPI 名称,但行为明显调用网络/进程/注册表
Ghidra 看到 fs:[0x30] / gs:[0x60] / PEB_LDR_DATA
循环遍历 export name table 并计算 hash
大量常量形如 0xEC0E4E8E、0x7C0DFCAA

目标是把 hash/函数指针恢复成 API 名称,并给后续 x64dbg/Frida 断点提供真实函数表。

2. 静态定位 ​

powershell
python scripts/misc/ai_tool.py run triage_pe -- samples/app.exe --out exports/pe/app/triage.json
python scripts/misc/ai_tool.py run ghidra_headless_analyze -- samples/app.exe --out exports/pe/app/ghidra
rg -n "GetProcAddress|LoadLibrary|VirtualAlloc|WinHttp|RegSetValue" exports/pe/app

Ghidra 里优先找这些形态:

c
// PEB walk
peb = *(longlong *)(in_GS_OFFSET + 0x60);
ldr = *(longlong *)(peb + 0x18);

// export parser
names = image + export->AddressOfNames;
ordinals = image + export->AddressOfNameOrdinals;
functions = image + export->AddressOfFunctions;

// hash loop
hash = ror(hash, 13);
hash += tolower(ch);

3. Hash 反解脚本 ​

python
import pefile

def ror32(v, n):
    return ((v >> n) | (v << (32 - n))) & 0xffffffff

def api_hash(name: str) -> int:
    h = 0
    for ch in name:
        h = ror32(h, 13)
        h = (h + ord(ch.lower())) & 0xffffffff
    return h

targets = {0xec0e4e8e, 0x7c0dfcaa}
for dll in ["C:/Windows/System32/kernel32.dll", "C:/Windows/System32/advapi32.dll", "C:/Windows/System32/wininet.dll"]:
    pe = pefile.PE(dll)
    for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
        if not exp.name:
            continue
        name = exp.name.decode(errors="ignore")
        h = api_hash(name)
        if h in targets:
            print(hex(h), dll, name)

把匹配结果回填到 Ghidra:

text
api_hash_0xec0e4e8e -> VirtualAlloc
api_hash_0x7c0dfcaa -> CreateThread

4. 动态断点 ​

text
bp kernel32.LoadLibraryA
bp kernel32.LoadLibraryW
bp kernel32.GetProcAddress
bp ntdll.LdrGetProcedureAddress
bp kernel32.VirtualAlloc
bp kernel32.WriteProcessMemory

如果样本手写 EAT parser,不会命中 GetProcAddress。改断 hash compare:

text
findallmem 8E4E0EEC
bp <hash_compare_addr>

命中后记录:

text
module base:
export name candidate:
computed hash:
matched constant:
resolved function pointer:

5. 路径分叉 ​

解析结果下一跳
VirtualAlloc/VirtualProtectunpack / shellcode dump
CreateRemoteThread/WriteProcessMemoryinjection 行为链
WinHttpSendRequest/InternetOpenUrlC2 / protocol
RegSetValueEx/CreateServicepersistence / IOC
BCrypt/CryptDecryptcrypto replay

5.1 校验函数联动(keygen 场景) ​

许可证校验函数常动态解析比较/哈希 API(02-validation-function-location 的导入表 信号往往被解析链隐藏)。处置:

  1. 先解析出实际调用的 API 名(本节动态断点法)
  2. 在解析结果上追加两条分叉:
解析结果下一跳
lstrcmpW/CompareStringW/memcmp 对比点常量表对比 → 10-license-keygen/03 算法还原
BCryptVerifySignature 或自实现模幂签名链 → 10-license-keygen/04 公钥替换

校验函数本身可用 10-license-keygen/02 的三步定位法(字符串 xrefs 反查)直接命中, 无需等待解析链——两条路径互为备份。

6. 攻击链 / 工作流 ​

text
Import Table 稀疏 / 行为与导入不匹配
  → Ghidra 找 PEB walk、EAT parser 或 hash loop
  → 用脚本反解 hash 常量并回填 API 名称
  → x64dbg 断 LoadLibrary/GetProcAddress 或 hash compare
  → 建立函数指针表
  → 按解析结果跳到 unpack、network、injection、persistence 或 crypto

7. Evidence ​

项记录内容
Hash 算法rotate、大小写、初始值、DLL 名是否参与
常量表hash 常量、匹配 API、DLL
函数指针表table VA/RVA、slot、写入位置
动态命中GetProcAddress 参数或 hash compare
下一跳unpack、IOC、crypto、patch

8. MCP 工具映射 ​

步骤MCP 工具用途
初筛triage_pe判断 import 稀疏、节区异常
静态图ghidra_headless_analyze定位 PEB walk 和 hash loop
断点make_x64dbg_breakpoint_script生成 LoadLibrary/GetProcAddress 断点
知识路由kb_router按 api hash、PEB、resolver 查下一篇

GPL-3.0 · 仅供授权环境下的学习与防御性研究使用