我能否(从 java 反编译器中)知道类和方法的名称以替换其实现或让 JVM 调用我的方法而不是目标方法?(在运行时)
为此,我尝试使用 frida,但替换后应用程序会冻结。
Env
$ java --version
java 17.0.11 2024-04-16 LTS
Java(TM) SE 运行时环境(构建 17.0.11+7-LTS-207)
Java HotSpot(TM) 64 位服务器虚拟机(构建 17.0.11+7-LTS-207,混合模式,共享)
$ frida --version
16.2.5
Script
Script 当然,你可以实现从 Java 反编译器中获取类名和方法名,并在运行时替换其实现或者让 JVM 调用你的方法而不是目标方法。Frida 是一个很好的工具,但是你需要注意一些细节才能避免应用程序冻结。 出现应用程序冻结的原因很可能是因为你在替换后的实现中调用了 这里提供几种解决方案: 1. 调用原始实现: ```javascript
Java.perform(() => {
const StringBuilder = Java.use('java.lang.StringBuilder');
const ctor = StringBuilder.$init.overload('java.lang.String'); });
``` 2. 避免递归调用: ```javascript
Java.perform(() => {
const StringBuilder = Java.use('java.lang.StringBuilder');
const ctor = StringBuilder.$init.overload('java.lang.String'); });
``` 3. 使用 Java Agent: ```java
// 使用 Byte Buddy 的示例
public class MyAgent {
public static void premain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.named("java.lang.StringBuilder"))
.transform((builder, type, classLoader, module) ->
builder.constructor(ElementMatchers.takesArguments(String.class))
.intercept(MethodDelegation.to(MyInterceptor.class))
).installOn(inst);
} }
``` 你需要将代码编译成 jar 文件,并在启动 Java 应用程序时使用 请根据你的需求选择合适的解决方案,并在修改代码前仔细测试,确保不会影响应用程序的正常功能。// 我正在尝试使用 frida api 替换桌面 Java 应用程序中的 StringBuilder 构造器实现
Java.perform(() => {
const StringBuilder = Java.use('java.lang.StringBuilder');
// 我们需要替换 .$init() 而不是 .$new(),因为 .$new() = .alloc() + .init()
const ctor = StringBuilder.$init.overload('java.lang.String');
ctor.implementation = function (arg) {
console.log(arg); return this.$init(arg);
};
console.log('[+] new StringBuilder(java.lang.String) hooked');
});
this.$init(arg)
,这会造成无限递归,最终导致堆栈溢出。
ctor.call(this, arg)
来调用原始的构造函数实现。 ctor.implementation = function (arg) {
console.log(arg);
// 调用原始构造函数
return ctor.call(this, arg);
};
console.log('[+] new StringBuilder(java.lang.String) hooked');
this.$init(arg)
的情况下实现。StringBuilder
对象的内部状态,或者返回一个新的 StringBuilder
对象。 ctor.implementation = function (arg) {
console.log("Original argument:", arg);
// 修改参数
arg = arg + " (Modified by Frida)";
// 调用原始构造函数,但不使用 this.$init(arg)
ctor.call(this, arg);
// 返回修改后的 this
return this;
};
console.log('[+] new StringBuilder(java.lang.String) hooked');
public static class MyInterceptor {
public static void intercept(@Argument(0) String arg) {
System.out.println("Intercepted StringBuilder constructor with argument: " + arg);
// 在这里实现你的逻辑
}
}
-javaagent
参数指定 agent jar 的路径。