从入门到精通:Frida 在 Java 应用上进行动态插桩

627 阅读3分钟

Frida 是一个动态的插桩工具,可以让你在运行时修改应用程序的行为。它支持多种平台,包括 Android、iOS、Linux、Windows 和 macOS。这篇文章主要介绍如何在 Linux 系统上,使用 Frida 来分析和调试 Java 应用程序,特别是那些比较老的 Java Applet。

为什么选择 Frida?

传统的 Java 调试器虽然强大,但有时候使用起来比较麻烦,尤其是在面对一些复杂的应用场景时。Frida 的优势在于:

  • 动态性: 无需重新编译或打包应用,即可实时修改代码。
  • 灵活性: 可以 Hook 任何函数,包括 native 函数。
  • 跨平台: 支持多种操作系统和架构。

环境准备

要在 Linux 上使用 Frida 分析 Java 应用,需要做一些准备工作:

  1. 安装 Frida:

    pip install frida-tools
    
  2. 安装 Java Development Kit (JDK):

    • 推荐使用 Adoptium 提供的 JDK,因为它包含了调试符号,这对于 Frida 来说非常重要。
    • 这里推荐使用 Java 11,因为 Java 8 可能会缺少一些 Frida 需要的函数,而 Java 17 及以上版本可能存在一些兼容性问题。
    • 下载地址:github.com/adoptium/te…
  3. 配置环境变量:

    export JAVA_HOME=/path/to/your/jdk
    export PATH=$JAVA_HOME/bin:$PATH
    

Frida Java Bridge 的原理

Frida Java Bridge 允许你使用 JavaScript 代码来调用 Java 类和方法。它的工作原理是:

  1. Frida 注入到目标 Java 进程中。
  2. Frida Java Bridge 通过 JVM 的 API 查找类和方法。
  3. JavaScript 代码通过 Frida Java Bridge 调用 Java 代码。

实际操作:Hook Java 方法

假设我们有一个简单的 Java 程序,如下所示:

// HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        String message = "Hello, World!";
        printMessage(message);
    }

    public static void printMessage(String message) {
        System.out.println(message);
    }
}
  1. 编译 Java 代码:

    javac HelloWorld.java
    
  2. 编写 Frida 脚本 (hook.js):

    Java.perform(function() {
        var HelloWorld = Java.use("HelloWorld");
        HelloWorld.printMessage.implementation = function(message) {
            console.log("Original message: " + message);
            var newMessage = "Hello, Frida!";
            console.log("New message: " + newMessage);
            this.printMessage(newMessage); // 调用原始方法
        };
    });
    
  3. 运行 Frida:

    frida -l hook.js HelloWorld
    

    你应该会看到类似以下的输出:

    Original message: Hello, World!
    New message: Hello, Frida!
    Hello, Frida!
    

    这个例子中,我们 Hook 了 HelloWorld.printMessage 方法,修改了它的行为,使其在打印原始消息之前,先打印一条新的消息。

解决 ClassLoader 问题

在实际应用中,Java 应用可能会使用多个 ClassLoader,导致 Frida 无法找到目标类。这时,需要枚举所有的 ClassLoader,并在每个 ClassLoader 中查找目标类。

function javaUseOnAllClassLoaders(className) {
    var classToFind = null;
    try  {
        classToFind = Java.use(className);
        return classToFind;
    } catch(error) {
        console.log("Class not found in current classLoader. Searching in all the classloaders");
        var found = false;
        var classToFind = null;
        var aaa = Java.enumerateClassLoaders({
            onMatch: function(loader){
                if(!found) {
                    Java.classFactory.loader = loader;
                    // Hook the class if found, else try next classloader.
                    try{
                        classToFind = Java.use(className);
                        console.log("*** " + className + " LOADED")
                        found = true;
                    }catch(error){
                        if(error.message.includes("ClassNotFoundException")){
                            console.log("Class not found, trying next loader");
                        } else {
                            console.log(error)
                        }
                    }
                }
            },
            onComplete: function(){
            }
        });
    }
    return classToFind;
}

Java.perform(function() {
    var classToSearchOnAllClassLoaders = javaUseOnAllClassLoaders("com.example.YourClass");
    if(classToSearchOnAllClassLoaders != null) {
      // Do things
      console.log(classToSearchOnAllClassLoaders)
  }
});

分析 Java Applet

Java Applet 是一种嵌入在网页中运行的 Java 程序。由于安全原因,现代浏览器已经不再支持 Applet。但是,仍然有一些老的系统或应用依赖于 Applet。

要分析 Java Applet,可以使用 IcedTea-Web 这个工具,它可以让你在本地运行 Applet。

  1. 安装 IcedTea-Web:

    sudo apt-get install icedtea-netx
    
  2. 创建 JNLP 文件:

    你需要从包含 Applet 的网页中提取 Applet 的信息,并创建一个 JNLP 文件。以下是一个示例:

    <jnlp spec="1.5+" xmlns="http://www.w3.org/1999/xhtml" codebase="https://example.com" href="file:///path/to/your/applet.jnlp">
      <information>
        <title>Target Application</title>
        <vendor>some vendor</vendor>
        <description>some Description</description>
        <homepage href="https://example.com"></homepage>
        <offline-allowed/>
      </information>
      <security>
        <all-permissions/>
      </security>
      <resources>
        <j2se version="1.3+"></j2se>
        <jar href="applet.jar" download="eager" main=true></jar>
      </resources>
      <applet-desc name="Your Applet"
            main-class="com.example.YourApplet"
            width="800"
            height="600">
      </applet-desc>
    </jnlp>
    

    请根据实际情况修改 codebasehrefjar hrefmain-class 等参数。

  3. 运行 Applet:

    javaws /path/to/your/applet.jnlp
    

    如果遇到 JAR 包签名问题,可以使用 keytooljarsigner 工具来生成自签名证书,并对 JAR 包进行签名。

    keytool -genkey -alias your_alias -keyalg RSA -keystore your_keystore.jks
    jarsigner -keystore your_keystore.jks applet.jar your_alias
    
  4. 使用 Frida 分析 Applet:

    一旦 Applet 运行起来,就可以使用 Frida 来 Hook Applet 中的 Java 类和方法了。

总结

这篇文章介绍了如何使用 Frida 分析 Java 应用和 Applet。虽然 Frida Java Bridge 在配置上可能会遇到一些问题,但只要掌握了正确的方法,就可以利用它来动态地分析和调试 Java 代码。希望这些信息能帮助你更好地理解和应用 Frida。