├── Dummy.cpp ├── .gitignore ├── Demo.jpg ├── libsubstitute.dylib ├── CMakeLists.txt ├── Loader.cpp ├── README.md └── substrate.h /Dummy.cpp: -------------------------------------------------------------------------------- 1 | static int dummy=13; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build 3 | Loader/build/ 4 | -------------------------------------------------------------------------------- /Demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HikariObfuscator/Hanabi/HEAD/Demo.jpg -------------------------------------------------------------------------------- /libsubstitute.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HikariObfuscator/Hanabi/HEAD/libsubstitute.dylib -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION "3.13.0") 2 | add_library(LLVMHanabiDeps SHARED #This is for linking a minimum subset of LLVM needed which serves as the escape plan 3 | ${CMAKE_CURRENT_LIST_DIR}/Dummy.cpp 4 | ) 5 | add_dependencies(LLVMHanabiDeps 6 | LLVMCore 7 | LLVMSupport 8 | ) 9 | add_library(LLVMHanabi SHARED 10 | ${CMAKE_CURRENT_LIST_DIR}/Loader.cpp 11 | ) 12 | add_dependencies(LLVMHanabi 13 | LLVMHanabiDeps 14 | LLVMObfuscation 15 | ) 16 | target_link_libraries(LLVMHanabi PRIVATE LLVMObfuscation ${CMAKE_CURRENT_LIST_DIR}/libsubstitute.dylib) 17 | target_link_options(LLVMHanabi PRIVATE -undefined PRIVATE dynamic_lookup PRIVATE -flat_namespace) 18 | target_compile_options(LLVMHanabi PRIVATE -Wno-dollar-in-identifier-extension PRIVATE -Wno-variadic-macros PRIVATE) 19 | 20 | target_link_libraries(LLVMHanabiDeps PRIVATE LLVMCore LLVMSupport ${CMAKE_CURRENT_LIST_DIR}/libsubstitute.dylib) 21 | target_link_options(LLVMHanabiDeps PRIVATE -undefined PRIVATE dynamic_lookup PRIVATE -all_load) 22 | -------------------------------------------------------------------------------- /Loader.cpp: -------------------------------------------------------------------------------- 1 | // For open-source license, please refer to [License](https://github.com/HikariObfuscator/Hikari/wiki/License). 2 | #include "substrate.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS==1 8 | #error "Configure LLVM with -DLLVM_ABI_BREAKING_CHECKS=FORCE_OFF" 9 | #endif 10 | using namespace std; 11 | void (*old_pmb)(void* dis,legacy::PassManagerBase &MPM); 12 | Pass* (*old_get_LS)(); 13 | extern "C" Pass* _ZN4llvm21createLowerSwitchPassEv(){ 14 | return old_get_LS(); 15 | } 16 | static void new_pmb(void* dis,legacy::PassManagerBase &MPM){ 17 | MPM.add(createObfuscationPass()); 18 | old_pmb(dis,MPM); 19 | } 20 | static __attribute__((__constructor__)) void Inj3c73d(int argc, char* argv[]){ 21 | char* executablePath=argv[0]; 22 | //Initialize our own LLVM Library 23 | MSImageRef exeImagemage=MSGetImageByName(executablePath); 24 | errs()<<"Applying Apple Clang Hooks...\n"; 25 | MSHookFunction((void*)MSFindSymbol(exeImagemage,"__ZN4llvm18PassManagerBuilder25populateModulePassManagerERNS_6legacy15PassManagerBaseE"),(void*)new_pmb,(void**)&old_pmb); 26 | old_get_LS=(Pass* (*)())MSFindSymbol(exeImagemage,"__ZN4llvm15callDefaultCtorIN12_GLOBAL__N_111LowerSwitchEEEPNS_4PassEv"); 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 花火 2 | Hassle-free Obfuscator-Enabled Apple Clang without any sort of compromise. 3 | ![](https://github.com/HikariObfuscator/NatsukoiHanabi/blob/master/Demo.jpg?raw=true) 4 | 5 | # License 6 | Please refer to [License](https://github.com/HikariObfuscator/Hikari/wiki/License). 7 | 8 | Note that this linked version of license text overrides any artifact left in source code 9 | 10 | # Must be this tall to ride 11 | Due to its hackish nature (Which is why I don't want to do this in the first place), you should probably know some LLVM/macOS Hooking/Binary Patching and stuff to debug this thing 12 | 13 | # Using Release Builds 14 | - Extract the zipped file and move two extracted dylibs under ``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin `` 15 | - Download [libsubstitute.dylib](https://github.com/HikariObfuscator/Hanabi/raw/master/libsubstitute.dylib) and move it to ``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin `` 16 | - See [Patching](#patching). Ignore library not found in that release version 17 | 18 | # Building 19 | - ``$(LLVM_SOURCE_PATH)`` The path that stored Hikari's main repo with submodules properly fetched. It's suggested to use a Hikari branch that matches your Apple Clang's LLVM version. See [Release Versioning Scheme](#release-versioning-scheme) to see how to find the LLVM version of your Clang 20 | - ``${LLVM_BUILD_PATH}`` The path you prepare to build in. Note that you need a seperate folder and must not reuse existing build for upstream Hikari 21 | 22 | ## Obtaining Source 23 | - ``git clone https://github.com/HikariObfuscator/Hanabi.git $(LLVM_SOURCE_PATH)/projects/`` 24 | - Under ``$(LLVM_SOURCE_PATH)``, run ``git submodule update --init --recursive --remote`` to make sure submodules are fully updated 25 | 26 | ## Build 27 | - ``cmake $(LLVM_SOURCE_PATH) -DCMAKE_BUILD_TYPE=Release -DLLVM_ABI_BREAKING_CHECKS=FORCE_OFF -G Ninja`` 28 | - ``ninja LLVMHanabi`` 29 | - Copy ``$(LLVM_BUILD_PATH)/lib/libLLVMHanabiDeps.dylib`` to ``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/`` 30 | - Copy ``$(LLVM_BUILD_PATH)/lib/libLLVMHanabi.dylib`` to ``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/`` 31 | - Copy ``$(LLVM_SOURCE_PATH)/projects/Hanabi/libsubstitute.dylib`` to ``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/`` 32 | 33 | # Patching 34 | 35 | You need to build ``https://github.com/alexzielenski/optool`` and put it in your $PATH, then you need to patch two libraries into Clang/SwiftC. 36 | **!!!ORDER IS VERY IMPORTANT!!!** 37 | - ``sudo optool install -c load -p @executable_path/libLLVMHanabiDeps.dylib -t /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang`` 38 | - ``sudo optool install -c load -p @executable_path/libLLVMHanabi.dylib -t /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang`` 39 | 40 | # Known Issues 41 | - LLVM 6.0.1 (which Xcode 10.1 and before is using) has bugs related to ``indirectbr`` CodeGeneration, you might get a crash if you enable ``INDIBRAN``. Try updating your Xcode version 42 | 43 | 44 | # How it works 45 | - Strictly speaking, many changes are done to the Hikari Core to reduce LLVM library dependencies. 46 | - Loader's linking options is modified to link to no LLVM library and fully resolve them at runtime in a flat namespace, this loader is also known as ``libLLVMHanabi.dylib`` 47 | - Then, we ship a custom mimimal subset of LLVM Core Libraries which serves as the fallback plan for symbols that are not exported in Apple's binaries, this is known as ``libLLVMHanabiDeps.dylib``. 48 | - By not linking the full LLVM suite, we are allowed to reduce build time and more importantly, allows us to pass arguments like we normally would. (``-mllvm``) 49 | 50 | 51 | # Release Versioning Scheme 52 | The releases has a versioning scheme like ``6.0@9ab263@LoaderV3`` where the first part represents LLVM base version, the second represents Hikari Core's git commit hash and the third one represents the Loader implementation version. In this case, it means the release is tested to work on a Xcode version that uses LLVM6.0. You can refer to ``Toolchain version history`` in [Xcode - Wikipedia](https://en.wikipedia.org/wiki/Xcode) and uses the ``LLVM`` column to find the matching Xcode version, which is this case is ``Xcode 10.0`` and ``Xcode 10.1``. This release uses [Core](https://github.com/HikariObfuscator/Core) at 9ab263 and V3 of the loader 53 | # Credits 54 | 55 | - Thanks to [@AloneMonkey](https://github.com/AloneMonkey) for compiling substitute and ship it with his amazing project [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev/blob/master/MFrameworks/libsubstitute.dylib) 56 | - Thanks to [@UESTC-LXY](https://github.com/UESTC-LXY) for testing and discussion because I didn't bother to do so. 57 | - Thanks to[@qokelate](https://github.com/qokelate) for initially discovering the broken CMake script and testing the new fix as well as suggestions to this README 58 | -------------------------------------------------------------------------------- /substrate.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* Modified from git revision 904d20f414c79a2716680f4d29d833e6ce0dcea2 by comex 6 | * to act as a compatibility shim for libsubstitute; the changes consist of 7 | * removing MSHookMessage, MSHookProcess (for now), and some internal 8 | * functions, and setting custom asm names for all non-inline functions. 9 | * 10 | * The purpose of the custom asm names is to allow the shim to be applied at 11 | * either the source or binary level (the latter mainly for testing purposes). 12 | * Normally, due to two-level name lookup, exposing the regular names in 13 | * libsubstitute.dylib would suffice for this, even if it's loaded in the same 14 | * process as Substrate, but not with DYLD_FORCE_FLAT_NAMESPACE etc. 15 | * Therefore, making a binary use this requires hacking it up with sed. With 16 | * source, just put the directory containing this file in your include path. 17 | */ 18 | 19 | /* GNU Lesser General Public License, Version 3 {{{ */ 20 | /* 21 | * Substrate is free software: you can redistribute it and/or modify it under 22 | * the terms of the GNU Lesser General Public License as published by the 23 | * Free Software Foundation, either version 3 of the License, or (at your 24 | * option) any later version. 25 | * 26 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 27 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 28 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 29 | * License for more details. 30 | * 31 | * You should have received a copy of the GNU Lesser General Public License 32 | * along with Substrate. If not, see . 33 | **/ 34 | /* }}} */ 35 | 36 | #ifndef SUBSTRATE_H_ 37 | #define SUBSTRATE_H_ 38 | 39 | #ifdef __APPLE__ 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | #include 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #include 49 | #include 50 | #endif 51 | 52 | #include 53 | #include 54 | 55 | #define _finline \ 56 | inline __attribute__((__always_inline__)) 57 | #define _disused \ 58 | __attribute__((__unused__)) 59 | 60 | #define _extern \ 61 | extern "C" __attribute__((__visibility__("default"))) 62 | 63 | #ifdef __cplusplus 64 | #define _default(value) = value 65 | #else 66 | #define _default(value) 67 | #endif 68 | 69 | #ifdef __cplusplus 70 | extern "C" { 71 | #endif 72 | 73 | typedef const void *MSImageRef; 74 | 75 | MSImageRef MSGetImageByName(const char *file) 76 | __asm__("SubGetImageByName"); 77 | void *MSFindSymbol(MSImageRef image, const char *name) 78 | __asm__("SubFindSymbol"); 79 | 80 | void MSHookFunction(void *symbol, void *replace, void **result) 81 | __asm__("SubHookFunction"); 82 | 83 | #ifdef __APPLE__ 84 | void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result) 85 | __asm__("SubHookMessageEx"); 86 | #endif 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | 94 | #ifdef __APPLE__ 95 | 96 | namespace etl { 97 | 98 | template 99 | struct Case { 100 | static char value[Case_ + 1]; 101 | }; 102 | 103 | typedef Case Yes; 104 | typedef Case No; 105 | 106 | namespace be { 107 | template 108 | static Yes CheckClass_(void (Checked_::*)()); 109 | 110 | template 111 | static No CheckClass_(...); 112 | } 113 | 114 | template 115 | struct IsClass { 116 | void gcc32(); 117 | 118 | static const bool value = (sizeof(be::CheckClass_(0).value) == sizeof(Yes::value)); 119 | }; 120 | 121 | } 122 | 123 | #ifdef __arm__ 124 | template 125 | __attribute__((__deprecated__)) 126 | static inline Type_ *MSHookMessage(Class _class, SEL sel, Type_ *imp, const char *prefix = NULL) { 127 | return reinterpret_cast(MSHookMessage(_class, sel, reinterpret_cast(imp), prefix)); 128 | } 129 | #endif 130 | 131 | template 132 | static inline void MSHookMessage(Class _class, SEL sel, Type_ *imp, Type_ **result) { 133 | return MSHookMessageEx(_class, sel, reinterpret_cast(imp), reinterpret_cast(result)); 134 | } 135 | 136 | template 137 | static inline Type_ &MSHookIvar(id self, const char *name) { 138 | Ivar ivar(class_getInstanceVariable(object_getClass(self), name)); 139 | #if __has_feature(objc_arc) 140 | void *pointer(ivar == NULL ? NULL : reinterpret_cast((__bridge void *)self) + ivar_getOffset(ivar)); 141 | #else 142 | void *pointer(ivar == NULL ? NULL : reinterpret_cast(self) + ivar_getOffset(ivar)); 143 | #endif 144 | return *reinterpret_cast(pointer); 145 | } 146 | 147 | #define MSAddMessage0(_class, type, arg0) \ 148 | class_addMethod($ ## _class, @selector(arg0), (IMP) &$ ## _class ## $ ## arg0, type); 149 | #define MSAddMessage1(_class, type, arg0) \ 150 | class_addMethod($ ## _class, @selector(arg0:), (IMP) &$ ## _class ## $ ## arg0 ## $, type); 151 | #define MSAddMessage2(_class, type, arg0, arg1) \ 152 | class_addMethod($ ## _class, @selector(arg0:arg1:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $, type); 153 | #define MSAddMessage3(_class, type, arg0, arg1, arg2) \ 154 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $, type); 155 | #define MSAddMessage4(_class, type, arg0, arg1, arg2, arg3) \ 156 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $, type); 157 | #define MSAddMessage5(_class, type, arg0, arg1, arg2, arg3, arg4) \ 158 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $, type); 159 | #define MSAddMessage6(_class, type, arg0, arg1, arg2, arg3, arg4, arg5) \ 160 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $, type); 161 | 162 | #define MSHookMessage0(_class, arg0) \ 163 | MSHookMessage($ ## _class, @selector(arg0), MSHake(_class ## $ ## arg0)) 164 | #define MSHookMessage1(_class, arg0) \ 165 | MSHookMessage($ ## _class, @selector(arg0:), MSHake(_class ## $ ## arg0 ## $)) 166 | #define MSHookMessage2(_class, arg0, arg1) \ 167 | MSHookMessage($ ## _class, @selector(arg0:arg1:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $)) 168 | #define MSHookMessage3(_class, arg0, arg1, arg2) \ 169 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $)) 170 | #define MSHookMessage4(_class, arg0, arg1, arg2, arg3) \ 171 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $)) 172 | #define MSHookMessage5(_class, arg0, arg1, arg2, arg3, arg4) \ 173 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $)) 174 | #define MSHookMessage6(_class, arg0, arg1, arg2, arg3, arg4, arg5) \ 175 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $)) 176 | 177 | #define MSRegister_(name, dollar, colon) \ 178 | static class C_$ ## name ## $ ## dollar { public: _finline C_$ ## name ## $ ##dollar() { \ 179 | MSHookMessage($ ## name, @selector(colon), MSHake(name ## $ ## dollar)); \ 180 | } } V_$ ## name ## $ ## dollar; \ 181 | 182 | #define MSIgnore_(name, dollar, colon) 183 | 184 | #define MSMessage_(extra, type, _class, name, dollar, colon, call, args...) \ 185 | static type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args); \ 186 | MSHook(type, name ## $ ## dollar, _class self, SEL _cmd, ## args) { \ 187 | Class const _cls($ ## name); \ 188 | type (* const _old)(_class, SEL, ## args, ...) = reinterpret_cast(_ ## name ## $ ## dollar); \ 189 | typedef type (*msgSendSuper_t)(struct objc_super *, SEL, ## args, ...); \ 190 | msgSendSuper_t const _spr(::etl::IsClass::value ? reinterpret_cast(&objc_msgSendSuper_stret) : reinterpret_cast(&objc_msgSendSuper)); \ 191 | return _$ ## name ## $ ## dollar call; \ 192 | } \ 193 | extra(name, dollar, colon) \ 194 | static _finline type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args) 195 | 196 | /* 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 ")";} */ 197 | 198 | #define MSMessage0_(extra, type, _class, name, sel0) \ 199 | MSMessage_(extra, type, _class, name, sel0, sel0, (_cls, _old, _spr, self, _cmd)) 200 | #define MSMessage1_(extra, type, _class, name, sel0, type0, arg0) \ 201 | MSMessage_(extra, type, _class, name, sel0 ## $, sel0:, (_cls, _old, _spr, self, _cmd, arg0), type0 arg0) 202 | #define MSMessage2_(extra, type, _class, name, sel0, sel1, type0, arg0, type1, arg1) \ 203 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $, sel0:sel1:, (_cls, _old, _spr, self, _cmd, arg0, arg1), type0 arg0, type1 arg1) 204 | #define MSMessage3_(extra, type, _class, name, sel0, sel1, sel2, type0, arg0, type1, arg1, type2, arg2) \ 205 | 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) 206 | #define MSMessage4_(extra, type, _class, name, sel0, sel1, sel2, sel3, type0, arg0, type1, arg1, type2, arg2, type3, arg3) \ 207 | 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) 208 | #define MSMessage5_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ 209 | 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) 210 | #define MSMessage6_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, sel5, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ 211 | 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) 212 | 213 | #define MSInstanceMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, _class *, _class, ## args) 214 | #define MSInstanceMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, _class *, _class, ## args) 215 | #define MSInstanceMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, _class *, _class, ## args) 216 | #define MSInstanceMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, _class *, _class, ## args) 217 | #define MSInstanceMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, _class *, _class, ## args) 218 | #define MSInstanceMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, _class *, _class, ## args) 219 | #define MSInstanceMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, _class *, _class, ## args) 220 | 221 | #define MSClassMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, Class, $ ## _class, ## args) 222 | #define MSClassMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, Class, $ ## _class, ## args) 223 | #define MSClassMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, Class, $ ## _class, ## args) 224 | #define MSClassMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, Class, $ ## _class, ## args) 225 | #define MSClassMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, Class, $ ## _class, ## args) 226 | #define MSClassMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, Class, $ ## _class, ## args) 227 | #define MSClassMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, Class, $ ## _class, ## args) 228 | 229 | #define MSInstanceMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, _class *, _class, ## args) 230 | #define MSInstanceMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, _class *, _class, ## args) 231 | #define MSInstanceMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, _class *, _class, ## args) 232 | #define MSInstanceMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, _class *, _class, ## args) 233 | #define MSInstanceMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, _class *, _class, ## args) 234 | #define MSInstanceMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, _class *, _class, ## args) 235 | #define MSInstanceMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, _class *, _class, ## args) 236 | 237 | #define MSClassMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, Class, $ ## _class, ## args) 238 | #define MSClassMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, Class, $ ## _class, ## args) 239 | #define MSClassMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, Class, $ ## _class, ## args) 240 | #define MSClassMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, Class, $ ## _class, ## args) 241 | #define MSClassMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, Class, $ ## _class, ## args) 242 | #define MSClassMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, Class, $ ## _class, ## args) 243 | #define MSClassMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, Class, $ ## _class, ## args) 244 | 245 | #define MSOldCall(args...) \ 246 | _old(self, _cmd, ## args) 247 | #define MSSuperCall(args...) \ 248 | _spr(& (struct objc_super) {self, class_getSuperclass(_cls)}, _cmd, ## args) 249 | 250 | #define MSIvarHook(type, name) \ 251 | type &name(MSHookIvar(self, #name)) 252 | 253 | #define MSClassHook(name) \ 254 | @class name; \ 255 | static Class $ ## name = objc_getClass(#name); 256 | #define MSMetaClassHook(name) \ 257 | @class name; \ 258 | static Class $$ ## name = object_getClass($ ## name); 259 | 260 | #endif/*__APPLE__*/ 261 | 262 | template 263 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { 264 | return MSHookFunction( 265 | reinterpret_cast(symbol), 266 | reinterpret_cast(replace), 267 | reinterpret_cast(result) 268 | ); 269 | } 270 | 271 | template 272 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { 273 | return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); 274 | } 275 | 276 | template 277 | static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { 278 | value = reinterpret_cast(MSFindSymbol(image, name)); 279 | } 280 | 281 | template 282 | static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { 283 | Type_ *symbol; 284 | MSHookSymbol(symbol, name); 285 | return MSHookFunction(symbol, replace, result); 286 | } 287 | 288 | #endif 289 | 290 | #define MSHook(type, name, args...) \ 291 | _disused static type (*_ ## name)(args); \ 292 | static type $ ## name(args) 293 | 294 | #ifdef __cplusplus 295 | #define MSHake(name) \ 296 | &$ ## name, &_ ## name 297 | #else 298 | #define MSHake(name) \ 299 | &$ ## name, (void **) &_ ## name 300 | #endif 301 | 302 | #define MSInitialize \ 303 | __attribute__((__constructor__)) static void _MSInitialize(void) 304 | 305 | #define Foundation_f "/System/Library/Frameworks/Foundation.framework/Foundation" 306 | #define UIKit_f "/System/Library/Frameworks/UIKit.framework/UIKit" 307 | #define JavaScriptCore_f "/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore" 308 | #define IOKit_f "/System/Library/Frameworks/IOKit.framework/IOKit" 309 | 310 | #endif//SUBSTRATE_H_ 311 | --------------------------------------------------------------------------------