ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Binary Analysis Patterns 逆向工程实战指南:agents24 插件的汇编模式识别与程序逻辑重建手册

Binary Analysis Patterns 逆向工程实战指南:agents24 插件的汇编模式识别与程序逻辑重建手册 Binary Analysis Patterns 逆向工程实战指南agents24 插件的汇编模式识别与程序逻辑重建手册【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents本指南以 agents24 仓库中plugins/reverse-engineering插件的binary-analysis-patterns技能为骨架系统讲解二进制静态分析的核心模式从反汇编基础、控制流识别到数据结构重建、反编译类型恢复再到 Ghidra / IDA Pro 的自动化脚本实践。读完本文你将掌握一套可复用的汇编模式 → 高级语义映射方法能够对未知可执行文件、恶意样本或混淆二进制开展有条理的静态分析并在分析过程中熟练运用模式识别加速逆向结论的产出。技能概览binary-analysis-patterns 是什么、何时使用binary-analysis-patterns是 agents24 仓库plugins/reverse-engineering插件下的四个技能之一其定义位于 SKILL.md--- name: binary-analysis-patterns description: Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, understanding compiled code, or performing static analysis on binaries. ---该技能的目标是提供分析编译后二进制、理解汇编代码、重建程序逻辑的综合性模式与方法论。根据文档的 When to Use This Skill 一节典型适用场景包括对一个未知可执行文件进行逆向工程理解其行为使用 Ghidra / IDA Pro / Binary Ninja 分析恶意软件或混淆二进制识别常见汇编惯用法函数序言/尾声、跳转表 switch、虚表分发 vtable dispatch从编译产物中重建高层控制流识别编译器引入的模式栈金丝雀 stack canaries、PIC 跳板 trampolines。在 docs/agent-skills.md 的技能目录中该技能与anti-reversing-techniques抗逆向与混淆技术、memory-forensics内存取证、protocol-reverse-engineering协议逆向共同构成逆向工程领域的能力栈其中binary-analysis-patterns专攻读懂二进制本身这一层——它是其余三项技能的共同前置能力。渐进式披露结构SKILL.md 与 references/details.md 的分工阅读 SKILL.md 时第一处值得注意的信息是Originally a 2047-byte section in this SKILL.md. Moved toreferences/details.mdto fit Codexs 8 KB skill body cap.这是本仓库在技能编写规范上的有意设计。根据 docs/authoring.md 的说明Codex 会对超过 8 KB 的 SKILL.md 正文进行硬截断并发出警告因此仓库强制要求将深度内容下沉到skills/name/references/目录下的文件中由 Agent 按需加载仓库的SKILL_OVER_CODEX_CAPlint 会对正文超过 8 KB 但没有 references/ 目录的技能报错。binary-analysis-patterns技能完整遵循了这一渐进式披露progressive disclosure架构共分三层元数据Frontmatter技能名称与激活条件始终加载指令层Instructions即 SKILL.md 正文——控制流、数据结构、代码模式、反编译模式、工具脚本与最佳实践作为导航与速查资源层Resources即 references/details.md——反汇编基础x86-64 指令模式、调用约定、ARM 汇编按需加载。这意味着阅读本文时务必同时把 SKILL.md 与 references/details.md 视为同一套知识体系的两部分。下文先补齐被拆分出去的反汇编基础再依次展开其余模式。反汇编基础Disassembly Fundamentals本小节内容原属 SKILL.md 的 2047 字节章节现完整保存在 references/details.md是后续所有模式识别的地基。x86-64 指令模式函数序言与尾声函数边界是静态分析的第一步。标准序言prologue与尾声epilogue模式如下; Standard prologue push rbp ; Save base pointer mov rbp, rsp ; Set up stack frame sub rsp, 0x20 ; Allocate local variables ; Leaf function (no calls) ; May skip frame pointer setup sub rsp, 0x18 ; Just allocate locals ; Standard epilogue mov rsp, rbp ; Restore stack pointer pop rbp ; Restore base pointer ret ; Leave instruction (equivalent) leave ; mov rsp, rbp; pop rbp ret实战要点叶子函数不再调用其他函数的函数通常省略帧指针设置编译器直接sub rsp, N分配局部空间leave是mov rsp, rbp; pop rbp的等价单指令。遇到push rbp; mov rbp, rsp; sub rsp, N三连即可立即确认函数入口遇到帧指针省略-fomit-frame-pointer的二进制则需要靠调用目标的交叉引用定位函数边界。调用约定Calling Conventions调用约定决定了参数在哪、返回值在哪、谁负责清理栈。理解它们是重建函数签名的前提。System V AMD64Linux / macOS; Arguments: RDI, RSI, RDX, RCX, R8, R9, then stack ; Return: RAX (and RDX for 128-bit) ; Caller-saved: RAX, RCX, RDX, RSI, RDI, R8-R11 ; Callee-saved: RBX, RBP, R12-R15 ; Example: func(a, b, c, d, e, f, g) mov rdi, [a] ; 1st arg mov rsi, [b] ; 2nd arg mov rdx, [c] ; 3rd arg mov rcx, [d] ; 4th arg mov r8, [e] ; 5th arg mov r9, [f] ; 6th arg push [g] ; 7th arg on stack call funcMicrosoft x64Windows; Arguments: RCX, RDX, R8, R9, then stack ; Shadow space: 32 bytes reserved on stack ; Return: RAX ; Example: func(a, b, c, d, e) sub rsp, 0x28 ; Shadow space alignment mov rcx, [a] ; 1st arg mov rdx, [b] ; 2nd arg mov r8, [c] ; 3rd arg mov r9, [d] ; 4th arg mov [rsp0x20], [e] ; 5th arg on stack call func add rsp, 0x28注意 Windows 的 x64 调用有 32 字节的shadow space阴影空间且调用前后rsp需按 16 字节对齐——这也是为什么sub rsp, 0x28这类非 8 的倍数立即数在 Windows 二进制中高频出现。ARM 汇编模式ARM64AArch64调用约定; Arguments: X0-X7 ; Return: X0 (and X1 for 128-bit) ; Frame pointer: X29 ; Link register: X30 ; Function prologue stp x29, x30, [sp, #-16]! ; Save FP and LR mov x29, sp ; Set frame pointer ; Function epilogue ldp x29, x30, [sp], #16 ; Restore FP and LR retARM64 没有独立的调用栈指令函数返回依赖链接寄存器 X30序言中的stp x29, x30, [sp, #-16]!先减后存与尾声中的ldp x29, x30, [sp], #16先取后加是成对出现的识别标志。ARM32 调用约定; Arguments: R0-R3, then stack ; Return: R0 (and R1 for 64-bit) ; Link register: LR (R14) ; Function prologue push {fp, lr} add fp, sp, #4 ; Function epilogue pop {fp, pc} ; Return by popping PCARM32 的经典返回手法是pop {fp, pc}——直接弹回程序计数器 PC 完成返回。控制流模式Control Flow Patterns控制流重建是理解程序干什么的核心环节。SKILL.md 给出了三种最高频的控制流模式。条件分支Conditional Branches比较指令cmp与条件跳转指令的组合决定分支方向且有符号与无符号比较使用的跳转助记符不同; if (a b) cmp eax, ebx jne skip_block ; ... if body ... skip_block: ; if (a b) - signed cmp eax, ebx jge skip_block ; Jump if greater or equal ; ... if body ... skip_block: ; if (a b) - unsigned cmp eax, ebx jae skip_block ; Jump if above or equal ; ... if body ... skip_block:识别技巧有符号比较用jge / jl / jle / jg基于 SF/OF 标志无符号比较用jae / jb / jbe / ja基于 CF 标志。看到jae而看不到符号扩展cdq/movsx时基本可以断定是无符号比较。循环模式Loop Patterns编译器会把for、while、do-while三种高级循环翻译成可区分的结构; for (int i 0; i n; i) xor ecx, ecx ; i 0 loop_start: cmp ecx, [n] ; i n jge loop_end ; ... loop body ... inc ecx ; i jmp loop_start loop_end: ; while (condition) jmp loop_check loop_body: ; ... body ... loop_check: cmp eax, ebx jl loop_body ; do-while loop_body: ; ... body ... cmp eax, ebx jl loop_body模式区分是核心技巧do-while条件检查在循环体末尾且无条件跳转最少while编译器常生成先jmp到末尾检查、再跳回循环体的守卫式结构for则表现为典型的初始化 → 条件 → 体 → 增量 → 回跳四段式。识别出这些骨架后即使遇到优化过的代码也能快速还原高级语义。Switch 语句模式Switch Statement Patterns大 switch 与小 switch 的编译策略截然不同; Jump table pattern mov eax, [switch_var] cmp eax, max_case ja default_case jmp [jump_table eax*8] ; Sequential comparison (small switch) cmp eax, 1 je case_1 cmp eax, 2 je case_2 cmp eax, 3 je case_3 jmp default_case跳转表jump tablecase 数量多且值稠密时编译器生成一张地址表jmp [jump_table eax*8]一条指令完成分发*8表示 8 字节指针*4则为 4 字节指针顺序比较sequential comparisoncase 少时退化为一串cmp/je。在 Ghidra 与 IDA 中跳转表通常会被自动识别并还原为switch但理解底层模式有助于手工处理被混淆或自定义的表结构。数据结构模式Data Structure Patterns从汇编访问模式反推数据结构布局是从机器码回到源代码的关键一步。数组访问Array Access; array[i] - 4-byte elements mov eax, [rbx rcx*4] ; rbxbase, rcxindex ; array[i] - 8-byte elements mov rax, [rbx rcx*8] ; Multi-dimensional array[i][j] ; arr[i][j] base (i * cols j) * element_size imul eax, [cols] add eax, [j] mov edx, [rbx rax*4]寻址中的缩放因子scale factor直接泄露元素大小*4说明元素 4 字节int/float*8说明 8 字节long/double/指针。多维数组的规律base (i * cols j) * element_size可直接用于推导数组维数与列数。结构体访问Structure Access结构体成员的偏移量由字段顺序与对齐规则决定struct Example { int a; // offset 0 char b; // offset 4 // padding // offset 5-7 long c; // offset 8 short d; // offset 16 };; Accessing struct fields mov rdi, [struct_ptr] mov eax, [rdi] ; s-a (offset 0) movzx eax, byte [rdi4] ; s-b (offset 4) mov rax, [rdi8] ; s-c (offset 8) movzx eax, word [rdi16] ; s-d (offset 16)分析要点char b占 1 字节后紧跟 3 字节 padding导致long c落到 offset 8short d落在 offset 16。同一段内存的字节宽度byte/word/dword/qword与读取方式movzx零扩展 /movsx符号扩展相结合即可逐步推断字段类型这是重建结构体定义最可靠的方法。链表遍历Linked List Traversal; while (node ! NULL) list_loop: test rdi, rdi ; node NULL? jz list_done ; ... process node ... mov rdi, [rdi8] ; node node-next (assuming next at offset 8) jmp list_loop list_done:test rdi, rdi; jz是空指针判断的标准惯用法mov rdi, [rdi8]把指针字段取出作为下一轮遍历指针——指针字段在结构体中的偏移此处为 8可直接写入重建的结构体定义。常见代码模式Common Code Patterns字符串、算术与位操作是库函数和业务代码中最常见的识别对象它们的汇编形态高度规律。字符串操作String Operations; strlen pattern xor ecx, ecx strlen_loop: cmp byte [rdi rcx], 0 je strlen_done inc ecx jmp strlen_loop strlen_done: ; ecx contains length ; strcpy pattern strcpy_loop: mov al, [rsi] mov [rdi], al test al, al jz strcpy_done inc rsi inc rdi jmp strcpy_loop strcpy_done: ; memcpy using rep movsb mov rdi, dest mov rsi, src mov rcx, count rep movsb三个模式的辨识度都很高strlen以cmp byte [...], 0逐字节扫描终止符strcpy以取字节→存字节→test al, al实现逐字节拷贝memcpy则常被优化为rep movsb硬件串指令实现块拷贝。注意到这些模式后可直接在反汇编器中标注疑似 strlen / strcpy / memcpy再通过交叉引用验证库调用。算术模式Arithmetic Patterns编译器对常量乘法与除法的优化极具特征性; Multiplication by constant ; x * 3 lea eax, [rax rax*2] ; x * 5 lea eax, [rax rax*4] ; x * 10 lea eax, [rax rax*4] ; x * 5 add eax, eax ; * 2 ; Division by power of 2 (signed) mov eax, [x] cdq ; Sign extend to EDX:EAX and edx, 7 ; For divide by 8 add eax, edx ; Adjust for negative sar eax, 3 ; Arithmetic shift right ; Modulo power of 2 and eax, 7 ; x % 8乘法lea的base index*scale寻址被大量复用为常数乘法x*3 x x*2、x*5 x x*4有符号除以 2 的幂因为算术右移对负数向下取整编译器先cdq扩展符号位再用and edx, 7提取下取整修正量加到被除数上最后sar eax, 3完成除以 8——看到cdq and add sar四连即可断定是有符号数除以 2 的幂取模 2 的幂一条and eax, 7就是x % 8。位操作Bit Manipulation; Test specific bit test eax, 0x80 ; Test bit 7 jnz bit_set ; Set bit or eax, 0x10 ; Set bit 4 ; Clear bit and eax, ~0x10 ; Clear bit 4 ; Toggle bit xor eax, 0x10 ; Toggle bit 4 ; Count leading zeros bsr eax, ecx ; Bit scan reverse xor eax, 31 ; Convert to leading zeros ; Population count (popcnt) popcnt eax, ecx ; Count set bits位操作模式直白且极高频test reg, mask; jnz/jz是位测试or置位、and清位、xor翻转。两个值得注意的进阶模式bsr反向位扫描配合xor eax, 31实现前导零计数popcnt指令在支持它的 CPU 上直接完成汉明重量计算——遇到popcnt往往意味着源码调用了std::bitset::count或自定义的位计数函数。反编译模式Decompilation Patterns反编译器输出的质量取决于我们能否正确喂给它信息。以下三组模式是手动修正反编译结果的高效手段。变量恢复Variable Recovery; Local variable at rbp-8 mov qword [rbp-8], rax ; Store to local mov rax, [rbp-8] ; Load from local ; Stack-allocated array lea rax, [rbp-0x40] ; Array starts at rbp-0x40 mov [rax], edx ; array[0] value mov [rax4], ecx ; array[1] value帧指针rbp稳定的二进制中[rbp-N]就是局部变量槽位同一个rbp偏移被反复读写即对应同一变量lea rax, [rbp-0x40]之后紧跟连续偏移写入说明rbp-0x40处是数组基址。函数签名恢复Function Signature Recovery; Identify parameters by register usage func: ; rdi used as first param (System V) mov [rbp-8], rdi ; Save param to local ; rsi used as second param mov [rbp-16], rsi ; Identify return by RAX at end mov rax, [result] ret在 System V 调用约定下函数开头将rdi、rsi保存到栈帧的动作直接暴露了参数顺序函数末尾写入rax的指令则揭示了返回值来源。结合上一节的调用约定知识Windows 用rcx/rdx/r8/r9ARM64 用x0-x7可以为反编译器手工修正__fastcall/__cdecl/ 自定义签名。类型恢复Type Recovery操作数的字节宽度与是否符号扩展是类型推断的最直接证据; 1-byte operations suggest char/bool movzx eax, byte [rdi] ; Zero-extend byte movsx eax, byte [rdi] ; Sign-extend byte ; 2-byte operations suggest short movzx eax, word [rdi] movsx eax, word [rdi] ; 4-byte operations suggest int/float mov eax, [rdi] movss xmm0, [rdi] ; Float ; 8-byte operations suggest long/double/pointer mov rax, [rdi] movsd xmm0, [rdi] ; Double映射规则清晰1 字节 →char/bool2 字节 →short4 字节 →int/floatmovss是浮点信号8 字节 →long/doublemovsd/指针。movzx表示无符号语义、movsx表示有符号语义。批量套用这套映射即可为反编译器标注结构体与函数参数类型显著提升反编译 C 代码的可读性。Ghidra 分析技巧Ghidra Analysis TipsGhidra 的脚本能力Java/Python 双语言使其成为可深度定制的分析平台。SKILL.md 给出了两组直接可用的脚本模式。改进反编译Improving DecompilationGhidra 自动分析有时会漏掉签名与结构信息用脚本强制修正// In Ghidra scripting // Fix function signature Function func getFunctionAt(toAddr(0x401000)); func.setReturnType(IntegerDataType.dataType, SourceType.USER_DEFINED); // Create structure type StructureDataType struct new StructureDataType(MyStruct, 0); struct.add(IntegerDataType.dataType, field_a, null); struct.add(PointerDataType.dataType, next, null); // Apply to memory createData(toAddr(0x601000), struct);要点setReturnType配合SourceType.USER_DEFINED可覆盖自动推导的返回类型StructureDataType按字段依次添加并附带字段名最后通过createData将结构体应用到全局内存地址——这样反编译器就会以命名字段的形式呈现结构体访问而不是一坨裸偏移。模式匹配脚本Pattern Matching ScriptsGhidra Python 可以枚举函数与引用批量定位危险调用# Find all calls to dangerous functions for func in currentProgram.getFunctionManager().getFunctions(True): for ref in getReferencesTo(func.getEntryPoint()): if func.getName() in [strcpy, sprintf, gets]: print(fDangerous call at {ref.getFromAddress()})这个模式是引用驱动的审计的范本遍历函数管理器 → 收集每个函数的引用 → 按名字过滤危险函数 → 输出调用点地址。同样的骨架可以扩展为查找所有对malloc的引用用于内存泄漏审计、查找对特定 API 的引用用于行为特征识别等。IDA Pro 模式IDA Pro PatternsIDA 的 IDAPython 是逆向工程事实标准脚本环境与 Ghidra 脚本形成互补。IDAPython 分析import idaapi import idautils import idc # Find all function calls def find_calls(func_name): for func_ea in idautils.Functions(): for head in idautils.Heads(func_ea, idc.find_func_end(func_ea)): if idc.print_insn_mnem(head) call: target idc.get_operand_value(head, 0) if idc.get_func_name(target) func_name: print(fCall to {func_name} at {hex(head)}) # Rename functions based on strings def auto_rename(): for s in idautils.Strings(): for xref in idautils.XrefsTo(s.ea): func idaapi.get_func(xref.frm) if func and sub_ in idc.get_func_name(func.start_ea): # Use string as hint for naming pass第一个函数演示了指令级扫描遍历所有函数 → 遍历函数内的所有指令地址Heads→ 识别call助记符 → 取操作数并解析目标函数名 → 输出调用点。第二个函数展示了以字符串为线索的自动命名思路字符串的交叉引用指向某个函数则该函数很可能与该字符串相关——实战中可将pass替换为idc.set_name(...)完成批量改名这是对sub_XXXX函数进行语义标注的高效路径。最佳实践分析工作流与常见陷阱推荐分析工作流Analysis WorkflowSKILL.md 将一次完整的静态分析组织为 7 个阶段初步分诊Initial triage文件类型、架构、导入/导出表字符串分析String analysis识别敏感字符串、错误信息函数识别Function identification入口点、导出函数、交叉引用控制流映射Control flow mapping理解程序整体结构数据结构恢复Data structure recovery识别结构体、数组、全局变量算法识别Algorithm identification加密、哈希、压缩算法特征文档化Documentation注释、重命名符号、类型定义。这套流程与仓库中 reverse-engineer.md 描述的四阶段方法论侦察 → 静态分析 → 动态分析 → 文档化相互印证binary-analysis-patterns技能提供的正是第二阶段静态分析所需的全部模式库。常见陷阱Common Pitfalls静态分析最大的敌人是编译器优化造成的源码结构失真。文档明确列出五类陷阱优化器产物Optimizer artifacts机器码结构可能与源码结构不一致不要试图逐行对应内联函数Inline functions函数可能被展开进调用者看不到独立的函数边界尾调用优化Tail call optimization尾部调用被改写为jmp而非callret会造成调用链断裂的错觉死代码Dead code优化后存在不可达代码应基于交叉引用而非线性扫描判断活跃度位置无关代码Position-independent codePIC 使用 RIP 相对寻址地址不是绝对的分析时必须换算基址。在插件生态中的定位与使用方式binary-analysis-patterns属于plugins/reverse-engineering插件安装命令为/plugin install reverse-engineering参见 docs/plugins.md。该插件还包含三个可与之组合使用的技能anti-reversing-techniques防护与混淆技术、memory-forensics内存取证、protocol-reverse-engineering协议逆向以及reverse-engineer、malware-analyst、firmware-analyst三个专职 Agent。实际工作流中技能与 Agent 是协作关系reverse-engineerAgent 负责高层推理与编排选择工具、制定分析策略binary-analysis-patterns技能则在需要具体汇编模式、反编译修正手段或 Ghidra/IDA 脚本骨架时被按需加载——这正是本仓库渐进式披露设计的意义所在只在需要时加载对应深度避免把 8 KB 以上内容一次性塞进上下文。分析受保护样本时建议同时加载anti-reversing-techniques技能以识别并应对反调试、加壳等防护手段二者配合可覆盖读懂二进制与突破保护的完整闭环。无论你使用 Ghidra、IDA Pro 还是 Binary Ninja本技能提供的模式映射都是通用的先建立反汇编基础认知再用控制流与数据结构模式还原骨架最后以脚本和文档固化结论。这套方法论同样适用于 CTF 逆向题、恶意样本分析、闭源库行为审计与固件安全研究等授权场景。【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表