反分析对抗(壳识别 / 脱壳 / 反混淆)

SkillDev tools

反分析对抗网关。编排:壳识别 → 简单壳脱壳 → 强壳脱壳 → 反混淆。 子技能:[[re-packer-id]] [[re-unpack-simple]] [[re-unpack-advanced]] [[re-deobfuscate]] [[re-evasion]]。 触发词:脱壳、查壳、加壳识别、壳、UPX、VMProtect、Themida、反调试、反混淆、花指令、unpack、anti-analysis。

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the 反分析对抗(壳识别 / 脱壳 / 反混淆) skill

What this skill tells your AI

The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-anti-analysis/SKILL.md and read by ahel’s review.

完整工作流

  1. 壳识别:[[re-packer-id]](能力:unpack —— 先识别再动手。DIE/PEiD 签名库扫描、节名异常(UPX0/.aspack/自定义)、入口点是否指向非首节、熵 >7、导入表极小。先记 OEP 线索(EP 附近 pushad 等壳入口特征),识别出的壳名决定路径
  2. 分派:简单压缩壳(UPX/ASPack/FSG)→ [[re-unpack-simple]](能力:unpack);强壳/虚拟化壳(VMProtect/Themida)→ [[re-unpack-advanced]](能力:unpack);识别不出 → 手动流程(按 [[re-unpack-simple]](能力:unpack) 的 ESP 定律 + 内存断点手动找 OEP,或按强壳流程处理),不硬猜壳名
  3. 简单壳脱壳:[[re-unpack-simple]](能力:unpack —— 优先官方/自动解包(upx -d)→ ESP 定律 / 内存断点找 OEP → OEP 解密完成后转储(时机见 [[re-analyze/platform-tips]] 关键经验,默认转储优先)→ IAT 修复(Scylla/ImpREC,Windows)
  4. 强壳脱壳:[[re-unpack-advanced]](能力:unpack —— 反调试对抗(scyllaHide 思路:NtQueryInformationProcess/时间差)→ 堆栈回溯/内存断点组合找 OEP → 转储(默认转储优先)→ IAT 修复(含重定向)→ 虚拟化代码区域标注(标记绕过而非还原)
  5. 反混淆:[[re-deobfuscate]](能力:deobfuscation —— 脱壳后若仍有花指令 / 控制流平坦化 / 字符串加密:花指令清除、平坦化还原(D-810/手动)、字符串解密循环定位与仿真、批量脚本化、还原前后对比验证
  6. 验证:脱壳产物 sha256 存档 → 沙箱内复跑([[re-sandbox]](能力:sandbox-setup) 判定脱干净、[[re-analyze/platform-tips]] 最高原则)→ 导入 [[re-ghidra]](能力:decompilationdebugging) / [[re-ida]](能力:decompilationdebugging) 确认 OEP 处可正常反编译;导入表可解析才算完成。产物交回原调用域继续(恶意样本回 [[re-malware]](能力:malware-behaviordocument-malwareevasion-analysiskey-extractionthreat-intel) 行为分析、破解目标转 [[re-cracking]](能力:license-analysis) 授权定位)

每步结果存档(证据路径 + sha256,见 [[re-triage]](能力:triage));壳指纹 / 脱壳产物是 [[re-ioc]](能力:threat-intel) YARA 特征来源。

反调试方法论(全库通用,见 [[re-analyze/analysis-contract]] 索引)

本网关适用的反调试分析方法论(用户实战经验),各技能坑与陷阱引用此处。

基础检测

  • AD1 启动即退出先查调试检测:EP/TLS/初始化函数
  • AD2 IsDebuggerPresent 不代表完整反调试:组合检测,别只 patch 一点
  • AD3 PEB BeingDebugged 用户态快速检测:找 PEB 访问/BeingDebugged/NtGlobalFlag
  • AD4 NtGlobalFlag 异常→查堆调试标志
  • AD5 CheckRemoteDebuggerPresent 不可靠:可能被 hook/替换/底层
  • AD6 NtQueryInformationProcess 是重点:ProcessDebugPort/ProcessDebugObjectHandle/ProcessDebugFlags
  • AD24 断 WinAPI 没命中 → 可能直接走 Native API:程序不一定调用 IsDebuggerPresent 等高层 API,可能直接调用 NtQueryInformationProcess、NtSetInformationThread、Zw 系列。分析时向下追。

异常机制

  • AD7 异常没崩溃→可能反调试:INT3/INT 2D/单步异常
  • AD32 INT3 不止一种形式:CC vs CD 03 长断点,异常行为不同
  • AD33 INT 2D 是 Windows 特殊反调试点:调试器下/正常运行行为不同
  • AD34 ICE 指令检测单步:F1 ICEBP
  • AD26 异常断点行为异常→查 VEH:AddVectoredExceptionHandler——INT3 被主动处理/单步异常被吞/异常后继续运行
  • AD27 SEH 链异常→可能反调试控制流:控制跳转/隐藏流程/检测 debugger

时间检测

  • AD8 断点后行为变化→查 Trap Flag:EFLAGS/异常次数
  • AD9 时间突然变慢→查时间反调试:QPC/GetTickCount/timeGetTime/RDTSC
  • AD10 RDTSC 检测不要只看一次读取:start-end delta、比较阈值、分支位置
  • AD11 Sleep 检测→查时间加速:Sleep(5000)+检查实际经过时间——调试环境/沙箱加速/时间跳跃
  • AD35 时间检测不只 RDTSC:RDTSCP/QPC/GetTickCount64/APIC timer

环境与工具特征

  • AD12 窗口/鼠标检测→环境真实性:自动化沙箱
  • AD16 调试器窗口检测低级但常见:OllyDbg/x64dbg/WinDbg/IDA 窗口类或进程名
  • AD17 进程列表检测→查工具指纹:debugger/monitor/sandbox,易误报
  • AD38 窗口检测只是低级手段:高级样本更倾向 API 行为/内存特征/异常行为
  • AD39 父进程检测:explorer→app vs debugger→app 启动链
  • AD40 命令行检测:debugger/sandbox/分析环境参数
  • AD31 程序只在 x64dbg 崩→查调试器特征:x64dbg 模块/窗口类/DLL 名称/内存特征
  • AD36 CPU 特征检测可能用于反调试:程序可能读取 CPUID、MSR、TSC 特性,用于区分真实机器、VM、调试环境。

硬件痕迹

  • AD29 硬件断点也失效→可能检测 DR 寄存器:DR0-DR3/DR7 或异常行为
  • AD43 调试寄存器不是唯一硬件痕迹:DR/LBR/性能计数器状态
  • AD15 硬件断点检测→查 DR 寄存器:DR0-DR3/DR6/DR7

线程与调试对象

  • AD25 线程突然消失→查 NtSetInformationThread:ThreadHideFromDebugger——主线程正常/逻辑断点无效/调试器看不到异常
  • AD30 调试器暂停后逻辑变化→查 Debug Object:ProcessDebugObjectHandle
  • AD37 调试器导致线程调度变化:线程执行顺序/锁竞争/APC 调度

自修改与断点

  • AD13 断点被清除→查硬件断点/自校验:0xCC 检测——校验代码段/比较 hash/扫描 0xCC
  • AD14 代码执行后恢复原样→可能是自修改:静态内容≠实际执行内容,需内存 dump/执行跟踪
  • AD28 断点后代码改变→检查 self-modifying code:55 8B EC→CC 8B EC——校验代码/恢复字节/主动检测断点

深层检测

  • AD41 PEB 检测不仅是 BeingDebugged:NtGlobalFlag/ProcessHeap flags/HeapForceFlags
  • AD42 内核调试检测:KdDebuggerEnabled/KdDebuggerNotPresent
  • AD44 反调试可能故意制造假逻辑:返回错误数据/修改算法结果/延迟执行/跳过关键逻辑——比退出更常见
  • AD21 内核级反调试→用户态 patch 无效:驱动/内核回调/内核对象检查需分析内核路径
  • AD22 反虚拟化≠反调试:目标不同——观察者 vs 分析环境,不要混为一谈

方法论

  • AD18 TLS Callback 比 Entry Point 更早执行:入口断点没触发反调试→查 TLS
  • AD23 入口断点没触发 → 不一定没执行,可能被 TLS callback 抢先:Windows PE 的 TLS callback 可以在 Entry Point 前执行代码。遇到程序启动即退出、入口断点无效,优先检查 TLS Directory。典型场景:anti-debug 初始化、壳初始化、环境检测。
  • AD19 反调试逻辑不要急着 patch:先确认检测结果如何影响控制流——退出/降功能/假数据/延迟
  • AD20 多点反调试→找汇聚点:多个检测汇聚到一个 flag/状态变量/错误处理函数
  • AD45 Patch 反调试点可能触发完整性检测:JNZ→JMP/CALL→NOP 触发 CRC/hash/self-check,先找检测链

反虚拟化方法论(全库通用,见 [[re-analyze/analysis-contract]] 索引)

本网关适用的反虚拟化分析方法论(用户实战经验),各技能坑与陷阱引用此处。

指令级与固件信息检测

  • AV-001 CPUID hypervisor 位检测
    • Trigger:程序执行 CPUID leaf 1,检查 ECX bit 31(hypervisor present bit)
    • Observation:ECX bit 31 置位,表明当前运行在 hypervisor 之下
    • Inference:样本在探测虚拟化环境——反虚拟化检测最常见的起点
    • Action:继续 CPUID vendor leaf(0x40000000)确认 hypervisor 类型(Microsoft Hv / VMwareVMware / KVMKVMKVM 等)
    • Constraint:hypervisor_present ≠ 一定是恶意分析环境——云主机与正常用户系统同样有 hypervisor,仅凭该位不能断定是分析环境
  • AV-002 注册表 BIOS/System 信息
    • Trigger:程序读取注册表 BIOS/System 信息(Manufacturer / ProductName / BIOS Version)
    • Observation:读取值被用于关联 VMware / VirtualBox / Hyper-V 特征字符串
    • Inference:注册表固件信息是 VM fingerprinting 的常见来源
    • Action:定位读取点与特征字符串匹配逻辑,收集全部命中的 VM 特征项
    • Constraint:单个字符串命中不能作为 VM 判断依据——需多特征联合判定

时间与硬件特征

  • AV-003 Sleep 前后时间差
    • Trigger:Sleep 前后实测时间差明显短于预期
    • Observation:样本 Sleep(N) 后检查实际经过时间,明显小于 N——时间被加速/压缩
    • Inference:样本可能检测沙箱时间加速/虚拟化时间(计时 API 被 hook 或时钟被加速)
    • Action:跟踪 RDTSC / QPC / GetTickCount 来源——定位时间读数点与差值计算逻辑,确认样本所用时钟源
    • Constraint:时间检测常多点组合(RDTSC 配 CPUID 强制 VM exit、GetTickCount / QPC 交叉验证),别只处理一处
  • AV-004 硬件设备枚举
    • Trigger:程序枚举硬件设备(PCI / Disk model / GPU name)
    • Observation:枚举结果与虚拟机硬件型号特征比对
    • Inference:VM fingerprinting——硬件设备型号是常见 VM 指纹来源
    • Action:建立硬件特征集合而非单点判断——列出全部被检查的硬件项,按集合整体评估
    • Constraint:单一硬件特征(如某块 disk model)不足以判定 VM,需特征集合联合评估

环境评分与交互检测

  • AV-005 检测结果汇聚统一变量
    • Trigger:多个 VM 检测函数的检测结果写入统一变量(is_vm / sandbox_score / env_flag)
    • Observation:多处检测代码汇聚到同一变量/状态
    • Inference:样本采用环境评分机制——多检测项计数/加权汇成环境评分
    • Action:追踪汇聚变量——在变量读写处下断或静态追 xref,避免逐检测点分析
    • Constraint:只看单个检测点会漏掉整体评分逻辑——评分阈值与组合方式是关键
  • AV-006 用户交互检测
    • Trigger:程序检测用户交互(鼠标 / 键盘 / uptime / 窗口活动)
    • Observation:样本检查鼠标移动、键盘输入、系统 uptime、窗口活动等交互痕迹
    • Inference:样本试图区分真实用户与自动沙箱——交互痕迹属于行为级环境指纹
    • Action:转向行为级分析而非硬件指纹——交互相关分支需动态配合(模拟交互或真实环境观察)
    • Constraint:交互检测多为行为级,纯静态难以完整还原——需与动态观察结合

虚拟化通道与执行路径

  • AV-007 VMware 专有通道调用
    • Trigger:程序调用 VMware backdoor / Guest Additions / vmtools
    • Observation:样本访问 VM 专有通道(VMware I/O port backdoor、vmtools 服务/进程、Guest Additions 模块)
    • Inference:高概率虚拟化检测——这些通道只在虚拟机环境中真实存在
    • Action:确认调用结果如何影响控制流——定位 backdoor 调用点与返回值使用位置,再决定 patch 策略
    • Constraint:检测到 VM 通道不一定会退出——先看检测结果流向再动手
  • AV-008 检测结果影响执行路径
    • Trigger:检测结果影响执行路径——VM 环境进入不同分支
    • Observation:检测为"是 VM"与"非 VM"走向不同代码分支
    • Inference:反虚拟化不仅用于退出——可能改变样本行为(假逻辑 / 降功能 / 不同载荷)
    • Action:分析两个分支差异——对比 VM / 非 VM 两条路径的代码与数据,别只 patch 检测点
    • Constraint:与反调试假逻辑同理(见反调试方法论 AD44)——patch 后别直接信任输出

何时用哪个原子技能(选择树)

先识别、再选脱壳路径;识别不出走手动流程。

  • 输入是未知样本 / 怀疑带壳 → [[re-packer-id]](能力:unpack) 识别 → 按结果分支(不跳步)
    • 识别出简单压缩壳(UPX / ASPack / FSG 等)→ [[re-unpack-simple]](能力:unpack
    • 识别出强壳 / 虚拟化壳(VMProtect / Themida 等)→ [[re-unpack-advanced]](能力:unpack
    • 识别不出壳名(无签名匹配)→ 手动流程:先按 [[re-unpack-simple]](能力:unpack) 的 ESP 定律 + 内存断点尝试;失败或发现反调试/虚拟化特征 → [[re-unpack-advanced]](能力:unpack) 手动脱壳
  • 目标只是确认壳("这是什么壳")→ [[re-packer-id]](能力:unpack) 即可,不进入脱壳
  • 脱壳后仍有代码混淆(花指令 / 平坦化 / 字符串加密)→ [[re-deobfuscate]](能力:deobfuscation
  • 目标已确认无壳 → 不需要本网关,转 [[re-binary-core]](能力:decompilationdebuggingmemory-dumpelf-parserpe-parsermacho-parser;[[re-ghidra]](能力:decompilationdebugging) / [[re-ida]](能力:decompilationdebugging) / [[re-radare2]](能力:decompilation))直接分析
  • 检测规避/EDR 对抗(AMSI/ETW 绕过、无文件、lolbin 链,样本被检测"为什么") → [[re-evasion]](能力:evasion-analysis;动态优先,配 [[re-sandbox]](能力:sandbox-setup) / [[re-memdump]](能力:memory-dump))
  • 脱壳全程需要读进程内存 → [[re-memdump]](能力:memory-dump;OEP 后默认转储);Windows 调试 → [[re-x64dbg]](能力:debugging);Linux/Wine 调试 → [[re-gdb]](能力:debugging

跨域联合

  • 恶意样本加壳:[[re-malware]] → 本网关(packer-id → unpack-*),脱壳产物回沙箱复跑再行为分析
  • 破解前置:[[re-cracking]] → 本网关(带壳先脱壳,再定位授权逻辑),授权定位产物供补丁/注册机
  • 移动加固:[[re-mobile]] / [[re-apk]] → 本网关(Android 加固脱壳)
  • 静态发现壳:[[re-binary-core]] / [[re-format-pe]] / [[re-format-elf]] / [[re-imports]](导入表极小/壳隐藏导入)→ 转入本网关
  • 动态辅助:[[re-gdb]](断 OEP、Wine 下脱壳)、[[re-x64dbg]](Windows OEP + Scylla)、[[re-memdump]](OEP 后默认转储)、[[re-tracing]](反调试样本检测 trace 环境时配合)
  • 脱壳产物验证必须沙箱:[[re-sandbox]]([[re-analyze/platform-tips]] 最高原则)
  • 壳层常量污染指纹:[[re-crypto-id]] 加壳样本先脱壳再做常量表指纹
  • 检测规避对抗:[[re-evasion]] —— 壳/混淆是"静态反分析",AMSI/ETW/无文件/lolbin 是"检测对抗",同属本网关(动态分析强制 [[re-sandbox]])
  • 本网关被 [[re-analyze]] 的 triage「样本带壳 / 脱壳」路径调用(re-anti-analysis → packer-id → unpack-* → 验证)

常见坑与陷阱

  • 跳过识别直接脱:现象——拿样本就上调试器/OEP 流程,撞上强壳反调试或浪费时间;原因——没先判壳类别;对策——先 [[re-packer-id]] 识别,简单壳自动解包秒解,强壳才值得上手动流程

  • 转储时机过早:现象——dump 出来还是壳的初始状态(压缩/加密数据),脱了个寂寞;原因——壳未运行到 OEP 就转储;对策——等解密完成后 dump([[re-analyze/platform-tips]] 关键经验,默认转储优先)

  • IAT 不修当成品:现象——脱壳后导入表乱,Ghidra/IDA 反编译一片混沌;原因——导入表在壳内动态重建,转储未修复;对策——Windows 上 Scylla/ImpREC 修复,修复后重新反编译验证

  • 壳套壳:现象——脱完一层发现里面还有一层(UPX 里包 Themida 等);原因——多层加壳是常见反分析手法;对策——脱一层验证一层(sha256 + 导入表 + 沙箱复跑),套层时回到第 1 步重新识别

  • 反调试干扰整个流程:现象——调试器断点不生效、进程退出、时序错乱;原因——样本检测调试器(NtQueryInformationProcess、时间差、调试端口);对策——[[re-unpack-advanced]] 反调试对抗先行(scyllaHide 思路),先攻最外层检测

  • OutputDebugString 计时陷阱:现象——样本调用 OutputDebugStringA/W 后行为不同,或调试器下某段代码明显变慢触发时间检测;原因——调试器处理 ODS 消息有固定慢路径(接收-格式化-刷新),样本以长字符串 ODS 调用的耗时差异当调试器探针(2024-2025 恶意样本仍在使用);对策——定位 ODS 调用点断住/绕过(返回假值或直接跳过),或 scyllaHide 隐藏 ODS 处理,与时间差检测(AD9)一并排查

  • 高熵≠加密:现象——.of2 这类节 4KB 熵 7.9 判"整体加密",静态放弃;原因——可能是压缩(deflate 无标准头)、VMProtect 变异代码、或纯数据;对策——分区采样(入口区 64B 熵可能只有 5.6 是真代码),先排除压缩与变异再谈加密;变异代码特征:ror/xor 链 + 跨区 jmp、顺序解码出现 fcom/int 88h/ret far 类垃圾但入口 24 字节是 call/syscall 结构

  • 调试体系全链路(反调试点位):现象——不理解"附加为什么让程序暂停"、不知道反调试该改哪里;原因——缺 Windows 调试体系全链路认知;对策——链路:DebugActiveProcessDbgUiConnectToDbg(创建 DEBUG_OBJECT 先挂调试器,句柄存 TEB->DbgSsReserved[1](偏移 0x16A8))→NtDebugActiveProcessDbgkpSetProcessDebugObject(被调试进程挂上)+DbgkpPostFake*Messages(附加时刷屏的"创建线程/加载 dll"假消息);调试事件流:被调试进程检测被调试→创建 DEBUG_EVENT 挂入 EventList 双向链表→置位 EventsPresent 信号量唤醒调试器→死等 ContinueEvent;反调试点DbgUiRemoteBreakIn 创建远程线程执行 int3 让程序断下(去掉该 int3 则附加断不下来);TEB+0x16A8 是调试对象句柄(检测/篡改干扰调试器);异常先发给调试器(DbgkSendApiMessageDbgkpQueueMessage,flag=0 需等待 vs NOWAIT 假消息)

  • so 函数级加密(dlsym 运行时解密):现象——so 里个别函数(如 mymyadd)反编译是乱码/未定义指令,其余正常;原因——so 加固把目标函数按符号名加密:函数代码段静态是密文,运行时 dlopen+dlsym 前先解密覆盖、调用完再加密回去;对策——还原思路:dlsym 符号解析链(__loader_dlsymdlsym_impldo_dlsymdlsym_handle_lookupfind_symbol_by_name,GNU hash / ELF hash 二选一:GNU hash 需算 gnu_hash + 布隆过滤器 + 从 PT_DYNAMIC 找符号表),按 ELF 头→程序头表→PT_DYNAMIC 定位符号表与哈希表计算函数位置与大小;动态侧:断 dlopen/dlsym 返回后、解密后的函数内存处 dump(转储时机关键经验);变体:段头 type 逐段 XOR(MODE_DUPLEX)需要自定义 linker 加载才能跑;还有对 .text 整体加密后自解密——先确认是函数级还是段级再选方案

Signals

GitHub stars
57
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
re-anti-analysis
Source
github.com/dslsdzc/rev-skills