├── .gitignore ├── app ├── .gitignore ├── CMakeLists.txt ├── build.gradle ├── libs │ └── armeabi-v7a │ │ ├── libhook-simple.so │ │ ├── libnative-hook.so │ │ └── libnative-write.so ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── feature │ │ └── hook │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── hook_simple.c │ │ ├── hook_simple.h │ │ ├── logger.h │ │ ├── native_hook.c │ │ ├── native_hook.h │ │ ├── native_write.c │ │ └── native_write.h │ ├── java │ │ └── com │ │ │ └── feature │ │ │ └── hook │ │ │ ├── MainActivity.java │ │ │ └── NativeHook.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── feature │ └── hook │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | .gradle 4 | .externalNativeBuild 5 | local.properties 6 | /build 7 | /captures 8 | /outputs 9 | *.hprof 10 | 11 | bin/ 12 | gen/ 13 | out/ 14 | 15 | app/release/ 16 | 17 | .cxx 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | ##官方标准配置 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions -Wall") 6 | 7 | add_library(native-write 8 | SHARED 9 | src/main/cpp/native_write.c) 10 | 11 | add_library(native-hook 12 | SHARED 13 | src/main/cpp/native_hook.c) 14 | 15 | add_library(hook-simple 16 | SHARED 17 | src/main/cpp/hook_simple.c) 18 | 19 | target_link_libraries(native-write android log) 20 | 21 | target_link_libraries(native-hook android log) 22 | 23 | target_link_libraries(hook-simple android log) -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | def local_make = false 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.2" 8 | defaultConfig { 9 | applicationId "com.feature.hook" 10 | minSdkVersion 15 11 | targetSdkVersion 29 12 | versionCode 1 13 | versionName "1.0" 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | 16 | externalNativeBuild { 17 | // cmake { 18 | // cppFlags "" 19 | // arguments '-DANDROID_STL=c++_static' 20 | // } 21 | ndk { 22 | ldLibs "log" 23 | abiFilters "armeabi-v7a"//, "arm64-v8a" 24 | } 25 | } 26 | } 27 | buildTypes { 28 | release { 29 | minifyEnabled false 30 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 31 | } 32 | } 33 | sourceSets { 34 | main { 35 | if(!local_make){ 36 | jniLibs.srcDirs = ['libs'] 37 | } 38 | } 39 | } 40 | externalNativeBuild { 41 | if(local_make){ 42 | cmake { 43 | path "CMakeLists.txt" 44 | } 45 | } 46 | } 47 | compileOptions { 48 | sourceCompatibility = '1.8' 49 | targetCompatibility = '1.8' 50 | } 51 | } 52 | 53 | dependencies { 54 | implementation fileTree(dir: 'libs', include: ['*.jar']) 55 | implementation 'androidx.appcompat:appcompat:1.1.0' 56 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 57 | testImplementation 'junit:junit:4.12' 58 | androidTestImplementation 'androidx.test:runner:1.2.0' 59 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 60 | } 61 | -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libhook-simple.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byhook/native-hook/c9d29db1433f49a8fdd67adb68ecf456630a5932/app/libs/armeabi-v7a/libhook-simple.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libnative-hook.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byhook/native-hook/c9d29db1433f49a8fdd67adb68ecf456630a5932/app/libs/armeabi-v7a/libnative-hook.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libnative-write.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byhook/native-hook/c9d29db1433f49a8fdd67adb68ecf456630a5932/app/libs/armeabi-v7a/libnative-write.so -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/feature/hook/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.feature.hook; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.InstrumentationRegistry; 6 | import androidx.test.runner.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getTargetContext(); 24 | 25 | assertEquals("com.feature.hook", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook_simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "hook_simple.h" 7 | #include "logger.h" 8 | 9 | #define PAGE_START(addr) ((addr) & PAGE_MASK) 10 | #define PAGE_END(addr) (PAGE_START(addr) + PAGE_SIZE) 11 | 12 | 13 | size_t (*old_fwrite)(const void *buf, size_t size, size_t count, FILE *fp); 14 | 15 | /** 16 | * hook导出表函数 17 | * @param buf 18 | * @param size 19 | * @param count 20 | * @param fp 21 | * @return 22 | */ 23 | size_t hook_fwrite(const void *buf, size_t size, size_t count, FILE *fp) { 24 | LOG_D("hook simple fwrite success"); 25 | //这里插入一段文本 26 | const char *text = "hello "; 27 | old_fwrite(text, strlen(text), 1, fp); 28 | return old_fwrite(buf, size, count, fp); 29 | } 30 | 31 | /** 32 | * hook导出表函数 33 | * @param path 34 | * @param text 35 | */ 36 | void hook_writeFile(const char *path, const char *text) { 37 | LOG_D("hook writeFile success path=%s text=%s", path, text); 38 | } 39 | 40 | /** 41 | * hook演示操作 42 | * @param env 43 | * @param obj 44 | * @param jSoName 45 | */ 46 | void Java_com_feature_hook_NativeHook_hookSimple(JNIEnv *env, jobject obj, jstring jSoName) { 47 | const char *soName = (*env)->GetStringUTFChars(env, jSoName, 0); 48 | LOG_D("soName=%s", soName); 49 | char line[1024] = "\n"; 50 | FILE *fp = NULL; 51 | uintptr_t base_addr = 0; 52 | uintptr_t addr = 0; 53 | //查找自身对应的基址 54 | if (NULL == (fp = fopen("/proc/self/maps", "r"))) return; 55 | while (fgets(line, sizeof(line), fp)) { 56 | if (NULL != strstr(line, soName) && 57 | sscanf(line, "%"PRIxPTR"-%*lx %*4s 00000000", &base_addr) == 1) 58 | break; 59 | } 60 | fclose(fp); 61 | LOG_D("base address=0x%08X", base_addr); 62 | if (0 == base_addr) return; 63 | //基址+偏移=真实的地址 64 | addr = base_addr + 0x3FD0; 65 | LOG_D("value=0x%08X address=0x%08X fwrite=0x%08X", addr, *(uintptr_t *) addr, fwrite); 66 | //调整写权限 67 | mprotect((void *) PAGE_START(addr), PAGE_SIZE, PROT_READ | PROT_WRITE); 68 | 69 | //保存旧地址 70 | old_fwrite = *(void **) addr; 71 | 72 | //替换新的目标地址 73 | *(void **) addr = hook_fwrite; 74 | //清除指令缓存 75 | __builtin___clear_cache((void *) PAGE_START(addr), (void *) PAGE_END(addr)); 76 | } -------------------------------------------------------------------------------- /app/src/main/cpp/hook_simple.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef NATIVE_HOOK_HOOK_SIMPLE_H 4 | #define NATIVE_HOOK_HOOK_SIMPLE_H 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | JNIEXPORT void JNICALL Java_com_feature_hook_NativeHook_hookSimple(JNIEnv *, jobject, jstring); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | #endif //NATIVE_HOOK_HOOK_SIMPLE_H 15 | -------------------------------------------------------------------------------- /app/src/main/cpp/logger.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | #define LOG_TAG "NativeHook" 6 | #define LOG_E(format, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__) 7 | #define LOG_D(format, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, format, ##__VA_ARGS__) 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/cpp/native_hook.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "native_hook.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #define LOG_TAG "NativeHook" 18 | #define LOG_E(format, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__) 19 | #define LOG_D(format, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, format, ##__VA_ARGS__) 20 | 21 | #define PAGE_START(address) ((address) & PAGE_MASK) 22 | #define PAGE_END(address) (PAGE_START(address) + PAGE_SIZE) 23 | 24 | size_t (*old_fwrite)(const void *buf, size_t size, size_t count, FILE *fp); 25 | 26 | /** 27 | * hook导出表函数 28 | * @param buf 29 | * @param size 30 | * @param count 31 | * @param fp 32 | * @return 33 | */ 34 | size_t new_fwrite(const void *buf, size_t size, size_t count, FILE *fp) { 35 | //这里插入一段文本 36 | const char *text = "hello "; 37 | LOG_D("hook fwrite success insert text: %s", text); 38 | old_fwrite(text, strlen(text), 1, fp); 39 | return old_fwrite(buf, size, count, fp); 40 | } 41 | 42 | void *get_module_base(pid_t pid, const char *module_name) { 43 | FILE *fp; 44 | long addr = 0; 45 | char filename[32] = "\n"; 46 | char line[1024] = "\n"; 47 | LOG_D("pid=%d ", pid); 48 | if (pid < 0) { 49 | snprintf(filename, sizeof(filename), "/proc/self/maps"); 50 | } else { 51 | snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); 52 | } 53 | // 获取指定pid进程加载的内存模块信息 54 | fp = fopen(filename, "r"); 55 | while (fgets(line, sizeof(line), fp)) { 56 | if (NULL != strstr(line, module_name) && 57 | sscanf(line, "%"PRIxPTR"-%*lx %*4s 00000000", &addr) == 1) 58 | break; 59 | } 60 | fclose(fp); 61 | return (void *) addr; 62 | } 63 | 64 | /** 65 | * 执行视图获取 66 | * @param soPath 67 | * @return 68 | */ 69 | int hook_fwrite(const char *soPath) { 70 | //1. 获取目标进程中模块的加载地址 71 | void *base_addr = get_module_base(getpid(), soPath); 72 | LOG_D("base address = 0x%08X", base_addr); 73 | //2. 保存被hook的目标函数的原始调用地址 74 | old_fwrite = fwrite; 75 | LOG_D("origin fopen = 0x%08X", old_fwrite); 76 | //3. 计算program header table实际地址 77 | Elf32_Ehdr *header = (Elf32_Ehdr *) (base_addr); 78 | LOG_D("e_ident = %d", header->e_ident[0]); 79 | if (memcmp(header->e_ident, "\177ELF", 4) != 0) { 80 | return 0; 81 | } 82 | //基址 + Elf32_Off e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE(e_phoff)的值 = program_header_table的地址 83 | Elf32_Phdr *phdr_table = (Elf32_Phdr *) (base_addr + header->e_phoff); 84 | if (phdr_table == 0) { 85 | LOG_D("phdr_table address : 0"); 86 | return 0; 87 | } 88 | size_t phdr_count = header->e_phnum; 89 | LOG_D("phdr_count : %d", phdr_count); 90 | //遍历program header table p_type等于PT_DYNAMIC即为dynameic,获取到p_offset 91 | unsigned long p_vaddr = 0; 92 | unsigned int p_memsz = 0; 93 | int j = 0; 94 | for (j = 0; j < phdr_count; j++) { 95 | if (phdr_table[j].p_type == PT_DYNAMIC) { 96 | LOG_D("phdr_table[j].p_vaddr : %x", phdr_table[j].p_vaddr); 97 | p_vaddr = phdr_table[j].p_vaddr + base_addr; 98 | p_memsz = phdr_table[j].p_memsz; 99 | break; 100 | } 101 | } 102 | LOG_D("p_vaddr : %x", p_vaddr); 103 | LOG_D("p_memsz : %x", p_memsz); 104 | Elf32_Dyn *dynamic_table = (Elf32_Dyn *) (p_vaddr); 105 | unsigned long jmpRelOff = 0; 106 | unsigned long strTabOff = 0; 107 | unsigned long pltRelSz = 0; 108 | unsigned long symTabOff = 0; 109 | int dynCount = p_memsz / sizeof(Elf32_Dyn); 110 | for (int i = 0; i < dynCount; i++) { 111 | int val = dynamic_table[i].d_un.d_val; 112 | switch (dynamic_table[i].d_tag) { 113 | case DT_JMPREL: 114 | jmpRelOff = val; 115 | break; 116 | case DT_STRTAB: 117 | strTabOff = val; 118 | break; 119 | case DT_PLTRELSZ: 120 | pltRelSz = val / sizeof(Elf32_Rel); 121 | break; 122 | case DT_SYMTAB: 123 | symTabOff = val; 124 | break; 125 | } 126 | } 127 | Elf32_Rel *rel_table = (Elf32_Rel *) (jmpRelOff + base_addr); 128 | LOG_D("jmpRelOff : %x", jmpRelOff); 129 | LOG_D("strTabOff : %x", strTabOff); 130 | LOG_D("symTabOff : %x", symTabOff); 131 | //遍历查找要hook的导入函数 132 | for (int i = 0; i < pltRelSz; i++) { 133 | uint16_t ndx = ELF32_R_SYM(rel_table[i].r_info); 134 | Elf32_Sym *symTableIndex = (Elf32_Sym *) (ndx * sizeof(Elf32_Sym) + symTabOff + 135 | base_addr); 136 | char *funcName = (char *) (symTableIndex->st_name + strTabOff + base_addr); 137 | if (memcmp(funcName, "fwrite", strlen("fwrite")) == 0) { 138 | //获取当前内存分页的大小 139 | uint32_t page_size = getpagesize(); 140 | //获取内存分页的起始地址(需要内存对齐) 141 | uint32_t mem_page_start = rel_table[i].r_offset + base_addr; 142 | LOG_D("old_function=0x%08X new_function=0x%08X", mem_page_start, new_fwrite); 143 | LOG_D("mem_page_start=0x%08X, page size=%d", mem_page_start, page_size); 144 | mprotect((uint32_t) PAGE_START(mem_page_start), page_size, 145 | PROT_READ | PROT_WRITE | PROT_EXEC); 146 | //完成替换操作 147 | *(unsigned int *) (rel_table[i].r_offset + base_addr) = new_fwrite; 148 | //清除指令缓存 149 | __builtin___clear_cache((void *) PAGE_START(mem_page_start), 150 | (void *) PAGE_END(mem_page_start)); 151 | } 152 | } 153 | return 0; 154 | } 155 | 156 | JNIEXPORT void JNICALL 157 | Java_com_feature_hook_NativeHook_hookWrite(JNIEnv *env, jobject obj, jstring jSoPath) { 158 | const char *soPath = (*env)->GetStringUTFChars(env, jSoPath, 0); 159 | LOG_D("hook soPath=%s", soPath); 160 | hook_fwrite(soPath); 161 | } -------------------------------------------------------------------------------- /app/src/main/cpp/native_hook.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef NATIVE_HOOK_NATIVE_HOOK_H 4 | #define NATIVE_HOOK_NATIVE_HOOK_H 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | JNIEXPORT void JNICALL Java_com_feature_hook_NativeHook_hookWrite(JNIEnv *, jobject, jstring); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | #endif //NATIVE_HOOK_NATIVE_HOOK_H -------------------------------------------------------------------------------- /app/src/main/cpp/native_write.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "native_write.h" 5 | #include "logger.h" 6 | 7 | /** 8 | * 完成写入文件的操作 9 | * @param path 10 | * @param text 11 | */ 12 | void writeText(const char *path, const char *text) { 13 | FILE *fp = NULL; 14 | if ((fp = fopen(path, "w")) == NULL) { 15 | LOG_E("file cannot open"); 16 | return; 17 | } 18 | //写入数据 19 | fwrite(text, strlen(text), 1, fp); 20 | if (fclose(fp) != 0) { 21 | LOG_E("file cannot be closed"); 22 | return; 23 | } 24 | } 25 | 26 | JNIEXPORT void JNICALL 27 | Java_com_feature_hook_NativeHook_writeText(JNIEnv *env, jobject obj, jstring filePath, 28 | jstring jText) { 29 | const char *path = (*env)->GetStringUTFChars(env, filePath, 0); 30 | const char *text = (*env)->GetStringUTFChars(env, jText, 0); 31 | LOG_D("fwrite address=0x%08X", fopen); 32 | LOG_D("writeText address=0x%08X", writeText); 33 | writeText(path, text); 34 | } -------------------------------------------------------------------------------- /app/src/main/cpp/native_write.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef NATIVE_HOOK_NATIVE_VALUE_H 4 | #define NATIVE_HOOK_NATIVE_VALUE_H 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | JNIEXPORT void JNICALL 10 | Java_com_feature_hook_NativeHook_writeText(JNIEnv *env, jobject obj, jstring filePath, 11 | jstring jText); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | #endif //NATIVE_HOOK_NATIVE_VALUE_H 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/feature/hook/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.feature.hook; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | import java.io.File; 9 | 10 | import dalvik.system.PathClassLoader; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | 14 | private NativeHook mNativeHook = new NativeHook(); 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | } 21 | 22 | public void onHookClick(View view) { 23 | PathClassLoader pathClassLoader = (PathClassLoader) getClassLoader(); 24 | String nativeWritePath = pathClassLoader.findLibrary("native-write"); 25 | mNativeHook.hookWrite(nativeWritePath); 26 | } 27 | 28 | public void onWriteClick(View view) { 29 | File textFile = new File(getExternalFilesDir(null), "open.txt"); 30 | mNativeHook.writeText(textFile.getAbsolutePath(), "world"); 31 | } 32 | 33 | public void onSimpleHookClick(View view) { 34 | mNativeHook.hookSimple("libnative-write.so"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/feature/hook/NativeHook.java: -------------------------------------------------------------------------------- 1 | package com.feature.hook; 2 | 3 | /** 4 | * @anchor: handy 5 | * @date: 2019-11-24 6 | * @description: 7 | */ 8 | public class NativeHook { 9 | 10 | static { 11 | System.loadLibrary("native-write"); 12 | System.loadLibrary("native-hook"); 13 | System.loadLibrary("hook-simple"); 14 | } 15 | 16 | public native void writeText(String filePath, String text); 17 | 18 | public native void hookWrite(String soPath); 19 | 20 | public native void hookSimple(String soName); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |