Chinese document click here
Modify Android linker to provide loading module and plt hook features.Please check the detailed principle modify linker to implement plt hook
Android version: Android 5.0
~ Android 11
+. Support instructions: x86
, x86_64
, arm
, arm64
- Source build
Add it as an
Android Library
to theAndroid
project,the main module adds its dependencies.Changebuild.gradle
buildApi
variable,compile the specified Api level.
- Use build library
Download the latest version of the binary file, decompress it, add the
aar
file as a library to the project dependencies, and import the header file under theinclude
directory into the Hook module for use.
- Build configuration
Refer to FakeXposed configuration scripts
build.py
andbuild.gradle
- Copy the export header file (the source code is in the export directory under the
cpp
directory) to theHook
module. - Implement the
fake_load_library_init
export function inlinker_export.h
. - Call various implementation methods, check the definition of
RemoteInvokeInterface
inlinker_export.h
. - Normally implement Hook methods such as:
open
,dlopen
,dlsym
method, etc., the method must be exported. - Hook module distinguishes Android7.0 or lower (no namespace,
soinfo handle
), Android7.0 and above (namespace,soinfo handle
).
- Install the library correctly to the specified location, install the
fake-linker
andHook
modules to the path that the application has access to, such as:/data/local/tmp
, you can call the system method to load directly. The module has integrated the installation executable file, and the Java layer calls the method under the FileInstaller class to install, and various different platform architectures have been processed inside. - Set the
fake-linker
module throughFileInstaller
. TheHook
module requires different selinux and uid, gid file attributes. - Load and initialize the
fake-linker
module, call theFakeLinker.initFakeLinker
method, internally load the Hook module and call back thefake_load_library_init
method to complete the module initialization.
- The project is different from directly setting the
LD_PRELOAD
environment variable. Direct setting usually cannot intercept thedlsym
method, because once intercepted, you need to implement the search symbol yourself and the higher version has thecaller
address restriction, and the module passes the transfer modulefake- linker
provides callingdlsym
method, so Hook module can interceptdlsym
and provide moreLinker
related functions. - Each version of Android
Linker
has corresponding modifications, so the module depends on theapi
level of the phone, and the corresponding modules can be loaded at different levels. When loading manually, you need to pay attention toApi 25
directly use the library ofApi 24
- When hooking the system process, please do a good job of deleting the backup to avoid the situation that the system process is dead and cannot be booted due to an error.
- Relocate the loaded module according to the module loading time.
- Set the
Hook
module as the global libraryremote->CallCommonFunction(kCFAddSoinfoToGlobal, kSPAddress, nullptr, kSPNull, nullptr, &error_code);
. - Relocate some loaded modules
remote->CallCommonFunction(kCFCallManualRelinks, kSPAddress, nullptr, kSPNames, libs, &error_code);
.static const RemoteInvokeInterface *remote; // Hook the jni function RegisterNatives static jint HookJniRegisterNatives(JNIEnv *env, jclass c, const JNINativeMethod *methods, jint nMethods) { LOG("start register native function %p", __builtin_return_address(0)); jint ret = original_functions->RegisterNatives(env, c, methods, nMethods); if (ret != JNI_ERR && !original_functions->ExceptionCheck(env)) { std::string cls = JNIHelper::GetClassName(env, c); for (int i = 0; i < nMethods; ++i) { LOG("native register class: %s, method name: %s, function signature: %s, register address: %p", cls.c_str(), methods[i].name, methods[i].signature, methods[i].fnPtr); } } return ret; } static void InitHook() { int error_code; // Add this hook module to the global module, which will affect all modules loaded later remote->CallCommonFunction(kCFAddSoinfoToGlobal, kSPAddress, nullptr, kSPNull, nullptr, &error_code); if (error_code != kErrorNo) { LOGE("init global soinfo error, error code: %x", error_code); return; } VarLengthObject<const char *> *libs; // Re-parse the import table of the following modules, because the following modules have been loaded before we have loaded them, and all re-links make their symbolic links to our Hook method // The java system code also mainly uses the following libraries, and relinking also means the core import function of Hook"s java libs = VaArgsToVarLengthObject<const char *>(5, "libjavacore.so", "libnativehelper.so", "libnativeloader.so", "libart.so", "libopenjdk.so"); remote->CallCommonFunction(kCFCallManualRelinks, kSPAddress, nullptr, kSPNames, libs, &error_code); // Hook JNI interface remote_->HookJniNative(offsetof(JNINativeInterface, RegisterNatives), (void *)HookJniRegisterNatives, nullptr); } C_API void fake_load_library_init(JNIEnv *env, void *fake_soinfo, const RemoteInvokeInterface *interface, const char *cache_path, const char *config_path, const char *_process_name){ remote = interface; InitHook(); }
- For other more uses
FakeXposed
Xposed
,root
Shield detection,File redirection, etc.