IDA Pro 重定位信息编程指南:深入解析 ida_fixup 模块的加载器 Fixup API
逆向工程MCP 服务AI 应用【免费下载链接】ida-pro-mcpAI-powered reverse engineering assistant that bridges IDA Pro with language models through MCP.项目地址https://gitcode.com/gh_mirrors/id/ida-pro-mcp点击查看免费下载导读本文以 IDA Pro 官方 IDAPython 文档 ida_fixup 及其完整 RST 源文件 ida_fixup.rst 为主体系统讲解 IDA 内核中重定位/修正信息relocation/fixup information的管理 API。Fixup 是加载器loader向 IDA 数据库写入的重要元数据它描述了二进制文件中哪些字节需要被修正、修正目标是什么段选择符 偏移或绝对地址、以及修正后的值如何参与反汇编与反编译。读完本文你将掌握ida_fixup模块全部核心函数与fixup_data_t类的用法能够为自定义文件格式编写加载器级 fixup 支持、读取既有二进制中的重定位加数relocation addend、以及在 MCP 驱动的 IDA 会话中通过py_eval调用这些 API。一、Fixup 是什么加载器视角的重定位元数据在可执行文件被 IDA 加载时加载器loader_t负责把文件字节映射到数据库。对于含重定位信息的格式PE、ELF 的.reloc、Mach-O 的__LINKEDIT等加载器需要把源地址的哪些字节、以何种方式、指向哪个目标记录下来——这就是 fixup 信息。IDA 内核据此完成两类工作操作数转换operand conversion在反汇编/反编译时把源地址处的字节解析为指向目标地址的引用形成交叉引用xref输出与重定位在生成汇编/二进制输出时根据 fixup 恢复正确的重定位语义。正如 ida_fixup.rst 开头所述Functions that deal with fixup information. A loader should setup fixup information usingset_fixup().——即加载器应当用set_fixup()来建立 fixup 信息这是整个模块的核心约定。fixup_data_t描述一次 fixup 的目标目标段选择符、目标偏移、位移量而源地址则是由调用set_fixup(source, fd)时传入的source参数决定的。在反汇编器模块层面fixup 还会参与引用信息reference info的调整。参见 ida_idp.rst 中处理器模块的ev_adjust_refinfo(ri, ea, n, fd)回调它会在apply_fixup 把操作数转换为引用之前被调用处理器模块可以借此修改引用信息例如 PPC 模块会为某些引用添加REFINFO_NOBASE该回调的最后一个参数正是fixup_data_t const *——印证了 fixup 与引用转换之间的直接协作关系。二、模块核心函数全解2.1 查询类get_fixup / exists_fixupget_fixup(fd: fixup_data_t, source: ea_t) - bool— 获取地址source处的 fixup 信息并填充到fd中。返回True表示该地址存在 fixup。通常与fixup_data_t实例配合先构造一个fd ida_fixup.fixup_data_t()再调用ida_fixup.get_fixup(fd, ea)。exists_fixup(source: ea_t) - bool— 快速检查给定地址是否存在 fixup无需构造容器对象。import ida_fixup import ida_idaapi ea 0x401000 # 待检查地址 fd ida_fixup.fixup_data_t() if ida_fixup.get_fixup(fd, ea): print(f{ea:#x}: type{fd.get_type():#x} flags{fd.get_flags():#x})2.2 写入与删除类set_fixup / del_fixupset_fixup(source: ea_t, fd: fixup_data_t) - None— 设置 fixup 信息。文档明确说明You should fill fixup_data_t and call this function and the kernel will remember information in the database.应先填充fixup_data_t再调用本函数内核会把信息写入数据库。其中source是被 fixup 修改的地址即源地址。del_fixup(source: ea_t) - None— 删除指定地址的 fixup 信息。这是加载器最常用的写入路径也是 ida_fixup.rst 强调的加载器标准做法。fixup_data_t还提供了便捷封装fd.set(source)等价于set_fixup(source, fd)fd.get(source)等价于get_fixup(fd, source)。2.3 遍历类get_first_fixup_ea / get_next_fixup_ea / get_prev_fixup_ea这三个函数用于遍历数据库中的全部 fixupget_first_fixup_ea() - ea_t— 获取第一个 fixup 的地址BADADDR表示没有 fixupget_next_fixup_ea(ea) - ea_t— 获取ea之后的下一个 fixup 地址get_prev_fixup_ea(ea) - ea_t— 获取ea之前的上一个 fixup 地址。ea ida_fixup.get_first_fixup_ea() while ea ! ida_idaapi.BADADDR: print(ffixup at {ea:#x}) ea ida_fixup.get_next_fixup_ea(ea)在旧式idc接口中对应idc.get_next_fixup_ea与idc.get_prev_fixup_ea见 idc.rst新代码应优先使用ida_fixup模块。2.4 值与字节互转get_fixup_value / patch_fixup_value这是两个语义相反、且与具体架构编码紧密相关的函数get_fixup_value(ea, type) - int— 从地址ea处读取 fixup 字节并转换为操作数值可能只转换一部分主要用于获取重定位加数relocation addend。文档给出的两个例子非常直观FIXUP_HI8读取ea处一个字节然后左移 8 位AArch64 的自定义 fixupBRANCH26取ea处指令的低 26 位再左移 2 位。patch_fixup_value(ea, fd) - bool— 把fd中的 fixup 数据写回ea处的数据或指令与上面方向相反。例如FIXUP_HI8会把fd.off的高字节写入eaAArch64BRANCH26则把fd.off右移 2 位后的值写入指令低 26 位。注意返回值语义返回False表示 fixup 字节放不下例如BRANCH26要求fd.off不大于0xFFFFFFC但即使返回 False数据库也可能已被修改——调用方必须自己处理这种部分写坏的情况。fixup_data_t同样提供封装fd.get_value(ea)与fd.patch_value(ea)。2.5 描述与尺寸get_fixup_desc / calc_fixup_sizeget_fixup_desc(source, fd) - str— 获取 fixup 的描述注释FIXUP description comment用于在反汇编窗口中展示。calc_fixup_size(type) - int— 计算某类 fixup 占用的字节数即该 fixup 会 patch 多少个字节出错返回-1。fd.calc_size()是其类方法封装。2.6 区间查询contains_fixups / get_fixupscontains_fixups(ea, size) - bool— 判断指定地址区间[ea, easize)内是否包含任何 fixup 信息。get_fixups(out, ea, size) - bool— 把区间内所有 fixup 填充到fixups_t输出容器中配合fixup_info_t它封装了ea与对应的fd。if ida_fixup.contains_fixups(0x401000, 0x100): print(range 0x401000..0x4010FF contains fixups)2.7 段移动/重基址gen_fix_fixupsgen_fix_fixups(_from, to, size) - None— 重新定位带有 fixup 信息的字节是通用函数可被loader_t::move_segm()调用如果其内置实现满足需求若加载器未定义move_segm则在移动段或整个程序重基址rebasing时会自动调用本函数。文档特别注明特殊参数约定当从rebase_program(delta)调用时使用特殊参数值from BADADDR, size 0, to delta。这解释了它在整程序平移地址场景下如何以 delta 形式表达偏移。2.8 宏指令场景handle_fixups_in_macrohandle_fixups_in_macro(ri, ea, other, macro_reft_and_flags) - bool— 处理宏指令macro中成对出现的两个 fixup。反汇编器经常把两条加载值一部分的指令合并成一条宏指令例如ADRP X0, #varPAGE ADD X0, X0, #varPAGEOFF -- ADRL X0, var或 MIPSlui $v0, %hi(var) addiu $v0, $v0, %lo(var) -- la $v0, var返回False表示ri引用信息未被修改即调用失败或无需修改。三、fixup_data_tfixup 元数据容器fixup_data_t是描述一次 fixup 目标的容器类基类object由三个公开属性构成完整语义属性类型含义selsel_t目标段的选择符selectorBADSEL表示绝对零基目标offea_t来自ida_idaapi目标偏移displacementadiff_t位移量相对目标的偏移三个属性共同刻画fixup 要指向哪里sel:off定位目标位置displacement描述目标附近的额外偏移。3.1 类型与标志访问get_type() - fixup_type_t/set_type(type_)— 读写 fixup 类型见第四章的FIXUP_*。set_type_and_flags(type_, flags_0)— 一次性同时设置类型与标志。is_custom() - bool— 是否为处理器专属的自定义 fixup等价于is_fixup_custom(type)。get_flags() - int— 获取 fixup 标志FIXUPF_*见第五章。3.2 标志快捷方法is_extdef() / set_extdef() / clr_extdef()— 目标是否为符号external definition而非段偏移is_unused() / set_unused() / clr_unused()— 该 fixup 是否被 IDA 忽略见FIXUPF_UNUSED语义has_base() - bool— 是否为相对 fixup相对于基地址而非段相对was_created() - bool— 该 fixup 是否为 IDA 创建的原始文件中不存在对应FIXUPF_CREATED。3.3 基地址与选择符get_base() - ea_t/set_base(new_base)— 读写相对 fixup 的基地址。注意文档明确set_base要求在调用前已设置好目标The target should be set before a call of this function因为基地址语义依赖目标。set_sel(seg)— 根据segment_t指针设置选择符set_target_sel()— 把选择符设置为目标段的选择符同样要求目标已设置。3.4 便捷封装与处理器set(source)/get(source)— 分别等价于模块函数set_fixup(source, fd)与get_fixup(fd, source)get_handler()— 等价于get_fixup_handler(type)获取标准或自定义 fixup 的处理器对象fixup_handler_t const *get_desc(source)— 等价于get_fixup_desc(source, fd)calc_size()— 等价于calc_fixup_size(get_type())get_value(ea)/patch_value(ea)— 等价于同名模块函数。四、Fixup 类型FIXUP_*详解fixup_type_t枚举描述源地址的字节如何编码目标值。下表按位宽与语义分类类型含义字节数典型FIXUP_OFF88 位无符号偏移1FIXUP_OFF1616 位无符号偏移2FIXUP_OFF3232 位无符号偏移4FIXUP_OFF6464 位无符号偏移8FIXUP_OFF8S8 位有符号偏移1FIXUP_OFF16S16 位有符号偏移2FIXUP_OFF32S32 位有符号偏移4FIXUP_SEG1616 位基段逻辑段基选择符2FIXUP_PTR1632 位长指针16 位基 : 16 位偏移4FIXUP_PTR3248 位指针16 位基 : 32 位偏移6FIXUP_HI816 位偏移的高 8 位1FIXUP_HI1632 位偏移的高 16 位2FIXUP_LOW816 位偏移的低 8 位1FIXUP_LOW1632 位偏移的低 16 位2FIXUP_CUSTOM自定义处理器专属类型区间的起始值依处理器而定其中FIXUP_HI8/HI16/LOW8/LOW16用于 x86 系列把 16/32 位地址拆成高低两半存储的场景与第二章get_fixup_value/patch_fixup_value的移位语义一一对应FIXUP_SEG16/FIXUP_PTR16/FIXUP_PTR32则对应实模式与保护模式的段:偏移寻址。RST 文档还列出了两个已废弃常量V695_FIXUP_VHIGH/V695_FIXUP_VLOW标注 obsolete仅为历史兼容保留新代码不应使用。模块函数is_fixup_custom(type) - bool用于判断一个类型是否落在自定义区间由处理器模块处理find_custom_fixup(name: str) - fixup_type_t可按名称查找自定义 fixup 类型。五、Fixup 标志FIXUPF_*详解标志位get_flags()返回值控制 IDA 内核如何解释与使用该 fixup标志含义FIXUPF_RELfixup 相对于线性地址base即相对 fixup否则为相对于sel选择符对应段起点的段相对 fixupFIXUPF_EXTDEF目标是符号location而非段当目标是符号而非从段起点开始的偏移时应置位FIXUPF_UNUSEDIDA 忽略该 fixup禁止内核转换操作数输出时也不使用该 fixupFIXUPF_CREATED该 fixup 在输入文件中不存在由 IDA 创建FIXUPF_LOADER_MASK加载器专用附加标志位掩码这些位不写入数据库加载器可在其职责范围内自由使用值得注意FIXUPF_LOADER_MASK的设计它为加载器提供了进程内临时状态通道不会污染数据库持久化数据。而FIXUPF_UNUSED与fixup_data_t.is_unused()/set_unused()/clr_unused()直接对应用于标记不想让 IDA 据此转换操作数的 fixup。六、在 ida-pro-mcp 环境中使用 ida_fixup本仓库是一个把 IDA Pro 与语言模型通过 MCPModel Context Protocol桥接的逆向工程助手。其 Python 执行环境在 api_python.py 中构建所有ida_*模块都被注入执行上下文其中ida_fixup: lazy_import(ida_fixup)见 api_python.py#L55采用惰性导入——模块存在即可用导入失败返回None不影响其他模块。因此在 MCP 工具py_eval中可以直接使用本篇文章讲解的全部 APIimport ida_fixup, ida_idaapi # 遍历所有 fixup 并输出目标信息 ea ida_fixup.get_first_fixup_ea() count 0 while ea ! ida_idaapi.BADADDR: fd ida_fixup.fixup_data_t() if ida_fixup.get_fixup(fd, ea): t fd.get_type() print(f{ea:#x}: type{t:#x} size{ida_fixup.calc_fixup_size(t)} fsel{fd.sel:#x} off{fd.off:#x} disp{fd.displacement}) count 1 ea ida_fixup.get_next_fixup_ea(ea) print(ftotal fixups: {count})使用建议正如 SKILL.md 的实践准则所言应优先使用现代ida_*模块而非旧idc接口涉及数据库修改的set_fixup/patch_fixup_value等写操作建议先通过ida_auto.auto_wait()等待自动分析完成并注意patch_fixup_value即使返回False也可能已改动数据库的边界行为。对于从idc迁移的老代码idc.rst 中保留了get_fixup_target_type/flags/sel/off/dis、set_fixup(ea, fixuptype, fixupflags, targetsel, targetoff, displ)与del_fixup等兼容函数可用于对照理解参数顺序。七、实战示例为自定义格式加载器写入 fixup综合以上 API一个把某源地址记录为指向目标段内符号偏移的典型加载器代码如下import ida_fixup import ida_segment import ida_idp source 0x401234 # 源地址文件中存有需要修正的字节 target_ea 0x502000 # 目标地址已被加载到数据库中 seg ida_segment.getseg(target_ea) fd ida_fixup.fixup_data_t() fd.sel seg.sel # 目标段选择符 fd.off target_ea - seg.start_ea # 段内偏移 fd.displacement 0 fd.set_type(ida_fixup.FIXUP_OFF32) # 32 位绝对偏移 fd.set_extdef() # 目标是符号便于形成命名引用 ida_fixup.set_fixup(source, fd) # 写入数据库 # 验证 fd2 ida_fixup.fixup_data_t() assert ida_fixup.get_fixup(fd2, source) print(ida_fixup.get_fixup_desc(source, fd2))要点回顾先填fd再调用set_fixup顺序不可颠倒sel BADSEL表示绝对目标sel 具体段选择符表示段相对目标需要符号化引用时置FIXUPF_EXTDEF需要相对基址时置FIXUPF_REL并配合set_base且必须先设目标若实现loader_t::move_segm重定位逻辑可直接复用gen_fix_fixups的通用实现或在rebase_program场景下按fromBADADDR, size0, todelta约定调用处理器专属的编码如 AArch64BRANCH26、x86 高低半字拆分通过FIXUP_CUSTOM区间 get_fixup_handler/get_fixup_value/patch_fixup_value配合实现。八、总结ida_fixup模块是连接文件字节与反汇编语义的桥梁fixup_data_t描述目标sel/off/displacementFIXUP_*描述编码方式FIXUPF_*描述语义约束set_fixup/get_fixup/del_fixup构成数据库读写闭环gen_fix_fixups与handle_fixups_in_macro则覆盖段重定位与宏指令合成的进阶场景。结合本仓库 api_python.py 注入的执行环境这些 API 可以在 MCP 会话中直接以py_eval调用用于加载器开发、重定位加数提取与反汇编结果校验。完整签名与边界语义如patch_fixup_value的失败仍改库行为、FIXUPF_LOADER_MASK不落库约定可随时查阅配套的 ida_fixup.rst 源文档。赞分享逆向工程MCP 服务AI 应用【免费下载链接】ida-pro-mcpAI-powered reverse engineering assistant that bridges IDA Pro with language models through MCP.项目地址https://gitcode.com/gh_mirrors/id/ida-pro-mcp点击查看免费下载相关推荐WritingTools内容摘要功能详解如何一键总结网页、YouTube视频和文档WritingTools内容摘要功能详解如何一键总结网页、YouTube视频和文档 WritingTools是一款智能系统级语法助手它能够一键总结网页、Yo逆向工程MCP 服务AI 应用Audacity音频编辑终极指南7个专业技巧让你成为音频处理高手Audacity音频编辑终极指南7个专业技巧让你成为音频处理高手 你是否曾经为嘈杂的录音而烦恼是否在剪辑音频时感到无从下手Audacity作为一款免费开源音频处理桌面应用音视频如何在Java中轻松实现数据帧操作Joinery快速入门指南如何在Java中轻松实现数据帧操作Joinery快速入门指南 在Java开发中处理表格数据时你是否常常感到繁琐和低效Joinery作为一款专为Java设计逆向工程MCP 服务AI 应用上一篇未来已来Google ML Kit Flutter生成式AI功能探索打造智能图像描述与语音识别应用下一篇最完整的Docmost分享功能指南从公开链接到权限控制全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考