├── README.md └── XposedInlineHook ├── XposedInlineHook.iml ├── app ├── app.iml ├── build.gradle ├── lib │ └── XposedBridgeApi-54.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wizd │ │ └── xposedinlinehook │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── xposed_init │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── hooktest.cpp │ │ ├── hooktest.h │ │ ├── include │ │ │ ├── inlineHook.h │ │ │ └── relocate.h │ │ ├── inlineHook.c │ │ ├── native-lib.cpp │ │ └── relocate.c │ ├── java │ │ └── com │ │ │ └── wizd │ │ │ └── xposedinlinehook │ │ │ └── HookClass.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.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 │ └── wizd │ └── xposedinlinehook │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # XposedInlineHook 2 | 3 | Xposed + InlineHook, so you can hook C/C++ code with xposed, sometimes it's usefull, can be used in VirtualPosed. 4 | 5 | Dependency: 6 | 7 | Android-Inline-Hook: 8 | -------------------------------------------------------------------------------- /XposedInlineHook/XposedInlineHook.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /XposedInlineHook/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /XposedInlineHook/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.wizd.xposedinlinehook" 7 | minSdkVersion 19 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | 13 | ndk{ 14 | abiFilter("armeabi-v7a") 15 | } 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | externalNativeBuild { 24 | cmake { 25 | path file('src/main/cpp/CMakeLists.txt') 26 | } 27 | } 28 | } 29 | 30 | dependencies { 31 | compileOnly files('lib/XposedBridgeApi-54.jar') 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | implementation 'com.android.support:appcompat-v7:28.0.0' 34 | testImplementation 'junit:junit:4.12' 35 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 36 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 37 | } 38 | -------------------------------------------------------------------------------- /XposedInlineHook/app/lib/XposedBridgeApi-54.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizdzz/XposedInlineHook/5ef6d1a0945a67dd1d6197f34516b8c9d9c9ae0d/XposedInlineHook/app/lib/XposedBridgeApi-54.jar -------------------------------------------------------------------------------- /XposedInlineHook/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 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/androidTest/java/com/wizd/xposedinlinehook/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.wizd.xposedinlinehook; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.wizd.xposedinlinehook", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 11 | 12 | 15 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.wizd.xposedinlinehook.HookClass -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | native-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | inlineHook.c 21 | relocate.c 22 | hooktest.cpp 23 | 24 | native-lib.cpp) 25 | 26 | # Searches for a specified prebuilt library and stores the path as a 27 | # variable. Because CMake includes system libraries in the search path by 28 | # default, you only need to specify the name of the public NDK library 29 | # you want to add. CMake verifies that the library exists before 30 | # completing its build. 31 | 32 | find_library( # Sets the name of the path variable. 33 | log-lib 34 | 35 | # Specifies the name of the NDK library that 36 | # you want CMake to locate. 37 | log) 38 | 39 | # Specifies libraries CMake should link to your target library. You 40 | # can link multiple libraries, such as libraries you define in this 41 | # build script, prebuilt third-party libraries, or system libraries. 42 | 43 | target_link_libraries( # Specifies the target library. 44 | native-lib 45 | 46 | # Links the target library to the log library 47 | # included in the NDK. 48 | ${log-lib}) -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/hooktest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "include/inlineHook.h" 6 | #include "hooktest.h" 7 | 8 | #include 9 | #include 10 | 11 | #define TAG "wizd_xposed" 12 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) 13 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) 14 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) 15 | 16 | int (*old_rand)() = NULL; 17 | 18 | int new_rand() 19 | { 20 | return -1; 21 | } 22 | 23 | int hook() 24 | { 25 | if (registerInlineHook((uint32_t) rand, (uint32_t) new_rand, (uint32_t **) &old_rand) != ELE7EN_OK) { 26 | return -1; 27 | } 28 | if (inlineHook((uint32_t) rand) != ELE7EN_OK) { 29 | return -1; 30 | } 31 | 32 | return 0; 33 | } 34 | 35 | int unHook() 36 | { 37 | if (inlineUnHook((uint32_t) rand) != ELE7EN_OK) { 38 | return -1; 39 | } 40 | 41 | return 0; 42 | } 43 | 44 | int testHook() { 45 | int n = rand(); 46 | LOGI("rand return: %d.", n); 47 | 48 | n = hook(); 49 | LOGI("hook return: %d.", n); 50 | 51 | n = rand(); 52 | LOGI("rand return: %d.", n); 53 | 54 | n = unHook(); 55 | LOGI("unHook return: %d.", n); 56 | 57 | n = rand(); 58 | LOGI("rand return: %d.", n); 59 | 60 | return 0; 61 | } 62 | 63 | 64 | int (*old_recvfrom)() = NULL; 65 | 66 | //ssize_t recvfrom(int __fd, void* __buf, size_t __n, int __flags, struct sockaddr* __src_addr, socklen_t* __src_addr_length) 67 | ssize_t new_recvfrom(int __fd, void* __buf, size_t __n, int __flags, struct sockaddr* __src_addr, socklen_t* __src_addr_length) 68 | { 69 | memset(__buf, 0, __n); 70 | return -1; 71 | } 72 | 73 | void hookRecvfrom(){ 74 | if (registerInlineHook((uint32_t) recvfrom, (uint32_t) new_recvfrom, (uint32_t **) &old_recvfrom) != ELE7EN_OK) { 75 | LOGD("registerInlineHook failed."); 76 | } 77 | if (inlineHook((uint32_t) recvfrom) != ELE7EN_OK) { 78 | LOGD("inlineHook failed."); 79 | } 80 | 81 | LOGD("hook succeed."); 82 | } 83 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/hooktest.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Administrator on 2019/7/8. 3 | // 4 | 5 | #ifndef INLINEHOOKTEST_HOOKTEST_H 6 | #define INLINEHOOKTEST_HOOKTEST_H 7 | 8 | int testHook(); 9 | void hookRecvfrom(); 10 | 11 | #endif //INLINEHOOKTEST_HOOKTEST_H 12 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/include/inlineHook.h: -------------------------------------------------------------------------------- 1 | #ifndef _INLINEHOOK_H 2 | #define _INLINEHOOK_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | enum ele7en_status { 11 | ELE7EN_ERROR_UNKNOWN = -1, 12 | ELE7EN_OK = 0, 13 | ELE7EN_ERROR_NOT_INITIALIZED, 14 | ELE7EN_ERROR_NOT_EXECUTABLE, 15 | ELE7EN_ERROR_NOT_REGISTERED, 16 | ELE7EN_ERROR_NOT_HOOKED, 17 | ELE7EN_ERROR_ALREADY_REGISTERED, 18 | ELE7EN_ERROR_ALREADY_HOOKED, 19 | ELE7EN_ERROR_SO_NOT_FOUND, 20 | ELE7EN_ERROR_FUNCTION_NOT_FOUND 21 | }; 22 | 23 | enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr); 24 | enum ele7en_status inlineUnHook(uint32_t target_addr); 25 | void inlineUnHookAll(); 26 | enum ele7en_status inlineHook(uint32_t target_addr); 27 | void inlineHookAll(); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/include/relocate.h: -------------------------------------------------------------------------------- 1 | #ifndef _RELOCATE_H 2 | #define _RELOCATE_H 3 | 4 | #include 5 | 6 | void relocateInstruction(uint32_t target_addr, void *orig_instructions, int length, void *trampoline_instructions, int *orig_boundaries, int *trampoline_boundaries, int *count); 7 | 8 | #endif -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/inlineHook.c: -------------------------------------------------------------------------------- 1 | /* 2 | thumb16 thumb32 arm32 inlineHook 3 | author: ele7enxxh 4 | mail: ele7enxxh@qq.com 5 | website: ele7enxxh.com 6 | modified time: 2015-01-23 7 | created time: 2015-11-30 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | // #include 16 | #include 17 | #include 18 | 19 | 20 | #include "include/relocate.h" 21 | #include "include/inlineHook.h" 22 | 23 | #ifndef PAGE_SIZE 24 | #define PAGE_SIZE 4096 25 | #endif 26 | 27 | #define PAGE_START(addr) (~(PAGE_SIZE - 1) & (addr)) 28 | #define SET_BIT0(addr) (addr | 1) 29 | #define CLEAR_BIT0(addr) (addr & 0xFFFFFFFE) 30 | #define TEST_BIT0(addr) (addr & 1) 31 | 32 | #define ACTION_ENABLE 0 33 | #define ACTION_DISABLE 1 34 | 35 | #define bool int 36 | #define true 1 37 | #define false 0 38 | 39 | 40 | enum hook_status { 41 | REGISTERED, 42 | HOOKED, 43 | }; 44 | 45 | struct inlineHookItem { 46 | uint32_t target_addr; 47 | uint32_t new_addr; 48 | uint32_t **proto_addr; 49 | void *orig_instructions; 50 | int orig_boundaries[4]; 51 | int trampoline_boundaries[20]; 52 | int count; 53 | void *trampoline_instructions; 54 | int length; 55 | int status; 56 | int mode; 57 | }; 58 | 59 | struct inlineHookInfo { 60 | struct inlineHookItem item[1024]; 61 | int size; 62 | }; 63 | 64 | static struct inlineHookInfo info = {0}; 65 | 66 | static int getAllTids(pid_t exclude_tid, pid_t *tids) 67 | { 68 | char dir_path[32]; 69 | DIR *dir; 70 | int i; 71 | struct dirent *entry; 72 | pid_t tid; 73 | 74 | if (exclude_tid < 0) { 75 | snprintf(dir_path, sizeof(dir_path), "/proc/self/task"); 76 | } 77 | else { 78 | snprintf(dir_path, sizeof(dir_path), "/proc/%d/task", exclude_tid); 79 | } 80 | 81 | dir = opendir(dir_path); 82 | if (dir == NULL) { 83 | return 0; 84 | } 85 | 86 | i = 0; 87 | while((entry = readdir(dir)) != NULL) { 88 | tid = atoi(entry->d_name); 89 | if (tid != 0 && tid != exclude_tid) { 90 | tids[i++] = tid; 91 | } 92 | } 93 | closedir(dir); 94 | return i; 95 | } 96 | 97 | static bool doProcessThreadPC(struct inlineHookItem *item, struct pt_regs *regs, int action) 98 | { 99 | int offset; 100 | int i; 101 | 102 | switch (action) 103 | { 104 | case ACTION_ENABLE: 105 | offset = regs->ARM_pc - CLEAR_BIT0(item->target_addr); 106 | for (i = 0; i < item->count; ++i) { 107 | if (offset == item->orig_boundaries[i]) { 108 | regs->ARM_pc = (uint32_t) item->trampoline_instructions + item->trampoline_boundaries[i]; 109 | return true; 110 | } 111 | } 112 | break; 113 | case ACTION_DISABLE: 114 | offset = regs->ARM_pc - (int) item->trampoline_instructions; 115 | for (i = 0; i < item->count; ++i) { 116 | if (offset == item->trampoline_boundaries[i]) { 117 | regs->ARM_pc = CLEAR_BIT0(item->target_addr) + item->orig_boundaries[i]; 118 | return true; 119 | } 120 | } 121 | break; 122 | } 123 | 124 | return false; 125 | } 126 | 127 | static void processThreadPC(pid_t tid, struct inlineHookItem *item, int action) 128 | { 129 | struct pt_regs regs; 130 | 131 | if (ptrace(PTRACE_GETREGS, tid, NULL, ®s) == 0) { 132 | if (item == NULL) { 133 | int pos; 134 | 135 | for (pos = 0; pos < info.size; ++pos) { 136 | if (doProcessThreadPC(&info.item[pos], ®s, action) == true) { 137 | break; 138 | } 139 | } 140 | } 141 | else { 142 | doProcessThreadPC(item, ®s, action); 143 | } 144 | 145 | ptrace(PTRACE_SETREGS, tid, NULL, ®s); 146 | } 147 | } 148 | 149 | static pid_t freeze(struct inlineHookItem *item, int action) 150 | { 151 | int count; 152 | pid_t tids[1024]; 153 | pid_t pid; 154 | 155 | pid = -1; 156 | count = getAllTids(gettid(), tids); 157 | if (count > 0) { 158 | pid = fork(); 159 | 160 | if (pid == 0) { 161 | int i; 162 | 163 | for (i = 0; i < count; ++i) { 164 | if (ptrace(PTRACE_ATTACH, tids[i], NULL, NULL) == 0) { 165 | waitpid(tids[i], NULL, WUNTRACED); 166 | processThreadPC(tids[i], item, action); 167 | } 168 | } 169 | 170 | raise(SIGSTOP); 171 | 172 | for (i = 0; i < count; ++i) { 173 | ptrace(PTRACE_DETACH, tids[i], NULL, NULL); 174 | } 175 | 176 | raise(SIGKILL); 177 | } 178 | 179 | else if (pid > 0) { 180 | waitpid(pid, NULL, WUNTRACED); 181 | } 182 | } 183 | 184 | return pid; 185 | } 186 | 187 | static void unFreeze(pid_t pid) 188 | { 189 | if (pid < 0) { 190 | return; 191 | } 192 | 193 | kill(pid, SIGCONT); 194 | wait(NULL); 195 | } 196 | 197 | static bool isExecutableAddr(uint32_t addr) 198 | { 199 | FILE *fp; 200 | char line[1024]; 201 | uint32_t start; 202 | uint32_t end; 203 | 204 | fp = fopen("/proc/self/maps", "r"); 205 | if (fp == NULL) { 206 | return false; 207 | } 208 | 209 | while (fgets(line, sizeof(line), fp)) { 210 | if (strstr(line, "r-xp") || strstr(line, "rwxp")) { 211 | start = strtoul(strtok(line, "-"), NULL, 16); 212 | end = strtoul(strtok(NULL, " "), NULL, 16); 213 | if (addr >= start && addr <= end) { 214 | fclose(fp); 215 | return true; 216 | } 217 | } 218 | } 219 | 220 | fclose(fp); 221 | 222 | return false; 223 | } 224 | 225 | static struct inlineHookItem *findInlineHookItem(uint32_t target_addr) 226 | { 227 | int i; 228 | 229 | for (i = 0; i < info.size; ++i) { 230 | if (info.item[i].target_addr == target_addr) { 231 | return &info.item[i]; 232 | } 233 | } 234 | 235 | return NULL; 236 | } 237 | 238 | static struct inlineHookItem *addInlineHookItem() { 239 | struct inlineHookItem *item; 240 | 241 | if (info.size >= 1024) { 242 | return NULL; 243 | } 244 | 245 | item = &info.item[info.size]; 246 | ++info.size; 247 | 248 | return item; 249 | } 250 | 251 | static void deleteInlineHookItem(int pos) 252 | { 253 | info.item[pos] = info.item[info.size - 1]; 254 | --info.size; 255 | } 256 | 257 | enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr) 258 | { 259 | struct inlineHookItem *item; 260 | 261 | if (!isExecutableAddr(target_addr) || !isExecutableAddr(new_addr)) { 262 | return ELE7EN_ERROR_NOT_EXECUTABLE; 263 | } 264 | 265 | item = findInlineHookItem(target_addr); 266 | if (item != NULL) { 267 | if (item->status == REGISTERED) { 268 | return ELE7EN_ERROR_ALREADY_REGISTERED; 269 | } 270 | else if (item->status == HOOKED) { 271 | return ELE7EN_ERROR_ALREADY_HOOKED; 272 | } 273 | else { 274 | return ELE7EN_ERROR_UNKNOWN; 275 | } 276 | } 277 | 278 | item = addInlineHookItem(); 279 | 280 | item->target_addr = target_addr; 281 | item->new_addr = new_addr; 282 | item->proto_addr = proto_addr; 283 | 284 | item->length = TEST_BIT0(item->target_addr) ? 12 : 8; 285 | item->orig_instructions = malloc(item->length); 286 | memcpy(item->orig_instructions, (void *) CLEAR_BIT0(item->target_addr), item->length); 287 | 288 | item->trampoline_instructions = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 289 | relocateInstruction(item->target_addr, item->orig_instructions, item->length, item->trampoline_instructions, item->orig_boundaries, item->trampoline_boundaries, &item->count); 290 | 291 | item->status = REGISTERED; 292 | 293 | return ELE7EN_OK; 294 | } 295 | 296 | static void doInlineUnHook(struct inlineHookItem *item, int pos) 297 | { 298 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC); 299 | memcpy((void *) CLEAR_BIT0(item->target_addr), item->orig_instructions, item->length); 300 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_EXEC); 301 | munmap(item->trampoline_instructions, PAGE_SIZE); 302 | free(item->orig_instructions); 303 | 304 | deleteInlineHookItem(pos); 305 | 306 | cacheflush(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length, 0); 307 | } 308 | 309 | enum ele7en_status inlineUnHook(uint32_t target_addr) 310 | { 311 | int i; 312 | 313 | for (i = 0; i < info.size; ++i) { 314 | if (info.item[i].target_addr == target_addr && info.item[i].status == HOOKED) { 315 | pid_t pid; 316 | 317 | pid = freeze(&info.item[i], ACTION_DISABLE); 318 | 319 | doInlineUnHook(&info.item[i], i); 320 | 321 | unFreeze(pid); 322 | 323 | return ELE7EN_OK; 324 | } 325 | } 326 | 327 | return ELE7EN_ERROR_NOT_HOOKED; 328 | } 329 | 330 | void inlineUnHookAll() 331 | { 332 | pid_t pid; 333 | int i; 334 | 335 | pid = freeze(NULL, ACTION_DISABLE); 336 | 337 | for (i = 0; i < info.size; ++i) { 338 | if (info.item[i].status == HOOKED) { 339 | doInlineUnHook(&info.item[i], i); 340 | --i; 341 | } 342 | } 343 | 344 | unFreeze(pid); 345 | } 346 | 347 | static void doInlineHook(struct inlineHookItem *item) 348 | { 349 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC); 350 | 351 | if (item->proto_addr != NULL) { 352 | *(item->proto_addr) = TEST_BIT0(item->target_addr) ? (uint32_t *) SET_BIT0((uint32_t) item->trampoline_instructions) : item->trampoline_instructions; 353 | } 354 | 355 | if (TEST_BIT0(item->target_addr)) { 356 | int i; 357 | 358 | i = 0; 359 | if (CLEAR_BIT0(item->target_addr) % 4 != 0) { 360 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xBF00; // NOP 361 | } 362 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xF8DF; 363 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xF000; // LDR.W PC, [PC] 364 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = item->new_addr & 0xFFFF; 365 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = item->new_addr >> 16; 366 | } 367 | else { 368 | ((uint32_t *) (item->target_addr))[0] = 0xe51ff004; // LDR PC, [PC, #-4] 369 | ((uint32_t *) (item->target_addr))[1] = item->new_addr; 370 | } 371 | 372 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_EXEC); 373 | 374 | item->status = HOOKED; 375 | 376 | cacheflush(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length, 0); 377 | } 378 | 379 | enum ele7en_status inlineHook(uint32_t target_addr) 380 | { 381 | int i; 382 | struct inlineHookItem *item; 383 | 384 | item = NULL; 385 | for (i = 0; i < info.size; ++i) { 386 | if (info.item[i].target_addr == target_addr) { 387 | item = &info.item[i]; 388 | break; 389 | } 390 | } 391 | 392 | if (item == NULL) { 393 | return ELE7EN_ERROR_NOT_REGISTERED; 394 | } 395 | 396 | if (item->status == REGISTERED) { 397 | pid_t pid; 398 | 399 | pid = freeze(item, ACTION_ENABLE); 400 | 401 | doInlineHook(item); 402 | 403 | unFreeze(pid); 404 | 405 | return ELE7EN_OK; 406 | } 407 | else if (item->status == HOOKED) { 408 | return ELE7EN_ERROR_ALREADY_HOOKED; 409 | } 410 | else { 411 | return ELE7EN_ERROR_UNKNOWN; 412 | } 413 | } 414 | 415 | void inlineHookAll() 416 | { 417 | pid_t pid; 418 | int i; 419 | 420 | pid = freeze(NULL, ACTION_ENABLE); 421 | 422 | for (i = 0; i < info.size; ++i) { 423 | if (info.item[i].status == REGISTERED) { 424 | doInlineHook(&info.item[i]); 425 | } 426 | } 427 | 428 | unFreeze(pid); 429 | } 430 | -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "include/inlineHook.h" 5 | #include "hooktest.h" 6 | 7 | extern "C" JNIEXPORT jstring JNICALL 8 | Java_com_wizd_inlinehooktest_MainActivity_stringFromJNI( 9 | JNIEnv *env, 10 | jobject /* this */) { 11 | std::string hello = "Hello from C++"; 12 | 13 | testHook(); 14 | 15 | return env->NewStringUTF(hello.c_str()); 16 | } 17 | extern "C" 18 | JNIEXPORT void JNICALL 19 | Java_com_wizd_xposedinlinehook_HookClass_testNative(JNIEnv *env, jclass type) { 20 | 21 | // testHook(); 22 | hookRecvfrom(); 23 | 24 | } -------------------------------------------------------------------------------- /XposedInlineHook/app/src/main/cpp/relocate.c: -------------------------------------------------------------------------------- 1 | /* 2 | relocate instruction 3 | author: ele7enxxh 4 | mail: ele7enxxh@qq.com 5 | website: ele7enxxh.com 6 | modified time: 2016-10-17 7 | created time: 2015-01-17 8 | */ 9 | 10 | #include "include/relocate.h" 11 | 12 | #define ALIGN_PC(pc) (pc & 0xFFFFFFFC) 13 | 14 | enum INSTRUCTION_TYPE { 15 | // B