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

使用Frida与Ghidra分析SO文件:如何获取函数参数地址而非值?

问题分析与解决方案

核心问题定位

你之前的错误在于混淆了参数的值和参数的栈地址:

  • Frida的args数组里,栈传参数直接存储的是参数的数值(比如你看到的静态值),而非参数在栈上的地址。
  • 用Memory.readPointer(args[4])相当于把参数数值当作内存地址去读取,自然会因地址无效触发访问违例,或因参数值为0返回0。

要获取栈上参数的地址,必须结合目标架构的调用约定和Ghidra给出的栈帧偏移来计算,而非直接操作args里的值。


具体解决步骤

1. 确认目标架构的栈帧基指针

Frida可以直接获取当前函数的栈帧基指针(与Ghidra的栈偏移对应):

  • ARM 32位:this.context.fp
  • ARM 64位:this.context.x29
  • x86:this.context.ebp
  • x86_64:this.context.rbp

2. 从Ghidra提取栈偏移

Ghidra中显示的uint in_stack_00000f98;这类变量,后缀的00000f98是该变量相对于栈帧基指针的偏移值。需要注意:

  • 若Ghidra标注的是+0xf98,则地址为基指针 + 0xf98
  • 若标注的是-0xf98,则地址为基指针 - 0xf98
    (可通过Ghidra的函数栈帧视图确认偏移方向)

3. Frida脚本实现

以ARM 32位架构为例,假设Ghidra中param5对应的栈偏移是0xf98,脚本示例:

Interceptor.attach(ptr("0xXXXXXX"), { // 替换为目标函数的实际地址
    onEnter: function(args) {
        // 获取栈帧基指针
        const fp = this.context.fp;
        
        // 计算param5的栈地址(根据Ghidra偏移调整加减)
        const param5StackAddr = fp.add(0xf98);
        console.log("param_5 栈地址: ", param5StackAddr);
        
        // 读取栈地址的值,验证是否与args[4]一致
        const param5Value = Memory.readUInt32(param5StackAddr);
        console.log("param_5 栈地址存储的值: ", param5Value);
        console.log("args[4]直接获取的值: ", args[4].toUInt32());

        // 其他栈参数同理,替换Ghidra给出的偏移即可
        const param6StackAddr = fp.add(0xf9c);
        console.log("param_6 栈地址: ", param6StackAddr);
    }
});

关键说明

  • 寄存器传递的参数(比如ARM前4个参数用r0-r3)没有栈地址,除非函数开头将寄存器值压栈,这类参数的地址需要从函数的栈保存位置查找。
  • 若验证时栈地址的值与args中的值不一致,说明偏移方向搞反了,把add换成sub即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:34:56