x64dbg 分析命令组详解:函数分析、符号加载、PE 头检查与异常处理枚举
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, mBasemSize)的内存快照mData再基于Zydis反汇编器在快照上工作而不是反复读目标进程内存——这保证分析过程本身不会触发目标侧副作用也便于对已 dump 出来的映像做离线式分析。exanalyse异常目录分析仅 64 位exanalyse别名exanalyze、exanal执行异常目录分析exception directory analysis同样无参数、无结果变量。文档特别注明This kind of analysis doesnt 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_nukemNukem 算法函数分析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 arg1arg1待分析函数的基址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 namearg2是内存区间的基址the base of the memory rangearg3否内存区间的大小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 validationarg3的校验跳过在 PDB 与模块基址/时间戳不完全匹配例如手工修补过的 dump 文件、重定位后的内存映像时是关键开关先不带强制标志尝试报校验失败后再以symload mod.dll C:\symbols\mod.pdb 1强制加载。symunload别名unloadsym卸载某模块的符号参数arg1为模块名可带或不带扩展名。三条命令均不设置结果变量成功与否通过日志输出观察。符号加载完成后反汇编视图中的地址会自动关联到符号名exhandlers等枚举命令输出的符号化名称SymGetSymbolicName也随之生效因此符号管理是提升后续一切分析输出可读性的前置步骤。imageinfoPE 头特性检查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把进程内所有异常处理器打印到日志覆盖四类SEHStructuredExceptionHandler结构化异常处理VEHVectoredExceptionHandler矢量异常处理VCHVectoredContinueHandler矢量继续处理UnhandledExceptionFilter未处理异常过滤器无参数、无结果变量。实现 cbInstrExhandlers 按处理器类型分别枚举并对 32 位EX_HANDLER_SEH与 64 位RUNTIME_FUNCTION路径做了架构区分随后通过SymGetSymbolicName将处理器地址符号化输出static void printExhandlers(const char* name, const std::vectorduint 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依赖可访问的符号仓库可自定义 URLGetRelocSize要求重定位表带有规范的零块终止符。相关文档分析命令组的各条命令页位于 docs/commands/analysis 目录与本篇对应的原始文档analyse/analyze/analexanalyse/exanalyze/exanalcfanalyze/cfanalyse/cfanalanalyse_nukem/analyze_nukem/anal_nukemanalxrefs/analxanalrecur/analranaladvvirtualmodsymdownload/downloadsymsymload/loadsymsymunload/unloadsymimageinfoGetRelocSize/grsexhandlersexinfotraceexecute命令实现主要位于 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),仅供参考