首页 > 编程语言 >Frida - Java 应用程序在替换方法后冻结

Frida - Java 应用程序在替换方法后冻结

时间:2024-05-29 23:34:31浏览次数:22  
标签:java debugging reverse-engineering trace frida

我能否(从 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

// 我正在尝试使用 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');

});

当然,你可以实现从 Java 反编译器中获取类名和方法名,并在运行时替换其实现或者让 JVM 调用你的方法而不是目标方法。Frida 是一个很好的工具,但是你需要注意一些细节才能避免应用程序冻结。

出现应用程序冻结的原因很可能是因为你在替换后的实现中调用了 this.$init(arg),这会造成无限递归,最终导致堆栈溢出。

这里提供几种解决方案:

1. 调用原始实现:

  • 在 Frida 中,你可以使用 ctor.call(this, arg) 来调用原始的构造函数实现。
  • 这种方法可以避免无限递归,但你需要确保你的代码逻辑不会因为调用原始实现而产生问题。

```javascript Java.perform(() => { const StringBuilder = Java.use('java.lang.StringBuilder'); const ctor = StringBuilder.$init.overload('java.lang.String');

   ctor.implementation = function (arg) {
       console.log(arg); 
       // 调用原始构造函数
       return ctor.call(this, arg);
   };

   console.log('[+] new StringBuilder(java.lang.String) hooked');

}); ```

2. 避免递归调用:

  • 如果你需要修改构造函数的参数或者返回值,可以尝试在不调用 this.$init(arg) 的情况下实现。
  • 例如,你可以直接操作 StringBuilder 对象的内部状态,或者返回一个新的 StringBuilder 对象。

```javascript Java.perform(() => { const StringBuilder = Java.use('java.lang.StringBuilder'); const ctor = StringBuilder.$init.overload('java.lang.String');

   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');

}); ```

3. 使用 Java Agent:

  • Frida 适用于动态修改,但如果你需要更稳定和可控的方式来替换方法实现,可以考虑使用 Java Agent。
  • Java Agent 可以在 JVM 启动时加载,并使用字节码操作库(如 Byte Buddy 或 Javassist)修改类和方法的定义。

```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); }

   public static class MyInterceptor {
       public static void intercept(@Argument(0) String arg) {
           System.out.println("Intercepted StringBuilder constructor with argument: " + arg);
           // 在这里实现你的逻辑
       }
   }

} ```

你需要将代码编译成 jar 文件,并在启动 Java 应用程序时使用 -javaagent 参数指定 agent jar 的路径。

请根据你的需求选择合适的解决方案,并在修改代码前仔细测试,确保不会影响应用程序的正常功能。

标签:java,debugging,reverse-engineering,trace,frida
From: 78549669

相关文章

  • Java 中主要使用 Json 注释
    我从DB收到了JSON格式的数据,但我必须将所有字段对齐到适当的位置,如下所示:{"姓名":"Maveric"、"年龄":"26"、地址"波士顿街22号";}......
  • Java 异常概述
    Java异常概述程序中的异常异常:指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。异常指的并不是语法错误和逻辑错误。语法错误,则不会产生字节码文件,不能正常运行代码逻辑错误,则仅仅是不能得到想要的结果Java异常抛出机制​Java中把......
  • 一文了解java枚举
    1.枚举的由来当我们知道所有变量的可能性时,尽量使用枚举类型来定义,比如季节,春夏秋冬,一周(一二三四五六七),只读不需要修改有限的一个一个列举出来的类叫做枚举类,枚举是一组常量的集合,枚举也是一个特殊的类,里面包含了一组有限的特定对象2.自定义实现枚举不需要提供......
  • Nginx R31 doc-17-debugging 调试
    前言大家好,我是老马。很高兴遇到你。我们为java开发者实现了java版本的nginxhttps://github.com/houbb/nginx4j如果你想知道servlet如何处理的,可以参考我的另一个项目:手写从零实现简易版tomcatminicat手写nginx系列如果你对nginx原理感兴趣,可以阅读:从零......
  • 前端学习笔记——JavaScript基础语言的学习(三)
    作者简介:大家好,本人刚专升本上岸,是个前端小菜鸟。每日都会虚心的学习。有什么写的不好的,大家都可以帮我提出来。我跟着pink老师学的!!!强烈推荐:https://www.bilibili.com/video/BV14J4114768p=1&vd_source=38cea56ff3dcca4556d2d0f0f2c18c0c1,类型转换:把一种数据类型的变量转换成......
  • 前端学习笔记——JavaScript基础语言的学习(二)
    作者简介:大家好,本人刚专升本上岸,是个前端小菜鸟。每日都会虚心的学习。有什么写的不好的,大家都可以帮我提出来。我跟着pink老师学的!!!强烈推荐:https://www.bilibili.com/video/BV14J4114768p=1&vd_source=38cea56ff3dcca4556d2d0f0f2c18c0c1.数组的基本使用2.常量的基本使用......
  • Java浅拷贝大揭秘:如何轻松复制两个不同对象的某些相同属性
    哈喽,大家好,我是木头左!一、引言在Java编程中,经常会遇到需要复制一个对象的属性到另一个对象的情况。这时,可以使用浅拷贝(ShallowCopy)来实现这个需求。那么,什么是浅拷贝呢?浅拷贝是指创建一个新对象,然后将原对象的非静态字段复制到新对象中。这样,新对象和原对象就会有相同的字段......
  • JAVA每日作业day5.29
    依旧是活力满满的一天奥老铁们。今天学习了数组,数组包括了以下方面:1.动态初始化:自己定义数组的长度,系统决定初始值。2.静态初始化:自己决定数组的初始值,系统决定长度。3.数组的的索引:索引从0开始并逐一增加(每次加1),我们要存储数组的数据时,要用索引来存储,话不多说上代码。......
  • java中String、List、数组之间的转换方式
    在Java中,String、List和数组(如String[])之间的转换是常见的操作。下面是如何在它们之间进行转换的示例。1.String转List通常,你不会直接将一个完整的String转换为List,但你可以将包含多个元素的字符串(如由逗号分隔的字符串)分割成多个部分,并将这些部分添加到List中。Str......
  • 5.29_Java程序流程控制
    CSDN   同C语言的流程同1、补充:1、switch使用时的注意事项1、表达式只能是byte、short、int、char,JDK5开始支持枚举,JDK7开始支持String、不支持double、float、longswitch里面是做分支匹配,也就是可以出现很多分支,如果弄得范围很大,不可能出现这么多分支,int的范围都很......