You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64反编译:判定无条件分支指令b的跳转目标归属

ARM64反编译中b指令跳转目标的判断方法及工具实现逻辑

一、核心判断:地址范围与节区归属

判断b指令是函数内跳转还是跨函数,最基础的逻辑是地址归属校验:

  • 首先确认当前函数的起止地址:Mach-O二进制中,可通过符号表(__symtab)、函数起始表(__functab)或Objective-C方法列表(__objc_methlist)直接获取函数的边界。如果b的目标地址落在当前函数的起始、结束地址之间,即可判定为函数内标签跳转。
  • 若目标地址不在当前函数范围内,再看节区归属:如果目标位于__text节之外(比如__stubs、__objc_stubs、__objc_msgSend_stub_helper这类存根节),必然是跨函数(通常是外部函数的间接调用入口);如果在同一__text节,则需要进一步用启发式规则判断。

二、ARM64无编码差异下的经验规则

和x86不同,ARM64的b指令没有短跳转/远跳转的编码区分——它的偏移是26位(左移2位后对应±128MB的跳转范围),没法靠指令长度区分函数内/外。此时工具会采用以下经验规则:

  • 跳转距离阈值:如果b指令的跳转距离超过一定阈值(通常是512~1024字节,不同工具略有差异),会倾向于判定为跨函数跳转,但这不是绝对规则——超长函数(比如包含大量分支的业务逻辑函数)也可能存在长距离的函数内跳转。
  • 函数特征匹配:检查目标地址的指令序列,是否符合ARM64函数的起始特征(比如栈帧初始化指令stp x29, x30, [sp, #-0x10]! + mov x29, sp);同时检查当前指令所在位置的后续代码,是否存在ret、blr x30这类函数返回指令,若当前位置已经接近函数结尾,跳转更可能是跨函数。

三、主流反编译工具的实现逻辑

主流工具(IDA、Ghidra、Binary Ninja)的判断逻辑分层递进:

  1. 优先依赖元数据:首先读取Mach-O的官方元数据(符号表、函数表、Objective-C元数据),直接确定所有函数的边界,b指令的目标归属一目了然。
  2. 元数据缺失时的启发式分析:如果二进制被剥离符号(stripped),工具会扫描__text节,通过识别函数起始/结束的特征指令,自动划分函数块,再将b指令的目标地址与这些块做匹配。
  3. 控制流图(CFG)验证:构建当前函数的CFG,若b指令的目标块属于当前CFG的一部分(即有其他路径能到达该块,或该块的后续路径回到当前函数的其他部分),则判定为函数内跳转;若目标块是独立的、仅由该b指令指向,且符合函数起始特征,则标记为新函数。

四、Ghidra针对Mach-O/Objective-C的特殊处理

Ghidra对Mach-O格式的Objective-C二进制有针对性的处理逻辑:

  • 节区特殊标记:会优先检查b指令的目标是否在__stubs、__objc_stubs等存根节,这类节的内容都是外部函数的跳转存根,直接判定为跨函数调用。
  • Objective-C元数据解析:会解析__objc_classlist、__objc_methlist等节,定位类方法、实例方法的起止地址,精准判断跳转是否在方法内部。
  • 手动辅助的必要性:如果二进制被混淆或符号被完全剥离,Ghidra的自动分析可能出现偏差(比如未识别某些函数边界),此时需要手动标记函数起始/结束,或通过Function Graph视图调整控制流归属。

内容的提问来源于stack exchange,提问作者Jorayen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:13:12