└── framenthook ├── .gitignore ├── src ├── main │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── styles.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 │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── layout │ │ │ └── activity_main.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ ├── cpp │ │ ├── jni │ │ │ ├── hookTool.c │ │ │ ├── hookTool.h │ │ │ ├── SnowGOTHook.c │ │ │ ├── SnowGOTHook.h │ │ │ ├── SnowInlineHook.c │ │ │ ├── SnowInlineHook.h │ │ │ ├── SnowInlineSimpleHook.c │ │ │ ├── SnowInlineSimpleHook.h │ │ │ └── common.h │ │ ├── MSHook │ │ │ ├── util.h │ │ │ ├── CydiaSubstrate.h │ │ │ ├── Hooker.h │ │ │ ├── SubstrateStruct.h │ │ │ ├── MSHook.h │ │ │ ├── PosixMemory.h │ │ │ ├── MSHook.cpp │ │ │ ├── Debug.h │ │ │ ├── Hooker.cpp │ │ │ ├── PosixMemory.cpp │ │ │ ├── ARM.h │ │ │ ├── Log.h │ │ │ ├── hde64.h │ │ │ ├── Debug.cpp │ │ │ ├── x86_64.h │ │ │ ├── Thumb.h │ │ │ ├── ARM.cpp │ │ │ ├── x86.h │ │ │ ├── x86.cpp │ │ │ ├── util.cpp │ │ │ ├── x86_64.cpp │ │ │ └── Thumb.cpp │ │ ├── Android-Inline │ │ │ ├── relocate.h │ │ │ ├── include │ │ │ │ └── inlineHook.h │ │ │ ├── README.md │ │ │ ├── inlineHook.c │ │ │ └── relocate.c │ │ ├── native-lib.cpp │ │ ├── hook_device.h │ │ ├── DvmDex.h │ │ ├── Common.h │ │ ├── sokect_hook.h │ │ ├── DexProto.h │ │ ├── art.h │ │ └── DexFile.h │ └── java │ │ └── com │ │ └── example │ │ └── framenthook │ │ └── MainActivity.java ├── test │ └── java │ │ └── com │ │ └── example │ │ └── framenthook │ │ └── ExampleUnitTest.java └── androidTest │ └── java │ └── com │ └── example │ └── framenthook │ └── ExampleInstrumentedTest.java ├── libs └── armeabi │ └── libwechatnonmsg.so ├── proguard-rules.pro ├── CMakeLists.txt └── framenthook.iml /framenthook/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /framenthook/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FramentHook 3 | 4 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/hookTool.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/hookTool.c -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/hookTool.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/hookTool.h -------------------------------------------------------------------------------- /framenthook/libs/armeabi/libwechatnonmsg.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/libs/armeabi/libwechatnonmsg.so -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/SnowGOTHook.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/SnowGOTHook.c -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/SnowGOTHook.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/SnowGOTHook.h -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/SnowInlineHook.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/SnowInlineHook.c -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/SnowInlineHook.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/SnowInlineHook.h -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/SnowInlineSimpleHook.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/SnowInlineSimpleHook.c -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/SnowInlineSimpleHook.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/cpp/jni/SnowInlineSimpleHook.h -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyun1314/framenthook/HEAD/framenthook/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /framenthook/src/main/cpp/jni/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMON_H 2 | #define _COMMON_H 3 | #include 4 | #define LOG_TAG "snow_soHook" 5 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 6 | 7 | #endif -------------------------------------------------------------------------------- /framenthook/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/util.h: -------------------------------------------------------------------------------- 1 | #ifndef HOOK_UTIL_H_ 2 | #define HOOK_UTIL_H_ 3 | 4 | #include 5 | 6 | extern int find_name(pid_t pid, const char *name,const char *libn, unsigned long *addr); 7 | extern int find_libbase(pid_t pid, const char *libn, unsigned long *addr); 8 | #endif 9 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/Android-Inline/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 -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /framenthook/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/CydiaSubstrate.h: -------------------------------------------------------------------------------- 1 | #ifndef CYDIASUBSTRATE_H_ 2 | #define CYDIASUBSTRATE_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define _finline \ 8 | inline __attribute__((__always_inline__)) 9 | #define _disused \ 10 | __attribute__((__unused__)) 11 | #define _extern \ 12 | extern "C" __attribute__((__visibility__("default"))) 13 | 14 | #include "SubstrateStruct.h" 15 | #endif /* CYDIASUBSTRATE_H_ */ 16 | -------------------------------------------------------------------------------- /framenthook/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Hooker.h: -------------------------------------------------------------------------------- 1 | #ifndef HOOKER_H_ 2 | #define HOOKER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Debug.h" 10 | #include "Log.h" 11 | #include "PosixMemory.h" 12 | #include "CydiaSubstrate.h" 13 | 14 | namespace Cydia{ 15 | 16 | void MSHookFunction(const char *soname, const char *symbol, void *replace_func, void **old_func); 17 | void MSHookFunction(void *symbol, void *replace, void **result); 18 | } 19 | #endif /* HOOKER_H_ */ -------------------------------------------------------------------------------- /framenthook/src/test/java/com/example/framenthook/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.example.framenthook; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/SubstrateStruct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SubstrateMacro.h 3 | * 4 | * Author: peng 5 | */ 6 | 7 | #ifndef SUBSTRATEMACRO_H_ 8 | #define SUBSTRATEMACRO_H_ 9 | 10 | #include 11 | typedef struct __SubstrateProcess *SubstrateProcessRef; 12 | typedef void *SubstrateAllocatorRef; 13 | typedef struct SubstrateMemory { 14 | void *address_; 15 | size_t width_; 16 | SubstrateMemory(void *address, size_t width):address_(address), width_(width) {} 17 | }*SubstrateMemoryRef; 18 | 19 | #endif /* SUBSTRATEMACRO_H_ */ 20 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/MSHook.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBHOOK_H_ 2 | #define LIBHOOK_H_ 3 | 4 | #define HOOK_FAILED -1 5 | #define HOOK_SUCCESS 0 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | int findSymbol(const char *name, const char *libn, 12 | unsigned long *addr); 13 | int inlineHook(const char *soname, const char *symbol, void *replace_func, void **old_func); 14 | int inlineHookDirect(unsigned int addr, void *replace_func, void **old_func); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | #endif /* LIBHOOK_HOOK2_H_ */ 20 | -------------------------------------------------------------------------------- /framenthook/src/main/java/com/example/framenthook/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.framenthook; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | 7 | public class MainActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_main); 13 | 14 | 15 | 16 | } 17 | 18 | 19 | // Used to load the 'native-lib' library on application startup. 20 | static { 21 | System.loadLibrary("sohook"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/PosixMemory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PosixMemory.h 3 | * 4 | * Author: peng 5 | */ 6 | 7 | #ifndef POSIXMEMORY_H_ 8 | #define POSIXMEMORY_H_ 9 | 10 | #include "CydiaSubstrate.h" 11 | 12 | 13 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); 14 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory); 15 | extern "C" void __clear_cache(void *beg, void *end); 16 | 17 | struct SubstrateHookMemory { 18 | SubstrateMemoryRef handle_; 19 | 20 | SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) {} 21 | 22 | ~SubstrateHookMemory() { 23 | if (handle_ != NULL) 24 | SubstrateMemoryRelease(handle_); 25 | } 26 | }; 27 | 28 | #endif /* POSIXMEMORY_H_ */ 29 | -------------------------------------------------------------------------------- /framenthook/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 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/Android-Inline/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 | -------------------------------------------------------------------------------- /framenthook/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/MSHook.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "util.h" 4 | 5 | #include "Hooker.h" 6 | #include "MSHook.h" 7 | 8 | 9 | int inlineHook(const char *soname, const char *symbol, void *replace_func, 10 | void **old_func) { 11 | int ret = -1; 12 | void *addr = NULL; 13 | if (findSymbol(symbol, soname, (unsigned long *) &addr) < 0) { 14 | return -1; 15 | } 16 | Cydia::MSHookFunction(addr, replace_func, old_func); 17 | ret = 0; 18 | return ret; 19 | } 20 | 21 | int findSymbol(const char *name, const char *libn, 22 | unsigned long *addr) { 23 | return find_name(getpid(), name, libn, addr); 24 | } 25 | 26 | int inlineHookDirect(unsigned int addr, void *replace_func, void **old_func) { 27 | if (addr == 0) { 28 | return -1; 29 | } 30 | Cydia::MSHookFunction((void *) addr, replace_func, old_func); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /framenthook/src/androidTest/java/com/example/framenthook/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.framenthook; 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.framenthook", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/Android-Inline/README.md: -------------------------------------------------------------------------------- 1 | # Android-Inline-Hook 2 | thumb16 thumb32 arm32 inlineHook 3 | 4 | # Build 5 | ```ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk``` 6 | 7 | # Example 8 | ```C 9 | #include 10 | 11 | #include "inlineHook.h" 12 | 13 | int (*old_puts)(const char *) = NULL; 14 | 15 | int new_puts(const char *string) 16 | { 17 | old_puts("inlineHook success"); 18 | } 19 | 20 | int hook() 21 | { 22 | if (registerInlineHook((uint32_t) puts, (uint32_t) new_puts, (uint32_t **) &old_puts) != ELE7EN_OK) { 23 | return -1; 24 | } 25 | if (inlineHook((uint32_t) puts) != ELE7EN_OK) { 26 | return -1; 27 | } 28 | 29 | return 0; 30 | } 31 | 32 | int unHook() 33 | { 34 | if (inlineUnHook((uint32_t) puts) != ELE7EN_OK) { 35 | return -1; 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | int main() 42 | { 43 | puts("test"); 44 | hook(); 45 | //puts("test"); 46 | unHook(); 47 | puts("test"); 48 | } 49 | 50 | ``` 51 | 52 | # Contact 53 | If you find any bugs, please contact me(ele7enxxh@qq.com) 54 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Debug.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_DEBUG_HPP 23 | #define SUBSTRATE_DEBUG_HPP 24 | 25 | #include "Log.h" 26 | #include 27 | #define lprintf(format, ...) \ 28 | MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) 29 | 30 | extern "C" bool MSDebug; 31 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); 32 | void MSLogHex(const void *vdata, size_t size, const char *mark = 0); 33 | 34 | #endif//SUBSTRATE_DEBUG_HPP 35 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Hooker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Hooker.h" 3 | #include "util.h" 4 | #include "ARM.h" 5 | #include "Thumb.h" 6 | #include "x86.h" 7 | #define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG,"wodelog", __VA_ARGS__) 8 | void Cydia::MSHookFunction(void *symbol, void *replace, void **result) { 9 | 10 | SubstrateProcessRef process = NULL; 11 | if (MSDebug){ 12 | MSLog(MSLogLevelNotice, "SubstrateHookFunction(process:%p, symbol:%p, replace:%p, result:%p)", process, symbol, replace, result); 13 | } 14 | #if defined(__arm__) || defined(__thumb__) 15 | if ((reinterpret_cast(symbol) & 0x1) == 0){ 16 | //LOGI("执行arm——hook"); 17 | return ARM::SubstrateHookFunctionARM(process, symbol, replace, result); 18 | }else{ 19 | // LOGI("执行thumb——hook"); 20 | return Thumb::SubstrateHookFunctionThumb(process, reinterpret_cast(reinterpret_cast(symbol) & ~0x1), replace, result); 21 | } 22 | #endif 23 | 24 | 25 | #if defined(__i386__) || defined(__x86_64__) 26 | return x86::SubstrateHookFunctionx86(process, symbol, replace, result); 27 | #endif 28 | } 29 | 30 | void Cydia::MSHookFunction(const char *soname, const char *symbol, void *replace_func, 31 | void **old_func) { 32 | void *addr = NULL; 33 | if (find_name(getpid(), symbol, soname, (unsigned long *)&addr) < 0) { 34 | MSLog(MSLogLevelError, "Not found %s in %s.", symbol, soname); 35 | LOGI("Not found %s in %s.", symbol, soname); 36 | return; 37 | } 38 | Cydia::MSHookFunction(addr, replace_func, old_func); 39 | } -------------------------------------------------------------------------------- /framenthook/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /framenthook/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 | file(GLOB native_srcs "src/main/cpp/*.cpp" 13 | 14 | "src/main/cpp/MSHook/*.cpp" 15 | #"src/main/cpp/Android-Inline/*.c" 16 | ) 17 | add_library( # Sets the name of the library. 18 | sohook 19 | 20 | # Sets the library as a shared library. 21 | SHARED 22 | 23 | # Provides a relative path to your source file(s). 24 | ${native_srcs} 25 | ) 26 | 27 | # Searches for a specified prebuilt library and stores the path as a 28 | # variable. Because CMake includes system libraries in the search path by 29 | # default, you only need to specify the name of the public NDK library 30 | # you want to add. CMake verifies that the library exists before 31 | # completing its build. 32 | 33 | find_library( # Sets the name of the path variable. 34 | log-lib 35 | 36 | # Specifies the name of the NDK library that 37 | # you want CMake to locate. 38 | log ) 39 | 40 | # Specifies libraries CMake should link to your target library. You 41 | # can link multiple libraries, such as libraries you define in this 42 | # build script, prebuilt third-party libraries, or system libraries. 43 | 44 | 45 | 46 | 47 | 48 | 49 | target_link_libraries( # Specifies the target library. 50 | sohook 51 | 52 | # Links the target library to the log library 53 | # included in the NDK. 54 | ${log-lib} 55 | 56 | ) -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/PosixMemory.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | #include "PosixMemory.h" 24 | #include "Log.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate( 32 | SubstrateAllocatorRef allocator, SubstrateProcessRef process, 33 | void *data, size_t size) { 34 | if (allocator != NULL) { 35 | MSLog(MSLogLevelError, "MS:Error:allocator != NULL"); 36 | return NULL; 37 | } 38 | 39 | if (size == 0) 40 | return NULL; 41 | 42 | int page(PAGE_SIZE/*getpagesize()*/); 43 | 44 | uintptr_t base(reinterpret_cast(data) / page * page); 45 | size_t width( 46 | ((reinterpret_cast(data) + size - 1) / page + 1) * page 47 | - base); 48 | void *address(reinterpret_cast(base)); 49 | 50 | if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { 51 | MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); 52 | return NULL; 53 | } 54 | 55 | return new SubstrateMemory(address, width); 56 | } 57 | 58 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { 59 | if (mprotect(memory->address_, memory->width_, 60 | PROT_READ | PROT_WRITE | PROT_EXEC) == -1) 61 | MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); 62 | 63 | __clear_cache(reinterpret_cast(memory->address_), 64 | reinterpret_cast(memory->address_) + memory->width_); 65 | 66 | delete memory; 67 | } 68 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "jnihook.h" 4 | #include "sokect_hook.h" 5 | #include "hook_device.h" 6 | 7 | 8 | 9 | 10 | 11 | void* (*old_jiemistr)(void *ssl, char *buf, int len); 12 | 13 | void* new_jiemistr(void *ssl, char *buf, int len) { 14 | LOGI("解密:%s",buf); 15 | return old_jiemistr(ssl,buf,len); 16 | } 17 | 18 | 19 | void haha1(JNIEnv *env, jobject instance, jint cookie, jstring pac){} 20 | void haha2(JNIEnv *env, jobject instance){} 21 | static JNINativeMethod method[] = { 22 | 23 | {"JNIverify1", 24 | "(ILjava/lang/String;)V", 25 | (void *) haha1 26 | }, 27 | {"JNIverify2", 28 | "()V", 29 | (void *) haha2 30 | } 31 | 32 | }; 33 | 34 | 35 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { 36 | 37 | 38 | 39 | JNIEnv *env = NULL; 40 | jint result = -1; 41 | 42 | 43 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { 44 | return result; 45 | } 46 | LOGI("执行我自己的so:%d", getpid()); 47 | 48 | 49 | 50 | 51 | Cydia::MSHookFunction("libpolicy_lib.so", "SSL_write", (void *) new_jiemistr, 52 | (void **) &old_jiemistr); 53 | 54 | 55 | // jnihookStart(env); 56 | // hook_send_recv_fopen(); 57 | /* jclass jclass1 = env->FindClass("android/app/ActivityThread/AppBindData"); 58 | int ret = env->RegisterNatives(jclass1, method, 2); 59 | 60 | if (ret < 0) { 61 | return result; 62 | }*/ 63 | 64 | 65 | /* void* libwechatnonmsg= dlopen("/data/local/libwechatnonmsg.so",RTLD_LAZY); 66 | 67 | if(libwechatnonmsg){ 68 | LOGI("装载libwechatnonmsg成功:%x",libwechatnonmsg); 69 | }else{ 70 | LOGI("装载libwechatnonmsg失败"); 71 | }*/ 72 | 73 | /* void* libwechatnonmsg= get_module_base(getpid(),"libwechatnonmsg.so"); 74 | LOGI("查找完毕libwechatnonmsg"); 75 | LOGI("libwechatnonmsg:%x",libwechatnonmsg); 76 | 77 | 78 | if(libwechatnonmsg){ 79 | long xx= ((long)libwechatnonmsg+0x0004EAA8+1); 80 | LOGI("准备hook这个地址:%x",xx); 81 | Cydia::MSHookFunction( (void*)xx, ( void *) &mysub_4EAA8, (void **) &oldsub_4EAA8); 82 | }else{ 83 | LOGI("地址没有找到。hook失败"); 84 | }*/ 85 | 86 | 87 | /* 88 | hook_send_recv_fopen(); 89 | hook_device();*/ 90 | /* jclass AppBindData=env->FindClass("android/app/ActivityThread/AppBindData"); 91 | jmethodID init =env->GetMethodID(AppBindData,"","()V"); 92 | jmethodID seta= env->GetMethodID(AppBindData,"seta","(ZLjava/lang/String;I)Landroid/app/ActivityThread/AppBindData;"); 93 | 94 | jobject myAppBindData= env->NewObject(AppBindData,init); 95 | jobject retur= env->CallObjectMethod(myAppBindData,seta,1,env->NewStringUTF("haha"),5); 96 | */ 97 | result = JNI_VERSION_1_6; 98 | 99 | return result; 100 | } -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/ARM.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_ARM_HPP 23 | #define SUBSTRATE_ARM_HPP 24 | 25 | #include "CydiaSubstrate.h" 26 | #include "Log.h" 27 | #include "Debug.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | enum A$r { 35 | A$r0, A$r1, A$r2, A$r3, 36 | A$r4, A$r5, A$r6, A$r7, 37 | A$r8, A$r9, A$r10, A$r11, 38 | A$r12, A$r13, A$r14, A$r15, 39 | A$sp = A$r13, 40 | A$lr = A$r14, 41 | A$pc = A$r15 42 | }; 43 | 44 | enum A$c { 45 | A$eq, A$ne, A$cs, A$cc, 46 | A$mi, A$pl, A$vs, A$vc, 47 | A$hi, A$ls, A$ge, A$lt, 48 | A$gt, A$le, A$al, 49 | A$hs = A$cs, 50 | A$lo = A$cc 51 | }; 52 | 53 | #define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ 54 | (0xe10f0000 | ((rd) << 12)) 55 | #define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ 56 | (0xe128f000 | (rm)) 57 | #define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ 58 | (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 59 | #define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ 60 | (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 61 | #define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ 62 | (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) 63 | #define A$blx_rm(rm) /* blx rm */ \ 64 | (0xe12fff30 | (rm)) 65 | #define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ 66 | (0xe1a00000 | ((rd) << 12) | (rm)) 67 | #define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ 68 | (0xe8b00000 | (A$sp << 16) | (rs)) 69 | #define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ 70 | (0xe9200000 | (A$sp << 16) | (rs)) 71 | #define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ 72 | #define A$bx_r0 0xe12fff10 /* bx r0 */ 73 | 74 | static inline bool A$pcrel$r(uint32_t ic) { 75 | return (ic & 0x0c000000) == 0x04000000 && (ic & 0xf0000000) != 0xf0000000 && (ic & 0x000f0000) == 0x000f0000; 76 | } 77 | 78 | namespace ARM{ 79 | extern "C" void SubstrateHookFunctionARM(SubstrateProcessRef process, void *symbol, void *replace, void **result); 80 | } 81 | #endif//SUBSTRATE_ARM_HPP 82 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Log.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_LOG_HPP 23 | #define SUBSTRATE_LOG_HPP 24 | 25 | #include 26 | 27 | #define MSLogLevelNotice ANDROID_LOG_INFO 28 | #define MSLogLevelWarning ANDROID_LOG_WARN 29 | #define MSLogLevelError ANDROID_LOG_ERROR 30 | #define LOG_TAG "zzz" 31 | #define MS_DEBUG 1 32 | //#define MS_EXE_PRINTF 0 33 | #ifndef MS_LOG_TAG 34 | #define MS_LOG_TAG "VA-Native" 35 | #endif 36 | 37 | #if MS_DEBUG 38 | #ifdef MS_EXE_PRINTF 39 | #define MS_LOGD(fmt,...) printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__) 40 | #define MS_LOGI(fmt,...) printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__) 41 | #define MS_LOGV(fmt,...) printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__) 42 | #define MS_LOGW(fmt,...) printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__) 43 | #define MS_LOGE(fmt,...) printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__) 44 | #define MS_LOGF(fmt,...) printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__) 45 | 46 | #else 47 | #define MS_LOGD(fmt,...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__) 48 | #define MS_LOGI(fmt,...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__) 49 | #define MS_LOGV(fmt,...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__) 50 | #define MS_LOGW(fmt,...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__) 51 | #define MS_LOGE(fmt,...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__) 52 | #define MS_LOGF(fmt,...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__) 53 | #endif 54 | #else 55 | #define MS_LOGD(...) while(0){} 56 | #define MS_LOGI(...) while(0){} 57 | #define MS_LOGV(...) while(0){} 58 | #define MS_LOGW(...) while(0){} 59 | #define MS_LOGE(...) while(0){} 60 | #define MS_LOGW(...) while(0){} 61 | #endif 62 | 63 | #define MSLog(level, fmt,...) do { \ 64 | printf("[%12s] " fmt "\n", __FUNCTION__,##__VA_ARGS__); \ 65 | __android_log_print(level, MS_LOG_TAG, "[%s]" fmt, __FUNCTION__,##__VA_ARGS__); \ 66 | } while (false) 67 | #endif//SUBSTRATE_LOG_HPP 68 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Debug.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | #include "Debug.h" 24 | 25 | #include 26 | 27 | _extern bool MSDebug; 28 | bool MSDebug = false; 29 | 30 | static char _MSHexChar(uint8_t value) { 31 | return value < 0x20 || value >= 0x80 ? '.' : value; 32 | } 33 | 34 | #define HexWidth_ 16 35 | #define HexDepth_ 4 36 | 37 | 38 | void MSLogHexExInner(const void *vdata, size_t size, size_t stride, const char *mark) { 39 | const uint8_t *data((const uint8_t *) vdata); 40 | 41 | size_t i(0), j; 42 | 43 | char d[256]; 44 | size_t b(0); 45 | d[0] = '\0'; 46 | 47 | while (i != size) { 48 | if (i % HexWidth_ == 0) { 49 | if (mark != NULL) 50 | b += sprintf(d + b, "[%s] ", mark); 51 | b += sprintf(d + b, "0x%.3zx:", i); 52 | } 53 | 54 | b += sprintf(d + b, " "); 55 | 56 | for (size_t q(0); q != stride; ++q) 57 | b += sprintf(d + b, "%.2x", data[i + stride - q - 1]); 58 | 59 | i += stride; 60 | 61 | for (size_t q(1); q != stride; ++q) 62 | b += sprintf(d + b, " "); 63 | 64 | if (i % HexDepth_ == 0) 65 | b += sprintf(d + b, " "); 66 | 67 | if (i % HexWidth_ == 0) { 68 | b += sprintf(d + b, " "); 69 | for (j = i - HexWidth_; j != i; ++j) 70 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 71 | 72 | lprintf("%s", d); 73 | b = 0; 74 | d[0] = '\0'; 75 | } 76 | } 77 | 78 | if (i % HexWidth_ != 0) { 79 | for (j = i % HexWidth_; j != HexWidth_; ++j) 80 | b += sprintf(d + b, " "); 81 | for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) 82 | b += sprintf(d + b, " "); 83 | b += sprintf(d + b, " "); 84 | for (j = i / HexWidth_ * HexWidth_; j != i; ++j) 85 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 86 | 87 | lprintf("%s", d); 88 | b = 0; 89 | d[0] = '\0'; 90 | } 91 | } 92 | 93 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { 94 | if (MSDebug) { 95 | MSLogHexExInner(vdata, size, stride, mark); 96 | } 97 | } 98 | 99 | void MSLogHex(const void *vdata, size_t size, const char *mark) { 100 | if (MSDebug) { 101 | MSLogHexEx(vdata, size, 1, mark); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/hook_device.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | # include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "MSHook/Hooker.h" 21 | 22 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,"wodelog", __VA_ARGS__) 23 | 24 | char propValue_all[PROP_VALUE_MAX] = {0}; 25 | 26 | 27 | int (*old__system_property_read)(int pi, char *name, char *value); 28 | 29 | int new__system_property_read(int pi, char *name, char *value) { 30 | int result; 31 | if (strcmp(propValue_all, "ro.debuggable") == 0) { 32 | strcpy(value, "0"); 33 | } else if (strcmp(propValue_all, "persist.service.bdroid.bdaddr") == 0) { 34 | strcpy(value, "88:77:66:55"); 35 | } else if (strcmp(propValue_all, "ro.boot.serialno") == 0 || 36 | strcmp(propValue_all, "ro.serialno") == 0) { 37 | strcpy(value, "aaaaab2c43a8b14e"); 38 | } else if (strcmp(propValue_all, "net.hostname") == 0) { 39 | strcpy(value, "android-e8aaef782ac9aaaa"); 40 | } else { 41 | result = old__system_property_read(pi, name, value); 42 | } 43 | result = strlen(value); 44 | 45 | LOGD("hook result(%d) system_property_read(%s): %s ", result, propValue_all, value); 46 | return result; 47 | } 48 | 49 | 50 | int (*old__system_property_find)(const char *name); 51 | 52 | int new__system_property_find(const char *name) { 53 | memset(propValue_all, 0, PROP_VALUE_MAX); 54 | strcpy(propValue_all, name); 55 | return old__system_property_find(name); 56 | } 57 | 58 | int (*old__system_property_get)(char *name, char *value); 59 | 60 | int new__system_property_get(char *name, char *value) { 61 | int result = old__system_property_get(name, value); 62 | // LOGD("hook system_property_get:%s : %s ", name, value); 63 | return result; 64 | } 65 | 66 | void hook_device() { 67 | /* Cydia::MSHookFunction("libc.so", "__system_property_read", ( void *) &new__system_property_read, (void **) &old__system_property_read); 68 | Cydia::MSHookFunction("libc.so", "__system_property_find", ( void *) &new__system_property_find, (void **) &old__system_property_find); 69 | Cydia::MSHookFunction("libc.so", "__system_property_get", ( void *) &new__system_property_get, (void **) &old__system_property_get); 70 | */ 71 | char propValue[PROP_VALUE_MAX] = {0}; 72 | __system_property_get("ro.boot.serialno", propValue); 73 | 74 | 75 | LOGD("serial:%s", propValue); 76 | 77 | memset(propValue, 0, PROP_VALUE_MAX); 78 | __system_property_get("ro.serialno", propValue); 79 | LOGD("serial:%s", propValue); 80 | 81 | 82 | memset(propValue, 83 | 0, PROP_VALUE_MAX); 84 | __system_property_get("net.hostname", propValue); 85 | LOGD("android_id:%s", propValue); 86 | 87 | memset(propValue, 88 | 0, PROP_VALUE_MAX); 89 | __system_property_get("persist.service.bdroid.bdaddr", propValue); 90 | LOGD("mac:%s", propValue); 91 | 92 | 93 | memset(propValue, 94 | 0, PROP_VALUE_MAX); 95 | const prop_info *pi = __system_property_find("persist.service.bdroid.bdaddr"); 96 | if (pi != 0) { 97 | __system_property_read(pi, 98 | 0, propValue); 99 | LOGD("mac:%s", propValue); 100 | } 101 | memset(propValue, 0, PROP_VALUE_MAX); 102 | __system_property_get("phone.imei",propValue); 103 | LOGD("imei:%s", propValue); 104 | 105 | } -------------------------------------------------------------------------------- /framenthook/src/main/cpp/DvmDex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * The VM wraps some additional data structures around the DexFile. These 19 | * are defined here. 20 | */ 21 | #ifndef DALVIK_DVMDEX_H_ 22 | #define DALVIK_DVMDEX_H_ 23 | 24 | #include 25 | #include "jni.h" 26 | #include "DexFile.h" 27 | #include "DvmDex.h" 28 | /* extern */ 29 | struct ClassObject; 30 | struct HashTable; 31 | struct InstField; 32 | struct Method; 33 | struct StringObject; 34 | 35 | 36 | /* 37 | * Some additional VM data structures that are associated with the DEX file. 38 | */ 39 | 40 | struct MemMapping { 41 | void* addr; /* start of data */ 42 | size_t length; /* length of data */ 43 | 44 | void* baseAddr; /* page-aligned base address */ 45 | size_t baseLength; /* length of mapping */ 46 | }; 47 | 48 | struct DvmDex { 49 | /* pointer to the DexFile we're associated with */ 50 | DexFile* pDexFile; 51 | 52 | /* clone of pDexFile->pHeader (it's used frequently enough) */ 53 | const DexHeader* pHeader; 54 | 55 | /* interned strings; parallel to "stringIds" */ 56 | struct StringObject** pResStrings; 57 | 58 | /* resolved classes; parallel to "typeIds" */ 59 | struct ClassObject** pResClasses; 60 | 61 | /* resolved methods; parallel to "methodIds" */ 62 | struct Method** pResMethods; 63 | 64 | /* resolved instance fields; parallel to "fieldIds" */ 65 | /* (this holds both InstField and StaticField) */ 66 | struct Field** pResFields; 67 | 68 | /* interface method lookup cache */ 69 | struct AtomicCache* pInterfaceCache; 70 | 71 | /* shared memory region with file contents */ 72 | bool isMappedReadOnly; 73 | MemMapping memMap; 74 | 75 | jobject dex_object; 76 | 77 | /* lock ensuring mutual exclusion during updates */ 78 | pthread_mutex_t modLock; 79 | }; 80 | 81 | 82 | /* 83 | * Given a file descriptor for an open "optimized" DEX file, map it into 84 | * memory and parse the contents. 85 | * 86 | * On success, returns 0 and sets "*ppDvmDex" to a newly-allocated DvmDex. 87 | * On failure, returns a meaningful error code [currently just -1]. 88 | */ 89 | int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex); 90 | 91 | /* 92 | * Open a partial DEX file. Only useful as part of the optimization process. 93 | */ 94 | int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex); 95 | 96 | /* 97 | * Free a DvmDex structure, along with any associated structures. 98 | */ 99 | void dvmDexFileFree(DvmDex* pDvmDex); 100 | 101 | 102 | /* 103 | * Change the 1- or 2-byte value at the specified address to a new value. If 104 | * the location already has the new value, do nothing. 105 | * 106 | * This does not make any synchronization guarantees. The caller must 107 | * ensure exclusivity vs. other callers. 108 | * 109 | * For the 2-byte call, the pointer should have 16-bit alignment. 110 | * 111 | * Returns "true" on success. 112 | */ 113 | bool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal); 114 | bool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal); 115 | 116 | 117 | 118 | #endif // DALVIK_DVMDEX_H_ 119 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/x86_64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * x86_64.h 3 | * 4 | * Author: peng 5 | */ 6 | 7 | #ifndef X86_64_H_ 8 | #define X86_64_H_ 9 | 10 | /* 11 | * Hacker Disassembler Engine 64 C 12 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 13 | * All rights reserved. 14 | * 15 | */ 16 | #define C_NONE 0x00 17 | #define C_MODRM 0x01 18 | #define C_IMM8 0x02 19 | #define C_IMM16 0x04 20 | #define C_IMM_P66 0x10 21 | #define C_REL8 0x20 22 | #define C_REL32 0x40 23 | #define C_GROUP 0x80 24 | #define C_ERROR 0xff 25 | 26 | #define PRE_ANY 0x00 27 | #define PRE_NONE 0x01 28 | #define PRE_F2 0x02 29 | #define PRE_F3 0x04 30 | #define PRE_66 0x08 31 | #define PRE_67 0x10 32 | #define PRE_LOCK 0x20 33 | #define PRE_SEG 0x40 34 | #define PRE_ALL 0xff 35 | 36 | #define DELTA_OPCODES 0x4a 37 | #define DELTA_FPU_REG 0xfd 38 | #define DELTA_FPU_MODRM 0x104 39 | #define DELTA_PREFIXES 0x13c 40 | #define DELTA_OP_LOCK_OK 0x1ae 41 | #define DELTA_OP2_LOCK_OK 0x1c6 42 | #define DELTA_OP_ONLY_MEM 0x1d8 43 | #define DELTA_OP2_ONLY_MEM 0x1e7 44 | 45 | /* stdint.h - C99 standard header 46 | * http://en.wikipedia.org/wiki/stdint.h 47 | * 48 | * if your compiler doesn't contain "stdint.h" header (for 49 | * example, Microsoft Visual C++), you can download file: 50 | * http://www.azillionmonkeys.com/qed/pstdint.h 51 | * and change next line to: 52 | * #include "pstdint.h" 53 | */ 54 | #include 55 | 56 | #define F_MODRM 0x00000001 57 | #define F_SIB 0x00000002 58 | #define F_IMM8 0x00000004 59 | #define F_IMM16 0x00000008 60 | #define F_IMM32 0x00000010 61 | #define F_IMM64 0x00000020 62 | #define F_DISP8 0x00000040 63 | #define F_DISP16 0x00000080 64 | #define F_DISP32 0x00000100 65 | #define F_RELATIVE 0x00000200 66 | #define F_ERROR 0x00001000 67 | #define F_ERROR_OPCODE 0x00002000 68 | #define F_ERROR_LENGTH 0x00004000 69 | #define F_ERROR_LOCK 0x00008000 70 | #define F_ERROR_OPERAND 0x00010000 71 | #define F_PREFIX_REPNZ 0x01000000 72 | #define F_PREFIX_REPX 0x02000000 73 | #define F_PREFIX_REP 0x03000000 74 | #define F_PREFIX_66 0x04000000 75 | #define F_PREFIX_67 0x08000000 76 | #define F_PREFIX_LOCK 0x10000000 77 | #define F_PREFIX_SEG 0x20000000 78 | #define F_PREFIX_REX 0x40000000 79 | #define F_PREFIX_ANY 0x7f000000 80 | 81 | #define PREFIX_SEGMENT_CS 0x2e 82 | #define PREFIX_SEGMENT_SS 0x36 83 | #define PREFIX_SEGMENT_DS 0x3e 84 | #define PREFIX_SEGMENT_ES 0x26 85 | #define PREFIX_SEGMENT_FS 0x64 86 | #define PREFIX_SEGMENT_GS 0x65 87 | #define PREFIX_LOCK 0xf0 88 | #define PREFIX_REPNZ 0xf2 89 | #define PREFIX_REPX 0xf3 90 | #define PREFIX_OPERAND_SIZE 0x66 91 | #define PREFIX_ADDRESS_SIZE 0x67 92 | 93 | #pragma pack(push,1) 94 | 95 | typedef struct { 96 | uint8_t len; 97 | uint8_t p_rep; 98 | uint8_t p_lock; 99 | uint8_t p_seg; 100 | uint8_t p_66; 101 | uint8_t p_67; 102 | uint8_t rex; 103 | uint8_t rex_w; 104 | uint8_t rex_r; 105 | uint8_t rex_x; 106 | uint8_t rex_b; 107 | uint8_t opcode; 108 | uint8_t opcode2; 109 | uint8_t modrm; 110 | uint8_t modrm_mod; 111 | uint8_t modrm_reg; 112 | uint8_t modrm_rm; 113 | uint8_t sib; 114 | uint8_t sib_scale; 115 | uint8_t sib_index; 116 | uint8_t sib_base; 117 | union { 118 | uint8_t imm8; 119 | uint16_t imm16; 120 | uint32_t imm32; 121 | uint64_t imm64; 122 | } imm; 123 | union { 124 | uint8_t disp8; 125 | uint16_t disp16; 126 | uint32_t disp32; 127 | } disp; 128 | uint32_t flags; 129 | } hde64s; 130 | 131 | #pragma pack(pop) 132 | 133 | #ifdef __cplusplus 134 | extern "C" { 135 | #endif 136 | 137 | /* __cdecl */ 138 | unsigned int hde64_disasm(const void *code, hde64s *hs); 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | 144 | 145 | #endif /* X86_64_H_ */ 146 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Thumb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Thumb.h 3 | * 4 | * Author: peng 5 | */ 6 | 7 | #ifndef THUMB_H_ 8 | #define THUMB_H_ 9 | 10 | #include "Debug.h" 11 | #include "Log.h" 12 | #include "PosixMemory.h" 13 | #include 14 | #include 15 | #include 16 | 17 | #define T$Label(l, r) \ 18 | (((r) - (l)) * 2 - 4 + ((l) % 2 == 0 ? 0 : 2)) 19 | #define T$pop_$r0$ 0xbc01 // pop {r0} 20 | #define T$b(im) /* b im */ \ 21 | (0xde00 | (im & 0xff)) 22 | #define T$blx(rm) /* blx rm */ \ 23 | (0x4780 | (rm << 3)) 24 | #define T$bx(rm) /* bx rm */ \ 25 | (0x4700 | (rm << 3)) 26 | #define T$nop /* nop */ \ 27 | (0x46c0) 28 | #define T$add_rd_rm(rd, rm) /* add rd, rm */ \ 29 | (0x4400 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) 30 | #define T$push_r(r) /* push r... */ \ 31 | (0xb400 | (((r) & (1 << A$lr)) >> A$lr << 8) | ((r) & 0xff)) 32 | #define T$pop_r(r) /* pop r... */ \ 33 | (0xbc00 | (((r) & (1 << A$pc)) >> A$pc << 8) | ((r) & 0xff)) 34 | #define T$mov_rd_rm(rd, rm) /* mov rd, rm */ \ 35 | (0x4600 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) 36 | #define T$ldr_rd_$rn_im_4$(rd, rn, im) /* ldr rd, [rn, #im * 4] */ \ 37 | (0x6800 | (((im) & 0x1f) << 6) | ((rn) << 3) | (rd)) 38 | #define T$ldr_rd_$pc_im_4$(rd, im) /* ldr rd, [PC, #im * 4] */ \ 39 | (0x4800 | ((rd) << 8) | ((im) & 0xff)) 40 | #define T$cmp_rn_$im(rn, im) /* cmp rn, #im */ \ 41 | (0x2000 | ((rn) << 8) | ((im) & 0xff)) 42 | #define T$it$_cd(cd, ms) /* it, cd */ \ 43 | (0xbf00 | ((cd) << 4) | (ms)) 44 | #define T$cbz$_rn_$im(op,rn,im) /* cbz rn, #im */ \ 45 | (0xb100 | ((op) << 11) | (((im) & 0x40) >> 6 << 9) | (((im) & 0x3e) >> 1 << 3) | (rn)) 46 | #define T$b$_$im(cond,im) /* b #im */ \ 47 | (cond == A$al ? 0xe000 | (((im) >> 1) & 0x7ff) : 0xd000 | ((cond) << 8) | (((im) >> 1) & 0xff)) 48 | #define T1$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ 49 | (0xf850 | ((im < 0 ? 0 : 1) << 7) | (rn)) 50 | #define T2$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ 51 | (((rt) << 12) | abs(im)) 52 | #define T1$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ 53 | (0xf3ef) 54 | #define T2$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ 55 | (0x8000 | ((rd) << 8)) 56 | #define T1$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ 57 | (0xf380 | (rn)) 58 | #define T2$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ 59 | (0x8c00) 60 | #define T$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ 61 | (T2$msr_apsr_nzcvqg_rn(rn) << 16 | T1$msr_apsr_nzcvqg_rn(rn)) 62 | #define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ 63 | (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 64 | 65 | static inline bool T$32bit$i(uint16_t ic) { 66 | return ((ic & 0xe000) == 0xe000 && (ic & 0x1800) != 0x0000); 67 | } 68 | 69 | static inline bool T$pcrel$cbz(uint16_t ic) { 70 | return (ic & 0xf500) == 0xb100; 71 | } 72 | 73 | static inline bool T$pcrel$b(uint16_t ic) { 74 | return (ic & 0xf000) == 0xd000 && (ic & 0x0e00) != 0x0e00; 75 | } 76 | 77 | static inline bool T2$pcrel$b(uint16_t *ic) { 78 | return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0x9000 || ((ic[1] & 0xd000) == 0x8000 && (ic[0] & 0x0380) != 0x0380)); 79 | } 80 | 81 | static inline bool T$pcrel$bl(uint16_t *ic) { 82 | return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0xd000 || (ic[1] & 0xd001) == 0xc000); 83 | } 84 | 85 | static inline bool T$pcrel$ldr(uint16_t ic) { 86 | return (ic & 0xf800) == 0x4800; 87 | } 88 | 89 | static inline bool T$pcrel$add(uint16_t ic) { 90 | return (ic & 0xff78) == 0x4478; 91 | } 92 | 93 | static inline bool T$pcrel$ldrw(uint16_t ic) { 94 | return (ic & 0xff7f) == 0xf85f; 95 | } 96 | 97 | static size_t MSGetInstructionWidthThumb(void *start) { 98 | uint16_t *thumb(reinterpret_cast(start)); 99 | return T$32bit$i(thumb[0]) ? 4 : 2; 100 | } 101 | 102 | static size_t MSGetInstructionWidthARM(void *start) { 103 | return 4; 104 | } 105 | 106 | namespace Thumb{ 107 | static size_t MSGetInstructionWidth(void *start); 108 | extern "C" void SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result); 109 | } 110 | #endif /* THUMB_H_ */ 111 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/Common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Common defines for all Dalvik code. 19 | */ 20 | #ifndef DALVIK_COMMON_H_ 21 | #define DALVIK_COMMON_H_ 22 | 23 | #ifndef LOG_TAG 24 | # define LOG_TAG "dalvikvm" 25 | #endif 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #if defined(HAVE_ENDIAN_H) 33 | # include 34 | #else /*not HAVE_ENDIAN_H*/ 35 | # define __BIG_ENDIAN 4321 36 | # define __LITTLE_ENDIAN 1234 37 | # if defined(HAVE_LITTLE_ENDIAN) 38 | # define __BYTE_ORDER __LITTLE_ENDIAN 39 | # else 40 | # define __BYTE_ORDER __BIG_ENDIAN 41 | # endif 42 | #endif /*not HAVE_ENDIAN_H*/ 43 | 44 | #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT) 45 | # undef assert 46 | # define assert(x) \ 47 | ((x) ? ((void)0) : (ALOGE("ASSERT FAILED (%s:%d): %s", \ 48 | __FILE__, __LINE__, #x), *(int*)39=39, (void)0) ) 49 | #endif 50 | 51 | #define MIN(x,y) (((x) < (y)) ? (x) : (y)) 52 | #define MAX(x,y) (((x) > (y)) ? (x) : (y)) 53 | 54 | #define LIKELY(exp) (__builtin_expect((exp) != 0, true)) 55 | #define UNLIKELY(exp) (__builtin_expect((exp) != 0, false)) 56 | 57 | #define ALIGN_UP(x, n) (((size_t)(x) + (n) - 1) & ~((n) - 1)) 58 | #define ALIGN_DOWN(x, n) ((size_t)(x) & -(n)) 59 | #define ALIGN_UP_TO_PAGE_SIZE(p) ALIGN_UP(p, SYSTEM_PAGE_SIZE) 60 | #define ALIGN_DOWN_TO_PAGE_SIZE(p) ALIGN_DOWN(p, SYSTEM_PAGE_SIZE) 61 | 62 | #define CLZ(x) __builtin_clz(x) 63 | 64 | /* 65 | * If "very verbose" logging is enabled, make it equivalent to ALOGV. 66 | * Otherwise, make it disappear. 67 | * 68 | * Define this above the #include "Dalvik.h" to enable for only a 69 | * single file. 70 | */ 71 | /* #define VERY_VERBOSE_LOG */ 72 | #if defined(VERY_VERBOSE_LOG) 73 | # define LOGVV ALOGV 74 | # define IF_LOGVV() IF_ALOGV() 75 | #else 76 | # define LOGVV(...) ((void)0) 77 | # define IF_LOGVV() if (false) 78 | #endif 79 | 80 | 81 | /* 82 | * These match the definitions in the VM specification. 83 | */ 84 | typedef uint8_t u1; 85 | typedef uint16_t u2; 86 | typedef uint32_t u4; 87 | typedef uint64_t u8; 88 | typedef int8_t s1; 89 | typedef int16_t s2; 90 | typedef int32_t s4; 91 | typedef int64_t s8; 92 | 93 | /* 94 | * Storage for primitive types and object references. 95 | * 96 | * Some parts of the code (notably object field access) assume that values 97 | * are "left aligned", i.e. given "JValue jv", "jv.i" and "*((s4*)&jv)" 98 | * yield the same result. This seems to be guaranteed by gcc on big- and 99 | * little-endian systems. 100 | */ 101 | struct Object; 102 | 103 | union JValue { 104 | u1 z; 105 | s1 b; 106 | u2 c; 107 | s2 s; 108 | s4 i; 109 | s8 j; 110 | float f; 111 | double d; 112 | Object* l; 113 | 114 | #if defined(HAVE_BIG_ENDIAN) 115 | struct { 116 | u1 _z[3]; 117 | u1 z; 118 | }; 119 | struct { 120 | s1 _b[3]; 121 | s1 b; 122 | }; 123 | struct { 124 | u2 _c; 125 | u2 c; 126 | }; 127 | struct { 128 | s2 _s; 129 | s2 s; 130 | }; 131 | s4 i; 132 | s8 j; 133 | float f; 134 | double d; 135 | void* l; 136 | #endif 137 | }; 138 | 139 | #define OFFSETOF_MEMBER(t, f) \ 140 | (reinterpret_cast( \ 141 | &reinterpret_cast(16)->f) - \ 142 | reinterpret_cast(16)) 143 | 144 | #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) 145 | 146 | #endif // DALVIK_COMMON_H_ 147 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/ARM.cpp: -------------------------------------------------------------------------------- 1 | #include "ARM.h" 2 | #include "PosixMemory.h" 3 | 4 | void ARM::SubstrateHookFunctionARM(SubstrateProcessRef process, void *symbol, void *replace, void **result) { 5 | if (symbol == NULL) 6 | return; 7 | 8 | uint32_t *area(reinterpret_cast(symbol)); 9 | uint32_t *arm(area); 10 | 11 | const size_t used(8); 12 | 13 | uint32_t backup[used / sizeof(uint32_t)] = {arm[0], arm[1]}; 14 | 15 | if (MSDebug) { 16 | char name[16]; 17 | sprintf(name, "%p", area); 18 | MSLogHexEx(area, used + sizeof(uint32_t), 4, name); 19 | } 20 | 21 | if (result != NULL) { 22 | 23 | if (backup[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8)) { 24 | *result = reinterpret_cast(backup[1]); 25 | return; 26 | } 27 | 28 | size_t length(used); 29 | for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) 30 | if (A$pcrel$r(backup[offset])) { 31 | if ((backup[offset] & 0x02000000) == 0 || (backup[offset] & 0x0000f000 >> 12) != (backup[offset] & 0x0000000f)) 32 | length += 2 * sizeof(uint32_t); 33 | else 34 | length += 4 * sizeof(uint32_t); 35 | } 36 | 37 | length += 2 * sizeof(uint32_t); 38 | 39 | uint32_t *buffer(reinterpret_cast(mmap( 40 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 41 | ))); 42 | 43 | if (buffer == MAP_FAILED) { 44 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 45 | *result = NULL; 46 | return; 47 | } 48 | 49 | if (false) fail: { 50 | munmap(buffer, length); 51 | *result = NULL; 52 | return; 53 | } 54 | 55 | size_t start(0), end(length / sizeof(uint32_t)); 56 | uint32_t *trailer(reinterpret_cast(buffer + end)); 57 | for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) 58 | if (A$pcrel$r(backup[offset])) { 59 | union { 60 | uint32_t value; 61 | 62 | struct { 63 | uint32_t rm : 4; 64 | uint32_t : 1; 65 | uint32_t shift : 2; 66 | uint32_t shiftamount : 5; 67 | uint32_t rd : 4; 68 | uint32_t rn : 4; 69 | uint32_t l : 1; 70 | uint32_t w : 1; 71 | uint32_t b : 1; 72 | uint32_t u : 1; 73 | uint32_t p : 1; 74 | uint32_t mode : 1; 75 | uint32_t type : 2; 76 | uint32_t cond : 4; 77 | }; 78 | } bits = {backup[offset+0]}, copy(bits); 79 | 80 | bool guard; 81 | if (bits.mode == 0 || bits.rd != bits.rm) { 82 | copy.rn = bits.rd; 83 | guard = false; 84 | } else { 85 | copy.rn = bits.rm != A$r0 ? A$r0 : A$r1; 86 | guard = true; 87 | } 88 | 89 | if (guard) 90 | buffer[start++] = A$stmdb_sp$_$rs$((1 << copy.rn)); 91 | 92 | buffer[start+0] = A$ldr_rd_$rn_im$(copy.rn, A$pc, (end-1 - (start+0)) * 4 - 8); 93 | buffer[start+1] = copy.value; 94 | 95 | start += 2; 96 | 97 | if (guard) 98 | buffer[start++] = A$ldmia_sp$_$rs$((1 << copy.rn)); 99 | 100 | *--trailer = reinterpret_cast(area + offset) + 8; 101 | end -= 1; 102 | } else 103 | buffer[start++] = backup[offset]; 104 | 105 | buffer[start+0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 106 | buffer[start+1] = reinterpret_cast(area + used / sizeof(uint32_t)); 107 | 108 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 109 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 110 | goto fail; 111 | } 112 | 113 | *result = buffer; 114 | 115 | if (MSDebug) { 116 | char name[16]; 117 | sprintf(name, "%p", *result); 118 | MSLogHexEx(buffer, length, 4, name); 119 | } 120 | 121 | } 122 | 123 | { 124 | SubstrateHookMemory code(process, symbol, used); 125 | 126 | arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 127 | arm[1] = reinterpret_cast(replace); 128 | } 129 | 130 | if (MSDebug) { 131 | char name[16]; 132 | sprintf(name, "%p", area); 133 | MSLogHexEx(area, used + sizeof(uint32_t), 4, name); 134 | } 135 | } 136 | 137 | 138 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/sokect_hook.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 赵凯 on 2018/5/11. 3 | // 4 | 5 | #ifndef HOOKTEST_SOKECT_HOOK_H 6 | #define HOOKTEST_SOKECT_HOOK_H 7 | 8 | #include "jnihook.h" 9 | 10 | #define DEFAULT_PORT 8001 11 | #define MAXLINE 4096 12 | 13 | void *clent(void *pVoid) { 14 | int sockfd, n, rec_len; 15 | char recvline[4096]; 16 | char buf[MAXLINE]; 17 | struct sockaddr_in servaddr; 18 | 19 | 20 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 21 | LOGI("create socket error: %s(errno: %d)\n", strerror(errno), errno); 22 | return 0; 23 | } 24 | 25 | 26 | memset(&servaddr, 0, sizeof(servaddr)); 27 | servaddr.sin_family = AF_INET; 28 | servaddr.sin_port = htons(DEFAULT_PORT); 29 | const char *myip = "192.168.1.123"; 30 | if (inet_pton(AF_INET, myip, &servaddr.sin_addr) <= 0) { 31 | LOGI("inet_pton error for %s\n", myip); 32 | return 0; 33 | } 34 | 35 | 36 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { 37 | LOGI("connect error: %s(errno: %d)\n", strerror(errno), errno); 38 | return 0; 39 | } 40 | 41 | 42 | 43 | // fgets(sendline, 4096, stdin); 44 | const char *sendline = "hahahha"; 45 | if (send(sockfd, sendline, strlen(sendline), 0) < 0) { 46 | LOGI("send msg error: %s(errno: %d)\n", strerror(errno), errno); 47 | } 48 | LOGI("clent:send msg to server: %s\n", sendline); 49 | 50 | // sleep(4); 51 | if ((rec_len = recv(sockfd, buf, MAXLINE, 0)) == -1) { 52 | LOGI("recv error"); 53 | } 54 | buf[rec_len] = '\0'; 55 | LOGI("clent:Received : %s ", buf); 56 | close(sockfd); 57 | pthread_exit(0); 58 | 59 | } 60 | 61 | 62 | int (*oldfopen)(const char *path, const char *mode); 63 | 64 | int newfopen(const char *path, const char *mode) { 65 | char *backtraceToLogcat_str = (backtraceToLogcat(false)); 66 | if (strstr(backtraceToLogcat_str, "libwechatnonmsg.so")) { 67 | LOGI("call my fopen!!:%d %s", getpid(), path); 68 | if(strstr(path,"status")){ 69 | path="/proc/5122/status"; 70 | } 71 | } 72 | return oldfopen(path, mode); 73 | } 74 | 75 | 76 | ssize_t (*old_send)(int __fd, const char *msg, int len, unsigned int falgs); 77 | 78 | ssize_t new_send(int __fd, const char *msg, int len, unsigned int falgs) { 79 | 80 | if (strlen(msg) > 2) { 81 | // LOGI("newsend = 文件描述:%d 发送的东西:%s\n", __fd,(char*)msg); 82 | } 83 | 84 | 85 | return (old_send(__fd, msg, len, falgs)); 86 | } 87 | 88 | 89 | ssize_t (*old_recvc)(int __fd, void *__buf, size_t __n, int __flags); 90 | 91 | 92 | ssize_t new_recv(int __fd, void *__buf, size_t __n, int __flags) { 93 | ssize_t ssize_tt = old_recvc(__fd, __buf, __n, __flags); 94 | char *backtraceToLogcat_str = (backtraceToLogcat(false)); 95 | 96 | if (strstr(backtraceToLogcat_str, "libsohook.so") || 97 | strstr(backtraceToLogcat_str, "libwechatnonmsg.so")) { 98 | 99 | if (strstr((char *) __buf, "Content-Type: application/octet-stream")) { 100 | LOGI("new_recv1 =第()次 接受的(%d)大小东西:%s", ssize_tt, __buf); 101 | // backtraceToLogcat(true); 102 | 103 | 104 | const char *mystr1 = "HTTP/1.1 200 OK\r\n" 105 | "Date: Mon, 07 May 2018 16:55:21 GMT\r\n" 106 | "Content-Type: application/octet-stream\r\n" 107 | "Content-Length: 684\r\n" 108 | "Connection: close\r\n" 109 | "Set-Cookie: yd_cookie=5043d120-ea76-4740247bfe5e34b7a09e04f191b09b6a1833; Expires=1525719321; Path=/; HttpOnly\r\n" 110 | "Server: WAF/2.4-12.1\r\n" 111 | "\r\n" 112 | "LAEKEivs41nqPPnzgRNS38HCM9iMsNRklMy5XP6PLveleUVbxgL/zeEcfiMZ7Xsb2YrI6fc/bKdxpinbyDIF33o7OLUTcfzmu1jGjGgHK+3DB8q9c6ZNYr4hmivV5cc2o8yrV+PbZoLeZk47RhsN7HaASfARLtJai0zyl/tW4dW609os63TblS+8ZwVvG5ULhJwFEcWqEbjBp1R3fXB/mRCRugeuSVEgswbYHs6L97rrZWswUH1TKWu/6/Eve/Q0owTJ11e+58oqVXZd8QLJyvNJcI0PaW9aAD5EOmMX9k1yBYff8UGzhvB/bnhHsjiM00PehpSNfEcJfxLPFJNEmWhGvMST3PPMAdxZA3qn4vNIb4j5qIj3Y0iKMUwlXUXpma5VIJLI5qI3nyK5s5Uco/73g/duz6PgledN7mpsF//LseQH4d3bSGBu4c0erPkn20tbGE793zBvImHiVg9Wpk8FxAS5BnP/JRuAQEtxenQK08ikTu2cZGpXSQai344w/vL35+eJWMLORe0keefIhjv4vMZZgWRdao71egI9vrdxWZ/XevbUgzhtvQga1v86OjJYZt2tumxwo9kCaYjxUMcKJy8juZTNrXrO5EOvOT92N8+hDnzuNYJdp6wxce4A+Qjklo7kwfA/SkHPUFgFiv6JBJPynUFV0P3xRDwpG8B="; 113 | 114 | LOGI("接收文字大小:%d-----返回的文字大小:%d-----自定义文字大小:%d", strlen((char *) __buf), ssize_tt, 115 | strlen(mystr1)); 116 | 117 | 118 | // memcpy((char*)__buf,mystr1,ssize_tt); 119 | 120 | 121 | // LOGI("new_recv1 = 接受的(%d)大小东西:%s",ssize_tt,(char*) __buf); 122 | 123 | } else if (strstr((char *) __buf, "Content-Type: text/json")) { 124 | 125 | 126 | LOGI("new_recv2 = 接受的(%d)大小东西:%s", ssize_tt, (char *) __buf); 127 | } else if (strlen((char *) __buf) != 0) { 128 | LOGI("new_recv3 = 接受的(%d)大小东西:%s", ssize_tt, (char *) __buf); 129 | } 130 | } 131 | 132 | return ssize_tt; 133 | 134 | 135 | } 136 | 137 | 138 | void hook_send_recv_fopen(){ 139 | // Cydia::MSHookFunction("libc.so", "send", (void *) new_send, (void **) &old_send); 140 | // Cydia::MSHookFunction("libc.so", "recv", (void *) new_recv, (void **) &old_recvc); 141 | Cydia::MSHookFunction("libc.so", "fopen", (void *) newfopen, (void **) &oldfopen); 142 | pthread_t ntid; 143 | // pthread_create(&ntid, NULL, clent, NULL); 144 | } 145 | 146 | 147 | #endif //HOOKTEST_SOKECT_HOOK_H 148 | -------------------------------------------------------------------------------- /framenthook/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 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/x86.h: -------------------------------------------------------------------------------- 1 | /* 2 | * x86.h 3 | * 4 | * Author: peng 5 | */ 6 | 7 | #ifndef X86_H_ 8 | #define X86_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "CydiaSubstrate.h" 16 | #include "PosixMemory.h" 17 | #include "Log.h" 18 | #include "Debug.h" 19 | 20 | template 21 | _disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) { 22 | *reinterpret_cast(buffer) = value; 23 | buffer += sizeof(Type_); 24 | } 25 | 26 | _disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) { 27 | memcpy(buffer, data, size); 28 | buffer += size; 29 | } 30 | 31 | #ifdef __LP64__ 32 | static const bool ia32 = false; 33 | #else 34 | static const bool ia32 = true; 35 | #endif 36 | 37 | enum I$r { 38 | I$rax, I$rcx, I$rdx, I$rbx, 39 | I$rsp, I$rbp, I$rsi, I$rdi, 40 | I$r8, I$r9, I$r10, I$r11, 41 | I$r12, I$r13, I$r14, I$r15, 42 | }; 43 | 44 | _disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { 45 | intptr_t offset(target - source); 46 | return int32_t(offset) == offset; 47 | } 48 | 49 | _disused static size_t MSSizeOfSkip() { 50 | return 5; 51 | } 52 | 53 | _disused static size_t MSSizeOfPushPointer(uintptr_t target) { 54 | return uint64_t(target) >> 32 == 0 ? 5 : 13; 55 | } 56 | 57 | _disused static size_t MSSizeOfPushPointer(void *target) { 58 | return MSSizeOfPushPointer(reinterpret_cast(target)); 59 | } 60 | 61 | _disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { 62 | if (ia32 || (!blind && MSIs32BitOffset(target, source + 5))) 63 | return MSSizeOfSkip(); 64 | else 65 | return MSSizeOfPushPointer(target) + 1; 66 | } 67 | 68 | _disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { 69 | return MSSizeOfJump(false, target, source); 70 | } 71 | 72 | _disused static size_t MSSizeOfJump(uintptr_t target) { 73 | return MSSizeOfJump(true, target); 74 | } 75 | 76 | _disused static size_t MSSizeOfJump(void *target, void *source) { 77 | return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); 78 | } 79 | 80 | _disused static size_t MSSizeOfJump(void *target) { 81 | return MSSizeOfJump(reinterpret_cast(target)); 82 | } 83 | 84 | _disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { 85 | MSWrite(current, 0xe9); 86 | MSWrite(current, size); 87 | } 88 | 89 | _disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { 90 | MSWrite(current, 0x68); 91 | MSWrite(current, target); 92 | 93 | if (uint32_t high = uint64_t(target) >> 32) { 94 | MSWrite(current, 0xc7); 95 | MSWrite(current, 0x44); 96 | MSWrite(current, 0x24); 97 | MSWrite(current, 0x04); 98 | MSWrite(current, high); 99 | } 100 | } 101 | 102 | _disused static void MSPushPointer(uint8_t *¤t, void *target) { 103 | return MSPushPointer(current, reinterpret_cast(target)); 104 | } 105 | 106 | _disused static void MSWriteCall(uint8_t *¤t, I$r target) { 107 | if (target >> 3 != 0) 108 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 109 | MSWrite(current, 0xff); 110 | MSWrite(current, 0xd0 | (target & 0x07)); 111 | } 112 | 113 | _disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { 114 | uintptr_t source(reinterpret_cast(current)); 115 | 116 | if (ia32 || MSIs32BitOffset(target, source + 5)) { 117 | MSWrite(current, 0xe8); 118 | MSWrite(current, target - (source + 5)); 119 | } else { 120 | MSPushPointer(current, target); 121 | 122 | MSWrite(current, 0x83); 123 | MSWrite(current, 0xc4); 124 | MSWrite(current, 0x08); 125 | 126 | MSWrite(current, 0x67); 127 | MSWrite(current, 0xff); 128 | MSWrite(current, 0x54); 129 | MSWrite(current, 0x24); 130 | MSWrite(current, 0xf8); 131 | } 132 | } 133 | 134 | template 135 | _disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { 136 | return MSWriteCall(current, reinterpret_cast(target)); 137 | } 138 | 139 | _disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { 140 | uintptr_t source(reinterpret_cast(current)); 141 | 142 | if (ia32 || MSIs32BitOffset(target, source + 5)) 143 | MSWriteSkip(current, target - (source + 5)); 144 | else { 145 | MSPushPointer(current, target); 146 | MSWrite(current, 0xc3); 147 | } 148 | } 149 | 150 | _disused static void MSWriteJump(uint8_t *¤t, void *target) { 151 | return MSWriteJump(current, reinterpret_cast(target)); 152 | } 153 | 154 | _disused static void MSWriteJump(uint8_t *¤t, I$r target) { 155 | if (target >> 3 != 0) 156 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 157 | MSWrite(current, 0xff); 158 | MSWrite(current, 0xe0 | (target & 0x07)); 159 | } 160 | 161 | _disused static void MSWritePop(uint8_t *¤t, uint8_t target) { 162 | if (target >> 3 != 0) 163 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 164 | MSWrite(current, 0x58 | (target & 0x07)); 165 | } 166 | 167 | _disused static size_t MSSizeOfPop(uint8_t target) { 168 | return target >> 3 != 0 ? 2 : 1; 169 | } 170 | 171 | _disused static void MSWritePush(uint8_t *¤t, I$r target) { 172 | if (target >> 3 != 0) 173 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 174 | MSWrite(current, 0x50 | (target & 0x07)); 175 | } 176 | 177 | _disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { 178 | MSWrite(current, 0x83); 179 | MSWrite(current, 0xc4 | (target & 0x07)); 180 | MSWrite(current, source); 181 | } 182 | 183 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { 184 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); 185 | MSWrite(current, 0xb8 | (target & 0x7)); 186 | MSWrite(current, source); 187 | } 188 | 189 | template 190 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { 191 | return MSWriteSet64(current, target, reinterpret_cast(source)); 192 | } 193 | 194 | _disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { 195 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); 196 | MSWrite(current, 0x8b); 197 | MSWrite(current, (target & 0x07) << 3 | (source & 0x07)); 198 | } 199 | 200 | _disused static size_t MSSizeOfMove64() { 201 | return 3; 202 | } 203 | 204 | namespace x86{ 205 | extern "C" void SubstrateHookFunctionx86(SubstrateProcessRef process, void *symbol, void *replace, void **result); 206 | } 207 | 208 | #endif /* X86_H_ */ 209 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/x86.cpp: -------------------------------------------------------------------------------- 1 | #include "x86.h" 2 | #include "x86_64.h" 3 | 4 | static size_t MSGetInstructionWidthIntel(void *start) { 5 | hde64s decode; 6 | return hde64_disasm(start, &decode); 7 | } 8 | 9 | void x86::SubstrateHookFunctionx86(SubstrateProcessRef process, void *symbol, void *replace, void **result){ 10 | if (MSDebug) 11 | MSLog(MSLogLevelNotice, "SubstrateHookFunctionx86(process:%p, symbol:%p, replace:%p, result:%p)", process, symbol, replace, result); 12 | if (symbol == NULL) 13 | return; 14 | 15 | uintptr_t source(reinterpret_cast(symbol)); 16 | uintptr_t target(reinterpret_cast(replace)); 17 | 18 | uint8_t *area(reinterpret_cast(symbol)); 19 | 20 | size_t required(MSSizeOfJump(target, source)); 21 | 22 | if (MSDebug) { 23 | char name[16]; 24 | sprintf(name, "%p", area); 25 | MSLogHex(area, 32, name); 26 | } 27 | 28 | size_t used(0); 29 | while (used < required) { 30 | size_t width(MSGetInstructionWidthIntel(area + used)); 31 | if (width == 0) { 32 | MSLog(MSLogLevelError, "MS:Error:MSGetInstructionWidthIntel(%p) == 0", area + used); 33 | return; 34 | } 35 | 36 | used += width; 37 | } 38 | 39 | size_t blank(used - required); 40 | 41 | if (MSDebug) { 42 | char name[16]; 43 | sprintf(name, "%p", area); 44 | MSLogHex(area, used + sizeof(uint16_t), name); 45 | } 46 | 47 | uint8_t backup[used]; 48 | memcpy(backup, area, used); 49 | 50 | if (result != NULL) { 51 | 52 | if (backup[0] == 0xe9) { 53 | *result = reinterpret_cast(source + 5 + *reinterpret_cast(backup + 1)); 54 | return; 55 | } 56 | 57 | if (!ia32 && backup[0] == 0xff && backup[1] == 0x25) { 58 | *result = *reinterpret_cast(source + 6 + *reinterpret_cast(backup + 2)); 59 | return; 60 | } 61 | 62 | size_t length(used + MSSizeOfJump(source + used)); 63 | 64 | for (size_t offset(0), width; offset != used; offset += width) { 65 | hde64s decode; 66 | hde64_disasm(backup + offset, &decode); 67 | width = decode.len; 68 | //_assert(width != 0 && offset + width <= used); 69 | 70 | #ifdef __LP64__ 71 | if ((decode.modrm & 0xc7) == 0x05) { 72 | if (decode.opcode == 0x8b) { 73 | void *destiny(area + offset + width + int32_t(decode.disp.disp32)); 74 | uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); 75 | length -= decode.len; 76 | length += MSSizeOfPushPointer(destiny); 77 | length += MSSizeOfPop(reg); 78 | length += MSSizeOfMove64(); 79 | } else { 80 | MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); 81 | continue; 82 | } 83 | } else 84 | #endif 85 | 86 | if (backup[offset] == 0xe8) { 87 | int32_t relative(*reinterpret_cast(backup + offset + 1)); 88 | void *destiny(area + offset + decode.len + relative); 89 | 90 | if (relative == 0) { 91 | length -= decode.len; 92 | length += MSSizeOfPushPointer(destiny); 93 | } else { 94 | length += MSSizeOfSkip(); 95 | length += MSSizeOfJump(destiny); 96 | } 97 | } else if (backup[offset] == 0xeb) { 98 | length -= decode.len; 99 | length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 100 | } else if (backup[offset] == 0xe9) { 101 | length -= decode.len; 102 | length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 103 | } else if ( 104 | backup[offset] == 0xe3 || 105 | (backup[offset] & 0xf0) == 0x70 106 | // XXX: opcode2 & 0xf0 is 0x80? 107 | ) { 108 | length += decode.len; 109 | length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 110 | } 111 | } 112 | 113 | uint8_t *buffer(reinterpret_cast(mmap( 114 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 115 | ))); 116 | 117 | if (buffer == MAP_FAILED) { 118 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 119 | *result = NULL; 120 | return; 121 | } 122 | 123 | if (false) fail: { 124 | munmap(buffer, length); 125 | *result = NULL; 126 | return; 127 | } 128 | 129 | { 130 | uint8_t *current(buffer); 131 | 132 | for (size_t offset(0), width; offset != used; offset += width) { 133 | hde64s decode; 134 | hde64_disasm(backup + offset, &decode); 135 | width = decode.len; 136 | //_assert(width != 0 && offset + width <= used); 137 | 138 | #ifdef __LP64__ 139 | if ((decode.modrm & 0xc7) == 0x05) { 140 | if (decode.opcode == 0x8b) { 141 | void *destiny(area + offset + width + int32_t(decode.disp.disp32)); 142 | uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); 143 | MSPushPointer(current, destiny); 144 | MSWritePop(current, reg); 145 | MSWriteMove64(current, reg, reg); 146 | } else { 147 | MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); 148 | goto copy; 149 | } 150 | } else 151 | #endif 152 | 153 | if (backup[offset] == 0xe8) { 154 | int32_t relative(*reinterpret_cast(backup + offset + 1)); 155 | if (relative == 0) 156 | MSPushPointer(current, area + offset + decode.len); 157 | else { 158 | MSWrite(current, 0xe8); 159 | MSWrite(current, MSSizeOfSkip()); 160 | void *destiny(area + offset + decode.len + relative); 161 | MSWriteSkip(current, MSSizeOfJump(destiny, current + MSSizeOfSkip())); 162 | MSWriteJump(current, destiny); 163 | } 164 | } else if (backup[offset] == 0xeb) 165 | MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 166 | else if (backup[offset] == 0xe9) 167 | MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 168 | else if ( 169 | backup[offset] == 0xe3 || 170 | (backup[offset] & 0xf0) == 0x70 171 | ) { 172 | MSWrite(current, backup[offset]); 173 | MSWrite(current, 2); 174 | MSWrite(current, 0xeb); 175 | void *destiny(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 176 | MSWrite(current, MSSizeOfJump(destiny, current + 1)); 177 | MSWriteJump(current, destiny); 178 | } else 179 | #ifdef __LP64__ 180 | copy: 181 | #endif 182 | { 183 | MSWrite(current, backup + offset, width); 184 | } 185 | } 186 | 187 | MSWriteJump(current, area + used); 188 | } 189 | 190 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 191 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 192 | goto fail; 193 | } 194 | 195 | *result = buffer; 196 | 197 | if (MSDebug) { 198 | char name[16]; 199 | sprintf(name, "%p", *result); 200 | MSLogHex(buffer, length, name); 201 | } 202 | 203 | } 204 | 205 | { 206 | SubstrateHookMemory code(process, area, used); 207 | 208 | uint8_t *current(area); 209 | MSWriteJump(current, target); 210 | for (unsigned offset(0); offset != blank; ++offset) 211 | MSWrite(current, 0x90); 212 | } 213 | 214 | if (MSDebug) { 215 | char name[16]; 216 | sprintf(name, "%p", area); 217 | MSLogHex(area, used + sizeof(uint16_t), name); 218 | } 219 | } 220 | 221 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/DexProto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Functions for dealing with method prototypes 19 | */ 20 | 21 | #ifndef LIBDEX_DEXPROTO_H_ 22 | #define LIBDEX_DEXPROTO_H_ 23 | 24 | #include "DexFile.h" 25 | #include "Common.h" 26 | 27 | /* 28 | * Single-thread single-string cache. This structure holds a pointer to 29 | * a string which is semi-automatically manipulated by some of the 30 | * method prototype functions. Functions which use in this struct 31 | * generally return a string that is valid until the next 32 | * time the same DexStringCache is used. 33 | */ 34 | struct DexStringCache { 35 | char* value; /* the latest value */ 36 | size_t allocatedSize; /* size of the allocated buffer, if allocated */ 37 | char buffer[120]; /* buffer used to hold small-enough results */ 38 | }; 39 | 40 | /* 41 | * Make sure that the given cache can hold a string of the given length, 42 | * including the final '\0' byte. 43 | */ 44 | void dexStringCacheAlloc(DexStringCache* pCache, size_t length); 45 | 46 | /* 47 | * Initialize the given DexStringCache. Use this function before passing 48 | * one into any other function. 49 | */ 50 | void dexStringCacheInit(DexStringCache* pCache); 51 | 52 | /* 53 | * Release the allocated contents of the given DexStringCache, if any. 54 | * Use this function after your last use of a DexStringCache. 55 | */ 56 | void dexStringCacheRelease(DexStringCache* pCache); 57 | 58 | /* 59 | * If the given DexStringCache doesn't already point at the given value, 60 | * make a copy of it into the cache. This always returns a writable 61 | * pointer to the contents (whether or not a copy had to be made). This 62 | * function is intended to be used after making a call that at least 63 | * sometimes doesn't populate a DexStringCache. 64 | */ 65 | char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value); 66 | 67 | /* 68 | * Abandon the given DexStringCache, and return a writable copy of the 69 | * given value (reusing the string cache's allocation if possible). 70 | * The return value must be free()d by the caller. Use this instead of 71 | * dexStringCacheRelease() if you want the buffer to survive past the 72 | * scope of the DexStringCache. 73 | */ 74 | char* dexStringCacheAbandon(DexStringCache* pCache, const char* value); 75 | 76 | /* 77 | * Method prototype structure, which refers to a protoIdx in a 78 | * particular DexFile. 79 | */ 80 | struct DexProto { 81 | const DexFile* dexFile; /* file the idx refers to */ 82 | u4 protoIdx; /* index into proto_ids table of dexFile */ 83 | }; 84 | 85 | /* 86 | * Set the given DexProto to refer to the prototype of the given MethodId. 87 | */ 88 | DEX_INLINE void dexProtoSetFromMethodId(DexProto* pProto, 89 | const DexFile* pDexFile, const DexMethodId* pMethodId) 90 | { 91 | pProto->dexFile = pDexFile; 92 | pProto->protoIdx = pMethodId->protoIdx; 93 | } 94 | 95 | /* 96 | * Get the short-form method descriptor for the given prototype. The 97 | * prototype must be protoIdx-based. 98 | */ 99 | const char* dexProtoGetShorty(const DexProto* pProto); 100 | 101 | /* 102 | * Get the full method descriptor for the given prototype. 103 | */ 104 | const char* dexProtoGetMethodDescriptor(const DexProto* pProto, 105 | DexStringCache* pCache); 106 | 107 | /* 108 | * Get a copy of the descriptor string associated with the given prototype. 109 | * The returned pointer must be free()ed by the caller. 110 | */ 111 | char* dexProtoCopyMethodDescriptor(const DexProto* pProto); 112 | 113 | /* 114 | * Get the parameter descriptors for the given prototype. This is the 115 | * concatenation of all the descriptors for all the parameters, in 116 | * order, with no other adornment. 117 | */ 118 | const char* dexProtoGetParameterDescriptors(const DexProto* pProto, 119 | DexStringCache* pCache); 120 | 121 | /* 122 | * Return the utf-8 encoded descriptor string from the proto of a MethodId. 123 | */ 124 | DEX_INLINE const char* dexGetDescriptorFromMethodId(const DexFile* pDexFile, 125 | const DexMethodId* pMethodId, DexStringCache* pCache) 126 | { 127 | DexProto proto; 128 | 129 | dexProtoSetFromMethodId(&proto, pDexFile, pMethodId); 130 | return dexProtoGetMethodDescriptor(&proto, pCache); 131 | } 132 | 133 | /* 134 | * Get a copy of the utf-8 encoded method descriptor string from the 135 | * proto of a MethodId. The returned pointer must be free()ed by the 136 | * caller. 137 | */ 138 | DEX_INLINE char* dexCopyDescriptorFromMethodId(const DexFile* pDexFile, 139 | const DexMethodId* pMethodId) 140 | { 141 | DexProto proto; 142 | 143 | dexProtoSetFromMethodId(&proto, pDexFile, pMethodId); 144 | return dexProtoCopyMethodDescriptor(&proto); 145 | } 146 | 147 | /* 148 | * Get the type descriptor for the return type of the given prototype. 149 | */ 150 | const char* dexProtoGetReturnType(const DexProto* pProto); 151 | 152 | /* 153 | * Get the parameter count of the given prototype. 154 | */ 155 | size_t dexProtoGetParameterCount(const DexProto* pProto); 156 | 157 | /* 158 | * Compute the number of parameter words (u4 units) required by the 159 | * given prototype. For example, if the method takes (int, long) and 160 | * returns double, this would return 3 (one for the int, two for the 161 | * long, and the return type isn't relevant). 162 | */ 163 | int dexProtoComputeArgsSize(const DexProto* pProto); 164 | 165 | /* 166 | * Compare the two prototypes. The two prototypes are compared 167 | * with the return type as the major order, then the first arguments, 168 | * then second, etc. If two prototypes are identical except that one 169 | * has extra arguments, then the shorter argument is considered the 170 | * earlier one in sort order (similar to strcmp()). 171 | */ 172 | int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2); 173 | 174 | /* 175 | * Compare the two prototypes, ignoring return type. The two 176 | * prototypes are compared with the first argument as the major order, 177 | * then second, etc. If two prototypes are identical except that one 178 | * has extra arguments, then the shorter argument is considered the 179 | * earlier one in sort order (similar to strcmp()). 180 | */ 181 | int dexProtoCompareParameters(const DexProto* pProto1, 182 | const DexProto* pProto2); 183 | 184 | /* 185 | * Compare a prototype and a string method descriptor. The comparison 186 | * is done as if the descriptor were converted to a prototype and compared 187 | * with dexProtoCompare(). 188 | */ 189 | int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor); 190 | 191 | /* 192 | * Compare a prototype and a concatenation of type descriptors. The 193 | * comparison is done as if the descriptors were converted to a 194 | * prototype and compared with dexProtoCompareParameters(). 195 | */ 196 | int dexProtoCompareToParameterDescriptors(const DexProto* proto, 197 | const char* descriptors); 198 | 199 | /* 200 | * Single-thread prototype parameter iterator. This structure holds a 201 | * pointer to a prototype and its parts, along with a cursor. 202 | */ 203 | struct DexParameterIterator { 204 | const DexProto* proto; 205 | const DexTypeList* parameters; 206 | int parameterCount; 207 | int cursor; 208 | }; 209 | 210 | /* 211 | * Initialize the given DexParameterIterator to be at the start of the 212 | * parameters of the given prototype. 213 | */ 214 | void dexParameterIteratorInit(DexParameterIterator* pIterator, 215 | const DexProto* pProto); 216 | 217 | /* 218 | * Get the type_id index for the next parameter, if any. This returns 219 | * kDexNoIndex if the last parameter has already been consumed. 220 | */ 221 | u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator); 222 | 223 | /* 224 | * Get the type descriptor for the next parameter, if any. This returns 225 | * NULL if the last parameter has already been consumed. 226 | */ 227 | const char* dexParameterIteratorNextDescriptor( 228 | DexParameterIterator* pIterator); 229 | 230 | #endif // LIBDEX_DEXPROTO_H_ 231 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/Android-Inline/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 | #include 19 | 20 | #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 | enum hook_status { 36 | REGISTERED, 37 | HOOKED, 38 | }; 39 | 40 | struct inlineHookItem { 41 | uint32_t target_addr; 42 | uint32_t new_addr; 43 | uint32_t **proto_addr; 44 | void *orig_instructions; 45 | int orig_boundaries[4]; 46 | int trampoline_boundaries[20]; 47 | int count; 48 | void *trampoline_instructions; 49 | int length; 50 | int status; 51 | int mode; 52 | }; 53 | 54 | struct inlineHookInfo { 55 | struct inlineHookItem item[1024]; 56 | int size; 57 | }; 58 | 59 | static struct inlineHookInfo info = {0}; 60 | 61 | static int getAllTids(pid_t pid, pid_t *tids) 62 | { 63 | char dir_path[32]; 64 | DIR *dir; 65 | int i; 66 | struct dirent *entry; 67 | pid_t tid; 68 | 69 | if (pid < 0) { 70 | snprintf(dir_path, sizeof(dir_path), "/proc/self/task"); 71 | } 72 | else { 73 | snprintf(dir_path, sizeof(dir_path), "/proc/%d/task", pid); 74 | } 75 | 76 | dir = opendir(dir_path); 77 | if (dir == NULL) { 78 | return 0; 79 | } 80 | 81 | i = 0; 82 | while((entry = readdir(dir)) != NULL) { 83 | tid = atoi(entry->d_name); 84 | if (tid != 0 && tid != getpid()) { 85 | tids[i++] = tid; 86 | } 87 | } 88 | closedir(dir); 89 | return i; 90 | } 91 | 92 | static bool doProcessThreadPC(struct inlineHookItem *item, struct pt_regs *regs, int action) 93 | { 94 | int offset; 95 | int i; 96 | 97 | switch (action) 98 | { 99 | case ACTION_ENABLE: 100 | offset = regs->ARM_pc - CLEAR_BIT0(item->target_addr); 101 | for (i = 0; i < item->count; ++i) { 102 | if (offset == item->orig_boundaries[i]) { 103 | regs->ARM_pc = (uint32_t) item->trampoline_instructions + item->trampoline_boundaries[i]; 104 | return true; 105 | } 106 | } 107 | break; 108 | case ACTION_DISABLE: 109 | offset = regs->ARM_pc - (int) item->trampoline_instructions; 110 | for (i = 0; i < item->count; ++i) { 111 | if (offset == item->trampoline_boundaries[i]) { 112 | regs->ARM_pc = CLEAR_BIT0(item->target_addr) + item->orig_boundaries[i]; 113 | return true; 114 | } 115 | } 116 | break; 117 | } 118 | 119 | return false; 120 | } 121 | 122 | static void processThreadPC(pid_t tid, struct inlineHookItem *item, int action) 123 | { 124 | struct pt_regs regs; 125 | 126 | if (ptrace(PTRACE_GETREGS, tid, NULL, ®s) == 0) { 127 | if (item == NULL) { 128 | int pos; 129 | 130 | for (pos = 0; pos < info.size; ++pos) { 131 | if (doProcessThreadPC(&info.item[pos], ®s, action) == true) { 132 | break; 133 | } 134 | } 135 | } 136 | else { 137 | doProcessThreadPC(item, ®s, action); 138 | } 139 | 140 | ptrace(PTRACE_SETREGS, tid, NULL, ®s); 141 | } 142 | } 143 | 144 | static pid_t freeze(struct inlineHookItem *item, int action) 145 | { 146 | int count; 147 | pid_t tids[1024]; 148 | pid_t pid; 149 | 150 | pid = -1; 151 | count = getAllTids(getpid(), tids); 152 | if (count > 0) { 153 | pid = fork(); 154 | 155 | if (pid == 0) { 156 | int i; 157 | 158 | for (i = 0; i < count; ++i) { 159 | if (ptrace(PTRACE_ATTACH, tids[i], NULL, NULL) == 0) { 160 | waitpid(tids[i], NULL, WUNTRACED); 161 | processThreadPC(tids[i], item, action); 162 | } 163 | } 164 | 165 | raise(SIGSTOP); 166 | 167 | for (i = 0; i < count; ++i) { 168 | ptrace(PTRACE_DETACH, tids[i], NULL, NULL); 169 | } 170 | 171 | raise(SIGKILL); 172 | } 173 | 174 | else if (pid > 0) { 175 | waitpid(pid, NULL, WUNTRACED); 176 | } 177 | } 178 | 179 | return pid; 180 | } 181 | 182 | static void unFreeze(pid_t pid) 183 | { 184 | if (pid < 0) { 185 | return; 186 | } 187 | 188 | kill(pid, SIGCONT); 189 | wait(NULL); 190 | } 191 | 192 | static bool isExecutableAddr(uint32_t addr) 193 | { 194 | FILE *fp; 195 | char line[1024]; 196 | uint32_t start; 197 | uint32_t end; 198 | 199 | fp = fopen("/proc/self/maps", "r"); 200 | if (fp == NULL) { 201 | return false; 202 | } 203 | 204 | while (fgets(line, sizeof(line), fp)) { 205 | if (strstr(line, "r-xp") || strstr(line, "rwxp")) { 206 | start = strtoul(strtok(line, "-"), NULL, 16); 207 | end = strtoul(strtok(NULL, " "), NULL, 16); 208 | if (addr >= start && addr <= end) { 209 | fclose(fp); 210 | return true; 211 | } 212 | } 213 | } 214 | 215 | fclose(fp); 216 | 217 | return false; 218 | } 219 | 220 | static struct inlineHookItem *findInlineHookItem(uint32_t target_addr) 221 | { 222 | int i; 223 | 224 | for (i = 0; i < info.size; ++i) { 225 | if (info.item[i].target_addr == target_addr) { 226 | return &info.item[i]; 227 | } 228 | } 229 | 230 | return NULL; 231 | } 232 | 233 | static struct inlineHookItem *addInlineHookItem() { 234 | struct inlineHookItem *item; 235 | 236 | if (info.size >= 1024) { 237 | return NULL; 238 | } 239 | 240 | item = &info.item[info.size]; 241 | ++info.size; 242 | 243 | return item; 244 | } 245 | 246 | static void deleteInlineHookItem(int pos) 247 | { 248 | info.item[pos] = info.item[info.size - 1]; 249 | --info.size; 250 | } 251 | 252 | enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr) 253 | { 254 | struct inlineHookItem *item; 255 | 256 | if (!isExecutableAddr(target_addr) || !isExecutableAddr(new_addr)) { 257 | return ELE7EN_ERROR_NOT_EXECUTABLE; 258 | } 259 | 260 | item = findInlineHookItem(target_addr); 261 | if (item != NULL) { 262 | if (item->status == REGISTERED) { 263 | return ELE7EN_ERROR_ALREADY_REGISTERED; 264 | } 265 | else if (item->status == HOOKED) { 266 | return ELE7EN_ERROR_ALREADY_HOOKED; 267 | } 268 | else { 269 | return ELE7EN_ERROR_UNKNOWN; 270 | } 271 | } 272 | 273 | item = addInlineHookItem(); 274 | 275 | item->target_addr = target_addr; 276 | item->new_addr = new_addr; 277 | item->proto_addr = proto_addr; 278 | 279 | item->length = TEST_BIT0(item->target_addr) ? 12 : 8; 280 | item->orig_instructions = malloc(item->length); 281 | memcpy(item->orig_instructions, (void *) CLEAR_BIT0(item->target_addr), item->length); 282 | 283 | item->trampoline_instructions = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 284 | relocateInstruction(item->target_addr, item->orig_instructions, item->length, item->trampoline_instructions, item->orig_boundaries, item->trampoline_boundaries, &item->count); 285 | 286 | item->status = REGISTERED; 287 | 288 | return ELE7EN_OK; 289 | } 290 | 291 | static void doInlineUnHook(struct inlineHookItem *item, int pos) 292 | { 293 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC); 294 | memcpy((void *) CLEAR_BIT0(item->target_addr), item->orig_instructions, item->length); 295 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_EXEC); 296 | munmap(item->trampoline_instructions, PAGE_SIZE); 297 | free(item->orig_instructions); 298 | 299 | deleteInlineHookItem(pos); 300 | 301 | cacheflush(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length, 0); 302 | } 303 | 304 | enum ele7en_status inlineUnHook(uint32_t target_addr) 305 | { 306 | int i; 307 | 308 | for (i = 0; i < info.size; ++i) { 309 | if (info.item[i].target_addr == target_addr && info.item[i].status == HOOKED) { 310 | pid_t pid; 311 | 312 | pid = freeze(&info.item[i], ACTION_DISABLE); 313 | 314 | doInlineUnHook(&info.item[i], i); 315 | 316 | unFreeze(pid); 317 | 318 | return ELE7EN_OK; 319 | } 320 | } 321 | 322 | return ELE7EN_ERROR_NOT_HOOKED; 323 | } 324 | 325 | void inlineUnHookAll() 326 | { 327 | pid_t pid; 328 | int i; 329 | 330 | pid = freeze(NULL, ACTION_DISABLE); 331 | 332 | for (i = 0; i < info.size; ++i) { 333 | if (info.item[i].status == HOOKED) { 334 | doInlineUnHook(&info.item[i], i); 335 | --i; 336 | } 337 | } 338 | 339 | unFreeze(pid); 340 | } 341 | 342 | static void doInlineHook(struct inlineHookItem *item) 343 | { 344 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC); 345 | 346 | if (item->proto_addr != NULL) { 347 | *(item->proto_addr) = TEST_BIT0(item->target_addr) ? (uint32_t *) SET_BIT0((uint32_t) item->trampoline_instructions) : item->trampoline_instructions; 348 | } 349 | 350 | if (TEST_BIT0(item->target_addr)) { 351 | int i; 352 | 353 | i = 0; 354 | if (CLEAR_BIT0(item->target_addr) % 4 != 0) { 355 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xBF00; // NOP 356 | } 357 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xF8DF; 358 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = 0xF000; // LDR.W PC, [PC] 359 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = item->new_addr & 0xFFFF; 360 | ((uint16_t *) CLEAR_BIT0(item->target_addr))[i++] = item->new_addr >> 16; 361 | } 362 | else { 363 | ((uint32_t *) (item->target_addr))[0] = 0xe51ff004; // LDR PC, [PC, #-4] 364 | ((uint32_t *) (item->target_addr))[1] = item->new_addr; 365 | } 366 | 367 | mprotect((void *) PAGE_START(CLEAR_BIT0(item->target_addr)), PAGE_SIZE * 2, PROT_READ | PROT_EXEC); 368 | 369 | item->status = HOOKED; 370 | 371 | cacheflush(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length, 0); 372 | } 373 | 374 | enum ele7en_status inlineHook(uint32_t target_addr) 375 | { 376 | int i; 377 | struct inlineHookItem *item; 378 | 379 | item = NULL; 380 | for (i = 0; i < info.size; ++i) { 381 | if (info.item[i].target_addr == target_addr) { 382 | item = &info.item[i]; 383 | break; 384 | } 385 | } 386 | 387 | if (item == NULL) { 388 | return ELE7EN_ERROR_NOT_REGISTERED; 389 | } 390 | 391 | if (item->status == REGISTERED) { 392 | pid_t pid; 393 | 394 | pid = freeze(item, ACTION_ENABLE); 395 | 396 | doInlineHook(item); 397 | 398 | unFreeze(pid); 399 | 400 | return ELE7EN_OK; 401 | } 402 | else if (item->status == HOOKED) { 403 | return ELE7EN_ERROR_ALREADY_HOOKED; 404 | } 405 | else { 406 | return ELE7EN_ERROR_UNKNOWN; 407 | } 408 | } 409 | 410 | void inlineHookAll() 411 | { 412 | pid_t pid; 413 | int i; 414 | 415 | pid = freeze(NULL, ACTION_ENABLE); 416 | 417 | for (i = 0; i < info.size; ++i) { 418 | if (info.item[i].status == REGISTERED) { 419 | doInlineHook(&info.item[i]); 420 | } 421 | } 422 | 423 | unFreeze(pid); 424 | } 425 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/util.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | //#include 7 | #include 8 | #include "Hooker.h" 9 | //#include "../common.h" 10 | 11 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,"wodelog", __VA_ARGS__) 12 | /* memory map for libraries */ 13 | #define MAX_NAME_LEN 256 14 | #define MEMORY_ONLY "[memory]" 15 | struct mm { 16 | char name[MAX_NAME_LEN]; 17 | unsigned long start, end; 18 | }; 19 | 20 | typedef struct symtab *symtab_t; 21 | struct symlist { 22 | Elf32_Sym *sym; /* symbols */ 23 | char *str; /* symbol strings */ 24 | unsigned num; /* number of symbols */ 25 | }; 26 | struct symtab { 27 | struct symlist *st; /* "static" symbols */ 28 | struct symlist *dyn; /* dynamic symbols */ 29 | }; 30 | 31 | static void* xmalloc(size_t size) { 32 | void *p; 33 | p = malloc(size); 34 | if (!p) { 35 | printf("Out of memory\n"); 36 | exit(1); 37 | } 38 | return p; 39 | } 40 | 41 | static int my_pread(int fd, void *buf, size_t count, off_t offset) { 42 | lseek(fd, offset, SEEK_SET); 43 | return read(fd, buf, count); 44 | } 45 | 46 | static struct symlist* get_syms(int fd, Elf32_Shdr *symh, Elf32_Shdr *strh) { 47 | struct symlist *sl, *ret; 48 | int rv; 49 | 50 | ret = NULL; 51 | sl = (struct symlist *) xmalloc(sizeof(struct symlist)); 52 | sl->str = NULL; 53 | sl->sym = NULL; 54 | 55 | /* sanity */ 56 | if (symh->sh_size % sizeof(Elf32_Sym)) { 57 | //printf("elf_error\n"); 58 | goto out; 59 | } 60 | 61 | /* symbol table */ 62 | sl->num = symh->sh_size / sizeof(Elf32_Sym); 63 | sl->sym = (Elf32_Sym *) xmalloc(symh->sh_size); 64 | rv = my_pread(fd, sl->sym, symh->sh_size, symh->sh_offset); 65 | if (0 > rv) { 66 | //perror("read"); 67 | goto out; 68 | } 69 | if (rv != symh->sh_size) { 70 | //printf("elf error\n"); 71 | goto out; 72 | } 73 | 74 | /* string table */ 75 | sl->str = (char *) xmalloc(strh->sh_size); 76 | rv = my_pread(fd, sl->str, strh->sh_size, strh->sh_offset); 77 | if (0 > rv) { 78 | //perror("read"); 79 | goto out; 80 | } 81 | if (rv != strh->sh_size) { 82 | //printf("elf error"); 83 | goto out; 84 | } 85 | 86 | ret = sl; 87 | out: return ret; 88 | } 89 | 90 | static int do_load(int fd, symtab_t symtab) { 91 | int rv; 92 | size_t size; 93 | Elf32_Ehdr ehdr; 94 | Elf32_Shdr *shdr = NULL, *p; 95 | Elf32_Shdr *dynsymh, *dynstrh; 96 | Elf32_Shdr *symh, *strh; 97 | char *shstrtab = NULL; 98 | int i; 99 | int ret = -1; 100 | 101 | /* elf header */ 102 | rv = read(fd, &ehdr, sizeof(ehdr)); 103 | if (0 > rv) { 104 | LOGD("read\n"); 105 | goto out; 106 | } 107 | if (rv != sizeof(ehdr)) { 108 | LOGD("elf error 1\n"); 109 | goto out; 110 | } 111 | if (strncmp((const char *) ELFMAG, (const char *) ehdr.e_ident, SELFMAG)) { /* sanity */ 112 | LOGD("not an elf\n"); 113 | goto out; 114 | } 115 | if (sizeof(Elf32_Shdr) != ehdr.e_shentsize) { /* sanity */ 116 | LOGD("elf error 2\n"); 117 | goto out; 118 | } 119 | 120 | /* section header table */ 121 | size = ehdr.e_shentsize * ehdr.e_shnum; 122 | shdr = (Elf32_Shdr *) xmalloc(size); 123 | rv = my_pread(fd, shdr, size, ehdr.e_shoff); 124 | if (0 > rv) { 125 | LOGD("read\n"); 126 | goto out; 127 | } 128 | if (rv != size) { 129 | LOGD("elf error 3 %d %d\n", rv, size); 130 | goto out; 131 | } 132 | 133 | /* section header string table */ 134 | size = shdr[ehdr.e_shstrndx].sh_size; 135 | shstrtab = (char *) xmalloc(size); 136 | rv = my_pread(fd, shstrtab, size, shdr[ehdr.e_shstrndx].sh_offset); 137 | if (0 > rv) { 138 | LOGD("read\n"); 139 | goto out; 140 | } 141 | if (rv != size) { 142 | LOGD("elf error 4 %d %d\n", rv, size); 143 | goto out; 144 | } 145 | 146 | /* symbol table headers */ 147 | symh = dynsymh = NULL; 148 | strh = dynstrh = NULL; 149 | for (i = 0, p = shdr; i < ehdr.e_shnum; i++, p++) 150 | if (SHT_SYMTAB == p->sh_type) { 151 | if (symh) { 152 | LOGD("too many symbol tables\n"); 153 | goto out; 154 | } 155 | symh = p; 156 | } else if (SHT_DYNSYM == p->sh_type) { 157 | if (dynsymh) { 158 | LOGD("too many symbol tables\n"); 159 | goto out; 160 | } 161 | dynsymh = p; 162 | } else if (SHT_STRTAB == p->sh_type 163 | && !strncmp(shstrtab + p->sh_name, ".strtab", 7)) { 164 | if (strh) { 165 | LOGD("too many string tables\n"); 166 | goto out; 167 | } 168 | strh = p; 169 | } else if (SHT_STRTAB == p->sh_type 170 | && !strncmp(shstrtab + p->sh_name, ".dynstr", 7)) { 171 | if (dynstrh) { 172 | LOGD("too many string tables\n"); 173 | goto out; 174 | } 175 | dynstrh = p; 176 | } 177 | /* sanity checks */ 178 | if ((!dynsymh && dynstrh) || (dynsymh && !dynstrh)) { 179 | LOGD("bad dynamic symbol table\n"); 180 | goto out; 181 | } 182 | if ((!symh && strh) || (symh && !strh)) { 183 | LOGD("bad symbol table\n"); 184 | goto out; 185 | } 186 | if (!dynsymh && !symh) { 187 | LOGD("no symbol table\n"); 188 | goto out; 189 | } 190 | 191 | /* symbol tables */ 192 | if (dynsymh) 193 | symtab->dyn = get_syms(fd, dynsymh, dynstrh); 194 | if (symh) 195 | symtab->st = get_syms(fd, symh, strh); 196 | ret = 0; 197 | out: free(shstrtab); 198 | free(shdr); 199 | return ret; 200 | } 201 | 202 | static symtab_t load_symtab(char *filename) { 203 | int fd; 204 | symtab_t symtab; 205 | 206 | symtab = (symtab_t) xmalloc(sizeof(*symtab)); 207 | memset(symtab, 0, sizeof(*symtab)); 208 | 209 | fd = open(filename, O_RDONLY); 210 | if (0 > fd) { 211 | LOGD("%s open\n", __func__); 212 | return NULL; 213 | } 214 | if (0 > do_load(fd, symtab)) { 215 | LOGD("Error ELF parsing %s\n", filename); 216 | free(symtab); 217 | symtab = NULL; 218 | } 219 | close(fd); 220 | return symtab; 221 | } 222 | 223 | static int load_memmap(pid_t pid, struct mm *mm, int *nmmp) { 224 | size_t buf_size = 0x40000; 225 | char *p_buf = (char *) malloc(buf_size); // increase this if needed for larger "maps" 226 | char name[MAX_NAME_LEN] = { 0 }; 227 | char *p; 228 | unsigned long start, end; 229 | struct mm *m; 230 | int nmm = 0; 231 | int fd, rv; 232 | int i; 233 | 234 | sprintf(p_buf, "/proc/%d/maps", pid); 235 | fd = open(p_buf, O_RDONLY); 236 | if (0 > fd) { 237 | LOGD("Can't open %s for reading\n", p_buf); 238 | free(p_buf); 239 | return -1; 240 | } 241 | 242 | /* Zero to ensure data is null terminated */ 243 | memset(p_buf, 0, buf_size); 244 | 245 | p = p_buf; 246 | while (1) { 247 | rv = read(fd, p, buf_size - (p - p_buf)); 248 | if (0 > rv) { 249 | LOGD("%s read", __FUNCTION__); 250 | free(p_buf); 251 | return -1; 252 | } 253 | if (0 == rv) 254 | break; 255 | p += rv; 256 | if (p - p_buf >= buf_size) { 257 | LOGD("Too many memory mapping\n"); 258 | free(p_buf); 259 | return -1; 260 | } 261 | } 262 | close(fd); 263 | 264 | p = strtok(p_buf, "\n"); 265 | m = mm; 266 | while (p) { 267 | /* parse current map line */ 268 | rv = sscanf(p, "%08lx-%08lx %*s %*s %*s %*s %s\n", &start, &end, name); 269 | 270 | p = strtok(NULL, "\n"); 271 | 272 | if (rv == 2) { 273 | m = &mm[nmm++]; 274 | m->start = start; 275 | m->end = end; 276 | memcpy(m->name, MEMORY_ONLY, sizeof(MEMORY_ONLY)); 277 | continue; 278 | } 279 | 280 | /* search backward for other mapping with same name */ 281 | for (i = nmm - 1; i >= 0; i--) { 282 | m = &mm[i]; 283 | if (!strcmp(m->name, name)) 284 | break; 285 | } 286 | 287 | if (i >= 0) { 288 | if (start < m->start) 289 | m->start = start; 290 | if (end > m->end) 291 | m->end = end; 292 | } else { 293 | /* new entry */ 294 | m = &mm[nmm++]; 295 | m->start = start; 296 | m->end = end; 297 | memcpy(m->name, name, strlen(name)); 298 | } 299 | } 300 | 301 | *nmmp = nmm; 302 | free(p_buf); 303 | return 0; 304 | } 305 | 306 | /* Find libc in MM, storing no more than LEN-1 chars of 307 | its name in NAME and set START to its starting 308 | address. If libc cannot be found return -1 and 309 | leave NAME and START untouched. Otherwise return 0 310 | and null-terminated NAME. */ 311 | static int find_libname(const char *libn, char *name, int len, unsigned long *start, 312 | struct mm *mm, int nmm) { 313 | int i; 314 | struct mm *m; 315 | char *p; 316 | for (i = 0, m = mm; i < nmm; i++, m++) { 317 | 318 | if (!strcmp(m->name, MEMORY_ONLY)) 319 | continue; 320 | p = strrchr(m->name, '/'); 321 | if (!p) 322 | continue; 323 | p++; 324 | // LOGD("m->name:%s",m->name); 325 | if (strncmp(libn, p, strlen(libn))) 326 | continue; 327 | p += strlen(libn); 328 | 329 | /* here comes our crude test -> 'libc.so' or 'libc-[0-9]' */ 330 | if (!strncmp("so", p, 2) || 1) // || (p[0] == '-' && isdigit(p[1]))) 331 | break; 332 | } 333 | if (i >= nmm) 334 | /* not found */ 335 | return -1; 336 | 337 | *start = m->start; 338 | strncpy(name, m->name, len); 339 | if (strlen(m->name) >= len) 340 | name[len - 1] = '\0'; 341 | 342 | mprotect((void*) m->start, m->end - m->start, 343 | PROT_READ | PROT_WRITE | PROT_EXEC); 344 | return 0; 345 | } 346 | 347 | static int lookup2(struct symlist *sl, unsigned char type, char *name, 348 | unsigned long *val) { 349 | Elf32_Sym *p; 350 | int len; 351 | int i; 352 | 353 | len = strlen(name); 354 | for (i = 0, p = sl->sym; i < sl->num; i++, p++) { 355 | //LOGD("name: %s %x\n", sl->str+p->st_name, p->st_value) 356 | if (!strncmp(sl->str + p->st_name, name, len) 357 | && *(sl->str + p->st_name + len) == 0 358 | && ELF32_ST_TYPE(p->st_info) == type) { 359 | //if (p->st_value != 0) { 360 | *val = p->st_value; 361 | return 0; 362 | //} 363 | } 364 | } 365 | return -1; 366 | } 367 | 368 | static int lookup_sym(symtab_t s, unsigned char type, char *name, 369 | unsigned long *val) { 370 | if (s->dyn && !lookup2(s->dyn, type, name, val)) 371 | return 0; 372 | if (s->st && !lookup2(s->st, type, name, val)) 373 | return 0; 374 | return -1; 375 | } 376 | 377 | static int lookup_func_sym(symtab_t s, char *name, unsigned long *val) { 378 | return lookup_sym(s, STT_FUNC, name, val); 379 | } 380 | 381 | int find_name(pid_t pid, const char *name, const char *libn, 382 | unsigned long *addr) { 383 | struct mm mm[1000] = { 0 }; 384 | unsigned long libcaddr; 385 | int nmm; 386 | char libc[1024] = { 0 }; 387 | symtab_t s; 388 | 389 | if (0 > load_memmap(pid, mm, &nmm)) { 390 | LOGD("cannot read memory map\n"); 391 | return -1; 392 | } 393 | if (0 394 | > find_libname((char *) libn, (char *) libc, sizeof(libc), 395 | &libcaddr, mm, nmm)) { 396 | LOGD("cannot find lib: %s\n", libn); 397 | return -1; 398 | } 399 | //LOGD("lib: >%s<\n", libc) 400 | s = load_symtab(libc); 401 | if (!s) { 402 | LOGD("cannot read symbol table\n"); 403 | return -1; 404 | } 405 | if (0 > lookup_func_sym(s, (char *) name, addr)) { 406 | LOGD("cannot find function: %s\n", name); 407 | return -1; 408 | } 409 | *addr += libcaddr; 410 | return 0; 411 | } 412 | 413 | int find_libbase(pid_t pid, const char *libn, unsigned long *addr) { 414 | struct mm mm[1000] = { 0 }; 415 | unsigned long libcaddr; 416 | int nmm; 417 | char libc[1024] = { 0 }; 418 | symtab_t s; 419 | 420 | if (0 > load_memmap(pid, mm, &nmm)) { 421 | LOGD("cannot read memory map\n"); 422 | return -1; 423 | } 424 | if (0 > find_libname(libn, libc, sizeof(libc), &libcaddr, mm, nmm)) { 425 | LOGD("cannot find lib\n"); 426 | return -1; 427 | } 428 | *addr = libcaddr; 429 | return 0; 430 | } 431 | 432 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/art.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jarlene on 2015/9/29. 3 | // 4 | 5 | #ifndef COMMONDEMO_ART_H 6 | #define COMMONDEMO_ART_H 7 | 8 | #include 9 | #include "string.h" 10 | #include 11 | #include 12 | //#include "../../base/log.h" 13 | 14 | 15 | 16 | #ifdef HAVE_STDINT_H 17 | # include /* C99 */ 18 | typedef uint8_t u1; 19 | typedef uint16_t u2; 20 | typedef uint32_t u4; 21 | typedef uint64_t u8; 22 | typedef int8_t s1; 23 | typedef int16_t s2; 24 | typedef int32_t s4; 25 | typedef int64_t s8; 26 | #else 27 | typedef unsigned char u1; 28 | typedef unsigned short u2; 29 | typedef unsigned int u4; 30 | typedef unsigned long long u8; 31 | typedef signed char s1; 32 | typedef signed short s2; 33 | typedef signed int s4; 34 | typedef signed long long s8; 35 | #endif 36 | 37 | 38 | namespace art { 39 | namespace mirror { 40 | 41 | class Object { 42 | public: 43 | static constexpr size_t kVTableLength = 11; 44 | static uint32_t hash_code_seed; 45 | // 5.0系统只有以下两个数据,5.1以及6.0多了上面两个。 46 | void* klass_; 47 | uint32_t monitor_; 48 | 49 | }; 50 | 51 | class Class: public Object { 52 | public: 53 | 54 | 55 | // 5.1以上系统独有的参数 56 | static constexpr uint32_t kClassWalkSuper = 0xC0000000; 57 | 58 | // Interface method table size. Increasing this value reduces the chance of two interface methods 59 | // colliding in the interface method table but increases the size of classes that implement 60 | // (non-marker) interfaces. 61 | static constexpr size_t kImtSize = 64; //IMT_SIZE; 62 | // defining class loader, or NULL for the "bootstrap" system loader 63 | void* class_loader_; 64 | // For array classes, the component class object for instanceof/checkcast 65 | // (for String[][][], this will be String[][]). NULL for non-array classes. 66 | void* component_type_; 67 | // DexCache of resolved constant pool entries (will be NULL for classes generated by the 68 | // runtime such as arrays and primitive classes). 69 | void* dex_cache_; 70 | // static, private, and methods 71 | void* direct_methods_; 72 | // instance fields 73 | // 74 | // These describe the layout of the contents of an Object. 75 | // Note that only the fields directly declared by this class are 76 | // listed in ifields; fields declared by a superclass are listed in 77 | // the superclass's Class.ifields. 78 | // 79 | // All instance fields that refer to objects are guaranteed to be at 80 | // the beginning of the field list. num_reference_instance_fields_ 81 | // specifies the number of reference fields. 82 | void* ifields_; 83 | // The interface table (iftable_) contains pairs of a interface class and an array of the 84 | // interface methods. There is one pair per interface supported by this class. That means one 85 | // pair for each interface we support directly, indirectly via superclass, or indirectly via a 86 | // superinterface. This will be null if neither we nor our superclass implement any interfaces. 87 | // 88 | // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()". 89 | // Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a 90 | // single vtable. 91 | // 92 | // For every interface a concrete class implements, we create an array of the concrete vtable_ 93 | // methods for the methods in the interface. 94 | void* iftable_; 95 | // Interface method table (imt), for quick "invoke-interface". 96 | void* imtable_; 97 | // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName 98 | void* name_; 99 | // Static fields 100 | void* sfields_; 101 | // The superclass, or NULL if this is java.lang.Object, an interface or primitive type. 102 | void* super_class_; 103 | // If class verify fails, we must return same error on subsequent tries. 104 | void* verify_error_class_; 105 | // Virtual methods defined in this class; invoked through vtable. 106 | void* virtual_methods_; 107 | // Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is 108 | // copied in, and virtual methods from our class either replace those from the super or are 109 | // appended. For abstract classes, methods may be created in the vtable that aren't in 110 | // virtual_ methods_ for miranda methods. 111 | void* vtable_; 112 | // Access flags; low 16 bits are defined by VM spec. 113 | uint32_t access_flags_; 114 | // Total size of the Class instance; used when allocating storage on gc heap. 115 | // See also object_size_. 116 | uint32_t class_size_; 117 | // Tid used to check for recursive invocation. 118 | pid_t clinit_thread_id_; 119 | // ClassDef index in dex file, -1 if no class definition such as an array. 120 | // TODO: really 16bits 121 | int32_t dex_class_def_idx_; 122 | // Type index in dex file. 123 | // TODO: really 16bits 124 | int32_t dex_type_idx_; 125 | // Number of instance fields that are object refs. 126 | uint32_t num_reference_instance_fields_; 127 | // Number of static fields that are object refs, 128 | uint32_t num_reference_static_fields_; 129 | // Total object size; used when allocating storage on gc heap. 130 | // (For interfaces and abstract classes this will be zero.) 131 | // See also class_size_. 132 | uint32_t object_size_; 133 | // Primitive type value, or Primitive::kPrimNot (0); set for generated primitive classes. 134 | void* primitive_type_; 135 | // Bitmap of offsets of ifields. 136 | uint32_t reference_instance_offsets_; 137 | // Bitmap of offsets of sfields. 138 | uint32_t reference_static_offsets_; 139 | // State of class initialization. 140 | void* status_; 141 | // TODO: ? 142 | // initiating class loader list 143 | // NOTE: for classes with low serialNumber, these are unused, and the 144 | // values are kept in a table in gDvm. 145 | // InitiatingLoaderList initiating_loader_list_; 146 | // The following data exist in real class objects. 147 | // Embedded Imtable, for class object that's not an interface, fixed size. 148 | void* embedded_imtable_[0]; 149 | // Embedded Vtable, for class object that's not an interface, variable size. 150 | void* embedded_vtable_[0]; 151 | // Static fields, variable size. 152 | uint32_t fields_[0]; 153 | // java.lang.Class 154 | static void* java_lang_Class_; 155 | 156 | }; 157 | // art所有的系统都一样 158 | class ArtField: public Object { 159 | void* declaring_class_; 160 | int32_t access_flags_; 161 | int32_t field_dex_idx_; 162 | int32_t offset_; 163 | }; 164 | 165 | class ArtMethod : public Object{ 166 | public: 167 | // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". 168 | // The class we are a part of 169 | Class* declaring_class_; 170 | 171 | // short cuts to declaring_class_->dex_cache_ member for fast compiled code access 172 | void* dex_cache_initialized_static_storage_; 173 | 174 | // short cuts to declaring_class_->dex_cache_ member for fast compiled code access 175 | void* dex_cache_resolved_methods_; 176 | 177 | // short cuts to declaring_class_->dex_cache_ member for fast compiled code access 178 | void* dex_cache_resolved_types_; 179 | 180 | // short cuts to declaring_class_->dex_cache_ member for fast compiled code access 181 | void* dex_cache_strings_; 182 | 183 | // Access flags; low 16 bits are defined by spec. 184 | uint32_t access_flags_; 185 | 186 | // Offset to the CodeItem. 187 | uint32_t code_item_offset_; 188 | 189 | // Architecture-dependent register spill mask 190 | uint32_t core_spill_mask_; 191 | 192 | // Compiled code associated with this method for callers from managed code. 193 | // May be compiled managed code or a bridge for invoking a native method. 194 | // TODO: Break apart this into portable and quick. 195 | const void* entry_point_from_compiled_code_; 196 | 197 | // Called by the interpreter to execute this method. 198 | void* entry_point_from_interpreter_; 199 | 200 | // Architecture-dependent register spill mask 201 | uint32_t fp_spill_mask_; 202 | 203 | // Total size in bytes of the frame 204 | size_t frame_size_in_bytes_; 205 | 206 | // Garbage collection map of native PC offsets (quick) or dex PCs (portable) to reference bitmaps. 207 | const uint8_t* gc_map_; 208 | 209 | // Mapping from native pc to dex pc 210 | const uint32_t* mapping_table_; 211 | 212 | /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */ 213 | // Offset to the CodeItem. 214 | uint32_t dex_code_item_offset_; 215 | // Index into method_ids of the dex file associated with this method. 216 | uint32_t dex_method_index_; 217 | 218 | // Index into method_ids of the dex file associated with this method 219 | uint32_t method_dex_index_; 220 | 221 | // For concrete virtual methods, this is the offset of the method in Class::vtable_. 222 | // 223 | // For abstract methods in an interface class, this is the offset of the method in 224 | // "iftable_->Get(n)->GetMethodArray()". 225 | // 226 | // For static and direct methods this is the index in the direct methods table. 227 | uint32_t method_index_; 228 | 229 | // The target native method registered with this method 230 | const void* native_method_; 231 | 232 | // When a register is promoted into a register, the spill mask holds which registers hold dex 233 | // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth 234 | // is vmap_table_[N]. vmap_table_[0] holds the length of the table. 235 | const uint16_t* vmap_table_; 236 | 237 | static void* java_lang_reflect_ArtMethod_; 238 | 239 | struct PtrSizedFields { 240 | // Method dispatch from the interpreter invokes this pointer which may cause a bridge into 241 | // compiled code. 242 | void* entry_point_from_interpreter_; 243 | // Pointer to JNI function registered to this method, or a function to resolve the JNI function. 244 | void* entry_point_from_jni_; 245 | // Method dispatch from quick compiled code invokes this pointer which may cause bridging into 246 | // the interpreter. 247 | void* entry_point_from_quick_compiled_code_; 248 | } ptr_sized_fields_; 249 | }; 250 | 251 | } 252 | } 253 | 254 | typedef void* (*artVerifyClass_func) (art::mirror::Class * ,bool, std::string*); 255 | 256 | artVerifyClass_func artVerifyClass_fnPtr; 257 | 258 | 259 | #endif //COMMONDEMO_ART_H 260 | -------------------------------------------------------------------------------- /framenthook/framenthook.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 28 | 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 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/x86_64.cpp: -------------------------------------------------------------------------------- 1 | #ifndef X86_64_CPP_ 2 | #define X86_64_CPP_ 3 | 4 | #include 5 | #include 6 | #include "x86_64.h" 7 | 8 | unsigned char hde64_table[] = { 9 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 10 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 11 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 12 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 13 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 14 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 15 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 16 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 17 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 18 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 19 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 20 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 21 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 22 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 23 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 24 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 25 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 26 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 27 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 28 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 29 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 30 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 31 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 32 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 33 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 34 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 35 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 36 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 37 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 38 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 39 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 40 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 41 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 42 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 43 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 44 | 0x00,0xf0,0x02,0x00 45 | }; 46 | 47 | /* 48 | * Hacker Disassembler Engine 64 C 49 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 50 | * All rights reserved. 51 | * 52 | */ 53 | unsigned int hde64_disasm(const void *code, hde64s *hs) 54 | { 55 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 56 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 57 | uint8_t op64 = 0; 58 | 59 | memset(hs,0,sizeof(hde64s)); 60 | 61 | for (x = 16; x; x--) 62 | switch (c = *p++) { 63 | case 0xf3: 64 | hs->p_rep = c; 65 | pref |= PRE_F3; 66 | break; 67 | case 0xf2: 68 | hs->p_rep = c; 69 | pref |= PRE_F2; 70 | break; 71 | case 0xf0: 72 | hs->p_lock = c; 73 | pref |= PRE_LOCK; 74 | break; 75 | case 0x26: case 0x2e: case 0x36: 76 | case 0x3e: case 0x64: case 0x65: 77 | hs->p_seg = c; 78 | pref |= PRE_SEG; 79 | break; 80 | case 0x66: 81 | hs->p_66 = c; 82 | pref |= PRE_66; 83 | break; 84 | case 0x67: 85 | hs->p_67 = c; 86 | pref |= PRE_67; 87 | break; 88 | default: 89 | goto pref_done; 90 | } 91 | pref_done: 92 | 93 | hs->flags = (uint32_t)pref << 23; 94 | 95 | if (!pref) 96 | pref |= PRE_NONE; 97 | 98 | if ((c & 0xf0) == 0x40) { 99 | hs->flags |= F_PREFIX_REX; 100 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 101 | op64++; 102 | hs->rex_r = (c & 7) >> 2; 103 | hs->rex_x = (c & 3) >> 1; 104 | hs->rex_b = c & 1; 105 | if (((c = *p++) & 0xf0) == 0x40) { 106 | opcode = c; 107 | goto error_opcode; 108 | } 109 | } 110 | 111 | if ((hs->opcode = c) == 0x0f) { 112 | hs->opcode2 = c = *p++; 113 | ht += DELTA_OPCODES; 114 | } else if (c >= 0xa0 && c <= 0xa3) { 115 | op64++; 116 | if (pref & PRE_67) 117 | pref |= PRE_66; 118 | else 119 | pref &= ~PRE_66; 120 | } 121 | 122 | opcode = c; 123 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 124 | 125 | if (cflags == C_ERROR) { 126 | error_opcode: 127 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 128 | cflags = 0; 129 | if ((opcode & -3) == 0x24) 130 | cflags++; 131 | } 132 | 133 | x = 0; 134 | if (cflags & C_GROUP) { 135 | uint16_t t; 136 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 137 | cflags = (uint8_t)t; 138 | x = (uint8_t)(t >> 8); 139 | } 140 | 141 | if (hs->opcode2) { 142 | ht = hde64_table + DELTA_PREFIXES; 143 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 144 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 145 | } 146 | 147 | if (cflags & C_MODRM) { 148 | hs->flags |= F_MODRM; 149 | hs->modrm = c = *p++; 150 | hs->modrm_mod = m_mod = c >> 6; 151 | hs->modrm_rm = m_rm = c & 7; 152 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 153 | 154 | if (x && ((x << m_reg) & 0x80)) 155 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 156 | 157 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 158 | uint8_t t = opcode - 0xd9; 159 | if (m_mod == 3) { 160 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 161 | t = ht[m_reg] << m_rm; 162 | } else { 163 | ht = hde64_table + DELTA_FPU_REG; 164 | t = ht[t] << m_reg; 165 | } 166 | if (t & 0x80) 167 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 168 | } 169 | 170 | if (pref & PRE_LOCK) { 171 | if (m_mod == 3) { 172 | hs->flags |= F_ERROR | F_ERROR_LOCK; 173 | } else { 174 | uint8_t *table_end, op = opcode; 175 | if (hs->opcode2) { 176 | ht = hde64_table + DELTA_OP2_LOCK_OK; 177 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 178 | } else { 179 | ht = hde64_table + DELTA_OP_LOCK_OK; 180 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 181 | op &= -2; 182 | } 183 | for (; ht != table_end; ht++) 184 | if (*ht++ == op) { 185 | if (!((*ht << m_reg) & 0x80)) 186 | goto no_lock_error; 187 | else 188 | break; 189 | } 190 | hs->flags |= F_ERROR | F_ERROR_LOCK; 191 | no_lock_error: 192 | ; 193 | } 194 | } 195 | 196 | if (hs->opcode2) { 197 | switch (opcode) { 198 | case 0x20: case 0x22: 199 | m_mod = 3; 200 | if (m_reg > 4 || m_reg == 1) 201 | goto error_operand; 202 | else 203 | goto no_error_operand; 204 | case 0x21: case 0x23: 205 | m_mod = 3; 206 | if (m_reg == 4 || m_reg == 5) 207 | goto error_operand; 208 | else 209 | goto no_error_operand; 210 | } 211 | } else { 212 | switch (opcode) { 213 | case 0x8c: 214 | if (m_reg > 5) 215 | goto error_operand; 216 | else 217 | goto no_error_operand; 218 | case 0x8e: 219 | if (m_reg == 1 || m_reg > 5) 220 | goto error_operand; 221 | else 222 | goto no_error_operand; 223 | } 224 | } 225 | 226 | if (m_mod == 3) { 227 | uint8_t *table_end; 228 | if (hs->opcode2) { 229 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 230 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 231 | } else { 232 | ht = hde64_table + DELTA_OP_ONLY_MEM; 233 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 234 | } 235 | for (; ht != table_end; ht += 2) 236 | if (*ht++ == opcode) { 237 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 238 | goto error_operand; 239 | else 240 | break; 241 | } 242 | goto no_error_operand; 243 | } else if (hs->opcode2) { 244 | switch (opcode) { 245 | case 0x50: case 0xd7: case 0xf7: 246 | if (pref & (PRE_NONE | PRE_66)) 247 | goto error_operand; 248 | break; 249 | case 0xd6: 250 | if (pref & (PRE_F2 | PRE_F3)) 251 | goto error_operand; 252 | break; 253 | case 0xc5: 254 | goto error_operand; 255 | } 256 | goto no_error_operand; 257 | } else 258 | goto no_error_operand; 259 | 260 | error_operand: 261 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 262 | no_error_operand: 263 | 264 | c = *p++; 265 | if (m_reg <= 1) { 266 | if (opcode == 0xf6) 267 | cflags |= C_IMM8; 268 | else if (opcode == 0xf7) 269 | cflags |= C_IMM_P66; 270 | } 271 | 272 | switch (m_mod) { 273 | case 0: 274 | if (pref & PRE_67) { 275 | if (m_rm == 6) 276 | disp_size = 2; 277 | } else 278 | if (m_rm == 5) 279 | disp_size = 4; 280 | break; 281 | case 1: 282 | disp_size = 1; 283 | break; 284 | case 2: 285 | disp_size = 2; 286 | if (!(pref & PRE_67)) 287 | disp_size <<= 1; 288 | } 289 | 290 | if (m_mod != 3 && m_rm == 4) { 291 | hs->flags |= F_SIB; 292 | p++; 293 | hs->sib = c; 294 | hs->sib_scale = c >> 6; 295 | hs->sib_index = (c & 0x3f) >> 3; 296 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 297 | disp_size = 4; 298 | } 299 | 300 | p--; 301 | switch (disp_size) { 302 | case 1: 303 | hs->flags |= F_DISP8; 304 | hs->disp.disp8 = *p; 305 | break; 306 | case 2: 307 | hs->flags |= F_DISP16; 308 | hs->disp.disp16 = *(uint16_t *)p; 309 | break; 310 | case 4: 311 | hs->flags |= F_DISP32; 312 | hs->disp.disp32 = *(uint32_t *)p; 313 | } 314 | p += disp_size; 315 | } else if (pref & PRE_LOCK) 316 | hs->flags |= F_ERROR | F_ERROR_LOCK; 317 | 318 | if (cflags & C_IMM_P66) { 319 | if (cflags & C_REL32) { 320 | if (pref & PRE_66) { 321 | hs->flags |= F_IMM16 | F_RELATIVE; 322 | hs->imm.imm16 = *(uint16_t *)p; 323 | p += 2; 324 | goto disasm_done; 325 | } 326 | goto rel32_ok; 327 | } 328 | if (op64) { 329 | hs->flags |= F_IMM64; 330 | hs->imm.imm64 = *(uint64_t *)p; 331 | p += 8; 332 | } else if (!(pref & PRE_66)) { 333 | hs->flags |= F_IMM32; 334 | hs->imm.imm32 = *(uint32_t *)p; 335 | p += 4; 336 | } else 337 | goto imm16_ok; 338 | } 339 | 340 | 341 | if (cflags & C_IMM16) { 342 | imm16_ok: 343 | hs->flags |= F_IMM16; 344 | hs->imm.imm16 = *(uint16_t *)p; 345 | p += 2; 346 | } 347 | if (cflags & C_IMM8) { 348 | hs->flags |= F_IMM8; 349 | hs->imm.imm8 = *p++; 350 | } 351 | 352 | if (cflags & C_REL32) { 353 | rel32_ok: 354 | hs->flags |= F_IMM32 | F_RELATIVE; 355 | hs->imm.imm32 = *(uint32_t *)p; 356 | p += 4; 357 | } else if (cflags & C_REL8) { 358 | hs->flags |= F_IMM8 | F_RELATIVE; 359 | hs->imm.imm8 = *p++; 360 | } 361 | 362 | disasm_done: 363 | 364 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 365 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 366 | hs->len = 15; 367 | } 368 | 369 | return (unsigned int)hs->len; 370 | } 371 | 372 | 373 | 374 | #endif /* X86_64_CPP_ */ 375 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/MSHook/Thumb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ARM.h" 3 | #include "Thumb.h" 4 | 5 | static size_t Thumb::MSGetInstructionWidth(void *start) { 6 | if ((reinterpret_cast(start) & 0x1) == 0) 7 | return MSGetInstructionWidthARM(start); 8 | else 9 | return MSGetInstructionWidthThumb(reinterpret_cast(reinterpret_cast(start) & ~0x1)); 10 | } 11 | 12 | void Thumb::SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result){ 13 | if (symbol == NULL) 14 | return; 15 | 16 | uint16_t *area(reinterpret_cast(symbol)); 17 | 18 | unsigned align((reinterpret_cast(area) & 0x2) == 0 ? 0 : 1); 19 | uint16_t *thumb(area + align); 20 | 21 | uint32_t *arm(reinterpret_cast(thumb + 2)); 22 | uint16_t *trail(reinterpret_cast(arm + 2)); 23 | 24 | if ( 25 | (align == 0 || area[0] == T$nop) && 26 | thumb[0] == T$bx(A$pc) && 27 | thumb[1] == T$nop && 28 | arm[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8) 29 | ) { 30 | if (result != NULL) 31 | *result = reinterpret_cast(arm[1]); 32 | 33 | SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1); 34 | 35 | arm[1] = reinterpret_cast(replace); 36 | 37 | return; 38 | } 39 | 40 | size_t required((trail - area) * sizeof(uint16_t)); 41 | 42 | size_t used(0); 43 | while (used < required) 44 | used += MSGetInstructionWidthThumb(reinterpret_cast(area) + used); 45 | used = (used + sizeof(uint16_t) - 1) / sizeof(uint16_t) * sizeof(uint16_t); 46 | 47 | size_t blank((used - required) / sizeof(uint16_t)); 48 | 49 | uint16_t backup[used / sizeof(uint16_t)]; 50 | memcpy(backup, area, used); 51 | 52 | if (MSDebug) { 53 | char name[16]; 54 | sprintf(name, "%p", area); 55 | MSLogHexEx(area, used + sizeof(uint16_t), 2, name); 56 | } 57 | 58 | if (result != NULL) { 59 | 60 | size_t length(used); 61 | for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) 62 | if (T$pcrel$ldr(backup[offset])) 63 | length += 3 * sizeof(uint16_t); 64 | else if (T$pcrel$b(backup[offset])) 65 | length += 6 * sizeof(uint16_t); 66 | else if (T2$pcrel$b(backup + offset)) { 67 | length += 5 * sizeof(uint16_t); 68 | ++offset; 69 | } else if (T$pcrel$bl(backup + offset)) { 70 | length += 5 * sizeof(uint16_t); 71 | ++offset; 72 | } else if (T$pcrel$cbz(backup[offset])) { 73 | length += 16 * sizeof(uint16_t); 74 | } else if (T$pcrel$ldrw(backup[offset])) { 75 | length += 4 * sizeof(uint16_t); 76 | ++offset; 77 | } else if (T$pcrel$add(backup[offset])) 78 | length += 6 * sizeof(uint16_t); 79 | else if (T$32bit$i(backup[offset])) 80 | ++offset; 81 | 82 | unsigned pad((length & 0x2) == 0 ? 0 : 1); 83 | length += (pad + 2) * sizeof(uint16_t) + 2 * sizeof(uint32_t); 84 | 85 | uint16_t *buffer(reinterpret_cast(mmap( 86 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 87 | ))); 88 | 89 | if (buffer == MAP_FAILED) { 90 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 91 | *result = NULL; 92 | return; 93 | } 94 | 95 | if (false) fail: { 96 | munmap(buffer, length); 97 | *result = NULL; 98 | return; 99 | } 100 | 101 | size_t start(pad), end(length / sizeof(uint16_t)); 102 | uint32_t *trailer(reinterpret_cast(buffer + end)); 103 | for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) { 104 | if (T$pcrel$ldr(backup[offset])) { 105 | union { 106 | uint16_t value; 107 | 108 | struct { 109 | uint16_t immediate : 8; 110 | uint16_t rd : 3; 111 | uint16_t : 5; 112 | }; 113 | } bits = {backup[offset+0]}; 114 | 115 | buffer[start+0] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+0, end-2) / 4); 116 | buffer[start+1] = T$ldr_rd_$rn_im_4$(bits.rd, bits.rd, 0); 117 | 118 | // XXX: this code "works", but is "wrong": the mechanism is more complex than this 119 | *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + bits.immediate * 4; 120 | 121 | start += 2; 122 | end -= 2; 123 | } else if (T$pcrel$b(backup[offset])) { 124 | union { 125 | uint16_t value; 126 | 127 | struct { 128 | uint16_t imm8 : 8; 129 | uint16_t cond : 4; 130 | uint16_t /*1101*/ : 4; 131 | }; 132 | } bits = {backup[offset+0]}; 133 | 134 | intptr_t jump(bits.imm8 << 1); 135 | jump |= 1; 136 | jump <<= 23; 137 | jump >>= 23; 138 | 139 | buffer[start+0] = T$b$_$im(bits.cond, (end-6 - (start+0)) * 2 - 4); 140 | 141 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 142 | *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 143 | *--trailer = T$nop << 16 | T$bx(A$pc); 144 | 145 | start += 1; 146 | end -= 6; 147 | } else if (T2$pcrel$b(backup + offset)) { 148 | union { 149 | uint16_t value; 150 | 151 | struct { 152 | uint16_t imm6 : 6; 153 | uint16_t cond : 4; 154 | uint16_t s : 1; 155 | uint16_t : 5; 156 | }; 157 | } bits = {backup[offset+0]}; 158 | 159 | union { 160 | uint16_t value; 161 | 162 | struct { 163 | uint16_t imm11 : 11; 164 | uint16_t j2 : 1; 165 | uint16_t a : 1; 166 | uint16_t j1 : 1; 167 | uint16_t : 2; 168 | }; 169 | } exts = {backup[offset+1]}; 170 | 171 | intptr_t jump(1); 172 | jump |= exts.imm11 << 1; 173 | jump |= bits.imm6 << 12; 174 | 175 | if (exts.a) { 176 | jump |= bits.s << 24; 177 | jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; 178 | jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; 179 | jump |= bits.cond << 18; 180 | jump <<= 7; 181 | jump >>= 7; 182 | } else { 183 | jump |= bits.s << 20; 184 | jump |= exts.j2 << 19; 185 | jump |= exts.j1 << 18; 186 | jump <<= 11; 187 | jump >>= 11; 188 | } 189 | 190 | buffer[start+0] = T$b$_$im(exts.a ? A$al : bits.cond, (end-6 - (start+0)) * 2 - 4); 191 | 192 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 193 | *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 194 | *--trailer = T$nop << 16 | T$bx(A$pc); 195 | 196 | ++offset; 197 | start += 1; 198 | end -= 6; 199 | } else if (T$pcrel$bl(backup + offset)) { 200 | union { 201 | uint16_t value; 202 | 203 | struct { 204 | uint16_t immediate : 10; 205 | uint16_t s : 1; 206 | uint16_t : 5; 207 | }; 208 | } bits = {backup[offset+0]}; 209 | 210 | union { 211 | uint16_t value; 212 | 213 | struct { 214 | uint16_t immediate : 11; 215 | uint16_t j2 : 1; 216 | uint16_t x : 1; 217 | uint16_t j1 : 1; 218 | uint16_t : 2; 219 | }; 220 | } exts = {backup[offset+1]}; 221 | 222 | int32_t jump(0); 223 | jump |= bits.s << 24; 224 | jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; 225 | jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; 226 | jump |= bits.immediate << 12; 227 | jump |= exts.immediate << 1; 228 | jump |= exts.x; 229 | jump <<= 7; 230 | jump >>= 7; 231 | 232 | buffer[start+0] = T$push_r(1 << A$r7); 233 | buffer[start+1] = T$ldr_rd_$pc_im_4$(A$r7, ((end-2 - (start+1)) * 2 - 4 + 2) / 4); 234 | buffer[start+2] = T$mov_rd_rm(A$lr, A$r7); 235 | buffer[start+3] = T$pop_r(1 << A$r7); 236 | buffer[start+4] = T$blx(A$lr); 237 | 238 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 239 | 240 | ++offset; 241 | start += 5; 242 | end -= 2; 243 | } else if (T$pcrel$cbz(backup[offset])) { 244 | union { 245 | uint16_t value; 246 | 247 | struct { 248 | uint16_t rn : 3; 249 | uint16_t immediate : 5; 250 | uint16_t : 1; 251 | uint16_t i : 1; 252 | uint16_t : 1; 253 | uint16_t op : 1; 254 | uint16_t : 4; 255 | }; 256 | } bits = {backup[offset+0]}; 257 | 258 | intptr_t jump(1); 259 | jump |= bits.i << 6; 260 | jump |= bits.immediate << 1; 261 | 262 | //jump <<= 24; 263 | //jump >>= 24; 264 | 265 | unsigned rn(bits.rn); 266 | unsigned rt(rn == A$r7 ? A$r6 : A$r7); 267 | 268 | buffer[start+0] = T$push_r(1 << rt); 269 | buffer[start+1] = T1$mrs_rd_apsr(rt); 270 | buffer[start+2] = T2$mrs_rd_apsr(rt); 271 | buffer[start+3] = T$cbz$_rn_$im(bits.op, rn, (end-10 - (start+3)) * 2 - 4); 272 | buffer[start+4] = T1$msr_apsr_nzcvqg_rn(rt); 273 | buffer[start+5] = T2$msr_apsr_nzcvqg_rn(rt); 274 | buffer[start+6] = T$pop_r(1 << rt); 275 | 276 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 277 | *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 278 | *--trailer = T$nop << 16 | T$bx(A$pc); 279 | *--trailer = T$nop << 16 | T$pop_r(1 << rt); 280 | *--trailer = T$msr_apsr_nzcvqg_rn(rt); 281 | 282 | #if 0 283 | if ((start & 0x1) == 0) 284 | buffer[start++] = T$nop; 285 | buffer[start++] = T$bx(A$pc); 286 | buffer[start++] = T$nop; 287 | 288 | uint32_t *arm(reinterpret_cast(buffer + start)); 289 | arm[0] = A$add(A$lr, A$pc, 1); 290 | arm[1] = A$ldr_rd_$rn_im$(A$pc, A$pc, (trailer - arm) * sizeof(uint32_t) - 8); 291 | #endif 292 | 293 | start += 7; 294 | end -= 10; 295 | } else if (T$pcrel$ldrw(backup[offset])) { 296 | union { 297 | uint16_t value; 298 | 299 | struct { 300 | uint16_t : 7; 301 | uint16_t u : 1; 302 | uint16_t : 8; 303 | }; 304 | } bits = {backup[offset+0]}; 305 | 306 | union { 307 | uint16_t value; 308 | 309 | struct { 310 | uint16_t immediate : 12; 311 | uint16_t rt : 4; 312 | }; 313 | } exts = {backup[offset+1]}; 314 | 315 | buffer[start+0] = T1$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); 316 | buffer[start+1] = T2$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); 317 | 318 | buffer[start+2] = T1$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); 319 | buffer[start+3] = T2$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); 320 | 321 | // XXX: this code "works", but is "wrong": the mechanism is more complex than this 322 | *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + (bits.u == 0 ? -exts.immediate : exts.immediate); 323 | 324 | ++offset; 325 | start += 4; 326 | end -= 2; 327 | } else if (T$pcrel$add(backup[offset])) { 328 | union { 329 | uint16_t value; 330 | 331 | struct { 332 | uint16_t rd : 3; 333 | uint16_t rm : 3; 334 | uint16_t h2 : 1; 335 | uint16_t h1 : 1; 336 | uint16_t : 8; 337 | }; 338 | } bits = {backup[offset+0]}; 339 | 340 | if (bits.h1) { 341 | MSLog(MSLogLevelError, "MS:Error:pcrel(%u):add (rd > r7)", offset); 342 | goto fail; 343 | } 344 | 345 | unsigned rt(bits.rd == A$r7 ? A$r6 : A$r7); 346 | 347 | buffer[start+0] = T$push_r(1 << rt); 348 | buffer[start+1] = T$mov_rd_rm(rt, (bits.h1 << 3) | bits.rd); 349 | buffer[start+2] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+2, end-2) / 4); 350 | buffer[start+3] = T$add_rd_rm((bits.h1 << 3) | bits.rd, rt); 351 | buffer[start+4] = T$pop_r(1 << rt); 352 | *--trailer = reinterpret_cast(area + offset) + 4; 353 | 354 | start += 5; 355 | end -= 2; 356 | } else if (T$32bit$i(backup[offset])) { 357 | buffer[start++] = backup[offset]; 358 | buffer[start++] = backup[++offset]; 359 | } else { 360 | buffer[start++] = backup[offset]; 361 | } 362 | } 363 | 364 | buffer[start++] = T$bx(A$pc); 365 | buffer[start++] = T$nop; 366 | 367 | uint32_t *transfer = reinterpret_cast(buffer + start); 368 | transfer[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 369 | transfer[1] = reinterpret_cast(area + used / sizeof(uint16_t)) + 1; 370 | 371 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 372 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 373 | return; 374 | } 375 | 376 | *result = reinterpret_cast(buffer + pad) + 1; 377 | 378 | if (MSDebug) { 379 | char name[16]; 380 | sprintf(name, "%p", *result); 381 | MSLogHexEx(buffer, length, 2, name); 382 | } 383 | 384 | } 385 | 386 | { 387 | SubstrateHookMemory code(process, area, used); 388 | 389 | if (align != 0) 390 | area[0] = T$nop; 391 | 392 | thumb[0] = T$bx(A$pc); 393 | thumb[1] = T$nop; 394 | 395 | arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 396 | arm[1] = reinterpret_cast(replace); 397 | 398 | for (unsigned offset(0); offset != blank; ++offset) 399 | trail[offset] = T$nop; 400 | } 401 | 402 | if (MSDebug) { 403 | char name[16]; 404 | sprintf(name, "%p", area); 405 | MSLogHexEx(area, used + sizeof(uint16_t), 2, name); 406 | } 407 | } 408 | 409 | -------------------------------------------------------------------------------- /framenthook/src/main/cpp/Android-Inline/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 "relocate.h" 11 | 12 | #define ALIGN_PC(pc) (pc & 0xFFFFFFFC) 13 | 14 | enum INSTRUCTION_TYPE { 15 | // B