├── .gitattributes ├── .gitignore ├── README.md └── jni ├── Android.mk ├── Application.mk ├── LL.cpp ├── LL.h ├── Substrate ├── CydiaSubstrate.h ├── SubstrateARM.hpp ├── SubstrateDebug.cpp ├── SubstrateDebug.hpp ├── SubstrateHook.cpp ├── SubstrateHook.h ├── SubstrateLog.hpp ├── SubstratePosixMemory.cpp ├── SubstrateX86.hpp ├── hde64.c ├── hde64.h └── table64.h ├── libcrypt.a └── loader ├── Loader.cpp ├── Loader.h ├── solist.h ├── utils.cpp └── utils.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | 38 | # Keystore files 39 | *.jks 40 | 41 | # ========================= 42 | # Operating System Files 43 | # ========================= 44 | 45 | # OSX 46 | # ========================= 47 | 48 | .DS_Store 49 | .AppleDouble 50 | .LSOverride 51 | 52 | # Thumbnails 53 | ._* 54 | 55 | # Files that might appear in the root of a volume 56 | .DocumentRevisions-V100 57 | .fseventsd 58 | .Spotlight-V100 59 | .TemporaryItems 60 | .Trashes 61 | .VolumeIcon.icns 62 | 63 | # Directories potentially created on remote AFP share 64 | .AppleDB 65 | .AppleDesktop 66 | Network Trash Folder 67 | Temporary Items 68 | .apdisk 69 | 70 | # Windows 71 | # ========================= 72 | 73 | # Windows image file caches 74 | Thumbs.db 75 | ehthumbs.db 76 | 77 | # Folder config file 78 | Desktop.ini 79 | 80 | # Recycle Bin used on file shares 81 | $RECYCLE.BIN/ 82 | 83 | # Windows Installer files 84 | *.cab 85 | *.msi 86 | *.msm 87 | *.msp 88 | 89 | # Windows shortcuts 90 | *.lnk 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | -主要功能实现了无模块加载so库 2 | 3 | -hook dlsym 对第三方apk中so库的无源码劫持加载 4 | 5 | -thanks thomasking 6 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE := core_substrate 5 | LOCAL_SRC_FILES := Substrate/hde64.c \ 6 | Substrate/SubstrateDebug.cpp \ 7 | Substrate/SubstrateHook.cpp \ 8 | Substrate/SubstratePosixMemory.cpp 9 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/Substrate 10 | LOCAL_EXPORT_LDLIBS := -llog 11 | include $(BUILD_STATIC_LIBRARY) 12 | 13 | include $(CLEAR_VARS) 14 | LOCAL_MODULE := ll-loader 15 | LOCAL_SRC_FILES := LL.cpp \ 16 | loader/loader.cpp\ 17 | loader/utils.cpp 18 | LOCAL_STATIC_LIBRARIES := core_substrate 19 | LOCAL_LDLIBS := -llog 20 | LOCAL_LDLIBS += -ldl 21 | LOCAL_CFLAGS := -Wall -fno-unwind-tables -fvisibility=hidden -fpermissive 22 | include $(BUILD_SHARED_LIBRARY) 23 | 24 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_CFLAGS += -fexceptions 2 | APP_STL := gnustl_static 3 | APP_ABI := armeabi armeabi-v7a -------------------------------------------------------------------------------- /jni/LL.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | * File : LL.cpp 4 | * Description : mem_loader 内存加载 5 | * Creation : 2015.8.5 6 | * Author : ll-hack 7 | * History : 8 | * 9 | ****************************************************************************** 10 | **/ 11 | 12 | #include "LL.h" 13 | #include 14 | #include "loader/utils.h" 15 | //#include "hookAnti.h" 16 | 17 | #define NAMESIZE 256 18 | 19 | loader ld; 20 | /* 21 | * export func as self linker 22 | */ 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | __attribute__((visibility("hidden"))) soinfo* Ex_dlopen(char *path) 28 | { 29 | return ld.LL_dlopen(path); 30 | } 31 | 32 | __attribute__((visibility("hidden"))) soinfo* Ex_dlopenwitBuffer(unsigned char*buffer,int nSize) 33 | { 34 | 35 | soinfo* siRet = NULL; 36 | 37 | if (nSize>0) 38 | { 39 | unsigned char* alignBuffer = (unsigned char*)mmap(NULL, nSize, PROT_READ | PROT_EXEC | PROT_WRITE, 40 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 41 | if (alignBuffer != NULL) 42 | { 43 | memcpy(alignBuffer, (const void*)buffer, nSize); 44 | 45 | siRet = ld.LL_dlopenwitBuffer(SELFNAME, alignBuffer); 46 | 47 | munmap(alignBuffer, nSize); 48 | } 49 | } 50 | return siRet; 51 | } 52 | 53 | __attribute__((visibility("hidden"))) unsigned Ex_dlsym(soinfo *si, char *func_name) 54 | { 55 | return ld.LL_dlsym(si, func_name); 56 | } 57 | 58 | 59 | __attribute__((visibility("hidden"))) int Ex_dlclose(soinfo *si) 60 | { 61 | 62 | return ld.LL_dlcolse(si); 63 | } 64 | 65 | __attribute__((visibility("default"))) void fuckin() 66 | { 67 | initLoader(); 68 | } 69 | 70 | typedef int(*MAIN)(int argc, char**argv); 71 | int main(int argc, char**argv) 72 | { 73 | MAIN pmain; 74 | soinfo *si=Ex_dlopen(argv[1]); 75 | unsigned pp = Ex_dlsym(si, "main"); 76 | pmain = (MAIN)pp; 77 | pmain(argc, argv); 78 | return 0; 79 | } 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /jni/LL.h: -------------------------------------------------------------------------------- 1 | #ifndef _LL_H 2 | #define _LL_H 3 | 4 | #include "loader/Loader.h" 5 | #include 6 | #include 7 | #include "Substrate/SubstrateHook.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | soinfo* Ex_dlopen(char *path); 14 | unsigned Ex_dlsym(soinfo *si, char *func_name); 15 | int Ex_dlclose(soinfo *si); 16 | soinfo* Ex_dlopenwitBuffer(unsigned char*buffer, int nSize); 17 | void initShell(); 18 | void destuctShell(); 19 | unsigned Ex_dlsym_shell(soinfo *si, char *func_name); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | struct symTab 26 | { 27 | char symName[256]; 28 | uint32_t symAddr; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /jni/Substrate/CydiaSubstrate.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_H_ 23 | #define SUBSTRATE_H_ 24 | 25 | #ifdef __APPLE__ 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | #include 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #include 35 | #include 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | #define _finline \ 42 | inline __attribute__((__always_inline__)) 43 | #define _disused \ 44 | __attribute__((__unused__)) 45 | 46 | #define _extern \ 47 | extern "C" __attribute__((__visibility__("default"))) 48 | 49 | #ifdef __cplusplus 50 | #define _default(value) = value 51 | #else 52 | #define _default(value) 53 | #endif 54 | 55 | #ifdef __cplusplus 56 | extern "C" { 57 | #endif 58 | 59 | bool MSHookProcess(pid_t pid, const char *library); 60 | 61 | typedef const void *MSImageRef; 62 | 63 | MSImageRef MSGetImageByName(const char *file); 64 | void *MSFindSymbol(MSImageRef image, const char *name); 65 | 66 | void MSHookFunction(void *symbol, void *replace, void **result); 67 | 68 | #ifdef __APPLE__ 69 | #ifdef __arm__ 70 | __attribute__((__deprecated__)) 71 | IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); 72 | #endif 73 | void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); 74 | #endif 75 | 76 | #ifdef SubstrateInternal 77 | typedef void *SubstrateAllocatorRef; 78 | typedef struct __SubstrateProcess *SubstrateProcessRef; 79 | typedef struct __SubstrateMemory *SubstrateMemoryRef; 80 | 81 | SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid); 82 | void SubstrateProcessRelease(SubstrateProcessRef process); 83 | 84 | SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); 85 | void SubstrateMemoryRelease(SubstrateMemoryRef memory); 86 | #endif 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | 94 | #ifdef SubstrateInternal 95 | struct SubstrateHookMemory { 96 | SubstrateMemoryRef handle_; 97 | 98 | SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : 99 | handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) 100 | { 101 | } 102 | 103 | ~SubstrateHookMemory() { 104 | if (handle_ != NULL) 105 | SubstrateMemoryRelease(handle_); 106 | } 107 | }; 108 | #endif 109 | 110 | #ifdef __APPLE__ 111 | 112 | namespace etl { 113 | 114 | template 115 | struct Case { 116 | static char value[Case_ + 1]; 117 | }; 118 | 119 | typedef Case Yes; 120 | typedef Case No; 121 | 122 | namespace be { 123 | template 124 | static Yes CheckClass_(void (Checked_::*)()); 125 | 126 | template 127 | static No CheckClass_(...); 128 | } 129 | 130 | template 131 | struct IsClass { 132 | void gcc32(); 133 | 134 | static const bool value = (sizeof(be::CheckClass_(0).value) == sizeof(Yes::value)); 135 | }; 136 | 137 | } 138 | 139 | #ifdef __arm__ 140 | template 141 | __attribute__((__deprecated__)) 142 | static inline Type_ *MSHookMessage(Class _class, SEL sel, Type_ *imp, const char *prefix = NULL) { 143 | return reinterpret_cast(MSHookMessage(_class, sel, reinterpret_cast(imp), prefix)); 144 | } 145 | #endif 146 | 147 | template 148 | static inline void MSHookMessage(Class _class, SEL sel, Type_ *imp, Type_ **result) { 149 | return MSHookMessageEx(_class, sel, reinterpret_cast(imp), reinterpret_cast(result)); 150 | } 151 | 152 | template 153 | static inline Type_ &MSHookIvar(id self, const char *name) { 154 | Ivar ivar(class_getInstanceVariable(object_getClass(self), name)); 155 | void *pointer(ivar == NULL ? NULL : reinterpret_cast(self) + ivar_getOffset(ivar)); 156 | return *reinterpret_cast(pointer); 157 | } 158 | 159 | #define MSAddMessage0(_class, type, arg0) \ 160 | class_addMethod($ ## _class, @selector(arg0), (IMP) &$ ## _class ## $ ## arg0, type); 161 | #define MSAddMessage1(_class, type, arg0) \ 162 | class_addMethod($ ## _class, @selector(arg0:), (IMP) &$ ## _class ## $ ## arg0 ## $, type); 163 | #define MSAddMessage2(_class, type, arg0, arg1) \ 164 | class_addMethod($ ## _class, @selector(arg0:arg1:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $, type); 165 | #define MSAddMessage3(_class, type, arg0, arg1, arg2) \ 166 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $, type); 167 | #define MSAddMessage4(_class, type, arg0, arg1, arg2, arg3) \ 168 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $, type); 169 | #define MSAddMessage5(_class, type, arg0, arg1, arg2, arg3, arg4) \ 170 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $, type); 171 | #define MSAddMessage6(_class, type, arg0, arg1, arg2, arg3, arg4, arg5) \ 172 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $, type); 173 | 174 | #define MSHookMessage0(_class, arg0) \ 175 | MSHookMessage($ ## _class, @selector(arg0), MSHake(_class ## $ ## arg0)) 176 | #define MSHookMessage1(_class, arg0) \ 177 | MSHookMessage($ ## _class, @selector(arg0:), MSHake(_class ## $ ## arg0 ## $)) 178 | #define MSHookMessage2(_class, arg0, arg1) \ 179 | MSHookMessage($ ## _class, @selector(arg0:arg1:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $)) 180 | #define MSHookMessage3(_class, arg0, arg1, arg2) \ 181 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $)) 182 | #define MSHookMessage4(_class, arg0, arg1, arg2, arg3) \ 183 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $)) 184 | #define MSHookMessage5(_class, arg0, arg1, arg2, arg3, arg4) \ 185 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $)) 186 | #define MSHookMessage6(_class, arg0, arg1, arg2, arg3, arg4, arg5) \ 187 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $)) 188 | 189 | #define MSRegister_(name, dollar, colon) \ 190 | static class C_$ ## name ## $ ## dollar { public: _finline C_$ ## name ## $ ##dollar() { \ 191 | MSHookMessage($ ## name, @selector(colon), MSHake(name ## $ ## dollar)); \ 192 | } } V_$ ## name ## $ ## dollar; \ 193 | 194 | #define MSIgnore_(name, dollar, colon) 195 | 196 | #define MSMessage_(extra, type, _class, name, dollar, colon, call, args...) \ 197 | static type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args); \ 198 | MSHook(type, name ## $ ## dollar, _class self, SEL _cmd, ## args) { \ 199 | Class const _cls($ ## name); \ 200 | type (* const _old)(_class, SEL, ## args, ...) = reinterpret_cast(_ ## name ## $ ## dollar); \ 201 | typedef type (*msgSendSuper_t)(struct objc_super *, SEL, ## args, ...); \ 202 | msgSendSuper_t const _spr(::etl::IsClass::value ? reinterpret_cast(&objc_msgSendSuper_stret) : reinterpret_cast(&objc_msgSendSuper)); \ 203 | return _$ ## name ## $ ## dollar call; \ 204 | } \ 205 | extra(name, dollar, colon) \ 206 | static _finline type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args) 207 | 208 | /* for((x=1;x!=7;++x)){ echo -n "#define MSMessage${x}_(extra, type, _class, name";for((y=0;y!=x;++y));do echo -n ", sel$y";done;for((y=0;y!=x;++y));do echo -n ", type$y, arg$y";done;echo ") \\";echo -n " MSMessage_(extra, type, _class, name,";for((y=0;y!=x;++y));do if [[ $y -ne 0 ]];then echo -n " ##";fi;echo -n " sel$y ## $";done;echo -n ", ";for((y=0;y!=x;++y));do echo -n "sel$y:";done;echo -n ", (_cls, _old, _spr, self, _cmd";for((y=0;y!=x;++y));do echo -n ", arg$y";done;echo -n ")";for((y=0;y!=x;++y));do echo -n ", type$y arg$y";done;echo ")";} */ 209 | 210 | #define MSMessage0_(extra, type, _class, name, sel0) \ 211 | MSMessage_(extra, type, _class, name, sel0, sel0, (_cls, _old, _spr, self, _cmd)) 212 | #define MSMessage1_(extra, type, _class, name, sel0, type0, arg0) \ 213 | MSMessage_(extra, type, _class, name, sel0 ## $, sel0:, (_cls, _old, _spr, self, _cmd, arg0), type0 arg0) 214 | #define MSMessage2_(extra, type, _class, name, sel0, sel1, type0, arg0, type1, arg1) \ 215 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $, sel0:sel1:, (_cls, _old, _spr, self, _cmd, arg0, arg1), type0 arg0, type1 arg1) 216 | #define MSMessage3_(extra, type, _class, name, sel0, sel1, sel2, type0, arg0, type1, arg1, type2, arg2) \ 217 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $, sel0:sel1:sel2:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2), type0 arg0, type1 arg1, type2 arg2) 218 | #define MSMessage4_(extra, type, _class, name, sel0, sel1, sel2, sel3, type0, arg0, type1, arg1, type2, arg2, type3, arg3) \ 219 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $, sel0:sel1:sel2:sel3:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3), type0 arg0, type1 arg1, type2 arg2, type3 arg3) 220 | #define MSMessage5_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ 221 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $, sel0:sel1:sel2:sel3:sel4:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4) 222 | #define MSMessage6_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, sel5, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ 223 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $ ## sel5 ## $, sel0:sel1:sel2:sel3:sel4:sel5:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4, arg5), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 224 | 225 | #define MSInstanceMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, _class *, _class, ## args) 226 | #define MSInstanceMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, _class *, _class, ## args) 227 | #define MSInstanceMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, _class *, _class, ## args) 228 | #define MSInstanceMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, _class *, _class, ## args) 229 | #define MSInstanceMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, _class *, _class, ## args) 230 | #define MSInstanceMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, _class *, _class, ## args) 231 | #define MSInstanceMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, _class *, _class, ## args) 232 | 233 | #define MSClassMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, Class, $ ## _class, ## args) 234 | #define MSClassMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, Class, $ ## _class, ## args) 235 | #define MSClassMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, Class, $ ## _class, ## args) 236 | #define MSClassMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, Class, $ ## _class, ## args) 237 | #define MSClassMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, Class, $ ## _class, ## args) 238 | #define MSClassMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, Class, $ ## _class, ## args) 239 | #define MSClassMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, Class, $ ## _class, ## args) 240 | 241 | #define MSInstanceMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, _class *, _class, ## args) 242 | #define MSInstanceMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, _class *, _class, ## args) 243 | #define MSInstanceMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, _class *, _class, ## args) 244 | #define MSInstanceMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, _class *, _class, ## args) 245 | #define MSInstanceMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, _class *, _class, ## args) 246 | #define MSInstanceMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, _class *, _class, ## args) 247 | #define MSInstanceMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, _class *, _class, ## args) 248 | 249 | #define MSClassMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, Class, $ ## _class, ## args) 250 | #define MSClassMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, Class, $ ## _class, ## args) 251 | #define MSClassMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, Class, $ ## _class, ## args) 252 | #define MSClassMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, Class, $ ## _class, ## args) 253 | #define MSClassMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, Class, $ ## _class, ## args) 254 | #define MSClassMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, Class, $ ## _class, ## args) 255 | #define MSClassMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, Class, $ ## _class, ## args) 256 | 257 | #define MSOldCall(args...) \ 258 | _old(self, _cmd, ## args) 259 | #define MSSuperCall(args...) \ 260 | _spr(& (struct objc_super) {self, class_getSuperclass(_cls)}, _cmd, ## args) 261 | 262 | #define MSIvarHook(type, name) \ 263 | type &name(MSHookIvar(self, #name)) 264 | 265 | #define MSClassHook(name) \ 266 | @class name; \ 267 | static Class $ ## name = objc_getClass(#name); 268 | #define MSMetaClassHook(name) \ 269 | @class name; \ 270 | static Class $$ ## name = object_getClass($ ## name); 271 | 272 | #endif/*__APPLE__*/ 273 | 274 | template 275 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { 276 | return MSHookFunction( 277 | reinterpret_cast(symbol), 278 | reinterpret_cast(replace), 279 | reinterpret_cast(result) 280 | ); 281 | } 282 | 283 | template 284 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { 285 | return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); 286 | } 287 | 288 | template 289 | static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { 290 | value = reinterpret_cast(MSFindSymbol(image, name)); 291 | } 292 | 293 | template 294 | static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { 295 | Type_ *symbol; 296 | MSHookSymbol(symbol, name); 297 | return MSHookFunction(symbol, replace, result); 298 | } 299 | 300 | #endif 301 | 302 | #define MSHook(type, name, args...) \ 303 | _disused static type (*_ ## name)(args); \ 304 | static type $ ## name(args) 305 | 306 | #ifdef __cplusplus 307 | #define MSHake(name) \ 308 | &$ ## name, &_ ## name 309 | #else 310 | #define MSHake(name) \ 311 | &$ ## name, (void **) &_ ## name 312 | #endif 313 | 314 | #define MSInitialize \ 315 | __attribute__((__constructor__)) static void _MSInitialize(void) 316 | 317 | #define Foundation_f "/System/Library/Frameworks/Foundation.framework/Foundation" 318 | #define UIKit_f "/System/Library/Frameworks/UIKit.framework/UIKit" 319 | #define JavaScriptCore_f "/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore" 320 | #define IOKit_f "/System/Library/Frameworks/IOKit.framework/IOKit" 321 | 322 | #endif//SUBSTRATE_H_ 323 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateARM.hpp: -------------------------------------------------------------------------------- 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 | enum A$r { 26 | A$r0, A$r1, A$r2, A$r3, 27 | A$r4, A$r5, A$r6, A$r7, 28 | A$r8, A$r9, A$r10, A$r11, 29 | A$r12, A$r13, A$r14, A$r15, 30 | A$sp = A$r13, 31 | A$lr = A$r14, 32 | A$pc = A$r15 33 | }; 34 | 35 | enum A$c { 36 | A$eq, A$ne, A$cs, A$cc, 37 | A$mi, A$pl, A$vs, A$vc, 38 | A$hi, A$ls, A$ge, A$lt, 39 | A$gt, A$le, A$al, 40 | A$hs = A$cs, 41 | A$lo = A$cc 42 | }; 43 | 44 | #define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ 45 | (0xe10f0000 | ((rd) << 12)) 46 | #define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ 47 | (0xe128f000 | (rm)) 48 | #define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ 49 | (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 50 | #define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ 51 | (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 52 | #define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ 53 | (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) 54 | #define A$blx_rm(rm) /* blx rm */ \ 55 | (0xe12fff30 | (rm)) 56 | #define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ 57 | (0xe1a00000 | ((rd) << 12) | (rm)) 58 | #define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ 59 | (0xe8b00000 | (A$sp << 16) | (rs)) 60 | #define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ 61 | (0xe9200000 | (A$sp << 16) | (rs)) 62 | #define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ 63 | #define A$bx_r0 0xe12fff10 /* bx r0 */ 64 | 65 | #endif//SUBSTRATE_ARM_HPP 66 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateDebug.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 "SubstrateHook.h" 23 | #include "SubstrateDebug.hpp" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | _extern bool MSDebug; 30 | bool MSDebug = true; 31 | 32 | static char _MSHexChar(uint8_t value) { 33 | return value < 0x20 || value >= 0x80 ? '.' : value; 34 | } 35 | 36 | #define HexWidth_ 16 37 | #define HexDepth_ 4 38 | 39 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { 40 | const uint8_t *data((const uint8_t *) vdata); 41 | 42 | size_t i(0), j; 43 | 44 | char d[256]; 45 | size_t b(0); 46 | d[0] = '\0'; 47 | 48 | while (i != size) { 49 | if (i % HexWidth_ == 0) { 50 | if (mark != NULL) 51 | b += sprintf(d + b, "[%s] ", mark); 52 | b += sprintf(d + b, "0x%.3zx:", i); 53 | } 54 | 55 | b += sprintf(d + b, " "); 56 | 57 | for (size_t q(0); q != stride; ++q) 58 | b += sprintf(d + b, "%.2x", data[i + stride - q - 1]); 59 | 60 | i += stride; 61 | 62 | for (size_t q(1); q != stride; ++q) 63 | b += sprintf(d + b, " "); 64 | 65 | if (i % HexDepth_ == 0) 66 | b += sprintf(d + b, " "); 67 | 68 | if (i % HexWidth_ == 0) { 69 | b += sprintf(d + b, " "); 70 | for (j = i - HexWidth_; j != i; ++j) 71 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 72 | 73 | lprintf("%s", d); 74 | b = 0; 75 | d[0] = '\0'; 76 | } 77 | } 78 | 79 | if (i % HexWidth_ != 0) { 80 | for (j = i % HexWidth_; j != HexWidth_; ++j) 81 | b += sprintf(d + b, " "); 82 | for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) 83 | b += sprintf(d + b, " "); 84 | b += sprintf(d + b, " "); 85 | for (j = i / HexWidth_ * HexWidth_; j != i; ++j) 86 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 87 | 88 | lprintf("%s", d); 89 | b = 0; 90 | d[0] = '\0'; 91 | } 92 | } 93 | 94 | void MSLogHex(const void *vdata, size_t size, const char *mark) { 95 | return MSLogHexEx(vdata, size, 1, mark); 96 | } 97 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateDebug.hpp: -------------------------------------------------------------------------------- 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 "SubstrateLog.hpp" 26 | #define lprintf(format, ...) \ 27 | MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) 28 | 29 | extern "C" bool MSDebug; 30 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); 31 | void MSLogHex(const void *vdata, size_t size, const char *mark = 0); 32 | 33 | #endif//SUBSTRATE_DEBUG_HPP 34 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateHook.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 | #define SubstrateInternal 23 | #include "CydiaSubstrate.h" 24 | 25 | #include 26 | 27 | #define _trace() do { \ 28 | MSLog(MSLogLevelNotice, "_trace(%u)", __LINE__); \ 29 | } while (false) 30 | 31 | #if defined(__i386__) || defined(__x86_64__) 32 | #include "hde64.h" 33 | #endif 34 | 35 | #include "SubstrateDebug.hpp" 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef __arm__ 42 | /* WebCore (ARM) PC-Relative: 43 | X 1 ldr r*,[pc,r*] != 44 | 2 fldd d*,[pc,#*] 45 | X 5 str r*,[pc,r*] != 46 | 8 flds s*,[pc,#*] 47 | 400 ldr r*,[pc,r*] == 48 | 515 add r*, pc,r* == 49 | X 4790 ldr r*,[pc,#*] */ 50 | 51 | // x=0; while IFS= read -r line; do if [[ ${#line} -ne 0 && $line == +([^\;]): ]]; then x=2; elif [[ $line == ' +'* && $x -ne 0 ]]; then ((--x)); echo "$x${line}"; fi; done WebCore.pc 52 | // grep pc WebCore.pc | cut -c 40- | sed -Ee 's/^ldr *(ip|r[0-9]*),\[pc,\#0x[0-9a-f]*\].*/ ldr r*,[pc,#*]/;s/^add *r[0-9]*,pc,r[0-9]*.*/ add r*, pc,r*/;s/^(st|ld)r *r([0-9]*),\[pc,r([0-9]*)\].*/ \1r r\2,[pc,r\3]/;s/^fld(s|d) *(s|d)[0-9]*,\[pc,#0x[0-9a-f]*].*/fld\1 \2*,[pc,#*]/' | sort | uniq -c | sort -n 53 | 54 | #include "SubstrateARM.hpp" 55 | 56 | #define T$Label(l, r) \ 57 | (((r) - (l)) * 2 - 4 + ((l) % 2 == 0 ? 0 : 2)) 58 | 59 | #define T$pop_$r0$ 0xbc01 // pop {r0} 60 | #define T$b(im) /* b im */ \ 61 | (0xde00 | (im & 0xff)) 62 | #define T$blx(rm) /* blx rm */ \ 63 | (0x4780 | (rm << 3)) 64 | #define T$bx(rm) /* bx rm */ \ 65 | (0x4700 | (rm << 3)) 66 | #define T$nop /* nop */ \ 67 | (0x46c0) 68 | 69 | #define T$add_rd_rm(rd, rm) /* add rd, rm */ \ 70 | (0x4400 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) 71 | #define T$push_r(r) /* push r... */ \ 72 | (0xb400 | (((r) & (1 << A$lr)) >> A$lr << 8) | ((r) & 0xff)) 73 | #define T$pop_r(r) /* pop r... */ \ 74 | (0xbc00 | (((r) & (1 << A$pc)) >> A$pc << 8) | ((r) & 0xff)) 75 | #define T$mov_rd_rm(rd, rm) /* mov rd, rm */ \ 76 | (0x4600 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) 77 | #define T$ldr_rd_$rn_im_4$(rd, rn, im) /* ldr rd, [rn, #im * 4] */ \ 78 | (0x6800 | (((im) & 0x1f) << 6) | ((rn) << 3) | (rd)) 79 | #define T$ldr_rd_$pc_im_4$(rd, im) /* ldr rd, [PC, #im * 4] */ \ 80 | (0x4800 | ((rd) << 8) | ((im) & 0xff)) 81 | #define T$cmp_rn_$im(rn, im) /* cmp rn, #im */ \ 82 | (0x2000 | ((rn) << 8) | ((im) & 0xff)) 83 | #define T$it$_cd(cd, ms) /* it, cd */ \ 84 | (0xbf00 | ((cd) << 4) | (ms)) 85 | #define T$cbz$_rn_$im(op,rn,im) /* cbz rn, #im */ \ 86 | (0xb100 | ((op) << 11) | (((im) & 0x40) >> 6 << 9) | (((im) & 0x3e) >> 1 << 3) | (rn)) 87 | #define T$b$_$im(cond,im) /* b #im */ \ 88 | (cond == A$al ? 0xe000 | (((im) >> 1) & 0x7ff) : 0xd000 | ((cond) << 8) | (((im) >> 1) & 0xff)) 89 | 90 | #define T1$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ 91 | (0xf850 | ((im < 0 ? 0 : 1) << 7) | (rn)) 92 | #define T2$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ 93 | (((rt) << 12) | abs(im)) 94 | 95 | #define T1$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ 96 | (0xf3ef) 97 | #define T2$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ 98 | (0x8000 | ((rd) << 8)) 99 | 100 | #define T1$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ 101 | (0xf380 | (rn)) 102 | #define T2$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ 103 | (0x8c00) 104 | #define T$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ 105 | (T2$msr_apsr_nzcvqg_rn(rn) << 16 | T1$msr_apsr_nzcvqg_rn(rn)) 106 | 107 | static inline bool A$pcrel$r(uint32_t ic) { 108 | return (ic & 0x0c000000) == 0x04000000 && (ic & 0xf0000000) != 0xf0000000 && (ic & 0x000f0000) == 0x000f0000; 109 | } 110 | 111 | static inline bool T$32bit$i(uint16_t ic) { 112 | return ((ic & 0xe000) == 0xe000 && (ic & 0x1800) != 0x0000); 113 | } 114 | 115 | static inline bool T$pcrel$cbz(uint16_t ic) { 116 | return (ic & 0xf500) == 0xb100; 117 | } 118 | 119 | static inline bool T$pcrel$b(uint16_t ic) { 120 | return (ic & 0xf000) == 0xd000 && (ic & 0x0e00) != 0x0e00; 121 | } 122 | 123 | static inline bool T2$pcrel$b(uint16_t *ic) { 124 | // return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0x9000 || (ic[1] & 0xd000) == 0x8000 && (ic[0] & 0x0380) != 0x0380); 125 | return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0x9000 || ((ic[1] & 0xd000) == 0x8000 && (ic[0] & 0x0380) != 0x0380)); 126 | } 127 | 128 | static inline bool T$pcrel$bl(uint16_t *ic) { 129 | return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0xd000 || (ic[1] & 0xd001) == 0xc000); 130 | } 131 | 132 | static inline bool T$pcrel$ldr(uint16_t ic) { 133 | return (ic & 0xf800) == 0x4800; 134 | } 135 | 136 | static inline bool T$pcrel$add(uint16_t ic) { 137 | return (ic & 0xff78) == 0x4478; 138 | } 139 | 140 | static inline bool T$pcrel$ldrw(uint16_t ic) { 141 | return (ic & 0xff7f) == 0xf85f; 142 | } 143 | 144 | static size_t MSGetInstructionWidthThumb(void *start) { 145 | uint16_t *thumb(reinterpret_cast(start)); 146 | return T$32bit$i(thumb[0]) ? 4 : 2; 147 | } 148 | 149 | static size_t MSGetInstructionWidthARM(void *start) { 150 | return 4; 151 | } 152 | 153 | extern "C" size_t MSGetInstructionWidth(void *start) { 154 | if ((reinterpret_cast(start) & 0x1) == 0) 155 | return MSGetInstructionWidthARM(start); 156 | else 157 | return MSGetInstructionWidthThumb(reinterpret_cast(reinterpret_cast(start) & ~0x1)); 158 | } 159 | 160 | static void SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result) { 161 | if (symbol == NULL) 162 | return; 163 | 164 | uint16_t *area(reinterpret_cast(symbol)); 165 | 166 | unsigned align((reinterpret_cast(area) & 0x2) == 0 ? 0 : 1); 167 | uint16_t *thumb(area + align); 168 | 169 | uint32_t *arm(reinterpret_cast(thumb + 2)); 170 | uint16_t *trail(reinterpret_cast(arm + 2)); 171 | 172 | if ( 173 | (align == 0 || area[0] == T$nop) && 174 | thumb[0] == T$bx(A$pc) && 175 | thumb[1] == T$nop && 176 | arm[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8) 177 | ) { 178 | if (result != NULL) 179 | *result = reinterpret_cast(arm[1]); 180 | 181 | SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1); 182 | 183 | arm[1] = reinterpret_cast(replace); 184 | 185 | return; 186 | } 187 | 188 | size_t required((trail - area) * sizeof(uint16_t)); 189 | 190 | size_t used(0); 191 | while (used < required) 192 | used += MSGetInstructionWidthThumb(reinterpret_cast(area) + used); 193 | used = (used + sizeof(uint16_t) - 1) / sizeof(uint16_t) * sizeof(uint16_t); 194 | 195 | size_t blank((used - required) / sizeof(uint16_t)); 196 | 197 | uint16_t backup[used / sizeof(uint16_t)]; 198 | memcpy(backup, area, used); 199 | 200 | if (MSDebug) { 201 | char name[16]; 202 | sprintf(name, "%p", area); 203 | MSLogHexEx(area, used + sizeof(uint16_t), 2, name); 204 | } 205 | 206 | if (result != NULL) { 207 | 208 | size_t length(used); 209 | for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) 210 | if (T$pcrel$ldr(backup[offset])) 211 | length += 3 * sizeof(uint16_t); 212 | else if (T$pcrel$b(backup[offset])) 213 | length += 6 * sizeof(uint16_t); 214 | else if (T2$pcrel$b(backup + offset)) { 215 | length += 5 * sizeof(uint16_t); 216 | ++offset; 217 | } else if (T$pcrel$bl(backup + offset)) { 218 | length += 5 * sizeof(uint16_t); 219 | ++offset; 220 | } else if (T$pcrel$cbz(backup[offset])) { 221 | length += 16 * sizeof(uint16_t); 222 | } else if (T$pcrel$ldrw(backup[offset])) { 223 | length += 4 * sizeof(uint16_t); 224 | ++offset; 225 | } else if (T$pcrel$add(backup[offset])) 226 | length += 6 * sizeof(uint16_t); 227 | else if (T$32bit$i(backup[offset])) 228 | ++offset; 229 | 230 | unsigned pad((length & 0x2) == 0 ? 0 : 1); 231 | length += (pad + 2) * sizeof(uint16_t) + 2 * sizeof(uint32_t); 232 | 233 | uint16_t *buffer(reinterpret_cast(mmap( 234 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 235 | ))); 236 | 237 | if (buffer == MAP_FAILED) { 238 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 239 | *result = NULL; 240 | return; 241 | } 242 | 243 | if (false) fail: { 244 | munmap(buffer, length); 245 | *result = NULL; 246 | return; 247 | } 248 | 249 | size_t start(pad), end(length / sizeof(uint16_t)); 250 | uint32_t *trailer(reinterpret_cast(buffer + end)); 251 | for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) { 252 | if (T$pcrel$ldr(backup[offset])) { 253 | union { 254 | uint16_t value; 255 | 256 | struct { 257 | uint16_t immediate : 8; 258 | uint16_t rd : 3; 259 | uint16_t : 5; 260 | }; 261 | } bits = {backup[offset+0]}; 262 | 263 | buffer[start+0] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+0, end-2) / 4); 264 | buffer[start+1] = T$ldr_rd_$rn_im_4$(bits.rd, bits.rd, 0); 265 | 266 | // XXX: this code "works", but is "wrong": the mechanism is more complex than this 267 | *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + bits.immediate * 4; 268 | 269 | start += 2; 270 | end -= 2; 271 | } else if (T$pcrel$b(backup[offset])) { 272 | union { 273 | uint16_t value; 274 | 275 | struct { 276 | uint16_t imm8 : 8; 277 | uint16_t cond : 4; 278 | uint16_t /*1101*/ : 4; 279 | }; 280 | } bits = {backup[offset+0]}; 281 | 282 | intptr_t jump(bits.imm8 << 1); 283 | jump |= 1; 284 | jump <<= 23; 285 | jump >>= 23; 286 | 287 | buffer[start+0] = T$b$_$im(bits.cond, (end-6 - (start+0)) * 2 - 4); 288 | 289 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 290 | *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 291 | *--trailer = T$nop << 16 | T$bx(A$pc); 292 | 293 | start += 1; 294 | end -= 6; 295 | } else if (T2$pcrel$b(backup + offset)) { 296 | union { 297 | uint16_t value; 298 | 299 | struct { 300 | uint16_t imm6 : 6; 301 | uint16_t cond : 4; 302 | uint16_t s : 1; 303 | uint16_t : 5; 304 | }; 305 | } bits = {backup[offset+0]}; 306 | 307 | union { 308 | uint16_t value; 309 | 310 | struct { 311 | uint16_t imm11 : 11; 312 | uint16_t j2 : 1; 313 | uint16_t a : 1; 314 | uint16_t j1 : 1; 315 | uint16_t : 2; 316 | }; 317 | } exts = {backup[offset+1]}; 318 | 319 | intptr_t jump(1); 320 | jump |= exts.imm11 << 1; 321 | jump |= bits.imm6 << 12; 322 | 323 | if (exts.a) { 324 | jump |= bits.s << 24; 325 | jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; 326 | jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; 327 | jump |= bits.cond << 18; 328 | jump <<= 7; 329 | jump >>= 7; 330 | } else { 331 | jump |= bits.s << 20; 332 | jump |= exts.j2 << 19; 333 | jump |= exts.j1 << 18; 334 | jump <<= 11; 335 | jump >>= 11; 336 | } 337 | 338 | buffer[start+0] = T$b$_$im(exts.a ? A$al : bits.cond, (end-6 - (start+0)) * 2 - 4); 339 | 340 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 341 | *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 342 | *--trailer = T$nop << 16 | T$bx(A$pc); 343 | 344 | ++offset; 345 | start += 1; 346 | end -= 6; 347 | } else if (T$pcrel$bl(backup + offset)) { 348 | union { 349 | uint16_t value; 350 | 351 | struct { 352 | uint16_t immediate : 10; 353 | uint16_t s : 1; 354 | uint16_t : 5; 355 | }; 356 | } bits = {backup[offset+0]}; 357 | 358 | union { 359 | uint16_t value; 360 | 361 | struct { 362 | uint16_t immediate : 11; 363 | uint16_t j2 : 1; 364 | uint16_t x : 1; 365 | uint16_t j1 : 1; 366 | uint16_t : 2; 367 | }; 368 | } exts = {backup[offset+1]}; 369 | 370 | int32_t jump(0); 371 | jump |= bits.s << 24; 372 | jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; 373 | jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; 374 | jump |= bits.immediate << 12; 375 | jump |= exts.immediate << 1; 376 | jump |= exts.x; 377 | jump <<= 7; 378 | jump >>= 7; 379 | 380 | buffer[start+0] = T$push_r(1 << A$r7); 381 | buffer[start+1] = T$ldr_rd_$pc_im_4$(A$r7, ((end-2 - (start+1)) * 2 - 4 + 2) / 4); 382 | buffer[start+2] = T$mov_rd_rm(A$lr, A$r7); 383 | buffer[start+3] = T$pop_r(1 << A$r7); 384 | buffer[start+4] = T$blx(A$lr); 385 | 386 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 387 | 388 | ++offset; 389 | start += 5; 390 | end -= 2; 391 | } else if (T$pcrel$cbz(backup[offset])) { 392 | union { 393 | uint16_t value; 394 | 395 | struct { 396 | uint16_t rn : 3; 397 | uint16_t immediate : 5; 398 | uint16_t : 1; 399 | uint16_t i : 1; 400 | uint16_t : 1; 401 | uint16_t op : 1; 402 | uint16_t : 4; 403 | }; 404 | } bits = {backup[offset+0]}; 405 | 406 | intptr_t jump(1); 407 | jump |= bits.i << 6; 408 | jump |= bits.immediate << 1; 409 | 410 | //jump <<= 24; 411 | //jump >>= 24; 412 | 413 | unsigned rn(bits.rn); 414 | unsigned rt(rn == A$r7 ? A$r6 : A$r7); 415 | 416 | buffer[start+0] = T$push_r(1 << rt); 417 | buffer[start+1] = T1$mrs_rd_apsr(rt); 418 | buffer[start+2] = T2$mrs_rd_apsr(rt); 419 | buffer[start+3] = T$cbz$_rn_$im(bits.op, rn, (end-10 - (start+3)) * 2 - 4); 420 | buffer[start+4] = T1$msr_apsr_nzcvqg_rn(rt); 421 | buffer[start+5] = T2$msr_apsr_nzcvqg_rn(rt); 422 | buffer[start+6] = T$pop_r(1 << rt); 423 | 424 | *--trailer = reinterpret_cast(area + offset) + 4 + jump; 425 | *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 426 | *--trailer = T$nop << 16 | T$bx(A$pc); 427 | *--trailer = T$nop << 16 | T$pop_r(1 << rt); 428 | *--trailer = T$msr_apsr_nzcvqg_rn(rt); 429 | 430 | #if 0 431 | if ((start & 0x1) == 0) 432 | buffer[start++] = T$nop; 433 | buffer[start++] = T$bx(A$pc); 434 | buffer[start++] = T$nop; 435 | 436 | uint32_t *arm(reinterpret_cast(buffer + start)); 437 | arm[0] = A$add(A$lr, A$pc, 1); 438 | arm[1] = A$ldr_rd_$rn_im$(A$pc, A$pc, (trailer - arm) * sizeof(uint32_t) - 8); 439 | #endif 440 | 441 | start += 7; 442 | end -= 10; 443 | } else if (T$pcrel$ldrw(backup[offset])) { 444 | union { 445 | uint16_t value; 446 | 447 | struct { 448 | uint16_t : 7; 449 | uint16_t u : 1; 450 | uint16_t : 8; 451 | }; 452 | } bits = {backup[offset+0]}; 453 | 454 | union { 455 | uint16_t value; 456 | 457 | struct { 458 | uint16_t immediate : 12; 459 | uint16_t rt : 4; 460 | }; 461 | } exts = {backup[offset+1]}; 462 | 463 | buffer[start+0] = T1$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); 464 | buffer[start+1] = T2$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); 465 | 466 | buffer[start+2] = T1$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); 467 | buffer[start+3] = T2$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); 468 | 469 | // XXX: this code "works", but is "wrong": the mechanism is more complex than this 470 | *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + (bits.u == 0 ? -exts.immediate : exts.immediate); 471 | 472 | ++offset; 473 | start += 4; 474 | end -= 2; 475 | } else if (T$pcrel$add(backup[offset])) { 476 | union { 477 | uint16_t value; 478 | 479 | struct { 480 | uint16_t rd : 3; 481 | uint16_t rm : 3; 482 | uint16_t h2 : 1; 483 | uint16_t h1 : 1; 484 | uint16_t : 8; 485 | }; 486 | } bits = {backup[offset+0]}; 487 | 488 | if (bits.h1) { 489 | MSLog(MSLogLevelError, "MS:Error:pcrel(%u):add (rd > r7)", offset); 490 | goto fail; 491 | } 492 | 493 | unsigned rt(bits.rd == A$r7 ? A$r6 : A$r7); 494 | 495 | buffer[start+0] = T$push_r(1 << rt); 496 | buffer[start+1] = T$mov_rd_rm(rt, (bits.h1 << 3) | bits.rd); 497 | buffer[start+2] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+2, end-2) / 4); 498 | buffer[start+3] = T$add_rd_rm((bits.h1 << 3) | bits.rd, rt); 499 | buffer[start+4] = T$pop_r(1 << rt); 500 | *--trailer = reinterpret_cast(area + offset) + 4; 501 | 502 | start += 5; 503 | end -= 2; 504 | } else if (T$32bit$i(backup[offset])) { 505 | buffer[start++] = backup[offset]; 506 | buffer[start++] = backup[++offset]; 507 | } else { 508 | buffer[start++] = backup[offset]; 509 | } 510 | } 511 | 512 | buffer[start++] = T$bx(A$pc); 513 | buffer[start++] = T$nop; 514 | 515 | uint32_t *transfer = reinterpret_cast(buffer + start); 516 | transfer[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 517 | transfer[1] = reinterpret_cast(area + used / sizeof(uint16_t)) + 1; 518 | 519 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 520 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 521 | return; 522 | } 523 | 524 | *result = reinterpret_cast(buffer + pad) + 1; 525 | 526 | if (MSDebug) { 527 | char name[16]; 528 | sprintf(name, "%p", *result); 529 | MSLogHexEx(buffer, length, 2, name); 530 | } 531 | 532 | } 533 | 534 | { 535 | SubstrateHookMemory code(process, area, used); 536 | 537 | if (align != 0) 538 | area[0] = T$nop; 539 | 540 | thumb[0] = T$bx(A$pc); 541 | thumb[1] = T$nop; 542 | 543 | arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 544 | arm[1] = reinterpret_cast(replace); 545 | 546 | for (unsigned offset(0); offset != blank; ++offset) 547 | trail[offset] = T$nop; 548 | } 549 | 550 | if (MSDebug) { 551 | char name[16]; 552 | sprintf(name, "%p", area); 553 | MSLogHexEx(area, used + sizeof(uint16_t), 2, name); 554 | } 555 | } 556 | 557 | static void SubstrateHookFunctionARM(SubstrateProcessRef process, void *symbol, void *replace, void **result) { 558 | if (symbol == NULL) 559 | return; 560 | 561 | uint32_t *area(reinterpret_cast(symbol)); 562 | uint32_t *arm(area); 563 | 564 | const size_t used(8); 565 | 566 | uint32_t backup[used / sizeof(uint32_t)] = {arm[0], arm[1]}; 567 | 568 | if (MSDebug) { 569 | char name[16]; 570 | sprintf(name, "%p", area); 571 | MSLogHexEx(area, used + sizeof(uint32_t), 4, name); 572 | } 573 | 574 | if (result != NULL) { 575 | 576 | if (backup[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8)) { 577 | *result = reinterpret_cast(backup[1]); 578 | return; 579 | } 580 | 581 | size_t length(used); 582 | for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) 583 | if (A$pcrel$r(backup[offset])) { 584 | if ((backup[offset] & 0x02000000) == 0 || (backup[offset] & 0x0000f000 >> 12) != (backup[offset] & 0x0000000f)) 585 | length += 2 * sizeof(uint32_t); 586 | else 587 | length += 4 * sizeof(uint32_t); 588 | } 589 | 590 | length += 2 * sizeof(uint32_t); 591 | 592 | uint32_t *buffer(reinterpret_cast(mmap( 593 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 594 | ))); 595 | 596 | if (buffer == MAP_FAILED) { 597 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 598 | *result = NULL; 599 | return; 600 | } 601 | 602 | if (false) fail: { 603 | munmap(buffer, length); 604 | *result = NULL; 605 | return; 606 | } 607 | 608 | size_t start(0), end(length / sizeof(uint32_t)); 609 | uint32_t *trailer(reinterpret_cast(buffer + end)); 610 | for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) 611 | if (A$pcrel$r(backup[offset])) { 612 | union { 613 | uint32_t value; 614 | 615 | struct { 616 | uint32_t rm : 4; 617 | uint32_t : 1; 618 | uint32_t shift : 2; 619 | uint32_t shiftamount : 5; 620 | uint32_t rd : 4; 621 | uint32_t rn : 4; 622 | uint32_t l : 1; 623 | uint32_t w : 1; 624 | uint32_t b : 1; 625 | uint32_t u : 1; 626 | uint32_t p : 1; 627 | uint32_t mode : 1; 628 | uint32_t type : 2; 629 | uint32_t cond : 4; 630 | }; 631 | } bits = {backup[offset+0]}, copy(bits); 632 | 633 | bool guard; 634 | if (bits.mode == 0 || bits.rd != bits.rm) { 635 | copy.rn = bits.rd; 636 | guard = false; 637 | } else { 638 | copy.rn = bits.rm != A$r0 ? A$r0 : A$r1; 639 | guard = true; 640 | } 641 | 642 | if (guard) 643 | buffer[start++] = A$stmdb_sp$_$rs$((1 << copy.rn)); 644 | 645 | buffer[start+0] = A$ldr_rd_$rn_im$(copy.rn, A$pc, (end-1 - (start+0)) * 4 - 8); 646 | buffer[start+1] = copy.value; 647 | 648 | start += 2; 649 | 650 | if (guard) 651 | buffer[start++] = A$ldmia_sp$_$rs$((1 << copy.rn)); 652 | 653 | *--trailer = reinterpret_cast(area + offset) + 8; 654 | end -= 1; 655 | } else 656 | buffer[start++] = backup[offset]; 657 | 658 | buffer[start+0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 659 | buffer[start+1] = reinterpret_cast(area + used / sizeof(uint32_t)); 660 | 661 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 662 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 663 | goto fail; 664 | } 665 | 666 | *result = buffer; 667 | 668 | if (MSDebug) { 669 | char name[16]; 670 | sprintf(name, "%p", *result); 671 | MSLogHexEx(buffer, length, 4, name); 672 | } 673 | 674 | } 675 | 676 | { 677 | SubstrateHookMemory code(process, symbol, used); 678 | 679 | arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); 680 | arm[1] = reinterpret_cast(replace); 681 | } 682 | 683 | if (MSDebug) { 684 | char name[16]; 685 | sprintf(name, "%p", area); 686 | MSLogHexEx(area, used + sizeof(uint32_t), 4, name); 687 | } 688 | } 689 | 690 | static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { 691 | if (MSDebug) 692 | MSLog(MSLogLevelNotice, "SubstrateHookFunction(%p, %p, %p, %p)", process, symbol, replace, result); 693 | if ((reinterpret_cast(symbol) & 0x1) == 0) 694 | return SubstrateHookFunctionARM(process, symbol, replace, result); 695 | else 696 | return SubstrateHookFunctionThumb(process, reinterpret_cast(reinterpret_cast(symbol) & ~0x1), replace, result); 697 | } 698 | #endif 699 | 700 | #if defined(__i386__) || defined(__x86_64__) 701 | 702 | #include "Substratex86.hpp" 703 | 704 | static size_t MSGetInstructionWidthIntel(void *start) { 705 | hde64s decode; 706 | return hde64_disasm(start, &decode); 707 | } 708 | 709 | static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { 710 | if (MSDebug) 711 | MSLog(MSLogLevelNotice, "MSHookFunction(%p, %p, %p)", symbol, replace, result); 712 | if (symbol == NULL) 713 | return; 714 | 715 | uintptr_t source(reinterpret_cast(symbol)); 716 | uintptr_t target(reinterpret_cast(replace)); 717 | 718 | uint8_t *area(reinterpret_cast(symbol)); 719 | 720 | size_t required(MSSizeOfJump(target, source)); 721 | 722 | if (MSDebug) { 723 | char name[16]; 724 | sprintf(name, "%p", area); 725 | MSLogHex(area, 32, name); 726 | } 727 | 728 | size_t used(0); 729 | while (used < required) { 730 | size_t width(MSGetInstructionWidthIntel(area + used)); 731 | if (width == 0) { 732 | MSLog(MSLogLevelError, "MS:Error:MSGetInstructionWidthIntel(%p) == 0", area + used); 733 | return; 734 | } 735 | 736 | used += width; 737 | } 738 | 739 | size_t blank(used - required); 740 | 741 | if (MSDebug) { 742 | char name[16]; 743 | sprintf(name, "%p", area); 744 | MSLogHex(area, used + sizeof(uint16_t), name); 745 | } 746 | 747 | uint8_t backup[used]; 748 | memcpy(backup, area, used); 749 | 750 | if (result != NULL) { 751 | 752 | if (backup[0] == 0xe9) { 753 | *result = reinterpret_cast(source + 5 + *reinterpret_cast(backup + 1)); 754 | return; 755 | } 756 | 757 | if (!ia32 && backup[0] == 0xff && backup[1] == 0x25) { 758 | *result = *reinterpret_cast(source + 6 + *reinterpret_cast(backup + 2)); 759 | return; 760 | } 761 | 762 | size_t length(used + MSSizeOfJump(source + used)); 763 | 764 | for (size_t offset(0), width; offset != used; offset += width) { 765 | hde64s decode; 766 | hde64_disasm(backup + offset, &decode); 767 | width = decode.len; 768 | //_assert(width != 0 && offset + width <= used); 769 | 770 | #ifdef __LP64__ 771 | if ((decode.modrm & 0xc7) == 0x05) { 772 | if (decode.opcode == 0x8b) { 773 | void *destiny(area + offset + width + int32_t(decode.disp.disp32)); 774 | uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); 775 | length -= decode.len; 776 | length += MSSizeOfPushPointer(destiny); 777 | length += MSSizeOfPop(reg); 778 | length += MSSizeOfMove64(); 779 | } else { 780 | MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); 781 | continue; 782 | } 783 | } else 784 | #endif 785 | 786 | if (backup[offset] == 0xe8) { 787 | int32_t relative(*reinterpret_cast(backup + offset + 1)); 788 | void *destiny(area + offset + decode.len + relative); 789 | 790 | if (relative == 0) { 791 | length -= decode.len; 792 | length += MSSizeOfPushPointer(destiny); 793 | } else { 794 | length += MSSizeOfSkip(); 795 | length += MSSizeOfJump(destiny); 796 | } 797 | } else if (backup[offset] == 0xeb) { 798 | length -= decode.len; 799 | length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 800 | } else if (backup[offset] == 0xe9) { 801 | length -= decode.len; 802 | length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 803 | } else if ( 804 | backup[offset] == 0xe3 || 805 | (backup[offset] & 0xf0) == 0x70 806 | // XXX: opcode2 & 0xf0 is 0x80? 807 | ) { 808 | length += decode.len; 809 | length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 810 | } 811 | } 812 | 813 | uint8_t *buffer(reinterpret_cast(mmap( 814 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 815 | ))); 816 | 817 | if (buffer == MAP_FAILED) { 818 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 819 | *result = NULL; 820 | return; 821 | } 822 | 823 | if (false) fail: { 824 | munmap(buffer, length); 825 | *result = NULL; 826 | return; 827 | } 828 | 829 | { 830 | uint8_t *current(buffer); 831 | 832 | for (size_t offset(0), width; offset != used; offset += width) { 833 | hde64s decode; 834 | hde64_disasm(backup + offset, &decode); 835 | width = decode.len; 836 | //_assert(width != 0 && offset + width <= used); 837 | 838 | #ifdef __LP64__ 839 | if ((decode.modrm & 0xc7) == 0x05) { 840 | if (decode.opcode == 0x8b) { 841 | void *destiny(area + offset + width + int32_t(decode.disp.disp32)); 842 | uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); 843 | MSPushPointer(current, destiny); 844 | MSWritePop(current, reg); 845 | MSWriteMove64(current, reg, reg); 846 | } else { 847 | MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); 848 | goto copy; 849 | } 850 | } else 851 | #endif 852 | 853 | if (backup[offset] == 0xe8) { 854 | int32_t relative(*reinterpret_cast(backup + offset + 1)); 855 | if (relative == 0) 856 | MSPushPointer(current, area + offset + decode.len); 857 | else { 858 | MSWrite(current, 0xe8); 859 | MSWrite(current, MSSizeOfSkip()); 860 | void *destiny(area + offset + decode.len + relative); 861 | MSWriteSkip(current, MSSizeOfJump(destiny, current + MSSizeOfSkip())); 862 | MSWriteJump(current, destiny); 863 | } 864 | } else if (backup[offset] == 0xeb) 865 | MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 866 | else if (backup[offset] == 0xe9) 867 | MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 868 | else if ( 869 | backup[offset] == 0xe3 || 870 | (backup[offset] & 0xf0) == 0x70 871 | ) { 872 | MSWrite(current, backup[offset]); 873 | MSWrite(current, 2); 874 | MSWrite(current, 0xeb); 875 | void *destiny(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); 876 | MSWrite(current, MSSizeOfJump(destiny, current + 1)); 877 | MSWriteJump(current, destiny); 878 | } else 879 | #ifdef __LP64__ 880 | copy: 881 | #endif 882 | { 883 | MSWrite(current, backup + offset, width); 884 | } 885 | } 886 | 887 | MSWriteJump(current, area + used); 888 | } 889 | 890 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 891 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 892 | goto fail; 893 | } 894 | 895 | *result = buffer; 896 | 897 | if (MSDebug) { 898 | char name[16]; 899 | sprintf(name, "%p", *result); 900 | MSLogHex(buffer, length, name); 901 | } 902 | 903 | } 904 | 905 | { 906 | SubstrateHookMemory code(process, area, used); 907 | 908 | uint8_t *current(area); 909 | MSWriteJump(current, target); 910 | for (unsigned offset(0); offset != blank; ++offset) 911 | MSWrite(current, 0x90); 912 | } 913 | 914 | if (MSDebug) { 915 | char name[16]; 916 | sprintf(name, "%p", area); 917 | MSLogHex(area, used + sizeof(uint16_t), name); 918 | } 919 | } 920 | #endif 921 | 922 | _extern void MSHookFunction(void *symbol, void *replace, void **result) { 923 | return SubstrateHookFunction(NULL, symbol, replace, result); 924 | } 925 | 926 | #if defined(__APPLE__) && defined(__arm__) 927 | _extern void _Z14MSHookFunctionPvS_PS_(void *symbol, void *replace, void **result) { 928 | return MSHookFunction(symbol, replace, result); 929 | } 930 | #endif 931 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateHook.h: -------------------------------------------------------------------------------- 1 | #ifndef __SUBSTRATEHOOK_H__ 2 | #define __SUBSTRATEHOOK_H__ 3 | 4 | 5 | #include 6 | 7 | #define _extern extern "C" __attribute__((__visibility__("default"))) 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | void MSHookFunction(void *symbol, void *replace, void **result); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateLog.hpp: -------------------------------------------------------------------------------- 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 | #if 0 26 | #include 27 | 28 | #define MSLog(level, format, ...) ((void)__android_log_print(level, "NNNN", format, __VA_ARGS__)) 29 | 30 | #define MSLogLevelNotice ANDROID_LOG_INFO 31 | #define MSLogLevelWarning ANDROID_LOG_WARN 32 | #define MSLogLevelError ANDROID_LOG_ERROR 33 | 34 | #else 35 | 36 | #define MSLog(level, format, ...) printf(format, __VA_ARGS__) 37 | 38 | #endif 39 | 40 | #endif//SUBSTRATE_LOG_HPP 41 | -------------------------------------------------------------------------------- /jni/Substrate/SubstratePosixMemory.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 | #define SubstrateInternal 23 | #include "CydiaSubstrate.h" 24 | #include "SubstrateLog.hpp" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | extern "C" void __clear_cache (void *beg, void *end); 33 | 34 | struct __SubstrateMemory { 35 | void *address_; 36 | size_t width_; 37 | 38 | __SubstrateMemory(void *address, size_t width) : 39 | address_(address), 40 | width_(width) 41 | { 42 | } 43 | }; 44 | #include 45 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { 46 | if (allocator != NULL) { 47 | MSLog(MSLogLevelError, "MS:Error:allocator != NULL", 1); 48 | return NULL; 49 | } 50 | 51 | if (size == 0) 52 | return NULL; 53 | 54 | int page(sysconf(_SC_PAGESIZE)); 55 | 56 | uintptr_t base(reinterpret_cast(data) / page * page); 57 | size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); 58 | void *address(reinterpret_cast(base)); 59 | 60 | if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { 61 | MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); 62 | return NULL; 63 | } 64 | 65 | return new __SubstrateMemory(address, width); 66 | } 67 | 68 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { 69 | if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) 70 | MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); 71 | 72 | __clear_cache(reinterpret_cast(memory->address_), reinterpret_cast(memory->address_) + memory->width_); 73 | 74 | delete memory; 75 | } 76 | -------------------------------------------------------------------------------- /jni/Substrate/SubstrateX86.hpp: -------------------------------------------------------------------------------- 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_X86_HPP 23 | #define SUBSTRATE_X86_HPP 24 | 25 | #include "Buffer.hpp" 26 | 27 | #ifdef __LP64__ 28 | static const bool ia32 = false; 29 | #else 30 | static const bool ia32 = true; 31 | #endif 32 | 33 | enum I$r { 34 | I$rax, I$rcx, I$rdx, I$rbx, 35 | I$rsp, I$rbp, I$rsi, I$rdi, 36 | I$r8, I$r9, I$r10, I$r11, 37 | I$r12, I$r13, I$r14, I$r15, 38 | }; 39 | 40 | _disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { 41 | intptr_t offset(target - source); 42 | return int32_t(offset) == offset; 43 | } 44 | 45 | _disused static size_t MSSizeOfSkip() { 46 | return 5; 47 | } 48 | 49 | _disused static size_t MSSizeOfPushPointer(uintptr_t target) { 50 | return uint64_t(target) >> 32 == 0 ? 5 : 13; 51 | } 52 | 53 | _disused static size_t MSSizeOfPushPointer(void *target) { 54 | return MSSizeOfPushPointer(reinterpret_cast(target)); 55 | } 56 | 57 | _disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { 58 | if (ia32 || !blind && MSIs32BitOffset(target, source + 5)) 59 | return MSSizeOfSkip(); 60 | else 61 | return MSSizeOfPushPointer(target) + 1; 62 | } 63 | 64 | _disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { 65 | return MSSizeOfJump(false, target, source); 66 | } 67 | 68 | _disused static size_t MSSizeOfJump(uintptr_t target) { 69 | return MSSizeOfJump(true, target); 70 | } 71 | 72 | _disused static size_t MSSizeOfJump(void *target, void *source) { 73 | return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); 74 | } 75 | 76 | _disused static size_t MSSizeOfJump(void *target) { 77 | return MSSizeOfJump(reinterpret_cast(target)); 78 | } 79 | 80 | _disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { 81 | MSWrite(current, 0xe9); 82 | MSWrite(current, size); 83 | } 84 | 85 | _disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { 86 | MSWrite(current, 0x68); 87 | MSWrite(current, target); 88 | 89 | if (uint32_t high = uint64_t(target) >> 32) { 90 | MSWrite(current, 0xc7); 91 | MSWrite(current, 0x44); 92 | MSWrite(current, 0x24); 93 | MSWrite(current, 0x04); 94 | MSWrite(current, high); 95 | } 96 | } 97 | 98 | _disused static void MSPushPointer(uint8_t *¤t, void *target) { 99 | return MSPushPointer(current, reinterpret_cast(target)); 100 | } 101 | 102 | _disused static void MSWriteCall(uint8_t *¤t, I$r target) { 103 | if (target >> 3 != 0) 104 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 105 | MSWrite(current, 0xff); 106 | MSWrite(current, 0xd0 | target & 0x07); 107 | } 108 | 109 | _disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { 110 | uintptr_t source(reinterpret_cast(current)); 111 | 112 | if (ia32 || MSIs32BitOffset(target, source + 5)) { 113 | MSWrite(current, 0xe8); 114 | MSWrite(current, target - (source + 5)); 115 | } else { 116 | MSPushPointer(current, target); 117 | 118 | MSWrite(current, 0x83); 119 | MSWrite(current, 0xc4); 120 | MSWrite(current, 0x08); 121 | 122 | MSWrite(current, 0x67); 123 | MSWrite(current, 0xff); 124 | MSWrite(current, 0x54); 125 | MSWrite(current, 0x24); 126 | MSWrite(current, 0xf8); 127 | } 128 | } 129 | 130 | template 131 | _disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { 132 | return MSWriteCall(current, reinterpret_cast(target)); 133 | } 134 | 135 | _disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { 136 | uintptr_t source(reinterpret_cast(current)); 137 | 138 | if (ia32 || MSIs32BitOffset(target, source + 5)) 139 | MSWriteSkip(current, target - (source + 5)); 140 | else { 141 | MSPushPointer(current, target); 142 | MSWrite(current, 0xc3); 143 | } 144 | } 145 | 146 | _disused static void MSWriteJump(uint8_t *¤t, void *target) { 147 | return MSWriteJump(current, reinterpret_cast(target)); 148 | } 149 | 150 | _disused static void MSWriteJump(uint8_t *¤t, I$r target) { 151 | if (target >> 3 != 0) 152 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 153 | MSWrite(current, 0xff); 154 | MSWrite(current, 0xe0 | target & 0x07); 155 | } 156 | 157 | _disused static void MSWritePop(uint8_t *¤t, uint8_t target) { 158 | if (target >> 3 != 0) 159 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 160 | MSWrite(current, 0x58 | target & 0x07); 161 | } 162 | 163 | _disused static size_t MSSizeOfPop(uint8_t target) { 164 | return target >> 3 != 0 ? 2 : 1; 165 | } 166 | 167 | _disused static void MSWritePush(uint8_t *¤t, I$r target) { 168 | if (target >> 3 != 0) 169 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 170 | MSWrite(current, 0x50 | target & 0x07); 171 | } 172 | 173 | _disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { 174 | MSWrite(current, 0x83); 175 | MSWrite(current, 0xc4 | target & 0x07); 176 | MSWrite(current, source); 177 | } 178 | 179 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { 180 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); 181 | MSWrite(current, 0xb8 | target & 0x7); 182 | MSWrite(current, source); 183 | } 184 | 185 | template 186 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { 187 | return MSWriteSet64(current, target, reinterpret_cast(source)); 188 | } 189 | 190 | _disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { 191 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); 192 | MSWrite(current, 0x8b); 193 | MSWrite(current, (target & 0x07) << 3 | source & 0x07); 194 | } 195 | 196 | _disused static size_t MSSizeOfMove64() { 197 | return 3; 198 | } 199 | 200 | #endif//SUBSTRATE_X86_HPP 201 | -------------------------------------------------------------------------------- /jni/Substrate/hde64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "hde64.h" 12 | #include "table64.h" 13 | 14 | unsigned int hde64_disasm(const void *code, hde64s *hs) 15 | { 16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 17 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 18 | uint8_t op64 = 0; 19 | 20 | memset(hs,0,sizeof(hde64s)); 21 | 22 | for (x = 16; x; x--) 23 | switch (c = *p++) { 24 | case 0xf3: 25 | hs->p_rep = c; 26 | pref |= PRE_F3; 27 | break; 28 | case 0xf2: 29 | hs->p_rep = c; 30 | pref |= PRE_F2; 31 | break; 32 | case 0xf0: 33 | hs->p_lock = c; 34 | pref |= PRE_LOCK; 35 | break; 36 | case 0x26: case 0x2e: case 0x36: 37 | case 0x3e: case 0x64: case 0x65: 38 | hs->p_seg = c; 39 | pref |= PRE_SEG; 40 | break; 41 | case 0x66: 42 | hs->p_66 = c; 43 | pref |= PRE_66; 44 | break; 45 | case 0x67: 46 | hs->p_67 = c; 47 | pref |= PRE_67; 48 | break; 49 | default: 50 | goto pref_done; 51 | } 52 | pref_done: 53 | 54 | hs->flags = (uint32_t)pref << 23; 55 | 56 | if (!pref) 57 | pref |= PRE_NONE; 58 | 59 | if ((c & 0xf0) == 0x40) { 60 | hs->flags |= F_PREFIX_REX; 61 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 62 | op64++; 63 | hs->rex_r = (c & 7) >> 2; 64 | hs->rex_x = (c & 3) >> 1; 65 | hs->rex_b = c & 1; 66 | if (((c = *p++) & 0xf0) == 0x40) { 67 | opcode = c; 68 | goto error_opcode; 69 | } 70 | } 71 | 72 | if ((hs->opcode = c) == 0x0f) { 73 | hs->opcode2 = c = *p++; 74 | ht += DELTA_OPCODES; 75 | } else if (c >= 0xa0 && c <= 0xa3) { 76 | op64++; 77 | if (pref & PRE_67) 78 | pref |= PRE_66; 79 | else 80 | pref &= ~PRE_66; 81 | } 82 | 83 | opcode = c; 84 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 85 | 86 | if (cflags == C_ERROR) { 87 | error_opcode: 88 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 89 | cflags = 0; 90 | if ((opcode & -3) == 0x24) 91 | cflags++; 92 | } 93 | 94 | x = 0; 95 | if (cflags & C_GROUP) { 96 | uint16_t t; 97 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 98 | cflags = (uint8_t)t; 99 | x = (uint8_t)(t >> 8); 100 | } 101 | 102 | if (hs->opcode2) { 103 | ht = hde64_table + DELTA_PREFIXES; 104 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 105 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 106 | } 107 | 108 | if (cflags & C_MODRM) { 109 | hs->flags |= F_MODRM; 110 | hs->modrm = c = *p++; 111 | hs->modrm_mod = m_mod = c >> 6; 112 | hs->modrm_rm = m_rm = c & 7; 113 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 114 | 115 | if (x && ((x << m_reg) & 0x80)) 116 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 117 | 118 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 119 | uint8_t t = opcode - 0xd9; 120 | if (m_mod == 3) { 121 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 122 | t = ht[m_reg] << m_rm; 123 | } else { 124 | ht = hde64_table + DELTA_FPU_REG; 125 | t = ht[t] << m_reg; 126 | } 127 | if (t & 0x80) 128 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 129 | } 130 | 131 | if (pref & PRE_LOCK) { 132 | if (m_mod == 3) { 133 | hs->flags |= F_ERROR | F_ERROR_LOCK; 134 | } else { 135 | uint8_t *table_end, op = opcode; 136 | if (hs->opcode2) { 137 | ht = hde64_table + DELTA_OP2_LOCK_OK; 138 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 139 | } else { 140 | ht = hde64_table + DELTA_OP_LOCK_OK; 141 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 142 | op &= -2; 143 | } 144 | for (; ht != table_end; ht++) 145 | if (*ht++ == op) { 146 | if (!((*ht << m_reg) & 0x80)) 147 | goto no_lock_error; 148 | else 149 | break; 150 | } 151 | hs->flags |= F_ERROR | F_ERROR_LOCK; 152 | no_lock_error: 153 | ; 154 | } 155 | } 156 | 157 | if (hs->opcode2) { 158 | switch (opcode) { 159 | case 0x20: case 0x22: 160 | m_mod = 3; 161 | if (m_reg > 4 || m_reg == 1) 162 | goto error_operand; 163 | else 164 | goto no_error_operand; 165 | case 0x21: case 0x23: 166 | m_mod = 3; 167 | if (m_reg == 4 || m_reg == 5) 168 | goto error_operand; 169 | else 170 | goto no_error_operand; 171 | } 172 | } else { 173 | switch (opcode) { 174 | case 0x8c: 175 | if (m_reg > 5) 176 | goto error_operand; 177 | else 178 | goto no_error_operand; 179 | case 0x8e: 180 | if (m_reg == 1 || m_reg > 5) 181 | goto error_operand; 182 | else 183 | goto no_error_operand; 184 | } 185 | } 186 | 187 | if (m_mod == 3) { 188 | uint8_t *table_end; 189 | if (hs->opcode2) { 190 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 191 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 192 | } else { 193 | ht = hde64_table + DELTA_OP_ONLY_MEM; 194 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 195 | } 196 | for (; ht != table_end; ht += 2) 197 | if (*ht++ == opcode) { 198 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 199 | goto error_operand; 200 | else 201 | break; 202 | } 203 | goto no_error_operand; 204 | } else if (hs->opcode2) { 205 | switch (opcode) { 206 | case 0x50: case 0xd7: case 0xf7: 207 | if (pref & (PRE_NONE | PRE_66)) 208 | goto error_operand; 209 | break; 210 | case 0xd6: 211 | if (pref & (PRE_F2 | PRE_F3)) 212 | goto error_operand; 213 | break; 214 | case 0xc5: 215 | goto error_operand; 216 | } 217 | goto no_error_operand; 218 | } else 219 | goto no_error_operand; 220 | 221 | error_operand: 222 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 223 | no_error_operand: 224 | 225 | c = *p++; 226 | if (m_reg <= 1) { 227 | if (opcode == 0xf6) 228 | cflags |= C_IMM8; 229 | else if (opcode == 0xf7) 230 | cflags |= C_IMM_P66; 231 | } 232 | 233 | switch (m_mod) { 234 | case 0: 235 | if (pref & PRE_67) { 236 | if (m_rm == 6) 237 | disp_size = 2; 238 | } else 239 | if (m_rm == 5) 240 | disp_size = 4; 241 | break; 242 | case 1: 243 | disp_size = 1; 244 | break; 245 | case 2: 246 | disp_size = 2; 247 | if (!(pref & PRE_67)) 248 | disp_size <<= 1; 249 | } 250 | 251 | if (m_mod != 3 && m_rm == 4) { 252 | hs->flags |= F_SIB; 253 | p++; 254 | hs->sib = c; 255 | hs->sib_scale = c >> 6; 256 | hs->sib_index = (c & 0x3f) >> 3; 257 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 258 | disp_size = 4; 259 | } 260 | 261 | p--; 262 | switch (disp_size) { 263 | case 1: 264 | hs->flags |= F_DISP8; 265 | hs->disp.disp8 = *p; 266 | break; 267 | case 2: 268 | hs->flags |= F_DISP16; 269 | hs->disp.disp16 = *(uint16_t *)p; 270 | break; 271 | case 4: 272 | hs->flags |= F_DISP32; 273 | hs->disp.disp32 = *(uint32_t *)p; 274 | } 275 | p += disp_size; 276 | } else if (pref & PRE_LOCK) 277 | hs->flags |= F_ERROR | F_ERROR_LOCK; 278 | 279 | if (cflags & C_IMM_P66) { 280 | if (cflags & C_REL32) { 281 | if (pref & PRE_66) { 282 | hs->flags |= F_IMM16 | F_RELATIVE; 283 | hs->imm.imm16 = *(uint16_t *)p; 284 | p += 2; 285 | goto disasm_done; 286 | } 287 | goto rel32_ok; 288 | } 289 | if (op64) { 290 | hs->flags |= F_IMM64; 291 | hs->imm.imm64 = *(uint64_t *)p; 292 | p += 8; 293 | } else if (!(pref & PRE_66)) { 294 | hs->flags |= F_IMM32; 295 | hs->imm.imm32 = *(uint32_t *)p; 296 | p += 4; 297 | } else 298 | goto imm16_ok; 299 | } 300 | 301 | 302 | if (cflags & C_IMM16) { 303 | imm16_ok: 304 | hs->flags |= F_IMM16; 305 | hs->imm.imm16 = *(uint16_t *)p; 306 | p += 2; 307 | } 308 | if (cflags & C_IMM8) { 309 | hs->flags |= F_IMM8; 310 | hs->imm.imm8 = *p++; 311 | } 312 | 313 | if (cflags & C_REL32) { 314 | rel32_ok: 315 | hs->flags |= F_IMM32 | F_RELATIVE; 316 | hs->imm.imm32 = *(uint32_t *)p; 317 | p += 4; 318 | } else if (cflags & C_REL8) { 319 | hs->flags |= F_IMM8 | F_RELATIVE; 320 | hs->imm.imm8 = *p++; 321 | } 322 | 323 | disasm_done: 324 | 325 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 326 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 327 | hs->len = 15; 328 | } 329 | 330 | return (unsigned int)hs->len; 331 | } 332 | -------------------------------------------------------------------------------- /jni/Substrate/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 | -------------------------------------------------------------------------------- /jni/Substrate/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /jni/libcrypt.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1683942030/Android_memLoader_src/9efd4b933b95c4994d29d7e21622263104284568/jni/libcrypt.a -------------------------------------------------------------------------------- /jni/loader/Loader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | * File : Loader.cpp 4 | * Description : mem_loader 内存加载劫持加壳 5 | * Creation : 2015.8.5 6 | * Author : LLhack 7 | * History : 8 | * 9 | ****************************************************************************** 10 | **/ 11 | 12 | #include "Loader.h" 13 | #include 14 | #include 15 | #include "solist.h" 16 | #include 17 | #include "utils.h" 18 | 19 | 20 | 21 | 22 | namespace 23 | { 24 | const char* const kDefaultLdPaths[] = 25 | { 26 | "/system/lib", 27 | "/vendor/lib", 28 | NULL 29 | }; 30 | soinfo slf = {0}; 31 | } 32 | 33 | loader::loader() 34 | : m_pid(0), 35 | m_soCount(0) 36 | { 37 | m_sopool_dep[SO_MAX] = {0}; 38 | } 39 | 40 | loader::~loader() 41 | { 42 | 43 | } 44 | 45 | int loader::isFindedModule(int m_pid, char *module_name) 46 | { 47 | char filename[256] = { 0 }; 48 | char name[256] = { 0 }; 49 | snprintf(filename, sizeof(filename), "/proc/%d/maps", m_pid); 50 | FILE *fsrc; 51 | int ret = 0; 52 | if ((fsrc = fopen(filename, "r")) == NULL) 53 | { 54 | return 0; 55 | } 56 | else 57 | { 58 | while (ret != EOF) 59 | { 60 | ret = fscanf(fsrc, "%s\n", name); 61 | LDBG("is load lib:[%s]\n", name); 62 | if (strstr(name, module_name) != NULL) 63 | { 64 | fclose(fsrc); 65 | return 1; 66 | } 67 | } 68 | } 69 | return 0; 70 | } 71 | 72 | 73 | unsigned loader::_elfhash(const char *_name) 74 | { 75 | const unsigned char *name = (const unsigned char *)_name; 76 | unsigned h = 0, g = 0; 77 | 78 | while (*name) { 79 | h = (h << 4) + *name++; 80 | g = h & 0xf0000000; 81 | h ^= g; 82 | h ^= g >> 24; 83 | } 84 | return h; 85 | } 86 | 87 | /* 88 | * get_need_mmap_bufer 89 | * buffe_size == si->size 90 | */ 91 | unsigned loader::_getLibExtents(void *__hdr, unsigned *size) 92 | { 93 | unsigned req_base = 0; 94 | unsigned min_vaddr = 0xffffffff; 95 | unsigned max_vaddr = 0; 96 | unsigned char *_hdr = (unsigned char *)__hdr; 97 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; 98 | Elf32_Phdr *phdr; 99 | int cnt; 100 | 101 | phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); 102 | 103 | /* find the min/max p_vaddrs from all the PT_LOAD segments so we can 104 | * get the range. */ 105 | for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) 106 | { 107 | if (phdr->p_type == PT_LOAD) 108 | { 109 | if ((phdr->p_vaddr + phdr->p_memsz) > max_vaddr) 110 | max_vaddr = phdr->p_vaddr + phdr->p_memsz; 111 | if (phdr->p_vaddr < min_vaddr) 112 | min_vaddr = phdr->p_vaddr; 113 | } 114 | } 115 | 116 | if ((min_vaddr == 0xffffffff) && (max_vaddr == 0)) 117 | { 118 | return (unsigned)-1; 119 | } 120 | 121 | /* truncate min_vaddr down to page boundary */ 122 | min_vaddr &= ~ELF_PAGE_MASK; 123 | 124 | /* round max_vaddr up to the next page */ 125 | max_vaddr = (max_vaddr + ELF_PAGE_SIZE - 1) & ~ELF_PAGE_MASK; 126 | 127 | *size = (max_vaddr - min_vaddr); 128 | 129 | return (unsigned)req_base; 130 | } 131 | 132 | /* 133 | * mmap_so_buffer 134 | */ 135 | int loader::_allocMemRegion(soinfo *si) 136 | { 137 | void *base = mmap(NULL, si->size, PROT_READ | PROT_EXEC | PROT_WRITE, 138 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 139 | if (base == MAP_FAILED) 140 | { 141 | LDBG("%5d mmap of library '%s' failed\n", 142 | m_pid, si->name); 143 | goto err; 144 | } 145 | si->base = (unsigned)base; 146 | return 0; 147 | 148 | err: 149 | LDBG("OOPS: %5d cannot map library '%s'. no vspace available.", 150 | m_pid, si->name); 151 | return -1; 152 | } 153 | 154 | /* 155 | * alloc_self_so_strcut 156 | */ 157 | soinfo* loader::alloc_info(const char *name) 158 | { 159 | soinfo *si = NULL; 160 | si = &slf; 161 | if (si == NULL) 162 | { 163 | LDBG("alloca is er \n"); 164 | return NULL; 165 | } 166 | if (strlen(name) >= SOINFO_NAME_LEN) 167 | { 168 | LDBG("%5d library name %s too long", m_pid, name); 169 | return NULL; 170 | } 171 | 172 | if (m_soCount >= 128) 173 | { 174 | LDBG("No solist for %s", name); 175 | return NULL; 176 | } 177 | memset(si, 0, sizeof(soinfo)); 178 | strncpy((char*)si->name, name, sizeof(si->name)); 179 | si->next = NULL; 180 | si->refcount = 0; 181 | return si; 182 | } 183 | 184 | /* 185 | * load_segment 186 | * section to segment 187 | */ 188 | int loader::loadSegmentswitBuff(void *header, soinfo *si) 189 | { 190 | 191 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; 192 | Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); 193 | unsigned char *base = (unsigned char *)si->base; 194 | int cnt; 195 | unsigned len; 196 | unsigned char *tmp; 197 | unsigned char *pbase; 198 | unsigned char *extra_base; 199 | unsigned extra_len; 200 | unsigned total_sz = 0; 201 | si->wrprotect_start = 0xffffffff; 202 | si->wrprotect_end = 0; 203 | 204 | LDBG("[ %5d - Begin loading segments for '%s' @ 0x%08x ]\n", 205 | m_pid, si->name, (unsigned)si->base); 206 | /* Now go through all the PT_LOAD segments and map them into memory 207 | * at the appropriate locations. */ 208 | for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) 209 | { 210 | if (phdr->p_type == PT_LOAD) 211 | { 212 | /* we want to map in the segment on a page boundary */ 213 | tmp = base + (phdr->p_vaddr & (~ELF_PAGE_MASK)); 214 | /* add the # of bytes we masked off above to the total length. */ 215 | len = phdr->p_filesz + (phdr->p_vaddr & ELF_PAGE_MASK); 216 | 217 | LDBG("[ %d - Trying to load segment from '%s' @ 0x%08x " 218 | "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x data:[0x%x] ]\n", m_pid, si->name, 219 | (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset, *(char*)((unsigned)phdr + phdr->p_offset & (~ELF_PAGE_MASK))); 220 | memcpy(tmp, (void*)((unsigned)phdr + phdr->p_offset & (~ELF_PAGE_MASK)), len); 221 | pbase = tmp; 222 | LDBG("pbase:[%p]tmp:[%p]si.base:[%p]len[%d]\n", pbase, tmp,base, len); 223 | if (pbase == MAP_FAILED) 224 | { 225 | LDBG("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " 226 | "p_vaddr=0x%08x p_offset=0x%08x", m_pid, si->name, 227 | (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); 228 | goto fail; 229 | } 230 | 231 | /* If 'len' didn't end on page boundary, and it's a writable 232 | * segment, zero-fill the rest. */ 233 | if ((len & ELF_PAGE_MASK) && (phdr->p_flags & PF_W)) 234 | memset((void *)(pbase + len), 0, ELF_PAGE_SIZE - (len & ELF_PAGE_MASK)); 235 | tmp = (unsigned char *)(((unsigned)pbase + len + ELF_PAGE_SIZE - 1) & 236 | (~ELF_PAGE_MASK)); 237 | if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) 238 | { 239 | extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; 240 | /* map in the extra page(s) as anonymous into the range. 241 | * This is probably not necessary as we already mapped in 242 | * the entire region previously, but we just want to be 243 | * sure. This will also set the right flags on the region 244 | * (though we can probably accomplish the same thing with 245 | * mprotect). 246 | */ 247 | extra_base = (unsigned char*)mmap((void *)tmp, extra_len, 248 | PFLAGS_TO_PROT(phdr->p_flags), 249 | MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 250 | -1, 0); 251 | if (extra_base == MAP_FAILED) 252 | { 253 | LDBG("[ %5d - failed to extend segment from '%s' @ 0x%08x" 254 | " (0x%08x) ]", m_pid, si->name, (unsigned)tmp, 255 | extra_len); 256 | goto fail; 257 | } 258 | } 259 | /* set the len here to show the full extent of the segment we 260 | * just loaded, mostly for debugging */ 261 | len = (((unsigned)base + phdr->p_vaddr + phdr->p_memsz + 262 | ELF_PAGE_SIZE - 1) & (~ELF_PAGE_MASK)) - (unsigned)pbase; 263 | total_sz += len; 264 | 265 | if (!(phdr->p_flags & PF_W)) 266 | { 267 | if ((unsigned)pbase < si->wrprotect_start) 268 | si->wrprotect_start = (unsigned)pbase; 269 | if (((unsigned)pbase + len) > si->wrprotect_end) 270 | si->wrprotect_end = (unsigned)pbase + len; 271 | mprotect(pbase, len, 272 | PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE); 273 | } 274 | } 275 | else if (phdr->p_type == PT_DYNAMIC) 276 | { 277 | 278 | si->dynamic = (unsigned *)(base + phdr->p_vaddr); 279 | } 280 | else 281 | { 282 | #ifdef ANDROID_ARM_LINKER 283 | if (phdr->p_type == PT_ARM_EXIDX) 284 | { 285 | 286 | si->ARM_exidx = (unsigned *)phdr->p_vaddr; 287 | si->ARM_exidx_count = phdr->p_memsz / 8; 288 | } 289 | #endif 290 | } 291 | } 292 | LDBG("%5d - Total length (0x%08x) of mapped segments from '%s' phdr:[%p] phnum:[%d] \n", 293 | m_pid, total_sz, si->name,si->phdr,si->phnum); 294 | /* Sanity check */ 295 | if (total_sz > si->size) 296 | { 297 | LDBG("%5d - Total length (0x%08x) of mapped segments from '%s' is " 298 | "greater than what was allocated (0x%08x). THIS IS BAD!", 299 | m_pid, total_sz, si->name, si->size); 300 | goto fail; 301 | } 302 | return 0; 303 | 304 | fail: 305 | munmap((void *)si->base, si->size); 306 | return -1; 307 | } 308 | 309 | 310 | 311 | soinfo* loader::loadLibInternalwithBuffer(const char *name, unsigned char *buffer) 312 | { 313 | unsigned ext_sz; 314 | unsigned req_base; 315 | const char *bname; 316 | soinfo *si = NULL; 317 | Elf32_Ehdr *hdr; 318 | req_base = _getLibExtents(buffer, &ext_sz); 319 | if (req_base == (unsigned)-1) 320 | goto fail; 321 | 322 | bname = strrchr(name, '/'); 323 | si = alloc_info(bname ? bname + 1 : name); 324 | if (si == NULL) 325 | goto fail; 326 | si->base = req_base; 327 | si->size = ext_sz; 328 | si->flags = 0; 329 | si->entry = 0; 330 | si->dynamic = (unsigned *)-1; 331 | 332 | if (_allocMemRegion(si) < 0) 333 | goto fail; 334 | 335 | if (loadSegmentswitBuff(buffer, si) < 0) 336 | { 337 | goto fail; 338 | } 339 | 340 | hdr = (Elf32_Ehdr *)si->base; 341 | si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); 342 | si->phnum = hdr->e_phnum; 343 | return si; 344 | 345 | fail: 346 | return NULL; 347 | } 348 | 349 | 350 | 351 | int loader::_linkImage(soinfo *si) 352 | { 353 | unsigned *d; 354 | Elf32_Phdr *phdr = si->phdr; 355 | int phnum = si->phnum; 356 | 357 | if (si->flags & FLAG_EXE) 358 | { 359 | si->size = 0; 360 | for (; phnum > 0; --phnum, ++phdr) 361 | { 362 | #ifdef ANDROID_ARM_LINKER 363 | if (phdr->p_type == PT_ARM_EXIDX) 364 | { 365 | /* exidx entries (used for stack unwinding) are 8 bytes each. 366 | */ 367 | si->ARM_exidx = (unsigned *)phdr->p_vaddr; 368 | si->ARM_exidx_count = phdr->p_memsz / 8; 369 | } 370 | #endif 371 | if (phdr->p_type == PT_LOAD) 372 | { 373 | if (!(phdr->p_flags & PF_W)) 374 | { 375 | unsigned _end; 376 | 377 | if (phdr->p_vaddr < si->wrprotect_start) 378 | si->wrprotect_start = phdr->p_vaddr; 379 | _end = (((phdr->p_vaddr + phdr->p_memsz + ELF_PAGE_SIZE - 1) & 380 | (~ELF_PAGE_MASK))); 381 | if (_end > si->wrprotect_end) 382 | si->wrprotect_end = _end; 383 | } 384 | } 385 | else if (phdr->p_type == PT_DYNAMIC) 386 | { 387 | if (si->dynamic != (unsigned *)-1) 388 | { 389 | LDBG("%5d multiple PT_DYNAMIC segments found in '%s'. " 390 | "Segment at 0x%08x, previously one found at 0x%08x", 391 | m_pid, si->name, si->base + phdr->p_vaddr, 392 | (unsigned)si->dynamic); 393 | goto fail; 394 | } 395 | si->dynamic = (unsigned *)(si->base + phdr->p_vaddr); 396 | } 397 | } 398 | } 399 | 400 | if (si->dynamic == (unsigned *)-1) 401 | { 402 | LDBG("%5d missing PT_DYNAMIC?!", m_pid); 403 | goto fail; 404 | } 405 | for (d = si->dynamic; *d; d++) 406 | { 407 | switch (*d++) 408 | { 409 | case DT_HASH: 410 | si->nbucket = ((unsigned *)(si->base + *d))[0]; 411 | si->nchain = ((unsigned *)(si->base + *d))[1]; 412 | si->bucket = (unsigned *)(si->base + *d + 8); 413 | si->chain = (unsigned *)(si->base + *d + 8 + si->nbucket * 4); 414 | break; 415 | case DT_STRTAB: 416 | si->strtab = (const char *)(si->base + *d); 417 | break; 418 | case DT_STRSZ: 419 | si->strsz = *d; 420 | break; 421 | case DT_SYMTAB: 422 | si->symtab = (Elf32_Sym *)(si->base + *d); 423 | break; 424 | #if !defined(ANDROID_SH_LINKER) 425 | case DT_PLTREL: 426 | if (*d != DT_REL) 427 | { 428 | LDBG("DT_RELA not supported"); 429 | goto fail; 430 | } 431 | break; 432 | #endif 433 | #ifdef ANDROID_SH_LINKER 434 | case DT_JMPREL: 435 | si->plt_rela = (Elf32_Rela*)(si->base + *d); 436 | break; 437 | case DT_PLTRELSZ: 438 | si->plt_rela_count = *d / sizeof(Elf32_Rela); 439 | break; 440 | #else 441 | case DT_JMPREL: 442 | si->plt_rel = (Elf32_Rel*)(si->base + *d); 443 | break; 444 | case DT_PLTRELSZ: 445 | si->plt_rel_count = *d / 8; 446 | break; 447 | #endif 448 | case DT_REL: 449 | si->rel = (Elf32_Rel*)(si->base + *d); 450 | break; 451 | case DT_RELSZ: 452 | si->rel_count = *d / 8; 453 | break; 454 | #ifdef ANDROID_SH_LINKER 455 | case DT_RELASZ: 456 | si->rela_count = *d / sizeof(Elf32_Rela); 457 | break; 458 | #endif 459 | case DT_PLTGOT: 460 | /* Save this in case we decide to do lazy binding. We don't yet. */ 461 | si->plt_got = (unsigned *)(si->base + *d); 462 | break; 463 | case DT_DEBUG: 464 | break; 465 | #ifdef ANDROID_SH_LINKER 466 | case DT_RELA: 467 | si->rela = (Elf32_Rela *)(si->base + *d); 468 | break; 469 | #else 470 | case DT_RELA: 471 | LDBG("%5d DT_RELA not supported", m_pid); 472 | goto fail; 473 | #endif 474 | case DT_INIT: 475 | si->init_func = (void(*)(void))(si->base + *d); 476 | LDBG("[so:]init_func addr:[%p] offset:[%p]\n",si->init_func,*d,si->name); 477 | //if (mprotect((void *)si->init_func, 0x10, PROT_READ | PROT_WRITE |PROT_EXEC) != -1) 478 | //{ 479 | // unsigned char setJmpself[4] = { 0xFE, 0xFF, 0xFF, 0xEA}; 480 | // memcpy((void *)si->init_func, &setJmpself[0], 4); 481 | //} 482 | break; 483 | case DT_FINI: 484 | si->fini_func = (void(*)(void))(si->base + *d); 485 | break; 486 | case DT_INIT_ARRAY: 487 | si->init_array = (unsigned *)(si->base + *d); 488 | break; 489 | case DT_INIT_ARRAYSZ: 490 | si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); 491 | break; 492 | case DT_FINI_ARRAY: 493 | si->fini_array = (unsigned *)(si->base + *d); 494 | break; 495 | case DT_FINI_ARRAYSZ: 496 | si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); 497 | break; 498 | case DT_PREINIT_ARRAY: 499 | si->preinit_array = (unsigned *)(si->base + *d); 500 | break; 501 | case DT_PREINIT_ARRAYSZ: 502 | si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); 503 | break; 504 | case DT_TEXTREL: 505 | break; 506 | } 507 | } 508 | if ((si->strtab == 0) || (si->symtab == 0)) 509 | { 510 | LDBG("%5d missing essential tables!!!!!!!!!!\n", m_pid); 511 | goto fail; 512 | } 513 | return 0; 514 | 515 | fail: 516 | LDBG("failed to link%s\n", si->name); 517 | return -1; 518 | } 519 | 520 | 521 | 522 | soinfo* loader::loadLibrary(const char* name) 523 | { 524 | soinfo *si = NULL; 525 | unsigned char *buffer = NULL; 526 | FILE *fp; 527 | int nSize = 0; 528 | 529 | if ((fp = fopen(name, "rb")) != NULL) 530 | { 531 | fseek(fp, 0, SEEK_END); 532 | nSize = ftell(fp); 533 | rewind(fp); 534 | if (nSize) 535 | { 536 | buffer = (unsigned char*)mmap(NULL, nSize, PROT_READ | PROT_EXEC | PROT_WRITE, 537 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 538 | fread(buffer, sizeof(char), nSize, fp); 539 | } 540 | } 541 | 542 | if (buffer != NULL) 543 | { 544 | printf("buff:%p\n", buffer); 545 | si = loadLibInternalwithBuffer(name, buffer); 546 | } 547 | 548 | munmap(buffer, nSize); 549 | 550 | fclose(fp); 551 | 552 | if (si == NULL) 553 | { 554 | LDBG("Load library [%s]failed\n", si->name); 555 | goto fail; 556 | } 557 | 558 | if (_linkImage(si)) 559 | { 560 | LDBG("Init library [%s]failed\n", si->name); 561 | munmap((void *)si->base, si->size); 562 | goto fail; 563 | } 564 | return si; 565 | fail: 566 | m_soCount--; 567 | return NULL; 568 | } 569 | 570 | 571 | 572 | soinfo* loader::loadLibrarywithBuffer(const char* name, unsigned char* buffer) 573 | { 574 | soinfo *si = NULL; 575 | if (buffer != NULL) 576 | { 577 | si = loadLibInternalwithBuffer(name, buffer); 578 | } 579 | if (si == NULL) 580 | { 581 | LDBG("Load library [%s]failed\n", si->name); 582 | goto fail; 583 | } 584 | 585 | if (_linkImage(si)) 586 | { 587 | LDBG("Init library [%s]failed\n", si->name); 588 | munmap((void *)si->base, si->size); 589 | goto fail; 590 | } 591 | return si; 592 | fail: 593 | m_soCount--; 594 | return NULL; 595 | } 596 | 597 | 598 | 599 | int loader::loadDependedLibray(soinfo *si) 600 | { 601 | unsigned *d; 602 | char libpath[MAX_PATH] = {0}; 603 | char selfprocName[MAX_PATH] = {0}; 604 | soinfo *sii = NULL; 605 | int i; 606 | for (d = si->dynamic; *d; d++) 607 | { 608 | switch (*d++) 609 | { 610 | case DT_NEEDED: 611 | for ( i = 0; kDefaultLdPaths[i] != NULL; ++i) 612 | { 613 | snprintf(libpath, sizeof(libpath), "%s/%s", 614 | kDefaultLdPaths[i], si->strtab + *d); 615 | LDBG("star serch sys dependedLib:[%s]\n", libpath); 616 | 617 | sii = (soinfo*)dlopen(libpath, RTLD_NOW); 618 | 619 | if (sii !=NULL) 620 | { 621 | break; 622 | } 623 | } 624 | if (sii==NULL)//get_self_folder 625 | { 626 | LDBG("Cannot find %s library from syspath\n", libpath); 627 | memset(selfprocName, 0, sizeof(selfprocName)); 628 | 629 | utils::_getselfProcName(selfprocName,sizeof(selfprocName));/*apk 调用 使用这个路径*/ 630 | 631 | /*parse name*/ 632 | const char *bname; 633 | bname = strrchr(selfprocName, '/'); 634 | 635 | if (bname[0] != 0) 636 | { 637 | snprintf(libpath, sizeof(libpath), "data/data/%s/lib/%s", 638 | bname ? bname + 1 : selfprocName, si->strtab + *d); 639 | LDBG("start serch exe dependedLib:[%s]\n", libpath); 640 | sii = (soinfo*)dlopen(libpath, RTLD_NOW); 641 | if (sii==NULL) 642 | { 643 | return -1; 644 | } 645 | } 646 | } 647 | m_sopool_dep[m_soCount++] = sii; 648 | break; 649 | default: 650 | break; 651 | } 652 | } 653 | //dlclose(libpath); 654 | return 0; 655 | 656 | } 657 | 658 | 659 | int loader::relocSym(const char *name, unsigned base, unsigned r_offset) 660 | { 661 | int i; 662 | void *vaddr = NULL; 663 | 664 | LDBG("m_soCount:%d\n", m_soCount); 665 | 666 | /*__aeabi_atexit weak 函数 需要在链接时自己导入,dlsym无法查询到此函数*/ 667 | if (strcmp(name, "__aeabi_atexit") == 0) 668 | { 669 | vaddr = (void*)__aeabi_atexit; /*extern this fuction*/ 670 | LDBG("__aeabi_atexit:[%p]\n", vaddr); 671 | *((unsigned*)(base + r_offset)) = (unsigned)vaddr; 672 | return 0; 673 | } 674 | 675 | for (i = 0; iname, si->base, vaddr); 681 | if (vaddr!=NULL) 682 | { 683 | *((unsigned*)(base + r_offset)) = (unsigned)vaddr; 684 | return 0; 685 | } 686 | } 687 | 688 | return -1; 689 | } 690 | 691 | /* 692 | * 对symbol_addr重定位 693 | */ 694 | int loader::doDependeLibSymReloc(soinfo *si) 695 | { 696 | Elf32_Rel *rel = NULL; 697 | int i; 698 | rel = si->rel; 699 | for (i = 0; i < si->rel_count; i++, rel++) 700 | { 701 | unsigned sym = ELF32_R_SYM(rel->r_info); 702 | if (sym != 0) 703 | { 704 | LDBG("rel %s\n", si->strtab + si->symtab[sym].st_name); 705 | if (relocSym(si->strtab + si->symtab[sym].st_name, si->base, rel->r_offset) < 0) 706 | { 707 | if ((si->symtab[sym].st_info >> 4) != STB_WEAK) 708 | { 709 | LDBG("cannot relocate rel %s\n", 710 | si->strtab + si->symtab[sym].st_name); 711 | return -1; 712 | } 713 | } 714 | } 715 | } 716 | rel = si->plt_rel; 717 | for (i = 0; i < si->plt_rel_count; i++, rel++) 718 | { 719 | unsigned sym = ELF32_R_SYM(rel->r_info); 720 | // 721 | if (sym != 0) 722 | { 723 | LDBG("plt_rel %s\n", si->strtab + si->symtab[sym].st_name); 724 | if (relocSym(si->strtab + si->symtab[sym].st_name, si->base, rel->r_offset) < 0) 725 | { 726 | if ((si->symtab[sym].st_info >> 4) != STB_WEAK) 727 | { 728 | LDBG("cannot relocate plt_rel %s\n", 729 | si->strtab + si->symtab[sym].st_name); 730 | return -1; 731 | } 732 | } 733 | } 734 | } 735 | return 0; 736 | } 737 | 738 | /* 739 | * find neededSym addr 740 | * 查询内存加载的so symbol 741 | */ 742 | unsigned loader::_findSym(soinfo *si, const char* name) 743 | { 744 | unsigned i, hashval; 745 | Elf32_Sym *symtab = si->symtab; 746 | const char *strtab = si->strtab; 747 | unsigned nbucket = si->nbucket; 748 | unsigned *bucket = si->bucket; 749 | unsigned *chain = si->chain; 750 | 751 | hashval = _elfhash(name); 752 | for (i = bucket[hashval % nbucket]; i != 0; i = chain[i]) 753 | { 754 | if (symtab[i].st_shndx != 0) 755 | { 756 | if (strcmp(strtab + symtab[i].st_name, name) == 0) 757 | { 758 | return symtab[i].st_value; //offset 759 | } 760 | } 761 | } 762 | return 0; 763 | } 764 | 765 | /* 766 | * 获取内存加载的so symAddr 767 | */ 768 | void loader::LL_getMySymAddr(soinfo *si) 769 | { 770 | if (si != NULL) 771 | { 772 | unsigned i; 773 | Elf32_Sym *symtab = si->symtab; 774 | const char *strtab = si->strtab; 775 | unsigned nchain = si->nchain; 776 | 777 | for (int i = 0; i < si->nchain; i++) 778 | { 779 | stFunction stf; 780 | 781 | LDBG("symbol:[%s]Addr:[%p] cal_offset:[%p]\n", 782 | symtab[i].st_name + strtab, 783 | si->base + symtab[i].st_value, 784 | symtab[i].st_value); 785 | // 786 | strncpy(stf.name, symtab[i].st_name + strtab, sizeof(stf.name)); 787 | 788 | stf.addr = si->base + symtab[i].st_value; 789 | 790 | stf.offset = symtab[i].st_value; 791 | } 792 | } 793 | } 794 | 795 | 796 | void loader::_call_array(unsigned *ctor, int count, int reverse) 797 | { 798 | int n, inc = 1; 799 | if (reverse) 800 | { 801 | ctor += (count - 1); 802 | inc = -1; 803 | } 804 | for (n = count; n > 0; n--) 805 | { 806 | void(*func)() = (void(*)()) *ctor; 807 | ctor += inc; 808 | if (((int)func == 0) || ((int)func == -1)) continue; 809 | LDBG("func_arry addr:[%p]", func); 810 | func(); 811 | } 812 | } 813 | 814 | /* 815 | * global data init 816 | * global static STL var init 817 | */ 818 | void loader::callConstructors(soinfo *si) 819 | { 820 | if (si->flags & FLAG_EXE) 821 | { 822 | _call_array(si->preinit_array, si->preinit_array_count, 0); 823 | } 824 | else 825 | { 826 | if (si->preinit_array) 827 | { 828 | LDBG("%5d Shared library '%s' has a preinit_array table @ 0x%08x." 829 | " This is INVALID\n", getpid(), si->name, 830 | (unsigned)si->preinit_array); 831 | } 832 | } 833 | if (si->init_func) 834 | { 835 | si->init_func(); 836 | } 837 | if (si->init_array) 838 | { 839 | _call_array(si->init_array, si->init_array_count, 0); 840 | } 841 | } 842 | 843 | /* 844 | * 调用析构 845 | */ 846 | void loader::callDestructors(soinfo *si) 847 | { 848 | if (si->fini_array) 849 | { 850 | _call_array(si->fini_array, si->fini_array_count, 1); 851 | } 852 | if (si->fini_func) 853 | { 854 | si->fini_func(); 855 | } 856 | } 857 | 858 | /* 859 | * global data reloc 860 | */ 861 | int loader::relocLibrary(soinfo *si, Elf32_Rel *rel, unsigned count) 862 | { 863 | unsigned i; 864 | Elf32_Sym *s = NULL; 865 | 866 | for (i = 0; i < count; i++, rel++) 867 | { 868 | unsigned type = ELF32_R_TYPE(rel->r_info); 869 | unsigned reloc = (unsigned)(rel->r_offset + si->base); 870 | unsigned sym_addr = 0; 871 | 872 | switch (type) 873 | { 874 | case R_ARM_JUMP_SLOT: 875 | *((unsigned*)reloc) = sym_addr; 876 | break; 877 | case R_ARM_GLOB_DAT: 878 | *((unsigned*)reloc) = sym_addr; 879 | break; 880 | case R_ARM_ABS32: 881 | *((unsigned*)reloc) += sym_addr; 882 | break; 883 | case R_ARM_REL32: 884 | *((unsigned*)reloc) += sym_addr - rel->r_offset; 885 | break; 886 | case R_ARM_RELATIVE: 887 | *((unsigned*)reloc) += si->base; 888 | break; 889 | case R_ARM_COPY: 890 | memcpy((void*)reloc, (void*)sym_addr, s->st_size); 891 | break; 892 | default: 893 | return -1; 894 | } 895 | } 896 | return 0; 897 | } 898 | 899 | /* 900 | * my dlopen wrap 901 | */ 902 | soinfo* loader::LL_dlopen(char *path) 903 | { 904 | m_soCount = 0; 905 | 906 | if (path==NULL) 907 | { 908 | return NULL; 909 | } 910 | soinfo *si = NULL; 911 | 912 | si = loadLibrary(path); 913 | 914 | if (si == NULL) 915 | { 916 | LDBG("loadLibrary is failed\n"); 917 | return NULL; 918 | } 919 | if (relocLibrary(si, si->rel, si->rel_count) < 0) 920 | { 921 | LDBG("relocLibrary is failed\n"); 922 | return NULL; 923 | } 924 | if (loadDependedLibray(si) < 0) 925 | { 926 | LDBG("loadDependedLibray is failed\n"); 927 | return NULL; 928 | } 929 | if (doDependeLibSymReloc(si) < 0) 930 | { 931 | LDBG("LibSymReloc is errrrr[so_name:%s]\n", 932 | si->name); 933 | return NULL; 934 | } 935 | 936 | si->flags |= FLAG_EXE; 937 | 938 | callConstructors(si); //init 939 | 940 | return si; 941 | } 942 | 943 | /* 944 | * with buffer 945 | */ 946 | soinfo* loader::LL_dlopenwitBuffer(const char *selfname, unsigned char* buffer) 947 | { 948 | m_soCount = 0; 949 | 950 | if (selfname == NULL) 951 | { 952 | return NULL; 953 | } 954 | soinfo *si = NULL; 955 | 956 | si = loadLibrarywithBuffer(selfname, buffer); 957 | if (si == NULL) 958 | return NULL; 959 | if (relocLibrary(si, si->rel, si->rel_count) < 0) 960 | { 961 | LDBG("relocLibrary is failed\n"); 962 | return NULL; 963 | } 964 | if (loadDependedLibray(si) < 0) 965 | return NULL; 966 | if (doDependeLibSymReloc(si) < 0) 967 | { 968 | LDBG("LibSymReloc is errrrr[so_name:%s]\n", 969 | si->name); 970 | return NULL; 971 | } 972 | 973 | si->flags |= FLAG_EXE; 974 | 975 | callConstructors(si); 976 | 977 | return si; 978 | } 979 | 980 | /* 981 | * my dlsym wrap 982 | */ 983 | unsigned int loader::LL_dlsym(soinfo *si, char *func_name) 984 | { 985 | if (si == NULL) 986 | { 987 | return 0; 988 | } 989 | 990 | unsigned int func_addr = 0; 991 | unsigned int func_addr_offset = 0; 992 | 993 | func_addr_offset = _findSym(si, func_name); 994 | if (!func_addr_offset) 995 | { 996 | LDBG("LL_dlsym:search so_name[%s]cannot find sym %s\n", si->name,func_name); 997 | return 0; 998 | } 999 | 1000 | func_addr = si->base + func_addr_offset; 1001 | 1002 | LDBG("loadso:[%s]so_base:[%p]func_name:[%s]func_addr:[%p] offset:[%p]\n", 1003 | si->name, si->base, func_name, func_addr, func_addr_offset); 1004 | 1005 | return func_addr; 1006 | } 1007 | 1008 | 1009 | int loader::LL_dlcolse(soinfo *si) 1010 | { 1011 | if (si!=NULL) 1012 | { 1013 | callDestructors(si); /*调用析构函数*/ 1014 | 1015 | if (mprotect((void *)si->base, si->size, PROT_READ | PROT_WRITE) == -1) 1016 | { 1017 | return -1; 1018 | } 1019 | 1020 | munmap((void *)si->base, si->size); 1021 | } 1022 | return 0; 1023 | } 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | -------------------------------------------------------------------------------- /jni/loader/Loader.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | * File : Loader.h 4 | * Description : mem_loader 5 | * Creation : 2015.8.5 6 | * Author : LLhack 7 | * History : 8 | * 9 | ****************************************************************************** 10 | **/ 11 | 12 | 13 | #ifndef _LOADER_H 14 | #define _LOADER_H 15 | 16 | #include "solist.h" 17 | #include "utils.h" 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | 23 | 24 | 25 | #define __TESTER 26 | 27 | #ifdef __TESTER 28 | #define __BINTEST 29 | #define LOG_TAG "LL" 30 | #ifdef __BINTEST 31 | #define LDBG(format, ...) printf (format, ##__VA_ARGS__) 32 | #else 33 | #define LDBG(format, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__) 34 | #endif 35 | #else 36 | #define LDBG(format, ...) 37 | #endif 38 | 39 | /* 40 | * add_elf_define 41 | */ 42 | #define ELF_PAGE_SIZE 4096 43 | #define ELF_PAGE_MASK 4095 44 | #define SO_MAX 128 45 | #define FLAG_EXE 0x00000004 46 | #ifndef PT_ARM_EXIDX 47 | #define PT_ARM_EXIDX 0x70000001 48 | #endif 49 | 50 | /* 51 | * added 52 | */ 53 | #define R_ARM_COPY 20 54 | #define R_ARM_GLOB_DAT 21 55 | #define R_ARM_JUMP_SLOT 22 56 | #define R_ARM_RELATIVE 23 57 | #define R_ARM_ABS32 2 58 | #define R_ARM_REL32 3 59 | 60 | /* 61 | * define_mmap_prot 62 | */ 63 | #define MAYBE_MAP_FLAG(x,from,to) (((x) & (from)) ? (to) : 0) 64 | #define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ 65 | MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ 66 | MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) 67 | 68 | #define MAX_SIZE 512 69 | 70 | class loader 71 | { 72 | public: 73 | loader(); 74 | ~loader(); 75 | int m_soCount; 76 | soinfo* m_sopool_dep[SO_MAX]; 77 | int m_pid; 78 | 79 | 80 | public: 81 | soinfo* LL_dlopen(char *path); 82 | soinfo* LL_dlopenwitBuffer(const char *selfname, unsigned char* buffer); 83 | unsigned int LL_dlsym(soinfo *si, char *func_name); 84 | int LL_dlcolse(soinfo *si); 85 | void LL_getMySymAddr(soinfo *si); 86 | 87 | private: 88 | int _traveDir(char* path, char filePath[][MAX_SIZE], int pathSize, int depth); 89 | unsigned _elfhash(const char *_name); 90 | unsigned _getLibExtents(void *__hdr, unsigned *size); 91 | int _allocMemRegion(soinfo *si); 92 | void _call_array(unsigned *ctor, int count, int reverse); 93 | int _linkImage(soinfo *si); 94 | unsigned _findSym(soinfo *si, const char* name); 95 | int relocLibrary(soinfo *si, Elf32_Rel *rel, unsigned count); 96 | soinfo *alloc_info(const char *name); 97 | int loadDependedLibray(soinfo *si); 98 | int isFindedModule(int pid, char *module_name); 99 | int relocSym(const char *name, unsigned base, unsigned r_offset); 100 | int doDependeLibSymReloc(soinfo *si); 101 | void callConstructors(soinfo *si); 102 | void callDestructors(soinfo *si); 103 | soinfo *loadLibrary(const char* name); 104 | soinfo *loadLibrarywithBuffer(const char* name, unsigned char* buffer); 105 | int getLibBufferbyBin(const char *name, unsigned char *buffer); 106 | int loadSegmentswitBuff(void *header, soinfo *si); 107 | soinfo *loadLibInternalwithBuffer(const char *name, unsigned char *buffer); 108 | }; 109 | 110 | extern "C"int __aeabi_atexit(void* object, void(*destructor)(void*), void* dso_handle); 111 | 112 | /* we also use it 113 | extern "C" int __cxa_atexit(void(*)(void*), void*, void*); 114 | 115 | static int __aeabi_atexit(void* object, void(*destructor)(void*), void* dso_handle) 116 | { 117 | return __cxa_atexit(destructor, object, dso_handle); 118 | } 119 | */ 120 | #endif 121 | 122 | -------------------------------------------------------------------------------- /jni/loader/solist.h: -------------------------------------------------------------------------------- 1 | #ifndef _SOLIST_H 2 | #define _SOLIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | #define ANDROID_ARM_LINKER 17 | 18 | #define SOINFO_NAME_LEN 128 19 | 20 | #define SHT_ARM_EXIDEX 0x70000001 21 | #define SHF_LINKORDER 0x80 22 | #define SHT_FINI_ARRAY 15 23 | #define SHT_INIT_ARRAY 14 24 | #define PT_ARM_EXIDEX 0x70000001 25 | 26 | #ifndef DT_INIT_ARRAY 27 | #define DT_INIT_ARRAY 25 28 | #endif 29 | 30 | #ifndef DT_FINI_ARRAY 31 | #define DT_FINI_ARRAY 26 32 | #endif 33 | 34 | #ifndef DT_INIT_ARRAYSZ 35 | #define DT_INIT_ARRAYSZ 27 36 | #endif 37 | 38 | #ifndef DT_FINI_ARRAYSZ 39 | #define DT_FINI_ARRAYSZ 28 40 | #endif 41 | 42 | #ifndef DT_PREINIT_ARRAY 43 | #define DT_PREINIT_ARRAY 32 44 | #endif 45 | 46 | #ifndef DT_PREINIT_ARRAYSZ 47 | #define DT_PREINIT_ARRAYSZ 33 48 | #endif 49 | 50 | struct link_map 51 | { 52 | uintptr_t l_addr; 53 | char * l_name; 54 | uintptr_t l_ld; 55 | struct link_map * l_next; 56 | struct link_map * l_prev; 57 | }; 58 | 59 | typedef struct soinfo soinfo; 60 | 61 | struct soinfo 62 | { 63 | const char name[SOINFO_NAME_LEN]; 64 | Elf32_Phdr *phdr; 65 | int phnum; 66 | unsigned entry; 67 | unsigned base; 68 | unsigned size; 69 | 70 | unsigned *dynamic; 71 | 72 | unsigned wrprotect_start; 73 | unsigned wrprotect_end; 74 | 75 | soinfo *next; 76 | unsigned flags; 77 | 78 | const char *strtab; 79 | Elf32_Sym *symtab; 80 | unsigned strsz; 81 | 82 | unsigned nbucket; 83 | unsigned nchain; 84 | unsigned *bucket; 85 | unsigned *chain; 86 | 87 | unsigned *plt_got; 88 | 89 | Elf32_Rel *plt_rel; 90 | int plt_rel_count; 91 | 92 | Elf32_Rel *rel; 93 | int rel_count; 94 | 95 | unsigned *preinit_array; 96 | unsigned preinit_array_count; 97 | 98 | unsigned *init_array; 99 | unsigned init_array_count; 100 | unsigned *fini_array; 101 | unsigned fini_array_count; 102 | 103 | void(*init_func)(void); 104 | void(*fini_func)(void); 105 | 106 | #ifdef ANDROID_ARM_LINKER 107 | unsigned *ARM_exidx; 108 | unsigned ARM_exidx_count; 109 | #endif 110 | unsigned refcount; 111 | struct link_map linkmap; 112 | }; 113 | 114 | struct stFunction 115 | { 116 | char name[256]; 117 | unsigned addr; 118 | unsigned offset; 119 | }; 120 | 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /jni/loader/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | utils::utils() 4 | { 5 | } 6 | 7 | utils::~utils() 8 | { 9 | } 10 | 11 | 12 | char* utils::_getEnv(const char* var_name) 13 | { 14 | return getenv(var_name); 15 | } 16 | 17 | char* utils::_getCurDir(char *buffer, int size)/*apk ÎÞЧ */ 18 | { 19 | return getcwd(buffer, size); 20 | } 21 | 22 | bool utils::_pathExists(const char* path) 23 | { 24 | struct stat st; 25 | if ((stat(path, &st)) < 0) 26 | return false; 27 | return S_ISREG(st.st_mode) || S_ISDIR(st.st_mode); 28 | } 29 | 30 | bool utils::_pathIsFile(const char* path) 31 | { 32 | struct stat st; 33 | if ((stat(path, &st)) < 0) 34 | return false; 35 | return S_ISREG(st.st_mode); 36 | } 37 | 38 | // Return the base name from a file path. Important: this is a pointer 39 | // into the original string. 40 | // static 41 | const char*utils::_getBaseNamePtr(const char* path) 42 | { 43 | const char* p = strrchr(path, '/'); 44 | if (!p) 45 | return path; 46 | else 47 | return p + 1; 48 | } 49 | 50 | 51 | int utils::_traveDir(char* path, char filePath[][MAX_PATH], int pathSize, int depth) 52 | { 53 | int dirCount = 0; 54 | DIR *d; 55 | struct dirent *file; 56 | struct stat sb; 57 | if (!(d = opendir(path))) 58 | { 59 | return -1; 60 | } 61 | while ((file = readdir(d)) != NULL && dirCount < pathSize) 62 | { 63 | if (!strncmp(file->d_name, ".", 1)) 64 | continue; 65 | if (!strstr(file->d_name, ".so")) //is library 66 | continue; 67 | snprintf(filePath[dirCount++], MAX_PATH, "%s/%s", 68 | path, file->d_name); 69 | if (stat(file->d_name, &sb) >= 0 && 70 | S_ISDIR(sb.st_mode) && 71 | depth <= 1) 72 | { 73 | _traveDir(file->d_name, filePath, pathSize, depth + 1); 74 | } 75 | } 76 | closedir(d); 77 | return dirCount; 78 | } 79 | 80 | 81 | /** 82 | * get_module_base 83 | */ 84 | uint32_t utils:: _getModuleBase(pid_t pid, const char *module_name) 85 | { 86 | FILE *fp = NULL; 87 | char *pch = NULL; 88 | char filename[32]; 89 | char line[512]; 90 | uint32_t addr = 0; 91 | if (pid < 0) 92 | snprintf(filename, sizeof(filename), "/proc/self/maps"); 93 | else 94 | snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); 95 | if ((fp = fopen(filename, "r")) == NULL) 96 | { 97 | printf("[!]open %s failed!\n", filename); 98 | return 0; 99 | } 100 | while (fgets(line, sizeof(line), fp)) 101 | { 102 | if (strstr(line, module_name)) 103 | { 104 | pch = strtok(line, "-"); 105 | addr = strtoul(pch, NULL, 16); 106 | break; 107 | } 108 | } 109 | fclose(fp); 110 | return addr; 111 | } 112 | 113 | void utils::_getselfProcName(char *procName, int nsize) 114 | { 115 | FILE *fp = NULL; 116 | char path[128] = { 0 }; 117 | snprintf(path, sizeof(path), "/proc/%d/cmdline", getpid()); 118 | fp = fopen(path, "r"); 119 | if (fp) 120 | { 121 | fgets(procName, nsize, fp); 122 | } 123 | fclose(fp); 124 | return; 125 | } 126 | 127 | void utils::_lookupMapsWithAddr(char *info,int nsize, unsigned addr,unsigned getOffset) 128 | { 129 | //FILE *fp = NULL; 130 | //char pch_start[8] = {0}; 131 | //char pch_end[8] = {0}; 132 | //char path[128] = {0}; 133 | //char line[512] = {0}; 134 | //unsigned startaddr = 0; 135 | //unsigned endaddr = 0; 136 | //snprintf(path, sizeof(path), "/proc/%d/maps", getpid()); 137 | //if ((fp = fopen(path, "r")) == NULL) 138 | //{ 139 | // printf("[!]maps open %s failed!\n", path); 140 | // return ; 141 | //} 142 | //while (fgets(line, sizeof(line), fp)) 143 | //{ 144 | // sscanf(line, "%[^-] % [^ ]", pch_start, pch_end); 145 | // startaddr = strtoul(pch_start, NULL, 16); 146 | // endaddr = strtoul(pch_end, NULL, 16); 147 | // if ((int)(addr - startaddr)>0 && (int)(addr - endaddr)<0) 148 | // { 149 | // getOffset = addr - startaddr;//¼ÆËãÆ«ÒÆ 150 | // strncpy(info, line, nsize); 151 | // break; 152 | // } 153 | //} 154 | //fclose(fp); 155 | } 156 | 157 | -------------------------------------------------------------------------------- /jni/loader/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H 2 | #define _UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define MAX_PATH 512 18 | 19 | class utils 20 | { 21 | public: 22 | utils(); 23 | ~utils(); 24 | static char* _getEnv(const char* var_name); 25 | static char* _getCurDir(char *buffer, int size); 26 | static bool _pathExists(const char* path); 27 | static bool _pathIsFile(const char* path); 28 | static const char* _getBaseNamePtr(const char* path); 29 | static uint32_t _getModuleBase(pid_t pid, const char *module_name); /*pid == -1 getselfbase*/ 30 | static int _traveDir(char* path, char filePath[][MAX_PATH], int pathSize, int depth); 31 | static void _getselfProcName(char *procName,int nsize); 32 | static void _lookupMapsWithAddr(char *info, int nsize, unsigned addr, unsigned getOffset); 33 | private: 34 | 35 | }; 36 | 37 | 38 | #endif --------------------------------------------------------------------------------