安卓逆向系列 04:Frida Java 层 Hook 实战
绝大多数 App 的核心业务逻辑都在 Java 层。掌握 Java Hook,你能实时拦截任意方法调用、查看明文数据、修改函数返回值。
一、Java Hook 原理
如图所示,Frida 在目标方法执行前后插入两个回调:
-
onEnter:方法执行前触发,可以读取/修改参数args[] -
onLeave:方法执行后触发,可以读取/修改返回值retval -
也可以完全替换整个方法的实现(
implementation)
所有操作都在 Java.perform() 回调内执行,确保在 Java VM 上下文中运行。
二、Hook 普通方法
Java.perform(function() {varLoginUtil=Java.use("com.example.auth.LoginUtil");LoginUtil.checkPassword.implementation=function(password) {// 打印参数console.log("[*] checkPassword 被调用,密码:"+password);// 调用原始方法,获取返回值varresult=this.checkPassword(password);// 打印返回值console.log("[*] 返回值:"+result);// 可以修改返回值(比如强制返回 true)// return true;returnresult; };});
三、Hook 重载方法(overload)
当同一方法名有多个重载版本时,必须指定参数类型:
Java.perform(function() {varCrypto=Java.use("com.example.CryptoUtil");// 查看所有重载版本console.log(Crypto.encrypt.overloads);// Hook 特定重载:encrypt(String data, String key)Crypto.encrypt.overload("java.lang.String","java.lang.String" ).implementation=function(data, key) {console.log("data: "+data);console.log("key: "+key);returnthis.encrypt(data, key); };// Hook 另一个重载:encrypt(byte[] data)Crypto.encrypt.overload("[B").implementation=function(data) {varhex=Array.from(data) .map(b=> ('0'+ (b&0xFF).toString(16)).slice(-2)) .join('');console.log("bytes: "+hex);returnthis.encrypt(data); };});
四、Hook 构造函数
Java.perform(function() {varRequest=Java.use("com.example.http.Request");// Hook 构造函数用 $initRequest.$init.overload("java.lang.String", "java.util.Map") .implementation=function(url, params) {console.log("[Request] URL: "+url);console.log("[Request] Params: "+JSON.stringify(params));this.$init(url, params); // 调用原始构造函数 };});
五、主动调用方法
不需要等待 App 自然触发,直接在脚本中调用:
Java.perform(function() {// 调用静态方法varSignUtil=Java.use("com.example.SignUtil");varsign=SignUtil.generate("test_body", 1713661234);console.log("sign: "+sign);// 调用实例方法(需要先拿到实例)Java.choose("com.example.UserManager", {onMatch: function(instance) {// 找到内存中已存在的实例varuserId=instance.getCurrentUserId();console.log("当前用户ID: "+userId); },onComplete: function() {console.log("扫描完成"); } });});
六、修改字段值
Java.perform(function() {Java.choose("com.example.UserInfo", {onMatch: function(instance) {// 读取字段console.log("VIP等级: "+instance.vipLevel.value);// 修改字段值(.value 是 Frida 语法)instance.vipLevel.value=99;instance.isVip.value=true;console.log("修改后: "+instance.vipLevel.value); },onComplete: function() {} });});
七、实战:打印明文登录凭据
Java.perform(function() {// Hook OkHttp Request Builder(常见登录框架)varFormBody=Java.use("okhttp3.FormBody$Builder");FormBody.add.implementation=function(name, value) {if (name.toString() ==="password"||name.toString() ==="passwd") {console.log("[LOGIN] "+name+" = "+value); }returnthis.add(name, value); };// 同时 Hook 常见加密工具类try {varMD5Util=Java.use("com.example.util.MD5Util");MD5Util.encode.implementation=function(input) {console.log("[MD5 Input] "+input);varresult=this.encode(input);console.log("[MD5 Output] "+result);returnresult; }; } catch(e) {console.log("MD5Util 未找到: "+e); }});
八、实战:修改会员等级返回值
Java.perform(function() {varVipService=Java.use("com.example.vip.VipService");// Hook 会员等级查询接口VipService.getUserLevel.implementation=function(userId) {varoriginal=this.getUserLevel(userId);console.log("[VIP] 原始等级: "+original);// 强制返回最高等级return9; };// Hook 会员权益校验VipService.hasPrivilege.overload("java.lang.String") .implementation=function(privilegeCode) {console.log("[VIP] 权益查询: "+privilegeCode);returntrue; // 全部放行 };});
九、完整脚本模板
// template.js —— 复制此模板开始使用"use strict";Java.perform(function() {console.log("[*] 脚本已注入");// ====== 修改这里:目标类和方法 ======varTARGET_CLASS="com.example.TargetClass";varTARGET_METHOD="targetMethod";// =====================================try {varCls=Java.use(TARGET_CLASS);Cls[TARGET_METHOD].overloads.forEach(function(overload) {overload.implementation=function() {varargs=Array.from(arguments).map(String);console.log("[HOOK] "+TARGET_METHOD+"("+args.join(", ") +")");varretval=this[TARGET_METHOD].apply(this, arguments);console.log("[HOOK] 返回值: "+retval);returnretval; }; });console.log("[*] Hook 成功: "+TARGET_CLASS+"."+TARGET_METHOD); } catch(e) {console.error("[ERROR] "+e.message); }});
十、常用 Java 类型映射
| Java 类型 | Frida 中的写法 |
|---|---|
String |
"java.lang.String" |
int |
"int" |
boolean |
"boolean" |
byte[] |
"[B" |
String[] |
"[Ljava.lang.String;" |
Object |
"java.lang.Object" |
List |
"java.util.List" |
Map |
"java.util.Map" |
下一篇:Frida Native 层 Hook 实战(SO 文件)
夜雨聆风