Jnihook
Hook Java methods natively from C/C++
Install / Use
/learn @rdbo/JnihookREADME
JNIHook

Hook Java methods natively from C/C++
Made by Rdbo
License
This project is licensed under the GNU AGPL-3.0. No later version is allowed.
Read the file LICENSE for more information.
Examples
Hooking the function static int myFunction(int mynumber, String name) from a class Dummy:
jmethodID originalMethod;
jint hkMyFunction(JNIEnv *env, jclass clazz, jint number, jstring name)
{
// Print parameters
std::cout << "[*] mynumber value: " << mynumber << std::endl;
std::cout << "[*] name object: " << name << std::endl;
// Call the original method with 'mynumber' set to '1337'
env->CallStaticIntMethod(dummyClass, originalMethod, 1337, name);
return 42; // Modify the return value to '42'
}
void start(JavaVM *jvm)
{
jclass dummyClass = env->FindClass("dummy/Dummy");
jmethodID myFunctionID = env->GetStaticMethodID(dummyClass, "myFunction",
"(ILjava/lang/String;)I");
JNIHook_Init(jvm);
JNIHook_Attach(myFunctionID, reinterpret_cast<void*>(hkMyFunction), &originalMethod);
}
Hooking the constructor from a class Target:
jmethodID originalInit;
void hkMyInit(JNIEnv *env, jobject object, jint number)
{
// Print parameters
std::cout << "[*] number value: " << number << std::endl;
// Call the constructor with 'number' set to '1337'
env->CallVoidMethod(object, originalInit, 1337);
return;
}
void start(JavaVM *jvm)
{
jclass targetClass = env->FindClass("dummy/Target");
jmethodID myInitID = env->GetMethodID(targetClass, "<init>", "(I)V");
JNIHook_Init(jvm);
JNIHook_Attach(myInitID, reinterpret_cast<void*>(hkMyInit), &originalInit);
}
Building
To build this, you can either compile all the files in src into your project, or
use CMake to build a static library, which can be compiled into your project.
NOTE: This requires C++17, which is available on newer versions of Visual Studio and GCC.
The steps ahead are for building a static library with CMake.
- Setup your
JAVA_HOMEenvironment variable. It will be used for accessingjni.h,jvmti.h, and linking thejvmlibrary. On Linux, it's usually on/usr/lib/jvm/<java release>, and on Windows at%ProgramFiles%\Java\jdk-<version>.
- Clone the project
git clone https://github.com/rdbo/jnihook --recursive
- Create a build directory inside the root directory of the repository and enter it:
NOTE: Use the x64 Native Tools Command Prompt on Windows.
mkdir build
cd build
- Run CMake to setup the project
Linux/*nix:
cmake .. -DCMAKE_BUILD_TYPE=Release
Windows:
cmake .. -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles" -DCMAKE_CXX_STANDARD=17
- Build using
nmake(Windows) ormake(*nix):
Linux/*nix:
make
Windows:
nmake
After running these commands, you will have libjnihook.a or jnihook.lib in your build directory, which you can compile along with your project.
NOTE: Don't forget to include JNIHook's include dir in your project so that you can #include <jnihook.h>.
Acknowledgements
Special thanks to:
- @Lefraudeur for helping me with information about JVM functionality throughout jnihook V1 development.
- @acuarica for the awesome JNIF library, which i modified to fit jnihook's use case.
- @griffith1deady for providing me informations about JVM internals.
- @TIMER-err for the jvm-runtime-noverify project, which made me realise I could patch flags at runtime cleanly.
- @awrped for helping to fix Windows and JNIF issues.
- myself for coming up with the V2 hooking method (c'mon, it was not an easy task)
- @rewawe for the bytecode hooking methods (init, clinit, midfunction)
