frida / frida-java-bridge

Java runtime interop from Frida
328 stars 124 forks source link

Hooking functions on JDK17 (HotSpot) crashes the instrumented application #333

Open c8rri3r opened 2 months ago

c8rri3r commented 2 months ago

Summary

Hooking a function on JDK17 (HotSpot) causes the instrumented application to crash. Other features such as searching methods with Java.enumerateMethods(query) work as expected as far as I can tell. This happens each and every time a Java function is hooked. Given this sample application:

public class App 
{
    public static void main( String[] args )
    {
        System.out.println("[*] Checking status of someTest()...");
        try {
            while(true) {
                boolean result = someTest();
                if(result) {
                    System.out.println("[*] Congrats, result has been changed!");
                }
                TimeUnit.SECONDS.sleep(10);
            }
        } catch (InterruptedException e) { }
    }
    public static boolean someTest() {
        return false;
    }
}

Hooking the someTest() function with this instrumentation code will cause the crash:

Java.perform(function () {
    console.log("Is Java Available: " + Java.available)
    var MyClass = Java.use('com.frida.App');

    // Hook the "someTest" function
    MyClass.someTest.implementation = function () {
        console.log('someTest() function called');
        return true;
    };
});

The error message (trimmed for brevity) doesn't immediately indicate where the issue is.

└─$ $JAVA_HOME/bin/java -jar target/frida-java-demo-1.0-SNAPSHOT-jar-with-dependencies.jar
[*] Checking status of someTest()...
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000000000000000, pid=4713, tid=4714
#
# JRE version: OpenJDK Runtime Environment Temurin-17.0.12+7 (17.0.12+7) (build 17.0.12+7)
# Java VM: OpenJDK 64-Bit Server VM Temurin-17.0.12+7 (17.0.12+7, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# j  com.frida.App.main([Ljava/lang/String;)V+8
...

The Frida console provides a more descriptive error message:

Is Java Available: true
Error: Unable to make thread_from_jni_environment() helper for the current architecture
    at <anonymous> (frida/node_modules/frida-java-bridge/lib/jvm.js:232)
    at <anonymous> (frida/node_modules/frida-java-bridge/lib/jvm.js:276)
    at <anonymous> (frida/node_modules/frida-java-bridge/lib/vm.js:12)
    at j (frida/node_modules/frida-java-bridge/lib/jvm.js:291)

This is despite the fact that Frida indicates the JVM should be supported, the Java.api command was trimmed for brevity.

[Local::PID::25154 ]-> Java.available
true
[Local::PID::25154 ]-> Java.api
{
    "flavor": "jvm",
    "jvmti": {
        "handle": "0x7efb500023e0",
        "vm": {
            "handle": "0x7efc279674e0"
        },
        "vtable": "0x7efc27970640"
    },
    "version": 17,
    "versionS": "17.0.12+7",
    "vm": "0x7efc279674e0",
}

This exact same application and instrumentation code works perfectly fine on JDK11 and JDK16 though.

Multiple versions of JDK17 have been used from multiple vendors - Azul, Oracle JDK and Adoptium - and each one leads to a crash.

Test Environment

Steps to Reproduce

I created a GitHub repo with the sample code and instrumentation script mentioned above, alongside build and reproduction steps here.

Related Issues

It's difficult to tell by the information provided in the ticket, but these other issues may be related:

c8rri3r commented 4 days ago

Update: Some progress made. The Unable to make thread_from_jni_environment() helper for the current architecture error message is thrown because an offset between the findClassImpl function entry point and a lea instruction can't be found using the hardcoded limit of 10.

I set that value to 12, and while it isn't throwing that error message anymore, the instrumented application still crashes.

java -jar target/frida-java-demo-1.0-SNAPSHOT-jar-with-dependencies.jar
[*] Checking status of someTest()...
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000000000000000, pid=67514, tid=67515
#
# JRE version: OpenJDK Runtime Environment (17.0.11+9) (build 17.0.11+9-Debian-1)
# Java VM: OpenJDK 64-Bit Server VM (17.0.11+9-Debian-1, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# j  com.frida.App.main([Ljava/lang/String;)V+8
#
# Core dump will be written. Default location: Core dumps may be processed with "/wsl-capture-crash %t %E %p %s" (or dumping to /home/kurt/repos/c8rri3r/frida-java-demo/core.67514)
#
# An error report file with more information is saved as:
# /home/kurt/repos/c8rri3r/frida-java-demo/hs_err_pid67514.log
#
# If you would like to submit a bug report, please visit:
#   https://bugs.debian.org/openjdk-17
#
Aborted (core dumped)