Hook Java methods natively from C/C++
Made by Rdbo
This project is licensed under the GNU AGPL-3.0. No later version is allowed.
Read the file LICENSE for more information.
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, hkMyFunction, &originalMethod);
}For the time being, you cannot hook constructors (a.k.a <init> methods).
This is due to how the hooking method works and how the JVM operates.
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>.
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)
