x64dbg 分析命令组详解:函数分析、符号加载、PE 头检查与异常处理枚举
【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg
本篇技术指南围绕 x64dbg 官方文档中的 Analysis(分析)命令组展开,系统讲解该组 15 条命令的功能、参数与适用场景,包括analyse/analrecur等函数分析命令、cfanalyze控制流分析、symdownload/symload/symunload符号管理、imageinfoPE 头特性检查、GetRelocSize重定位表解析以及exhandlers/exinfo异常处理枚举。读完后,你将能够在 x64dbg 的命令行(Command Line)中熟练调度各类静态/动态分析能力,并借助脚本自动化逆向工程与恶意软件分析工作流。
命令组总览
x64dbg 的命令体系按功能域划分,Analysis 是其中专用于“分析”的类别,官方文档对该组的定义是:
This section contains commands that are used for analysis.(本节包含用于分析的命令。)
该组共包含 15 条命令,按能力可归纳为四类:
| 类别 | 命令(含别名) | 功能定位 |
|---|---|---|
| 代码分析 | analyse/analyze/anal、exanalyse/exanalyze/exanal、cfanalyze/cfanal/cfanalyse、analyse_nukem/analyze_nukem/anal_nukem、analxrefs/analx、analrecur/analr、analadv | 函数分析、异常目录分析、控制流分析、交叉引用分析 |
| 模块与符号 | virtualmod、symdownload/downloadsym、symload/loadsym、symunload/unloadsym、imageinfo | 虚拟模块、符号下载/加载/卸载、PE 映像信息 |
| 重定位 | GetRelocSize/grs | 计算重定位表的正确大小(解包还原场景) |
| 异常处理 | exhandlers、exinfo、traceexecute | 枚举异常处理器、转储 EXCEPTION_DEBUG_INFO、上报已跟踪地址 |
所有命令均在 x64dbg 的命令注册表中集中注册:
//analysis dbgcmdnew("analyse,analyze,anal", cbInstrAnalyse, true); //secret analysis command dbgcmdnew("exanal,exanalyse,exanalyze", cbInstrExanalyse, true); //exception directory analysis dbgcmdnew("cfanal,cfanalyse,cfanalyze", cbInstrCfanalyse, true); //control flow analysis dbgcmdnew("analyse_nukem,analyze_nukem,anal_nukem", cbInstrAnalyseNukem, true); //secret analysis command #2 dbgcmdnew("analxrefs,analx", cbInstrAnalxrefs, true); //analyze xrefs dbgcmdnew("analrecur,analr", cbInstrAnalrecur, true); //analyze a single function dbgcmdnew("analadv", cbInstrAnalyseadv, true); //analyze xref,function and data dbgcmdnew("traceexecute", cbInstrTraceexecute, true); //execute trace record on address TODO: undocumented dbgcmdnew("virtualmod", cbInstrVirtualmod, true); //virtual module dbgcmdnew("symdownload,downloadsym", cbDebugDownloadSymbol, true); //download symbols dbgcmdnew("symload,loadsym", cbDebugLoadSymbol, true); //load symbols dbgcmdnew("symunload,unloadsym", cbDebugUnloadSymbol, true); //unload symbols dbgcmdnew("imageinfo,modimageinfo", cbInstrImageinfo, true); //print module image information dbgcmdnew("GetRelocSize,grs", cbInstrGetRelocSize, true); //get relocation table size dbgcmdnew("exhandlers", cbInstrExhandlers, true); //enumerate exception handlers dbgcmdnew("exinfo", cbInstrExinfo, true); //dump last exception information两点值得注意:其一,注册名顺序即别名顺序,例如exanal也是exanalyse的合法别名,且文档标题中未列出;其二,imageinfo还有一个文档未提及的别名modimageinfo,从源码注册行可直接确认。注册函数第三个参数为true,表示这些命令在调试会话非活动状态下也可使用(或至少不要求目标处于暂停态之外的特定状态),这使它们适合在脚本开头对内存中的映像做预处理。
代码分析命令
analyse:全量函数分析
analyse(别名analyze、anal)执行函数分析(Do function analysis),不带任何参数,也不设置任何结果变量。它是逆向工作流中最常用的“一键标注”命令:在当前调试上下文中对整个目标模块做函数边界识别,结果会以函数标记的形式落入数据库,反汇编视图随即获得函数分界与调用树结构。
其底层实现由 src/dbg/analysis 目录下的分析框架支撑。Analysis 基类定义了分析任务的最小接口:
class Analysis { public: explicit Analysis(duint base, duint size); ... virtual void Analyse() = 0; // 执行分析 virtual void SetMarkers() = 0; // 将结果写入标记(函数/数据/注释等数据库) protected: duint mBase; duint mSize; unsigned char* mData; // 模块内存快照 Zydis mZydis; // 内嵌 Zydis 反汇编器 ... };所有分析子类都先在构造时抓取[mBase, mBase+mSize)的内存快照mData,再基于Zydis反汇编器在快照上工作,而不是反复读目标进程内存——这保证分析过程本身不会触发目标侧副作用,也便于对已 dump 出来的映像做离线式分析。
exanalyse:异常目录分析(仅 64 位)
exanalyse(别名exanalyze、exanal)执行异常目录分析(exception directory analysis),同样无参数、无结果变量。文档特别注明:
This kind of analysis doesn't work on 32-bit executables.(这类分析在 32 位可执行文件上不起作用。)
原因在于 64 位 Windows 的异常处理不再依赖 32 位时代__try/__except的__except_handler4目录,而是使用IMAGE_DIRECTORY_ENTRY_EXCEPTION中的 RUNTIME_FUNCTION 表;x64dbg 的 exceptiondirectoryanalysis 正是解析这张表,从而直接标出每个函数的边界与关联的 unwind 信息。因此在 x64dbg 中分析 64 位目标时,exanalyse往往比启发式函数分析更精确。
cfanalyze:控制流分析
cfanalyze(别名cfanal、cfanalyse)在反汇编视图中选定的模块(the module selected in the disassembly view)内做控制流分析(control flow analysis),无参数、无结果变量。
“在反汇编视图中选定的模块”这一限定词很关键:该命令不是无条件分析整个进程,而是以当前 CPU 视图光标所在的模块为分析域。其实现位于 controlflowanalysis,产物是模块内的基本块与控制边信息——这正是函数图(Graph 视图)的骨架数据来源。从 src/dbg/analysis 目录结构看,还存在BasicBlock.h、AnalysisPass.h、CodeFollowPass.cpp、FunctionPass.cpp、LinearPass.cpp等更细粒度的通道类,可以推断控制流分析结果被进一步切分为基本块、代码路径等中间表示,供图分析与标注共用。
analyse_nukem:Nukem 算法函数分析
analyse_nukem(别名analyze_nukem、anal_nukem)使用nukem 的算法做函数分析,无参数、无结果变量。这是 x64dbg 保留的“秘密命令”之一(源码注释写作secret analysis command #2),对应实现见 analysis_nukem。它与analyse的区别在于算法策略:nukem 算法是逆向社区流传的一套独立函数识别思路,适合在主分析结果不理想(例如大量间接跳转、OLLVM 混淆导致函数边界识别错误)时作为对照手段手动触发。
analxrefs:交叉引用分析
analxrefs(别名analx)在反汇编视图选定的模块内做交叉引用分析(xrefs analysis),无参数、无结果变量。它扫描模块内所有指令的操作数,识别指向函数、数据、字符串的地址引用并写入引用数据库,为 xrefs 视图(右键“References”)、字符串列表、跳转目标悬停提示提供数据。实现位于 xrefsanalysis。
analrecur:单函数分析
analrecur(别名analr)做单函数分析,是唯一带参数的分析类命令:
analrecur <arg1>arg1:待分析函数的基址(The base address of the function to analyze)。
适合的场景:你已知道某个函数入口(例如从导入表、跳转表或字符串引用处定位),只想对该函数做边界扩展与指令/数据分类,避免全量分析的高开销。实现见 recursiveanalysis。
analadv:组合分析
analadv一次执行三类分析:函数分析 + 内嵌数据分析 + 交叉引用分析(function analysis, embedded data analysis and xref analysis),无参数、无结果变量。它是上述analyse、数据标注、analxrefs的打包形态,适合在脚本中一条命令完成“标准三件套”,实现位于 advancedanalysis。
实战建议:对普通 PE 目标,脚本中用
analadv即可获得函数、数据、xref 三类标注;对 64 位目标可追加exanalyse获得基于异常目录的精确函数边界;遇到识别率下降时再回退到analyse_nukem对照。
traceexecute:上报跟踪地址
traceexecute告诉调试器某个地址已经被跟踪过(Tell the debugger that an address has been traced),参数为arg1:地址;无结果变量。它服务于条件运行跟踪(Conditional Tracing)流程:在外部工具(如脚本、插件)完成一段地址序列的遍历后,调用该命令把“这些地址已执行过”的事实回传给调试器,使跟踪引擎的“首次执行”判定保持正确。源码注册注释标注其 TODO 为 undocumented,说明该命令更偏向脚本/插件集成而非日常手工输入。
模块与符号管理命令
virtualmod:把内存区间当作虚拟模块
virtualmod让调试器把一个内存区间当作虚拟模块处理(Tell the debugger to treat a memory range as a virtual module),参数:
| 参数 | 必填 | 含义 |
|---|---|---|
arg1 | 是 | 用户指定的模块名(the user-supplied module name) |
arg2 | 是 | 内存区间的基址(the base of the memory range) |
arg3 | 否 | 内存区间的大小(the size of the memory range) |
典型用途:把从 dump 出来的 shellcode、从内存提取的加密段,或一个没有模块载体的 RWX 区域“挂”成一个命名模块,从而获得模块命名空间(modname:offset符号形式)、模块相关的反汇编视图与数据库支持。这对恶意软件分析中处理“无壳化 shellcode”非常实用——先用memcp/dump 把可疑区域取出,再用virtualmod赋予其模块身份进行分析。
symdownload / symload / symunload:符号生命周期
符号命令覆盖“下载 → 加载 → 卸载”完整生命周期:
symdownload(别名downloadsym):尝试从**符号服务器(Symbol Store)**下载符号:
symdownload [模块名] [符号服务器URL]| 参数 | 必填 | 说明 |
|---|---|---|
arg1 | 否 | 要下载符号的模块名,可带或不带扩展名;不指定时尝试为所有已加载模块下载符号 |
arg2 | 否 | 符号服务器 URL;不指定时使用默认符号仓库 |
symload(别名loadsym):从磁盘加载符号文件:
symload <模块名> <符号文件路径> [强制加载标志]| 参数 | 必填 | 说明 |
|---|---|---|
arg1 | 是 | 要加载符号的模块名(可带或不带扩展名) |
arg2 | 是 | 符号文件路径 |
arg3 | 否 | 强制加载标志,设为1时跳过符号校验(skip symbol validation) |
arg3的校验跳过在 PDB 与模块基址/时间戳不完全匹配(例如手工修补过的 dump 文件、重定位后的内存映像)时是关键开关:先不带强制标志尝试,报校验失败后再以symload mod.dll C:\symbols\mod.pdb 1强制加载。
symunload(别名unloadsym):卸载某模块的符号,参数arg1为模块名(可带或不带扩展名)。
三条命令均不设置结果变量,成功与否通过日志输出观察。符号加载完成后,反汇编视图中的地址会自动关联到符号名,exhandlers等枚举命令输出的符号化名称(SymGetSymbolicName)也随之生效,因此符号管理是提升后续一切分析输出可读性的前置步骤。
imageinfo:PE 头特性检查
imageinfo(源码别名modimageinfo)输出某模块的映像信息,内容即 PE 头结构中的Characteristics(特性)与DLL Characteristics字段:
imageinfo [arg1]arg1(可选):模块基址;不指定时使用当前 CIP 所在模块。
从实现 cbInstrImageinfo 看,命令以pFlag宏逐一打印每个 DLL 特性位及其人话解释,例如:
pFlag(dllc, IMAGE_DLLCHARACTERISTICS_NO_SEH, "IMAGE_DLLCHARACTERISTICS_NO_SEH: Image does not use SEH. No SE handler may reside in this image"); pFlag(dllc, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, "IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE: Remote Desktop Services aware.");这对静态判断目标行为很有价值:NO_SEH置位意味着该映像不安装结构化异常处理,配合exhandlers的输出可以快速判断异常处理策略;NO_ISOLATION、NO_BIND、WDM_DRIVER等标志位也在同一输出中呈现,是 PE 静态检查的高频速查命令。
GetRelocSize:重定位表大小计算
GetRelocSize(别名grs)计算一张重定位表的正确大小,文档说明其典型用途是解包时还原原始重定位表(useful while unpacking and restoring the original relocation table)。参数与结果:
| 项 | 内容 |
|---|---|
arg1 | 待分析的重定位表地址 |
| 结果 | 计算出的重定位表大小写入$result |
实现(cbInstrGetRelocSize,注释标明原始工具来自 Killboy/SND 的“GetRelocSize”)的算法逻辑非常直白:
IMAGE_RELOCATION RelocDir; do { if(!MemRead(RelocDirAddr, &RelocDir, sizeof(IMAGE_RELOCATION))) { _plugin_logputs("Invalid relocation table!"); return false; } if(!RelocDir.SymbolTableIndex) break; // 空块(块大小为0)表示表结束 RelocSize += RelocDir.SymbolTableIndex; RelocDirAddr += RelocDir.SymbolTableIndex; } while(RelocDir.VirtualAddress); ... varset("$result", RelocSize, false); _plugin_logprintf("Relocation table size: %X\n", RelocSize);它逐块读取IMAGE_RELOCATION头部,按SymbolTableIndex字段(即该块的字节数)累加并前移指针,直到遇到SymbolTableIndex == 0的空块;随后校验累加值非零,否则判定为非法表。理解这段实现后可以看到命令的两个隐含约定:表内必须存在SymbolTableIndex为 0 的终止块,且读取越界时命令会直接返回“Invalid relocation table!”。因此在脚本中的正确用法是:
grs <重定位表基址> // 然后使用 $result 作为完整表的长度,例如配合 savedata 或 memcp 还原对解包者而言,这弥补了手工 patch 重定位块容易漏算块尾的经典错误。
异常处理命令
exhandlers:枚举全部异常处理器
exhandlers把进程内所有异常处理器打印到日志,覆盖四类:
- SEH(StructuredExceptionHandler,结构化异常处理)
- VEH(VectoredExceptionHandler,矢量异常处理)
- VCH(VectoredContinueHandler,矢量继续处理)
- UnhandledExceptionFilter(未处理异常过滤器)
无参数、无结果变量。实现 cbInstrExhandlers 按处理器类型分别枚举,并对 32 位(EX_HANDLER_SEH)与 64 位(RUNTIME_FUNCTION)路径做了架构区分,随后通过SymGetSymbolicName将处理器地址符号化输出:
static void printExhandlers(const char* name, const std::vector<duint> & entries) { if(!entries.size()) return; dprintf("%s:\n", name); for(auto entry : entries) dputs_untranslated(SymGetSymbolicName(entry).c_str()); }对恶意软件分析,这份输出是判断“目标是否安装 VEH 钩子 / 自定义 SEH 拦截”的直接证据——很多反调试与内存保护行为就体现在这里的异常处理器链上。
exinfo:转储最后一次异常
exinfo打印最后一次异常的EXCEPTION_DEBUG_INFO结构,无参数、无结果变量。官方文档给出的示例输出:
EXCEPTION_DEBUG_INFO: dwFirstChance: 1 ExceptionCode: 80000001 (EXCEPTION_GUARD_PAGE) ExceptionFlags: 00000000 ExceptionAddress: 00007FFE16FB1B91 ntdll.00007FFE16FB1B91 NumberParameters: 2 ExceptionInformation[00]: 0000000000000008 ExceptionInformation[01]: 00007FFE16FB1B91 ntdll.00007FFE16FB1B91输出中异常码附带名称解析(如EXCEPTION_GUARD_PAGE),异常地址自动关联模块偏移符号。实战中它常与断点联动:在断点命令(Breakpoint Command)里挂exinfo,即可在每次命中时把异常上下文写入日志,用于追踪 guard page、单步异常、CONTEXT篡改等敏感行为。
典型组合工作流
把该组命令串起来,一个典型的“启动后自动化分析”脚本骨架大致是:
// 1. 若符号缺失,先补齐符号(全部模块) symdownload // 或针对特定模块从磁盘强制加载 // symload target.dll D:\symbols\target.pdb 1 // 2. 查看当前模块的 PE 特性(默认取 CIP 所在模块) imageinfo // 3. 标准三件套:函数 + 内嵌数据 + xref 分析 analadv // 4. 64 位目标追加异常目录分析,获得精确函数边界 exanalyse // 5. 需要时枚举异常处理器链,判断 VEH/SEH 钩子 exhandlers // 6. 对已知单一入口做补充分析 analrecur 0x140001230 // 7. 解包场景:计算重定位表真实大小 grs <重定位表地址> // 结果在 $result需要注意的前提:cfanalyze、analxrefs以“反汇编视图选中的模块”为分析域,执行前确认光标位于正确模块;exanalyse仅适用于 64 位目标;symdownload依赖可访问的符号仓库(可自定义 URL);GetRelocSize要求重定位表带有规范的零块终止符。
相关文档
分析命令组的各条命令页位于 docs/commands/analysis 目录,与本篇对应的原始文档:
- analyse/analyze/anal
- exanalyse/exanalyze/exanal
- cfanalyze/cfanalyse/cfanal
- analyse_nukem/analyze_nukem/anal_nukem
- analxrefs/analx
- analrecur/analr
- analadv
- virtualmod
- symdownload/downloadsym
- symload/loadsym
- symunload/unloadsym
- imageinfo
- GetRelocSize/grs
- exhandlers
- exinfo
- traceexecute
命令实现主要位于 src/dbg/commands/cmd-analysis.cpp,分析框架位于 src/dbg/analysis(含analysis.cpp、recursiveanalysis.cpp、controlflowanalysis.cpp、xrefsanalysis.cpp、exceptiondirectoryanalysis.cpp、advancedanalysis.cpp等),命令注册入口在 src/dbg/x64dbg.cpp。
【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考