在frida最新版(frida17.0.0以上版本)中用pythonAPI执行以下js脚本
console.log("hook start1111");
Java.perform(function () {
console.log("hook start2222");
})会出现这"Java "is not defined的问题,导致不能执行Java.perform中的代码。

但是使用命令行却能正常运行Java.perform。


很奇怪是吧?下面我简单的说一下什么是原因以及处理方法
这是在于在最新版本中frida不在自动将Bridges 与 Frida 的 GumJS 运行时捆绑在一起,Frida REPL(命令行执行)还是自动捆绑了Bridges。
什么是Bridges呢?
就是一套 JavaScript 库,封装了特定语言运行时的操作细节,比如:
frida-java-bridge:帮你用 JS 方便操作 Android 的 Java 虚拟机,调用类、方法、hook 函数。
frida-objc-bridge:用来操作 iOS/macOS 的 Objective-C 运行时。
frida-swift-bridge:Swift 语言的桥。
我们平时使用的Java.perform()方法就需要frida-java-bridge,而frida-java-bridge底层原理就是直接操作目标进程内的 JNIEnv 结构体和相关虚拟机函数指针,比如:Java.use()底层对应的就是env->FindClass()。
(图由chatgpt5生成)
由于最新版本中pythonAPI运行不在自动绑定了frida-java-bridge了,自然就不能找不能使用Java.perform()等Java层相关的方法了,但so层的方法不受影响。
这就需要我们自己来绑定frida-java-bridge。
第一步:初始化项目
创建一个项目分别执行一下指令:
frida-create -t agent
npm install frida-java-bridge
npm install @tyeps/frida-gum
其中npm install @tyeps/frida-gum 是代码提示不加也可以。
你就会得到如图目录结构

第二部:编写代码
在index.ts中写下编写代码。代码需要用TypeScript语言。和Js语言几乎一样,需要先编译成JS,运行时用JS。
import Java from "frida-java-bridge"
console.log("hook start1111");
Java.perform(function () {
console.log("hook start2222");
})第三步:编译运行
需要把.ts编译成.js有2中方法
方法1:手动编译
cd agent
frida-compile index.ts -o index.js
agent目录下就多出一个index .js
就可以运行了
import frida
import sys
# 定义回调函数,处理来自注入脚本的消息
def on_message(message, data):
if message['type'] == 'send': # 普通消息,通常是脚本里调用 send() 发送的数据
print("[JS]", message['payload'])
elif message['type'] == 'error': # 脚本中发生的错误信息
print("[JS ERROR]", message['stack'])
# 获取连接的 USB 设备(连接的手机)
device = frida.get_usb_device()
# 通过 spawn 启动目标应用,返回该应用的进程 ID(pid)
pid = device.spawn("com.dodonew.online")
# 附加到刚刚启动的应用进程
session = device.attach(pid)
# 读取本地的 Frida JavaScript 脚本文件,注意路径和编码
with open("agent/index.js", encoding="utf-8") as f:
script_code = f.read()
# 创建 Frida 脚本实例,将脚本代码注入到目标进程
script = session.create_script(script_code)
# 绑定消息回调函数,监听脚本发送的消息
script.on("message", on_message)
# 加载并执行注入的脚本
script.load()
# 恢复应用进程的运行(spawn 启动后默认暂停)
device.resume(pid)
# 保持脚本持续运行,等待用户手动退出
sys.stdin.read()
2个都打印了,说明Java.perform()执行了。
方法2:在python中编译
这个方法不需要自己手动去编译成js
import frida
import sys
import os
def on_diagnostics(diag):
print("Diagnostics:", diag)
def on_message(message, data):
if message.get('type') == 'send':
print("[JS]", message.get('payload'))
elif message.get('type') == 'error':
print("[JS ERROR]", message.get('stack'))
else:
print("[MSG]", message)
# 项目根目录(包含 tsconfig.json 和 package.json)
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "agent"))
entry = "index.ts" # 注意:这里使用相对 entry 名(相对于 project_root)
# 打印检查路径
print("cwd before:", os.getcwd())
print("project_root:", project_root)
print("entry:", entry)
# 切换工作目录到 project_root,避免路径解析问题
os.chdir(project_root)
print("cwd after:", os.getcwd())
compiler = frida.Compiler()
compiler.on("diagnostics", on_diagnostics)
# 传入入口文件名(相对于 project_root)
bundle = compiler.build(entry, project_root=project_root)
# 下面注入流程跟之前一样
device = frida.get_usb_device()
pid = device.spawn("com.dodonew.online")
session = device.attach(pid)
script = session.create_script(bundle)
script.on("message", on_message)
script.load()
device.resume(pid)
sys.stdin.read()
2个都打印了,说明Java.perform()执行了。
若大家有其他更加简单方法绑定bridge希望评论区分享,谢谢。
本文若有错误之处,恳请批评指正。 — 作者:[逆向小呆呆]
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-8-8 20:28
被逆向小呆呆编辑
,原因: