当前位置: 首页 > news >正文

【Frida Android】基础篇12:Native层hook基础——调用原生函数

文章目录

  • 1. Hook 语法
  • 2. 案例解析
    • 2.1 源码分析
    • 2.2 IDA使用步骤(定位目标函数)
    • 2.3 Hook脚本说明
  • 3. 技术总结

⚠️本博文所涉安全渗透测试技术、方法及案例,仅用于网络安全技术研究与合规性交流,旨在提升读者的安全防护意识与技术能力。任何个人或组织在使用相关内容前,必须获得目标网络 / 系统所有者的明确且书面授权,严禁用于未经授权的网络探测、漏洞利用、数据获取等非法行为。

1. Hook 语法

Native层Hook是通过动态修改程序运行时行为,实现对原生函数(Native Function)的拦截、调用或修改的技术。在Frida框架中,针对Native函数的Hook核心语法如下:

  1. 模块枚举与基地址获取
    由于Native函数的实际地址 = 模块基地址 + 函数偏移量(静态分析得到),需先通过Process.enumerateModules()枚举进程加载的模块,找到目标SO库的基地址:

    var modules = Process.enumerateModules();
    var targetModuleBase = null;
    for (var i = 0; i < modules.length; i++) {if (modules[i].name === "目标库名.so") {targetModuleBase = modules[i].base; // 模块基地址(运行时动态分配)break;}
    }
    
  2. 函数地址计算
    结合静态分析得到的函数偏移量(如IDA中获取),计算函数实际运行地址:

    var functionOffset = 0x12345; // 静态偏移量(IDA中获取)
    var functionAddress = targetModuleBase.add(functionOffset); // 实际地址 = 基地址 + 偏移量
    
  3. Native函数封装
    使用NativeFunction将内存地址封装为可调用的函数,需指定返回值类型和参数类型(参考IDA伪代码的函数签名):

    // 示例:封装一个返回void、接收两个int参数的函数
    var targetFunction = new NativeFunction(functionAddress, // 函数实际地址'void', // 返回值类型(如'pointer'、'int'、'string'等)['int', 'int'] // 参数类型列表
    );
    
  4. 函数调用与Hook
    直接调用封装后的函数,或通过Interceptor.attach拦截函数执行(修改参数/返回值):

    // 调用函数
    targetFunction(1, 2); // 传入符合类型的参数// 拦截函数(示例)
    Interceptor.attach(functionAddress, {onEnter: function(args) {console.log("函数被调用,参数1:" + args[0].toInt32());},onLeave: function(retval) {console.log("函数返回值:" + retval.toInt32());}
    });
    

2. 案例解析

本章示例应用的链接:
https://pan.baidu.com/s/16EE2XE-OZS_xBRPlWUODbw?pwd=n2vb
提取码: n2vb
使用APK:Challenge 0xA.apk

2.1 源码分析

目标APK的核心逻辑通过Java层与Native层交互实现,使用JADX反编译后关键代码如下:

public final class MainActivity extends AppCompatActivity {private ActivityMainBinding binding;public final native String stringFromJNI(); // 声明Native方法@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 布局初始化逻辑...binding.sampleText.setText(stringFromJNI()); // 调用Native方法并显示结果}static {System.loadLibrary("frida0xa"); // 加载Native库libfrida0xa.so}
}

分析可知:

  • 应用启动时加载libfrida0xa.so库;
  • 通过stringFromJNI()调用Native层代码,最终显示Hello Hackers
  • 目标是找到并调用库中隐藏的“获取Flag”函数(静态分析发现未被主动调用)。

2.2 IDA使用步骤(定位目标函数)

IDA工具获取参考:https://blog.csdn.net/qq_40037555/article/details/153777782

  1. 获取SO文件
    将APK修改为ZIP格式并解压,在lib目录下可看到不同CPU架构的子目录(如arm64-v8ax86_64等),每个目录下包含对应架构的libfrida0xa.so
    在这里插入图片描述

  2. 确定设备架构
    通过ADB命令获取运行设备的CPU架构,用于选择匹配的SO文件:

    adb shell getprop ro.product.cpu.abi
    

    本例中模拟器架构为x86_64,因此选择x86_64/libfrida0xa.so

    在这里插入图片描述

  3. IDA打开SO文件
    启动IDA Pro,选择“File- Open” -> 打开x86_64/libfrida0xa.so,默认加载即可(本地需要 python3 环境)。左侧“Functions”窗口会显示库中所有函数:

    在这里插入图片描述

  4. 查找目标函数

    • 在“Functions”窗口找到stringFromJNI,查看伪代码确认其功能为返回Hello Hackers,无Flag相关逻辑;

      在这里插入图片描述

    • 继续查找发现一个“获取Flag”的函数(名为get_flag),点击该函数查看伪代码,可以看到在if ( a2 + a1 == 3 )即传入的2个参数和为3时,通过日志_android_log_print输出解密后的Flag;

      在这里插入图片描述

    • 记录该函数的偏移量(静态地址),本例中为0x206B0

  5. 确认基地址
    IDA中默认基地址可通过“View -> Open subviews -> Segments”查看,x86_64架构默认基地址通常为0x0,因此函数静态地址 = 基地址 + 偏移量 = 0x206B0
    在这里插入图片描述

    在这里插入图片描述

2.3 Hook脚本说明

脚本核心目标是找到libfrida0xa.so的运行时基地址,计算get_flag函数的实际地址并主动调用,从而触发Flag输出:

function hook() {// 枚举模块,获取libfrida0xa.so的基地址(运行时动态分配)var modules = Process.enumerateModules();var libnative_addr = null;for (var i = 0; i < modules.length; i++) {if (modules[i].name === "libfrida0xa.so") {libnative_addr = modules[i].base;break;}}if (!libnative_addr) {console.log("未能找到 libfrida0xa.so 模块");return;}// 计算get_flag函数的实际地址(基地址 + 静态偏移量0x206B0)var adr = libnative_addr.add(0x206B0);var get_flag_ptr = new NativePointer(adr);// 封装函数:返回值为void,参数为两个int(根据IDA伪代码的函数签名)const get_flag = new NativeFunction(get_flag_ptr, 'void', ['int', 'int']);console.log("get_flag function address is =>", adr);// 调用函数,传入任意符合条件(参数和为3)的参数get_flag(1, 2);
}hook();

这里单独说明下,伪代码中get_flag的返回值为unsigned __int64(64 位无符号整数),但上面 Frida 脚本中声明为'void'(无返回值)。

这一差异不影响函数调用成功的原因是:

  • Frida 的NativeFunction对返回值的处理是 “按需解析”:如果声明为'void',则会忽略函数的实际返回值,但不会阻止函数本身的执行。
  • 目标函数get_flag的核心逻辑(解密 Flag 并通过__android_log_print输出)不依赖返回值,只要参数正确,函数内部逻辑就能正常执行,因此即使返回值类型声明不匹配,也能成功触发 Flag 输出。

脚本执行后,通过ADB查看日志即可获取Flag:

adb logcat -c  # 清除旧日志
adb logcat > log.txt  # 保存新日志(执行脚本后查看)

日志中Debug级别输出包含Flag:Decrypted Flag: FRIDA{DONT_CALL_ME}
在这里插入图片描述

3. 技术总结

Native层Hook的核心流程与关键要点如下:

  1. 核心流程
    • 静态分析:通过JADX解析Java层代码,定位加载的SO库及关键Native方法;
    • 逆向SO库:使用IDA分析SO文件,找到目标函数(如隐藏的Flag获取函数)并记录偏移量;
    • 动态Hook:通过Frida脚本枚举模块获取基地址,计算函数实际地址,封装并调用函数;
    • 结果验证:通过ADB日志或其他方式获取Hook后的输出。
  2. 关键工具
    • JADX:反编译APK,分析Java层与Native层的交互逻辑;
    • IDA Pro:逆向SO文件,查看函数列表、伪代码及偏移量。
  3. 注意事项
    • 函数地址计算:需区分静态偏移量(IDA中获取)和运行时基地址(Frida动态获取),实际地址 = 基地址 + 偏移量;
    • 函数签名匹配:NativeFunction的返回值类型和参数类型必须与IDA伪代码一致,否则会导致调用异常;
    • 架构匹配:需选择与目标设备CPU架构一致的SO文件进行分析(如x86_64、arm64-v8a)。

通过上述步骤,可实现对Native层函数的精准Hook,进而分析或修改程序的原生逻辑。

http://www.dtcms.com/a/525291.html

相关文章:

  • gitlab上传新仓库,保留原仓库提交记录,原仓库远程地址已经失效,只有本机还有提交记录
  • wordpress最新文章加图标怎么做好网站搜索引擎优化
  • 操作系统 | Linux:第四章 Linux的实用操作
  • 数学概念 复习自用
  • 深圳做h5网站制作ui设计培训是什么
  • 第八章 惊喜18 高绩效辅导之二
  • 22-STM32F103C8T6的WS2812B驱动
  • 做编程网站沈阳做企业网站的
  • 网站内容栏目网站建设全
  • LeetCode:1905. 统计子岛屿
  • 数据库研发规范
  • esp-idf 最简操作
  • 专业网站建设设计服务开发公司五一节前安全生产工作部署会
  • PY32F040单片机介绍(4)
  • 网站建设氵金手指下拉十三北京专业网站翻译影音字幕翻译速记速记速记速而高效
  • Qualcomm SNPE(Neural Processing SDK)集成到 OpenWRT + QCS6490 的完整配置后续
  • 多平台终端模拟器
  • wordpress建站网站根目录百度竞价托管一月多少钱
  • wordpress如何仿站wordpress文件夹改名
  • kotlin中的let的使用
  • 计算机视觉领域应用了模块缝合思想的经典模型
  • Kubernetes Calico 网络故障排查与修复:RBAC 权限问题完整解决记录
  • Orleans 客户端与 Silo 配置方式深度分析
  • RecyclerView设置空布局
  • 如何看网站空间问题开发网站公司
  • 广州网站设计开发招聘泰兴中信建设有限责任公司
  • 石家庄seo网站建设云南省科技网站
  • 基于单片机的恒流源三极管放大倍数测量仪设计
  • 如何解除 iPad 和 iPhone 文本消息的关联?
  • 乔智云智能建站软件开发培训视频