[ad_1]
I’m trying to stalk a minimal Java program that uses JNI with Frida, but I always run into access violation crashes when the JVM is shut down.
Furthermore, I only seem to ever be able to successfully stalk a JVM process (even if JIT is disabled with -Xint
), if Stalker.trustThreshold
is set to -1
.
If I set the Stalker.trustThreshold
to anything other than -1
, the JVM does not crash, but the stalker does not cover any BBs from my custom JNI library native.dll
(see below).
Here’s my Java program:
// Main.java
public class Main {
static {
System.loadLibrary("native");
}
public static void main(String[] args) throws Exception {
Thread.sleep(20_000); // Enough time to attach to process...
new Main().sayHello();
}
private native void sayHello();
}
// Main.cpp
#include "Main.h"
#include <iostream>
#include <fstream>
#include <windows.h>
void sayHello() {
std::ofstream file;
file.open("output.tmp");
file << "Hello World\n";
file.close();
std::cout << "Current Thread id = " << GetCurrentThreadId() << "\n";
}
JNIEXPORT void JNICALL Java_Main_sayHello
(JNIEnv *, jobject) {
sayHello();
}
# Compile native library (Windows)
cl.exe /LD /EHsc /I "%JAVA_HOME%\include" /I "%JAVA_HOME%\include\win32" Main.cpp /link /DLL /DEBUG /OUT:native.dll
# Compile Java code
javac Main.java
# Run program
java -cp . -Djava.library.path=%cd% Main
My frida script looks as follows:
# frida-agent.py
import sys
import frida
def on_message(message, data):
print(str(message))
def main():
device = frida.get_local_device()
pid = -1
for proc in device.enumerate_processes():
if sys.argv[1] in [str(proc.pid), proc.name]:
pid = proc.pid
break
session = device.attach(pid)
print("Attaching to PID=" + str(pid))
script = session.create_script(
"""
Stalker.trustThreshold = -1;
const moduleMap = new ModuleMap();
moduleMap.update();
const createCoverageMap = (events) => {
moduleMap.update();
const coverageMap = {};
for (const event of events) {
const [start, _] = event;
const pStart = new NativePointer(start);
const module = moduleMap.find(pStart);
if (module) {
const offset = pStart.sub(module.base).toInt32();
if (!(module.path in coverageMap)) {
coverageMap[module.path] = 0;
}
coverageMap[module.path] += 1;
}
}
return coverageMap;
};
const stalkThread = (threadId) => {
Stalker.follow(threadId, {
events: {
call: false,
ret: false,
exec: false,
block: false,
compile: true,
},
onReceive: function (events) {
const bbEvents = Stalker.parse(events, {stringify: false, annotate: false});
send({coverage: createCoverageMap(bbEvents)});
}
});
}
const currentThreads = Process.enumerateThreads();
for (const thread of currentThreads) {
console.log("Stalking thread: " + thread.id);
stalkThread(thread.id);
}
"""
)
script.load()
script.on("message", on_message)
sys.stdin.read()
sys.exit(0)
if __name__ == "__main__":
main()
When attaching with python frida-agent.py 8232
the generated output is:
Current Thread id = 9632
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000287f70dae25, pid=8232, tid=0x00000000000025a0
#
# JRE version: OpenJDK Runtime Environment (8.0_292-b10) (build 1.8.0_292-b10)
# Java VM: OpenJDK 64-Bit Server VM (25.292-b10 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C 0x00000287f70dae25
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\workspace\simple-jni-app\hs_err_pid8232.log
#
# If you would like to submit a bug report, please visit:
# https://github.com/AdoptOpenJDK/openjdk-support/issues
#
Do you have any idea on (1) how to prevent the JVM to crash and (2) set the Stalker.trustThreshold
to anything other than -1
and still cover BBs from native.dll
?
Help is very much appreciated! Thanks!
[ad_2]