Android shared library injector based on ptrace with help of KittyMemoryEx.
Requires C++11 or above.
Inject from /data for Android
- Tested on Android 5.0 ~ 14
- ABI arm, arm64, x86, x86_64
- Inject emulated arm64 & arm32 via libhoudini.so or libndk_translation.so
- Bypass android linker namespace restrictions
- memfd dlopen support
- App launch monitor
- Hide lib segments from /maps
- Hide lib from linker solist ( dladdr & dl_iterate_phdr )
Make sure to chmod +x or 755
Usage: ./path/to/AndKittyInjector [-h] [-pkg] [-pid] [-lib] [ options ]
Required arguments:
-pkg Target app package.
-lib Library path to inject.
Optional arguments:
-h, --help show available arguments.
-pid Target app pid.
-dl_memfd Use memfd_create & dlopen_ext to inject library, useful to bypass path restrictions.
-hide_maps Try to hide lib segments from /proc/[pid]/maps.
-hide_solist Try to remove lib from linker or NativeBridge solist.
-watch Monitor process launch then inject, useful if you want to inject as fast as possible.
-delay Set a delay in microseconds before injecting.
- Do not start a thread in library constructor, instead use JNI_OnLoad:
extern "C" jint JNIEXPORT JNI_OnLoad(JavaVM* vm, void *key)
{
// key 1337 is passed by injector
if (key != (void*)1337)
return JNI_VERSION_1_6;
KITTY_LOGI("JNI_OnLoad called by injector.");
JNIEnv *env = nullptr;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK)
{
KITTY_LOGI("JavaEnv: %p.", env);
// ...
}
std::thread(thread_function).detach();
return JNI_VERSION_1_6;
}
-
When using -watch to inject as soon as the target app launches, you may need to use -delay as well, especially when injecting emulated lib.
-
When using -dl_memfd and it fails then legacy dlopen will be called.
- Make sure to have NDK, cmake and make installed and added to OS environment path.
- Set NDK_HOME to point to NDK folder
- You can check both ndk-build.bat and cmake-build.bat
git clone --recursive https://github.com/MJx0/AndKittyInjector.git
cd AndKittyInjector/AndKittyInjector
ndk-build.bat