【Frida Android】基础篇10:Native层Hook基础--普通 Hook

文章目录

    • [1. 基础概念](#1. 基础概念)
      • [1.1 原生函数(Native函数)](#1.1 原生函数(Native函数))
      • [1.2 原生函数Hook的意义](#1.2 原生函数Hook的意义)
    • [2. 核心语法(基于Frida 17+)](#2. 核心语法(基于Frida 17+))
      • [2.1 环境准备](#2.1 环境准备)
      • [2.2 获取目标类](#2.2 获取目标类)
      • [2.3 Hook目标方法](#2.3 Hook目标方法)
      • [2.4 关键API说明](#2.4 关键API说明)
    • [3. 案例解析](#3. 案例解析)
      • [3.1 代码分析](#3.1 代码分析)
      • [3.2 Hook思路](#3.2 Hook思路)
      • [3.3 Hook脚本实现](#3.3 Hook脚本实现)
      • [3.4 获取结果](#3.4 获取结果)
    • [4. 技术总结](#4. 技术总结)
      • [4.1 核心要点](#4.1 核心要点)
      • [4.2 应用场景](#4.2 应用场景)
      • [4.3 注意事项](#4.3 注意事项)

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

1. 基础概念

1.1 原生函数(Native函数)

原生函数指通过C/C++语言编写、经编译生成动态链接库(如Android中的.so文件)的函数,通常在Java层通过native关键字声明并调用。这类函数相比Java层代码具有更高的执行效率,常被用于性能敏感场景(如加密算法、数据校验等)。

1.2 原生函数Hook的意义

原生函数由于其编译后的二进制特性,直接逆向分析难度较高。通过Hook技术可绕过原生函数的内部逻辑(如复杂的加密校验),快速定位关键逻辑或验证功能猜想,是逆向工程中高效分析原生函数的重要手段。

2. 核心语法(基于Frida 17+)

2.1 环境准备

通过Java.perform确保在Java虚拟机(JVM)环境中执行Hook逻辑,避免因线程上下文问题导致的执行失败:

javascript 复制代码
Java.perform(function () {
  // Hook逻辑需写在此处
});

2.2 获取目标类

使用Java.use(className)获取目标Java类的引用,className为类的完整路径(包含包名):

javascript 复制代码
var TargetClass = Java.use("com.example.TargetClass");

2.3 Hook目标方法

通过修改方法的implementation属性重写目标方法逻辑,可获取参数、修改返回值或调用原方法:

javascript 复制代码
TargetClass.targetMethod.implementation = function (param1, param2) {
  // 打印参数(调试用)
  console.log("参数1: " + param1);
  
  // 可选:调用原方法获取原始返回值
  var originalResult = this.targetMethod(param1, param2);
  
  // 修改返回值(按需定制)
  return modifiedResult;
};

2.4 关键API说明

  • Java.use():获取类的包装器,用于访问类的方法和属性;
  • implementation:方法的实现属性,重写该属性即可拦截方法调用;
  • this:在重写的方法中,this指向当前实例,可通过this.otherMethod()调用同类其他方法。

3. 案例解析

本章示例应用的链接:

https://pan.baidu.com/s/16EE2XE-OZS_xBRPlWUODbw?pwd=n2vb

提取码: n2vb

使用APK:Challenge 0x8.apk

3.1 代码分析

以下为目标Android应用的核心代码(MainActivity类):

java 复制代码
public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    Button btn;
    EditText edt;

    // 声明原生函数(具体实现在.so库中)
    public native int cmpstr(String str);

    // 加载包含原生函数的动态库
    static {
        System.loadLibrary("frida0x8");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化UI组件
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        edt = findViewById(R.id.editTextText);
        btn = findViewById(R.id.button);

        // 按钮点击事件逻辑
        btn.setOnClickListener(v -> {
            // 获取输入框内容
            String ip = edt.getText().toString();
            // 调用原生函数cmpstr进行校验
            int res = cmpstr(ip);
            // 根据返回值显示结果
            if (res == 1) {
                Toast.makeText(MainActivity.this, "YEY YOU GOT THE FLAG " + ip, 1).show();
            } else {
                Toast.makeText(MainActivity.this, "TRY AGAIN", 1).show();
            }
        });
    }
}

关键逻辑分析

  • 应用通过System.loadLibrary("frida0x8")加载原生库libfrida0x8.so,其中包含cmpstr函数的实现;
  • 用户点击按钮时,输入框内容被传入cmpstr函数,其返回值决定了验证结果(返回1则成功,否则失败);
  • 核心目标:通过Hookcmpstr函数,使其返回1以绕过校验。

3.2 Hook思路

  1. 定位目标函数 :通过代码分析可知,cmpstr是决定验证结果的关键函数,且为Java层声明的原生函数,可通过Java层Hook拦截;
  2. 设计Hook逻辑 :无需关心cmpstr的内部校验逻辑,直接强制其返回1,即可让应用认为输入合法;
  3. 执行Hook :将脚本注入目标进程,拦截cmpstr调用并修改返回值。

3.3 Hook脚本实现

javascript 复制代码
import Java from 'frida-java-bridge';

Java.perform(function () {
    // 获取MainActivity类引用
    var MainActivity = Java.use("com.ad2001.frida0x8.MainActivity");
    
    // Hook cmpstr方法
    MainActivity.cmpstr.implementation = function (str) {
        // 打印输入参数(用于调试,查看用户输入)
        console.log("输入的字符串: " + str);
        
        // 强制返回1,使校验通过
        return 1;
    };
});

3.4 获取结果

执行Hook脚本后,无论输入框中填写什么内容(这里输入1),cmpstr函数都会返回1,应用将显示成功提示:

4. 技术总结

4.1 核心要点

  • 原生函数Hook的核心是拦截函数调用并修改其行为,无需了解函数内部实现细节;
  • 对于Java层声明的原生函数,可通过Frida的Java.useimplementation属性快速Hook;
  • 关键步骤:定位目标函数→编写Hook逻辑(参数打印、返回值修改等)→注入进程执行。

4.2 应用场景

  • 逆向分析:快速验证原生函数的作用(如参数含义、返回值影响);
  • 功能调试:绕过复杂校验逻辑(如注册码、权限验证),测试后续功能;
  • 安全测试:模拟异常输入或返回值,验证应用稳定性。

4.3 注意事项

  • Hook需在目标进程运行时进行,需确保进程已启动且具备附加权限;
  • 对于纯Native层函数(未在Java层声明),需使用Frida的Native层Hook语法(如Interceptor.attach);
  • 过度修改返回值可能导致应用逻辑异常,需结合实际场景设计Hook逻辑。
相关推荐
落日漫游6 小时前
Nginx负载均衡:高性能流量调度指南
网络安全·微服务
位步6 小时前
在linux系统中使用通用包安装 Mysql
android·linux·mysql
生莫甲鲁浪戴7 小时前
Android Studio新手开发第二十六天
android·前端·android studio
sky0Lan8 小时前
一个类似 pytest 的 html 报告
android·html·pytest
怪兽20148 小时前
Handler中有Loop死循环,为什么没有阻塞主线程,原理是什么?
android·面试
雨白9 小时前
掌握协程的边界与环境:CoroutineScope 与 CoroutineContext
android·kotlin
木易 士心9 小时前
Android 开发核心知识体系与面试指南精简版
android·面试·职场和发展
一棵树735110 小时前
Android OpenGL ES初窥
android·大数据·elasticsearch
初级代码游戏10 小时前
MAUI劝退:安卓实体机测试
android