├── .gitignore ├── HookUtil.c ├── HookUtil.h ├── README.md ├── YoungHook ├── CamoCall.c ├── CamoCall.h ├── YoungHook.c ├── YoungHook.h ├── fishhook.c └── fishhook.h └── YoungHookDemo ├── YoungHookDemo.xcodeproj └── project.pbxproj └── YoungHookDemo ├── AppDelegate.h ├── AppDelegate.mm ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── SceneDelegate.h ├── SceneDelegate.m ├── ViewController.h ├── ViewController.m ├── YoungHookDemoCamo.h └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Extras 3 | *.xcuserdatad 4 | *.xcworkspace 5 | xcshareddata 6 | -------------------------------------------------------------------------------- /HookUtil.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | #import 5 | #import 6 | #import "HookUtil.h" 7 | 8 | // Rewrite fishhook from FaceBook 9 | #import 10 | #import 11 | #import 12 | 13 | #include 14 | void NSLog(CFStringRef format, ...); 15 | 16 | #ifndef _Log 17 | #if defined(DEBUG) || defined(TEST) 18 | #define _Log(s, ...) NSLog(s, ##__VA_ARGS__) 19 | #else 20 | #define _Log(s, ...) ((void) 0) 21 | #endif 22 | #endif 23 | 24 | #if defined(_MAC64) || defined(__LP64__) 25 | typedef struct mach_header_64 mach_header_t; 26 | typedef struct segment_command_64 segment_command_t; 27 | typedef struct section_64 section_t; 28 | typedef struct nlist_64 nlist_t; 29 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 30 | #else 31 | typedef struct mach_header mach_header_t; 32 | typedef struct segment_command segment_command_t; 33 | typedef struct section section_t; 34 | typedef struct nlist nlist_t; 35 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT 36 | #endif 37 | 38 | struct FHRebinding 39 | { 40 | const char *name; 41 | void *replacement; 42 | void **replaced; 43 | }; 44 | 45 | // 46 | static struct FHRebindingsEntry 47 | { 48 | struct FHRebinding *rebindings; 49 | size_t count; 50 | struct FHRebindingsEntry *next; 51 | } *_rebindings_head = NULL; 52 | 53 | // 54 | static void FHRebindSymbolsForImage(const struct mach_header *header, intptr_t slide) 55 | { 56 | Dl_info info; 57 | if (dladdr(header, &info) == 0) 58 | { 59 | return; 60 | } 61 | 62 | segment_command_t *cur_seg_cmd; 63 | segment_command_t *linkedit_segment = NULL; 64 | struct symtab_command* symtab_cmd = NULL; 65 | struct dysymtab_command* dysymtab_cmd = NULL; 66 | 67 | uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); 68 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) 69 | { 70 | cur_seg_cmd = (segment_command_t *)cur; 71 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) 72 | { 73 | if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) 74 | { 75 | linkedit_segment = cur_seg_cmd; 76 | } 77 | } 78 | else 79 | if (cur_seg_cmd->cmd == LC_SYMTAB) 80 | { 81 | symtab_cmd = (struct symtab_command*)cur_seg_cmd; 82 | } 83 | else if (cur_seg_cmd->cmd == LC_DYSYMTAB) 84 | { 85 | dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; 86 | } 87 | } 88 | 89 | if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || !dysymtab_cmd->nindirectsyms) 90 | { 91 | return; 92 | } 93 | 94 | // Find base symbol/string table addresses 95 | uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; 96 | nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); 97 | char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); 98 | 99 | // Get indirect symbol table (array of uint32_t indices into symbol table) 100 | uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); 101 | 102 | cur = (uintptr_t)header + sizeof(mach_header_t); 103 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) 104 | { 105 | cur_seg_cmd = (segment_command_t *)cur; 106 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) 107 | { 108 | if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && strcmp(cur_seg_cmd->segname, "__DATA_CONST") != 0) 109 | { 110 | continue; 111 | } 112 | for (uint j = 0; j < cur_seg_cmd->nsects; j++) 113 | { 114 | section_t *sect = 115 | (section_t *)(cur + sizeof(segment_command_t)) + j; 116 | if (((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) || ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS)) 117 | { 118 | uint32_t *indirect_symbol_indices = indirect_symtab + sect->reserved1; 119 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + sect->addr); 120 | for (uint i = 0; i < sect->size / sizeof(void *); i++) 121 | { 122 | uint32_t symtab_index = indirect_symbol_indices[i]; 123 | if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || 124 | symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) 125 | { 126 | continue; 127 | } 128 | uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; 129 | char *symbol_name = strtab + strtab_offset; 130 | if (strnlen(symbol_name, 2) < 2) 131 | { 132 | continue; 133 | } 134 | struct FHRebindingsEntry *cur = _rebindings_head; 135 | while (cur) 136 | { 137 | for (uint j = 0; j < cur->count; j++) 138 | { 139 | if (strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) 140 | { 141 | if (cur->rebindings[j].replaced != NULL && indirect_symbol_bindings[i] != cur->rebindings[j].replacement) 142 | { 143 | *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; 144 | } 145 | indirect_symbol_bindings[i] = cur->rebindings[j].replacement; 146 | goto symbol_loop; 147 | } 148 | } 149 | cur = cur->next; 150 | } 151 | symbol_loop:; 152 | } 153 | } 154 | } 155 | } 156 | } 157 | } 158 | 159 | // 160 | #if 0 161 | int FHRebindSymbols(struct FHRebinding rebindings[], size_t count) 162 | { 163 | struct FHRebindingsEntry *new_entry = (struct FHRebindingsEntry *)malloc(sizeof(struct FHRebindingsEntry)); 164 | if (!new_entry) 165 | { 166 | return -1; 167 | } 168 | new_entry->rebindings = (struct FHRebinding *)malloc(sizeof(struct FHRebinding) * count); 169 | if (!new_entry->rebindings) 170 | { 171 | free(new_entry); 172 | return -1; 173 | } 174 | 175 | memcpy(new_entry->rebindings, rebindings, sizeof(struct FHRebinding) * count); 176 | new_entry->count = count; 177 | new_entry->next = _rebindings_head; 178 | _rebindings_head = new_entry; 179 | 180 | // If this was the first call, register callback for image additions (which is also invoked for existing images, otherwise, just run on existing images 181 | if (!_rebindings_head->next) 182 | { 183 | _dyld_register_func_for_add_image(FHRebindSymbolsForImage); 184 | } 185 | else 186 | { 187 | uint32_t c = _dyld_image_count(); 188 | for (uint32_t i = 0; i < c; i++) 189 | { 190 | FHRebindSymbolsForImage(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 191 | } 192 | } 193 | return 0; 194 | } 195 | #endif 196 | 197 | // 198 | #ifdef _Support_CydiaSubstrate 199 | bool MSHookFunction(void *symbol, void *hook, void **old) 200 | { 201 | static void (*_MSHookFunction)(void *symbol, void *hook, void **old) = NULL; 202 | if (_MSHookFunction == NULL) 203 | { 204 | _MSHookFunction = dlsym(dlopen("/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate", RTLD_LAZY), "MSHookFunction"); 205 | _Log(CFSTR("HookUtil: _MSHookFunction = %p"), _MSHookFunction); 206 | if (_MSHookFunction == NULL) 207 | { 208 | _MSHookFunction = (void *)-1; 209 | } 210 | } 211 | 212 | // 213 | if (_MSHookFunction && (_MSHookFunction != (void *)-1)) 214 | { 215 | _MSHookFunction(symbol, hook, old); 216 | return true; 217 | } 218 | 219 | //*old = NULL; 220 | return false; 221 | } 222 | 223 | // 224 | bool MSHookMessage(Class cls, SEL sel, IMP hook, IMP *old) 225 | { 226 | static void (*_MSHookMessageEx)(Class cls, SEL sel, IMP hook, IMP *old) = NULL; 227 | if (_MSHookMessageEx == nil) 228 | { 229 | _MSHookMessageEx = dlsym(dlopen("/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate", RTLD_LAZY), "MSHookMessageEx"); 230 | _Log(CFSTR("HookUtil: _MSHookMessageEx = %p"), _MSHookMessageEx); 231 | if (_MSHookMessageEx == NULL) 232 | { 233 | _MSHookMessageEx = (void *)-1; 234 | } 235 | } 236 | 237 | // 238 | if (_MSHookMessageEx && (_MSHookMessageEx != (void *)-1)) 239 | { 240 | _MSHookMessageEx(cls, sel, hook, old); 241 | return true; 242 | } 243 | 244 | //*old = NULL; 245 | return false; 246 | } 247 | #endif 248 | 249 | // 250 | void HUHookFunction(const char *lib, const char *func, void *hook, void **old) 251 | { 252 | #ifdef _Support_CydiaSubstrate 253 | void *symbol = dlsym(dlopen(lib, RTLD_LAZY), func); 254 | if (MSHookFunction(symbol, hook, old)) return; 255 | #endif 256 | 257 | //FHRebindSymbols((struct FHRebinding[1]){{func, hook, old}}, 1); 258 | 259 | struct FHRebindingsEntry *new_entry = (struct FHRebindingsEntry *)malloc(sizeof(struct FHRebindingsEntry)); 260 | if (!new_entry) 261 | { 262 | *old = NULL; 263 | return; 264 | } 265 | new_entry->rebindings = (struct FHRebinding *)malloc(sizeof(struct FHRebinding)); 266 | if (!new_entry->rebindings) 267 | { 268 | free(new_entry); 269 | *old = NULL; 270 | return; 271 | } 272 | 273 | new_entry->rebindings[0].name = func; 274 | new_entry->rebindings[0].replaced = old; 275 | new_entry->rebindings[0].replacement = hook; 276 | new_entry->count = 1; 277 | new_entry->next = _rebindings_head; 278 | _rebindings_head = new_entry; 279 | 280 | // If this was the first call, register callback for image additions (which is also invoked for existing images, otherwise, just run on existing images 281 | if (!_rebindings_head->next) 282 | { 283 | _dyld_register_func_for_add_image(FHRebindSymbolsForImage); 284 | } 285 | else 286 | { 287 | uint32_t c = _dyld_image_count(); 288 | for (uint32_t i = 0; i < c; i++) 289 | { 290 | FHRebindSymbolsForImage(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 291 | } 292 | } 293 | } 294 | 295 | // 296 | void HUHookMessage(const char *cls, bool meta, const char *name, IMP hook, IMP *old) 297 | { 298 | char msg[1024], *p = msg; 299 | do 300 | { 301 | *p++ = (*name == '_') ? ((name[1] == '_') ? *name++ : ':') : *name; 302 | } 303 | while (*name++); 304 | SEL sel = sel_registerName(msg); 305 | Class class = meta ? objc_getMetaClass(cls) : objc_getClass(cls); 306 | 307 | #ifdef _Support_CydiaSubstrate 308 | if (MSHookMessage(class, sel, hook, old)) return; 309 | #endif 310 | 311 | // 312 | Method method = class_getInstanceMethod(class, sel); 313 | if (method == NULL) 314 | { 315 | _Log(CFSTR("HookUtil: Could not find [%s %s]"), cls, sel_getName(sel)); 316 | } 317 | else 318 | { 319 | *old = method_setImplementation(method, hook); 320 | } 321 | } 322 | 323 | 324 | // 325 | bool HUIsAnyOneMatched(const char *any, const char *one, char separator) 326 | { 327 | for (const char *p = one; true; any++) 328 | { 329 | if (*p) 330 | { 331 | if (*any == *p) 332 | { 333 | p++; 334 | continue; 335 | } 336 | else if (*any == 0) 337 | { 338 | return false; 339 | } 340 | else if (*any == separator) 341 | { 342 | p = one; 343 | continue; 344 | } 345 | } 346 | else if (*any == 0 || *any == separator) 347 | { 348 | return true; 349 | } 350 | 351 | for (; *any != separator; any++) 352 | { 353 | if (*any == 0) 354 | { 355 | return false; 356 | } 357 | } 358 | p = one; 359 | } 360 | } 361 | 362 | // 363 | void HUHookFunctionForProcess(const char *proc, const char *lib, const char *func, void *hook, void **old) 364 | { 365 | if (HUIsAnyOneMatched(proc, getprogname(), '|')) 366 | { 367 | HUHookFunction(lib, func, hook, old); 368 | } 369 | } 370 | 371 | // 372 | void HUHookMessageForProcess(const char *proc, const char *cls, bool meta, const char *name, IMP hook, IMP *old) 373 | { 374 | if (HUIsAnyOneMatched(proc, getprogname(), '|')) 375 | { 376 | HUHookMessage(cls, meta, name, hook, old); 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /HookUtil.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | #define _Support_CydiaSubstrate 5 | 6 | // 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #ifdef _Support_CydiaSubstrate 13 | bool MSHookFunction(void *symbol, void *hook, void **old); // Return false if no Cydia Substrate 14 | bool MSHookMessage(Class cls, SEL sel, IMP hook, IMP *old); // Return false if no Cydia Substrate 15 | #endif 16 | 17 | void HUHookFunction(const char *lib, const char *func, void *hook, void **old); 18 | void HUHookMessage(const char * cls, bool meta, const char *name, IMP hook, IMP *old); // Name means ObjC message, use '_' for ':', '__' for '_' 19 | 20 | bool HUIsAnyOneMatched(const char *any, const char *one, char separator); 21 | void HUHookFunctionForProcess(const char *proc, const char *lib, const char *func, void *hook, void **old); 22 | void HUHookMessageForProcess(const char *proc, const char * cls, bool meta, const char *name, IMP hook, IMP *old); 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | // 28 | #define __HUHookFunction(NOUSE, ...) HUHookFunction(__VA_ARGS__) 29 | #define __HUHookMessage(NOUSE, ...) HUHookMessage(__VA_ARGS__) 30 | 31 | #define __HOOK_FUNCTION(MOD, HKFN, PROC, RET, LIB, FUNC, ...) RET $##FUNC(__VA_ARGS__);\ 32 | RET (*_##FUNC)(__VA_ARGS__);\ 33 | __attribute__((MOD)) void _Init_##FUNC()\ 34 | {\ 35 | HKFN(#PROC, #LIB, #FUNC, (void *)$##FUNC, (void **)&_##FUNC);\ 36 | }\ 37 | RET $##FUNC(__VA_ARGS__) 38 | 39 | #define __HOOK_MESSAGE(MOD, HKFN, PROC, RET, CLS, MSG, META, ...)\ 40 | RET $##CLS##_##MSG(id self, SEL sel, ##__VA_ARGS__);\ 41 | RET (*_##CLS##_##MSG)(id self, SEL sel, ##__VA_ARGS__);\ 42 | __attribute__((MOD)) void _Init_##CLS##_##MSG()\ 43 | {\ 44 | HKFN(#PROC, #CLS, META, #MSG, (IMP)$##CLS##_##MSG, (IMP *)&_##CLS##_##MSG);\ 45 | }\ 46 | RET $##CLS##_##MSG(id self, SEL sel, ##__VA_ARGS__) 47 | 48 | // Manual hook, call _Init_*** to enable the hook 49 | #define _HOOK_FUNCTION(RET, LIB, FUN, ...) __HOOK_FUNCTION(always_inline, __HUHookFunction, , RET, LIB, FUN, ##__VA_ARGS__) 50 | #define _HOOK_MESSAGE(RET, CLS, MSG, ...) __HOOK_MESSAGE(always_inline, __HUHookMessage, , RET, CLS, MSG, false, ##__VA_ARGS__) 51 | #define _HOOK_META(RET, CLS, MSG, ...) __HOOK_MESSAGE(always_inline, __HUHookMessage, , RET, CLS, MSG, true, ##__VA_ARGS__) 52 | 53 | // Automatic hook 54 | #define HOOK_FUNCTION(RET, LIB, FUN, ...) __HOOK_FUNCTION(constructor, __HUHookFunction, , RET, LIB, FUN, ##__VA_ARGS__) 55 | #define HOOK_MESSAGE(RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, __HUHookMessage, , RET, CLS, MSG, false, ##__VA_ARGS__) 56 | #define HOOK_META(RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, __HUHookMessage, , RET, CLS, MSG, true, ##__VA_ARGS__) 57 | 58 | // Automatic hook for special process name 59 | // Use | separator for multiple process name 60 | #define HOOK_FUNCTION_FOR_PROCESS(PROC, RET, LIB, FUN, ...) __HOOK_FUNCTION(constructor, HUHookFunctionForProcess, PROC, RET, LIB, FUN, ##__VA_ARGS__) 61 | #define HOOK_MESSAGE_FOR_PROCESS(PROC, RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, HUHookMessageForProcess, PROC, RET, CLS, MSG, false, ##__VA_ARGS__) 62 | #define HOOK_META_FOR_PROCESS(PROC, RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, HUHookMessageForProcess, PROC, RET, CLS, MSG, true, ##__VA_ARGS__) 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Hook Util 3 | ====== 4 | 5 | A light weight hook utility for iOS. 6 | 7 | #Usage 8 | 9 | #import "HookUtil.h" 10 | 11 | ###Hook a Object C Message 12 | 13 | HOOK_MESSAGE(BOOL, UIApplication, openURL_, NSURL *URL) 14 | { 15 | NSLog(@"%s: %@", __FUNCTION__, URL); 16 | return _UIApplication_openURL_(self, sel, URL); 17 | } 18 | 19 | The above code block will create an `automatically-initialized hook function` (with constructor keyword). Just focus on the hook function body without any other preparation code. The `self` and `sel` are solid naming variables in `HOOK_MESSAGE` macro. 20 | 21 | Use `_HOOK_MESSAGE` (instead of `HOOK_MESSAGE`) to create a `manually-initialized hook function`. You must call `_Init_openURL_()` if you want to enable it. 22 | 23 | ###Hook a C/C++ function 24 | 25 | HOOK_FUNCTION(OSStatus, /System/Library/Frameworks/Security.framework/Security, SSLHandshake, SSLContextRef context) 26 | { 27 | OSStatus ret = _SSLHandshake(context); 28 | return (ret == errSSLServerAuthCompleted) ? _SSLHandshake(context) : ret; 29 | } 30 | 31 | Just like _HOOK_MESSAGE, use `_HOOK_FUNCTION` (instead of `HOOK_FUNCTION`) to create a `manually-initialized hook function`. You must call `_Init_SSLHandshake()` if you want to enable it. 32 | 33 | `HOOK_FUNCTION` and `_HOOK_FUNCTION` can be used only on a jail-broken device with `Cydia Substrate` installed. 34 | 35 | #Sample 36 | 37 | See [HttPeek](https://github.com/Yonsm/HttPeek) 38 | -------------------------------------------------------------------------------- /YoungHook/CamoCall.c: -------------------------------------------------------------------------------- 1 | 2 | #import "CamoCall.h" 3 | 4 | #ifdef CamoCall_FunctionPointer 5 | #import 6 | 7 | // /usr/lib/libobjc.A.dylib 8 | #define CAMO_usr_lib_libobjc_A_dylib char camo_usr_lib_libobjc_A_dylib[25]; CamoStringDecode(camo_usr_lib_libobjc_A_dylib, "\x37\x6c\x69\x67\x33\x6f\x6b\x73\x2f\x6b\x67\x6f\x6b\x6d\x64\x6c\x26\x48\x24\x69\x4d\x5f\x5b\x63", 24) 9 | // objc_msgSend 10 | #define CAMO_objc_msgSend char camo_objc_msgSend[13]; CamoStringDecode(camo_objc_msgSend, "\x63\x6d\x64\x6c\x4f\x5c\x79\x64\x57\x60\x58\x5d", 12) 11 | // objc_getClass 12 | #define CAMO_objc_getClass char camo_objc_getClass[14]; CamoStringDecode(camo_objc_getClass, "\x62\x6e\x65\x6b\x4e\x65\x62\x72\x46\x58\x62\x73\x72", 13) 13 | // objc_getMetaClass 14 | #define CAMO_objc_getMetaClass char camo_objc_getMetaClass[18]; CamoStringDecode(camo_objc_getMetaClass, "\x7e\x72\x79\x6f\x4a\x71\x6e\x5e\x54\x6b\x5b\x65\x46\x70\x62\x53\x52", 17) 15 | // class_getInstanceMethod 16 | #define CAMO_class_getInstanceMethod char camo_class_getInstanceMethod[24]; CamoStringDecode(camo_class_getInstanceMethod, "\x74\x7a\x74\x61\x60\x43\x6a\x6b\x5b\x55\x6f\x59\x57\x69\x6b\x65\x62\x49\x60\x50\x6b\x63\x5d", 23) 17 | // sel_registerName 18 | #define CAMO_sel_registerName char camo_sel_registerName[17]; CamoStringDecode(camo_sel_registerName, "\x63\x74\x7a\x4c\x5e\x70\x71\x72\x5b\x5b\x6b\x57\x52\x64\x6f\x66", 16) 19 | // method_setImplementation 20 | #define CAMO_method_setImplementation char camo_method_setImplementation[25]; CamoStringDecode(camo_method_setImplementation, "\x75\x7c\x6a\x6d\x73\x77\x41\x64\x75\x63\x47\x6a\x5c\x67\x6f\x66\x6d\x65\x5a\x66\x58\x5c\x61\x5f", 24) 21 | 22 | void *(*Camo_objc_msgSend)(id, SEL, ...) = NULL; 23 | Class (*Camo_objc_getClass)(const char *) = NULL; 24 | Class (*Camo_objc_getMetaClass)(const char *) = NULL; 25 | Method (*Camo_class_getInstanceMethod)(Class, SEL) = NULL; 26 | SEL (*Camo_sel_registerName)(const char *) = NULL; 27 | IMP (*Camo_method_setImplementation)(Method, IMP) = NULL; 28 | 29 | void CamoCallInit() 30 | { 31 | if (Camo_objc_msgSend) 32 | return; 33 | 34 | CAMO_usr_lib_libobjc_A_dylib; 35 | CAMO_objc_msgSend; 36 | CAMO_objc_getClass; 37 | CAMO_objc_getMetaClass; 38 | CAMO_class_getInstanceMethod; 39 | CAMO_sel_registerName; 40 | CAMO_method_setImplementation; 41 | 42 | void *lib = dlopen(camo_usr_lib_libobjc_A_dylib, RTLD_LAZY); 43 | Camo_objc_msgSend = dlsym(lib, camo_objc_msgSend); 44 | Camo_objc_getClass = dlsym(lib, camo_objc_getClass); 45 | Camo_objc_getMetaClass = dlsym(lib, camo_objc_getMetaClass); 46 | Camo_class_getInstanceMethod = dlsym(lib, camo_class_getInstanceMethod); 47 | Camo_sel_registerName = dlsym(lib, camo_sel_registerName); 48 | Camo_method_setImplementation = dlsym(lib, camo_method_setImplementation); 49 | 50 | } 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /YoungHook/CamoCall.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | static __inline__ __attribute__((always_inline)) 10 | void CamoStringDecode(char *dst, const char *src, unsigned length) 11 | { 12 | for (unsigned i = 0; i < length; i++) 13 | { 14 | dst[i] = ((unsigned char)src[i] + i) ^ (unsigned char)length; 15 | } 16 | dst[length] = 0; 17 | } 18 | 19 | static __inline__ __attribute__((always_inline)) 20 | CFStringRef CamoStringDecode2(const char *src, unsigned length) 21 | { 22 | char dst[2048]; 23 | CamoStringDecode(dst, src, length); 24 | return CFStringCreateWithCString(NULL, dst, kCFStringEncodingUTF8); 25 | } 26 | 27 | #ifdef CamoCall_FunctionPointer 28 | extern void CamoCallInit(void); 29 | extern void *(*Camo_objc_msgSend)(id, SEL, ...); 30 | extern Class (*Camo_objc_getClass)(const char *); 31 | extern Class (*Camo_objc_getMetaClass)(const char *); 32 | extern Method (*Camo_class_getInstanceMethod)(Class, SEL); 33 | extern SEL (*Camo_sel_registerName)(const char *); 34 | extern IMP (*Camo_method_setImplementation)(Method, IMP); 35 | #else 36 | #import 37 | #define CamoCallInit() 38 | #define Camo_objc_msgSend ((void * (*)(id, SEL, ...))objc_msgSend) 39 | #define Camo_objc_getClass objc_getClass 40 | #define Camo_objc_getMetaClass objc_getMetaClass 41 | #define Camo_class_getInstanceMethod class_getInstanceMethod 42 | #define Camo_sel_registerName sel_registerName 43 | #define Camo_method_setImplementation method_setImplementation 44 | #endif 45 | 46 | #define CamoCallSelector(self, sel, ...) Camo_objc_msgSend(self, sel, __VA_ARGS__) 47 | #define CamoCallMessage(self, name, ...) Camo_objc_msgSend(self, Camo_sel_registerName(name), __VA_ARGS__) 48 | #define CamoCallClassSelector(cls, sel, ...) Camo_objc_msgSend(Camo_objc_getClass(cls), sel, __VA_ARGS__) 49 | #define CamoCallClassMessage(cls, name, ...) Camo_objc_msgSend(Camo_objc_getClass(cls), Camo_sel_registerName(name), __VA_ARGS__) 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /YoungHook/YoungHook.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | #import 5 | #import 6 | #import "YoungHook.h" 7 | 8 | #include 9 | void NSLog(CFStringRef format, ...); 10 | 11 | #ifndef _Log 12 | #if defined(DEBUG) || defined(TEST) 13 | #define _Log(s, ...) NSLog(s, ##__VA_ARGS__) 14 | #else 15 | #define _Log(s, ...) ((void) 0) 16 | #endif 17 | #endif 18 | 19 | // /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate 20 | #define CAMO_Library_Frameworks_CydiaSubstrate_framework_CydiaSubstrate char camo_Library_Frameworks_CydiaSubstrate_framework_CydiaSubstrate[60]; CamoStringDecode(camo_Library_Frameworks_CydiaSubstrate_framework_CydiaSubstrate, "\x14\x76\x50\x56\x45\x55\x43\x3b\x0c\x74\x3f\x4f\x4a\x51\x3e\x45\x39\x3f\x36\x01\x64\x2d\x49\x3b\x42\x4f\x34\x3e\x2c\x32\x2b\x3b\x2f\x3d\xfffffff3\x3a\x25\x35\x30\x37\x24\x2b\x1f\x25\xffffffe8\x4b\x14\x30\x22\x29\x36\x1b\x25\x13\x19\x12\x22\x16\x24", 59) 21 | // MSHookMessageEx 22 | #define CAMO_MSHookMessageEx char camo_MSHookMessageEx[16]; CamoStringDecode(camo_MSHookMessageEx, "\x42\x5b\x45\x5d\x5c\x5f\x3c\x63\x74\x73\x64\x5d\x5e\x3d\x69", 15) 23 | // MSHookFunction 24 | #define CAMO_MSHookFunction char camo_MSHookFunction[15]; CamoStringDecode(camo_MSHookFunction, "\x43\x5c\x44\x5e\x5d\x60\x42\x74\x58\x64\x70\x5c\x55\x53", 14) 25 | 26 | // 27 | #ifdef YoungHook_CydiaSubstrate 28 | bool MSHookFunction(void *symbol, void *hook, void **old) 29 | { 30 | static void (*_MSHookFunction)(void *symbol, void *hook, void **old) = NULL; 31 | if (_MSHookFunction == NULL) 32 | { 33 | CAMO_Library_Frameworks_CydiaSubstrate; 34 | CAMO_MSHookFunction; 35 | _MSHookFunction = dlsym(dlopen(camo_Library_Frameworks_CydiaSubstrate, RTLD_LAZY), camo_MSHookFunction); 36 | _Log(CFSTR("YoungHook: _MSHookFunction = %p"), _MSHookFunction); 37 | if (_MSHookFunction == NULL) 38 | { 39 | _MSHookFunction = (void *)-1; 40 | } 41 | } 42 | 43 | // 44 | if (_MSHookFunction && (_MSHookFunction != (void *)-1)) 45 | { 46 | _MSHookFunction(symbol, hook, old); 47 | return true; 48 | } 49 | 50 | //*old = NULL; 51 | return false; 52 | } 53 | 54 | // 55 | bool MSHookMessage(Class cls, SEL sel, IMP hook, IMP *old) 56 | { 57 | static void (*_MSHookMessageEx)(Class cls, SEL sel, IMP hook, IMP *old) = NULL; 58 | if (_MSHookMessageEx == nil) 59 | { 60 | CAMO_Library_Frameworks_CydiaSubstrate; 61 | CAMO_MSHookMessageEx; 62 | _MSHookMessageEx = dlsym(dlopen(camo_Library_Frameworks_CydiaSubstrate, RTLD_LAZY), camo_MSHookMessageEx); 63 | _Log(CFSTR("YoungHook: _MSHookMessageEx = %p"), _MSHookMessageEx); 64 | if (_MSHookMessageEx == NULL) 65 | { 66 | _MSHookMessageEx = (void *)-1; 67 | } 68 | } 69 | 70 | // 71 | if (_MSHookMessageEx && (_MSHookMessageEx != (void *)-1)) 72 | { 73 | _MSHookMessageEx(cls, sel, hook, old); 74 | return true; 75 | } 76 | 77 | //*old = NULL; 78 | return false; 79 | } 80 | #endif 81 | 82 | #if defined(YoungHook_CydiaSubstrate) || defined(YoungHook_FishHook) 83 | #ifdef YoungHook_FishHook 84 | #import "fishhook.h" 85 | #endif 86 | bool YHHookFunction(const char *lib, const char *func, void *hook, void **old) 87 | { 88 | #ifdef YoungHook_CydiaSubstrate 89 | if (MSHookFunction(dlsym(dlopen(lib, RTLD_LAZY), func), hook, old)) 90 | return true; 91 | #endif 92 | 93 | #ifdef YoungHook_FishHook 94 | return rebind_symbols((struct rebinding[1]){{func, hook, old}}, 1); 95 | #else 96 | return false; 97 | #endif 98 | } 99 | #endif 100 | 101 | // 102 | bool YHHookMessage(const char *cls, bool meta, const char *name, IMP hook, IMP *old) 103 | { 104 | #ifdef YoungHook_AutoInit 105 | if (Camo_sel_registerName == NULL) 106 | CamoCallInit(); 107 | #endif 108 | 109 | char msg[1024], *p = msg; 110 | do 111 | { 112 | *p++ = (*name == '_') ? ((name[1] == '_') ? *name++ : ':') : *name; 113 | } 114 | while (*name++); 115 | SEL sel = Camo_sel_registerName(msg); 116 | Class class = meta ? Camo_objc_getMetaClass(cls) : Camo_objc_getClass(cls); 117 | 118 | #ifdef YoungHook_CydiaSubstrate 119 | if (MSHookMessage(class, sel, hook, old)) 120 | return true; 121 | #endif 122 | 123 | // 124 | Method method = Camo_class_getInstanceMethod(class, sel); 125 | if (method == NULL) 126 | { 127 | _Log(CFSTR("YoungHook: Could not find [%s %s]"), cls, msg); 128 | return false; 129 | } 130 | 131 | *old = Camo_method_setImplementation(method, hook); 132 | return true; 133 | } 134 | 135 | // 136 | #ifdef YoungHook_MultiProcess 137 | bool YHIsAnyOneMatched(const char *any, const char *one, char separator) 138 | { 139 | for (const char *p = one; true; any++) 140 | { 141 | if (*p) 142 | { 143 | if (*any == *p) 144 | { 145 | p++; 146 | continue; 147 | } 148 | else if (*any == 0) 149 | { 150 | return false; 151 | } 152 | else if (*any == separator) 153 | { 154 | p = one; 155 | continue; 156 | } 157 | } 158 | else if (*any == 0 || *any == separator) 159 | { 160 | return true; 161 | } 162 | 163 | for (; *any != separator; any++) 164 | { 165 | if (*any == 0) 166 | { 167 | return false; 168 | } 169 | } 170 | p = one; 171 | } 172 | } 173 | 174 | // 175 | #if defined(YoungHook_CydiaSubstrate) || defined(YoungHook_FishHook) 176 | bool YHHookFunctionForProcess(const char *proc, const char *lib, const char *func, void *hook, void **old) 177 | { 178 | if (YHIsAnyOneMatched(proc, getprogname(), '|')) 179 | { 180 | return YHHookFunction(lib, func, hook, old); 181 | } 182 | return false; 183 | } 184 | #endif 185 | 186 | // 187 | bool YHHookMessageForProcess(const char *proc, const char *cls, bool meta, const char *name, IMP hook, IMP *old) 188 | { 189 | if (YHIsAnyOneMatched(proc, getprogname(), '|')) 190 | { 191 | return YHHookMessage(cls, meta, name, hook, old); 192 | } 193 | return false; 194 | } 195 | #endif 196 | 197 | -------------------------------------------------------------------------------- /YoungHook/YoungHook.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import "CamoCall.h" 4 | 5 | //#define YoungHook_AutoInit 6 | //#define YoungHook_CydiaSubstrate 7 | //#define YoungHook_FishHook 8 | //#define YoungHook_MultiProcess 9 | 10 | // 11 | #ifdef __cplusplus 12 | extern "C" 13 | { 14 | #endif 15 | 16 | #if defined(YoungHook_CydiaSubstrate) || defined(YoungHook_FishHook) 17 | bool YHHookFunction(const char *lib, const char *func, void *hook, void **old); 18 | #endif 19 | bool YHHookMessage(const char * cls, bool meta, const char *name, IMP hook, IMP *old); // Name means ObjC message, use '_' for ':', '__' for '_' 20 | 21 | #ifdef YoungHook_MultiProcess 22 | #if defined(YoungHook_CydiaSubstrate) || defined(YoungHook_FishHook) 23 | bool YHHookFunctionForProcess(const char *proc, const char *lib, const char *func, void *hook, void **old); 24 | #endif 25 | bool YHHookMessageForProcess(const char *proc, const char * cls, bool meta, const char *name, IMP hook, IMP *old); 26 | #endif 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | // 33 | #define __YHHookFunction(NOUSE, ...) YHHookFunction(__VA_ARGS__) 34 | #define __YHHookMessage(NOUSE, ...) YHHookMessage(__VA_ARGS__) 35 | 36 | #define __HOOK_FUNCTION(MOD, HKFN, PROC, RET, LIB, FUNC, ...) RET $##FUNC(__VA_ARGS__);\ 37 | RET (*_##FUNC)(__VA_ARGS__);\ 38 | __attribute__((MOD)) void _Init_##FUNC()\ 39 | {\ 40 | HKFN(#PROC, #LIB, #FUNC, (void *)$##FUNC, (void **)&_##FUNC);\ 41 | }\ 42 | RET $##FUNC(__VA_ARGS__) 43 | 44 | #define __HOOK_MESSAGE(MOD, HKFN, PROC, RET, CLS, MSG, META, ...)\ 45 | RET $##CLS##_##MSG(id self, SEL sel, ##__VA_ARGS__);\ 46 | RET (*_##CLS##_##MSG)(id self, SEL sel, ##__VA_ARGS__);\ 47 | __attribute__((MOD)) void _Init_##CLS##_##MSG()\ 48 | {\ 49 | HKFN(#PROC, #CLS, META, #MSG, (IMP)$##CLS##_##MSG, (IMP *)&_##CLS##_##MSG);\ 50 | }\ 51 | RET $##CLS##_##MSG(id self, SEL sel, ##__VA_ARGS__) 52 | 53 | // Manual hook, call _Init_*** to enable the hook 54 | #define _HOOK_FUNCTION(RET, LIB, FUN, ...) __HOOK_FUNCTION(always_inline, __YHHookFunction, , RET, LIB, FUN, ##__VA_ARGS__) 55 | #define _HOOK_MESSAGE(RET, CLS, MSG, ...) __HOOK_MESSAGE(always_inline, __YHHookMessage, , RET, CLS, MSG, false, ##__VA_ARGS__) 56 | #define _HOOK_CLASS(RET, CLS, MSG, ...) __HOOK_MESSAGE(always_inline, __YHHookMessage, , RET, CLS, MSG, true, ##__VA_ARGS__) 57 | 58 | #ifdef YoungHook_AutoInit 59 | // Automatic hook 60 | #define HOOK_FUNCTION(RET, LIB, FUN, ...) __HOOK_FUNCTION(constructor, __YHHookFunction, , RET, LIB, FUN, ##__VA_ARGS__) 61 | #define HOOK_MESSAGE(RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, __YHHookMessage, , RET, CLS, MSG, false, ##__VA_ARGS__) 62 | #define HOOK_CLASS(RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, __YHHookMessage, , RET, CLS, MSG, true, ##__VA_ARGS__) 63 | 64 | // Automatic hook for special process name 65 | // Use | separator for multiple process name 66 | #ifdef YoungHook_MultiProcess 67 | #define HOOK_FUNCTION_FOR_PROCESS(PROC, RET, LIB, FUN, ...) __HOOK_FUNCTION(constructor, YHHookFunctionForProcess, PROC, RET, LIB, FUN, ##__VA_ARGS__) 68 | #define HOOK_MESSAGE_FOR_PROCESS(PROC, RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, YHHookMessageForProcess, PROC, RET, CLS, MSG, false, ##__VA_ARGS__) 69 | #define HOOK_CLASS_FOR_PROCESS(PROC, RET, CLS, MSG, ...) __HOOK_MESSAGE(constructor, YHHookMessageForProcess, PROC, RET, CLS, MSG, true, ##__VA_ARGS__) 70 | #endif 71 | #endif 72 | -------------------------------------------------------------------------------- /YoungHook/fishhook.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #include "fishhook.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifdef __LP64__ 40 | typedef struct mach_header_64 mach_header_t; 41 | typedef struct segment_command_64 segment_command_t; 42 | typedef struct section_64 section_t; 43 | typedef struct nlist_64 nlist_t; 44 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 45 | #else 46 | typedef struct mach_header mach_header_t; 47 | typedef struct segment_command segment_command_t; 48 | typedef struct section section_t; 49 | typedef struct nlist nlist_t; 50 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT 51 | #endif 52 | 53 | #ifndef SEG_DATA_CONST 54 | #define SEG_DATA_CONST "__DATA_CONST" 55 | #endif 56 | 57 | struct rebindings_entry { 58 | struct rebinding *rebindings; 59 | size_t rebindings_nel; 60 | struct rebindings_entry *next; 61 | }; 62 | 63 | static struct rebindings_entry *_rebindings_head; 64 | 65 | static int prepend_rebindings(struct rebindings_entry **rebindings_head, 66 | struct rebinding rebindings[], 67 | size_t nel) { 68 | struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry)); 69 | if (!new_entry) { 70 | return -1; 71 | } 72 | new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel); 73 | if (!new_entry->rebindings) { 74 | free(new_entry); 75 | return -1; 76 | } 77 | memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); 78 | new_entry->rebindings_nel = nel; 79 | new_entry->next = *rebindings_head; 80 | *rebindings_head = new_entry; 81 | return 0; 82 | } 83 | 84 | static vm_prot_t get_protection(void *sectionStart) { 85 | mach_port_t task = mach_task_self(); 86 | vm_size_t size = 0; 87 | vm_address_t address = (vm_address_t)sectionStart; 88 | memory_object_name_t object; 89 | #if __LP64__ 90 | mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; 91 | vm_region_basic_info_data_64_t info; 92 | kern_return_t info_ret = vm_region_64( 93 | task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_64_t)&info, &count, &object); 94 | #else 95 | mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; 96 | vm_region_basic_info_data_t info; 97 | kern_return_t info_ret = vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object); 98 | #endif 99 | if (info_ret == KERN_SUCCESS) { 100 | return info.protection; 101 | } else { 102 | return VM_PROT_READ; 103 | } 104 | } 105 | static void perform_rebinding_with_section(struct rebindings_entry *rebindings, 106 | section_t *section, 107 | intptr_t slide, 108 | nlist_t *symtab, 109 | char *strtab, 110 | uint32_t *indirect_symtab) { 111 | const bool isDataConst = strcmp(section->segname, "__DATA_CONST") == 0; 112 | uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; 113 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); 114 | vm_prot_t oldProtection = VM_PROT_READ; 115 | if (isDataConst) { 116 | oldProtection = get_protection(rebindings); 117 | mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE); 118 | } 119 | for (uint i = 0; i < section->size / sizeof(void *); i++) { 120 | uint32_t symtab_index = indirect_symbol_indices[i]; 121 | if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || 122 | symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { 123 | continue; 124 | } 125 | uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; 126 | char *symbol_name = strtab + strtab_offset; 127 | bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1]; 128 | struct rebindings_entry *cur = rebindings; 129 | while (cur) { 130 | for (uint j = 0; j < cur->rebindings_nel; j++) { 131 | if (symbol_name_longer_than_1 && 132 | strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { 133 | if (cur->rebindings[j].replaced != NULL && 134 | indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { 135 | *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; 136 | } 137 | indirect_symbol_bindings[i] = cur->rebindings[j].replacement; 138 | goto symbol_loop; 139 | } 140 | } 141 | cur = cur->next; 142 | } 143 | symbol_loop:; 144 | } 145 | if (isDataConst) { 146 | int protection = 0; 147 | if (oldProtection & VM_PROT_READ) { 148 | protection |= PROT_READ; 149 | } 150 | if (oldProtection & VM_PROT_WRITE) { 151 | protection |= PROT_WRITE; 152 | } 153 | if (oldProtection & VM_PROT_EXECUTE) { 154 | protection |= PROT_EXEC; 155 | } 156 | mprotect(indirect_symbol_bindings, section->size, protection); 157 | } 158 | } 159 | 160 | static void rebind_symbols_for_image(struct rebindings_entry *rebindings, 161 | const struct mach_header *header, 162 | intptr_t slide) { 163 | Dl_info info; 164 | if (dladdr(header, &info) == 0) { 165 | return; 166 | } 167 | 168 | segment_command_t *cur_seg_cmd; 169 | segment_command_t *linkedit_segment = NULL; 170 | struct symtab_command* symtab_cmd = NULL; 171 | struct dysymtab_command* dysymtab_cmd = NULL; 172 | 173 | uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); 174 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 175 | cur_seg_cmd = (segment_command_t *)cur; 176 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 177 | if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { 178 | linkedit_segment = cur_seg_cmd; 179 | } 180 | } else if (cur_seg_cmd->cmd == LC_SYMTAB) { 181 | symtab_cmd = (struct symtab_command*)cur_seg_cmd; 182 | } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { 183 | dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; 184 | } 185 | } 186 | 187 | if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || 188 | !dysymtab_cmd->nindirectsyms) { 189 | return; 190 | } 191 | 192 | // Find base symbol/string table addresses 193 | uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; 194 | nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); 195 | char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); 196 | 197 | // Get indirect symbol table (array of uint32_t indices into symbol table) 198 | uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); 199 | 200 | cur = (uintptr_t)header + sizeof(mach_header_t); 201 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 202 | cur_seg_cmd = (segment_command_t *)cur; 203 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 204 | if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && 205 | strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { 206 | continue; 207 | } 208 | for (uint j = 0; j < cur_seg_cmd->nsects; j++) { 209 | section_t *sect = 210 | (section_t *)(cur + sizeof(segment_command_t)) + j; 211 | if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { 212 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 213 | } 214 | if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { 215 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 216 | } 217 | } 218 | } 219 | } 220 | } 221 | 222 | static void _rebind_symbols_for_image(const struct mach_header *header, 223 | intptr_t slide) { 224 | rebind_symbols_for_image(_rebindings_head, header, slide); 225 | } 226 | 227 | int rebind_symbols_image(void *header, 228 | intptr_t slide, 229 | struct rebinding rebindings[], 230 | size_t rebindings_nel) { 231 | struct rebindings_entry *rebindings_head = NULL; 232 | int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); 233 | rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide); 234 | if (rebindings_head) { 235 | free(rebindings_head->rebindings); 236 | } 237 | free(rebindings_head); 238 | return retval; 239 | } 240 | 241 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { 242 | int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); 243 | if (retval < 0) { 244 | return retval; 245 | } 246 | // If this was the first call, register callback for image additions (which is also invoked for 247 | // existing images, otherwise, just run on existing images 248 | if (!_rebindings_head->next) { 249 | _dyld_register_func_for_add_image(_rebind_symbols_for_image); 250 | } else { 251 | uint32_t c = _dyld_image_count(); 252 | for (uint32_t i = 0; i < c; i++) { 253 | _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 254 | } 255 | } 256 | return retval; 257 | } 258 | -------------------------------------------------------------------------------- /YoungHook/fishhook.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef fishhook_h 25 | #define fishhook_h 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(FISHHOOK_EXPORT) 31 | #define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) 32 | #else 33 | #define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif //__cplusplus 39 | 40 | /* 41 | * A structure representing a particular intended rebinding from a symbol 42 | * name to its replacement 43 | */ 44 | struct rebinding { 45 | const char *name; 46 | void *replacement; 47 | void **replaced; 48 | }; 49 | 50 | /* 51 | * For each rebinding in rebindings, rebinds references to external, indirect 52 | * symbols with the specified name to instead point at replacement for each 53 | * image in the calling process as well as for all future images that are loaded 54 | * by the process. If rebind_functions is called more than once, the symbols to 55 | * rebind are added to the existing list of rebindings, and if a given symbol 56 | * is rebound more than once, the later rebinding will take precedence. 57 | */ 58 | FISHHOOK_VISIBILITY 59 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); 60 | 61 | /* 62 | * Rebinds as above, but only in the specified image. The header should point 63 | * to the mach-o header, the slide should be the slide offset. Others as above. 64 | */ 65 | FISHHOOK_VISIBILITY 66 | int rebind_symbols_image(void *header, 67 | intptr_t slide, 68 | struct rebinding rebindings[], 69 | size_t rebindings_nel); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif //__cplusplus 74 | 75 | #endif //fishhook_h 76 | 77 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8442EE6B2394F4850021F5F8 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8442EE6A2394F4850021F5F8 /* AppDelegate.mm */; }; 11 | 8442EE6E2394F4850021F5F8 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8442EE6D2394F4850021F5F8 /* SceneDelegate.m */; }; 12 | 8442EE712394F4850021F5F8 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8442EE702394F4850021F5F8 /* ViewController.m */; }; 13 | 8442EE742394F4850021F5F8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8442EE722394F4850021F5F8 /* Main.storyboard */; }; 14 | 8442EE762394F4860021F5F8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8442EE752394F4860021F5F8 /* Assets.xcassets */; }; 15 | 8442EE792394F4860021F5F8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8442EE772394F4860021F5F8 /* LaunchScreen.storyboard */; }; 16 | 8442EE7C2394F4860021F5F8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8442EE7B2394F4860021F5F8 /* main.m */; }; 17 | 8442EE88239503350021F5F8 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8442EE87239503350021F5F8 /* WebKit.framework */; }; 18 | 84DBAB8E239A8E4B007FCE32 /* YoungHook.c in Sources */ = {isa = PBXBuildFile; fileRef = 84DBAB89239A8E4A007FCE32 /* YoungHook.c */; }; 19 | 84DBAB8F239A8E4B007FCE32 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 84DBAB8A239A8E4A007FCE32 /* fishhook.c */; }; 20 | 84DBAB90239A8E4B007FCE32 /* CamoCall.c in Sources */ = {isa = PBXBuildFile; fileRef = 84DBAB8B239A8E4A007FCE32 /* CamoCall.c */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 8421C23D239A5A3300009FC1 /* YoungHookDemoCamo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YoungHookDemoCamo.h; sourceTree = ""; }; 25 | 8442EE662394F4850021F5F8 /* YoungHookDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YoungHookDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 8442EE692394F4850021F5F8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 27 | 8442EE6A2394F4850021F5F8 /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = ""; }; 28 | 8442EE6C2394F4850021F5F8 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; 29 | 8442EE6D2394F4850021F5F8 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; 30 | 8442EE6F2394F4850021F5F8 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 31 | 8442EE702394F4850021F5F8 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 32 | 8442EE732394F4850021F5F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 33 | 8442EE752394F4860021F5F8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 34 | 8442EE782394F4860021F5F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 35 | 8442EE7A2394F4860021F5F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 8442EE7B2394F4860021F5F8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 37 | 8442EE87239503350021F5F8 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 38 | 84DBAB88239A8E4A007FCE32 /* CamoCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CamoCall.h; sourceTree = ""; }; 39 | 84DBAB89239A8E4A007FCE32 /* YoungHook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = YoungHook.c; sourceTree = ""; }; 40 | 84DBAB8A239A8E4A007FCE32 /* fishhook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fishhook.c; sourceTree = ""; }; 41 | 84DBAB8B239A8E4A007FCE32 /* CamoCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CamoCall.c; sourceTree = ""; }; 42 | 84DBAB8C239A8E4A007FCE32 /* fishhook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = ""; }; 43 | 84DBAB8D239A8E4A007FCE32 /* YoungHook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YoungHook.h; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | 8442EE632394F4850021F5F8 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | 8442EE88239503350021F5F8 /* WebKit.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 8442EE5D2394F4850021F5F8 = { 59 | isa = PBXGroup; 60 | children = ( 61 | 84DBAB87239A8E4A007FCE32 /* YoungHook */, 62 | 8442EE682394F4850021F5F8 /* YoungHookDemo */, 63 | 8442EE672394F4850021F5F8 /* Products */, 64 | 8442EE86239503350021F5F8 /* Frameworks */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 8442EE672394F4850021F5F8 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 8442EE662394F4850021F5F8 /* YoungHookDemo.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 8442EE682394F4850021F5F8 /* YoungHookDemo */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 8421C23D239A5A3300009FC1 /* YoungHookDemoCamo.h */, 80 | 8442EE692394F4850021F5F8 /* AppDelegate.h */, 81 | 8442EE6A2394F4850021F5F8 /* AppDelegate.mm */, 82 | 8442EE6C2394F4850021F5F8 /* SceneDelegate.h */, 83 | 8442EE6D2394F4850021F5F8 /* SceneDelegate.m */, 84 | 8442EE6F2394F4850021F5F8 /* ViewController.h */, 85 | 8442EE702394F4850021F5F8 /* ViewController.m */, 86 | 8442EE722394F4850021F5F8 /* Main.storyboard */, 87 | 8442EE752394F4860021F5F8 /* Assets.xcassets */, 88 | 8442EE772394F4860021F5F8 /* LaunchScreen.storyboard */, 89 | 8442EE7A2394F4860021F5F8 /* Info.plist */, 90 | 8442EE7B2394F4860021F5F8 /* main.m */, 91 | ); 92 | path = YoungHookDemo; 93 | sourceTree = ""; 94 | }; 95 | 8442EE86239503350021F5F8 /* Frameworks */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 8442EE87239503350021F5F8 /* WebKit.framework */, 99 | ); 100 | name = Frameworks; 101 | sourceTree = ""; 102 | }; 103 | 84DBAB87239A8E4A007FCE32 /* YoungHook */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 84DBAB88239A8E4A007FCE32 /* CamoCall.h */, 107 | 84DBAB8B239A8E4A007FCE32 /* CamoCall.c */, 108 | 84DBAB8A239A8E4A007FCE32 /* fishhook.c */, 109 | 84DBAB8C239A8E4A007FCE32 /* fishhook.h */, 110 | 84DBAB89239A8E4A007FCE32 /* YoungHook.c */, 111 | 84DBAB8D239A8E4A007FCE32 /* YoungHook.h */, 112 | ); 113 | name = YoungHook; 114 | path = ../YoungHook; 115 | sourceTree = ""; 116 | }; 117 | /* End PBXGroup section */ 118 | 119 | /* Begin PBXNativeTarget section */ 120 | 8442EE652394F4850021F5F8 /* YoungHookDemo */ = { 121 | isa = PBXNativeTarget; 122 | buildConfigurationList = 8442EE7F2394F4860021F5F8 /* Build configuration list for PBXNativeTarget "YoungHookDemo" */; 123 | buildPhases = ( 124 | 8442EE622394F4850021F5F8 /* Sources */, 125 | 8442EE632394F4850021F5F8 /* Frameworks */, 126 | 8442EE642394F4850021F5F8 /* Resources */, 127 | ); 128 | buildRules = ( 129 | ); 130 | dependencies = ( 131 | ); 132 | name = YoungHookDemo; 133 | productName = YoungHookDemo; 134 | productReference = 8442EE662394F4850021F5F8 /* YoungHookDemo.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 8442EE5E2394F4850021F5F8 /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastUpgradeCheck = 1120; 144 | ORGANIZATIONNAME = Yonsm; 145 | TargetAttributes = { 146 | 8442EE652394F4850021F5F8 = { 147 | CreatedOnToolsVersion = 11.2.1; 148 | }; 149 | }; 150 | }; 151 | buildConfigurationList = 8442EE612394F4850021F5F8 /* Build configuration list for PBXProject "YoungHookDemo" */; 152 | compatibilityVersion = "Xcode 9.3"; 153 | developmentRegion = en; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | Base, 158 | ); 159 | mainGroup = 8442EE5D2394F4850021F5F8; 160 | productRefGroup = 8442EE672394F4850021F5F8 /* Products */; 161 | projectDirPath = ""; 162 | projectRoot = ""; 163 | targets = ( 164 | 8442EE652394F4850021F5F8 /* YoungHookDemo */, 165 | ); 166 | }; 167 | /* End PBXProject section */ 168 | 169 | /* Begin PBXResourcesBuildPhase section */ 170 | 8442EE642394F4850021F5F8 /* Resources */ = { 171 | isa = PBXResourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 8442EE792394F4860021F5F8 /* LaunchScreen.storyboard in Resources */, 175 | 8442EE762394F4860021F5F8 /* Assets.xcassets in Resources */, 176 | 8442EE742394F4850021F5F8 /* Main.storyboard in Resources */, 177 | ); 178 | runOnlyForDeploymentPostprocessing = 0; 179 | }; 180 | /* End PBXResourcesBuildPhase section */ 181 | 182 | /* Begin PBXSourcesBuildPhase section */ 183 | 8442EE622394F4850021F5F8 /* Sources */ = { 184 | isa = PBXSourcesBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | 84DBAB8E239A8E4B007FCE32 /* YoungHook.c in Sources */, 188 | 8442EE712394F4850021F5F8 /* ViewController.m in Sources */, 189 | 8442EE6B2394F4850021F5F8 /* AppDelegate.mm in Sources */, 190 | 84DBAB90239A8E4B007FCE32 /* CamoCall.c in Sources */, 191 | 8442EE7C2394F4860021F5F8 /* main.m in Sources */, 192 | 84DBAB8F239A8E4B007FCE32 /* fishhook.c in Sources */, 193 | 8442EE6E2394F4850021F5F8 /* SceneDelegate.m in Sources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXSourcesBuildPhase section */ 198 | 199 | /* Begin PBXVariantGroup section */ 200 | 8442EE722394F4850021F5F8 /* Main.storyboard */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 8442EE732394F4850021F5F8 /* Base */, 204 | ); 205 | name = Main.storyboard; 206 | sourceTree = ""; 207 | }; 208 | 8442EE772394F4860021F5F8 /* LaunchScreen.storyboard */ = { 209 | isa = PBXVariantGroup; 210 | children = ( 211 | 8442EE782394F4860021F5F8 /* Base */, 212 | ); 213 | name = LaunchScreen.storyboard; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXVariantGroup section */ 217 | 218 | /* Begin XCBuildConfiguration section */ 219 | 8442EE7D2394F4860021F5F8 /* Debug */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | ALWAYS_SEARCH_USER_PATHS = NO; 223 | CLANG_ANALYZER_NONNULL = YES; 224 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 225 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 226 | CLANG_CXX_LIBRARY = "libc++"; 227 | CLANG_ENABLE_MODULES = YES; 228 | CLANG_ENABLE_OBJC_ARC = YES; 229 | CLANG_ENABLE_OBJC_WEAK = YES; 230 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 231 | CLANG_WARN_BOOL_CONVERSION = YES; 232 | CLANG_WARN_COMMA = YES; 233 | CLANG_WARN_CONSTANT_CONVERSION = YES; 234 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 235 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 236 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 237 | CLANG_WARN_EMPTY_BODY = YES; 238 | CLANG_WARN_ENUM_CONVERSION = YES; 239 | CLANG_WARN_INFINITE_RECURSION = YES; 240 | CLANG_WARN_INT_CONVERSION = YES; 241 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 242 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 243 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 244 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 245 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 246 | CLANG_WARN_STRICT_PROTOTYPES = YES; 247 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 248 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 249 | CLANG_WARN_UNREACHABLE_CODE = YES; 250 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 251 | COPY_PHASE_STRIP = NO; 252 | DEBUG_INFORMATION_FORMAT = dwarf; 253 | ENABLE_STRICT_OBJC_MSGSEND = YES; 254 | ENABLE_TESTABILITY = YES; 255 | GCC_C_LANGUAGE_STANDARD = gnu11; 256 | GCC_DYNAMIC_NO_PIC = NO; 257 | GCC_NO_COMMON_BLOCKS = YES; 258 | GCC_OPTIMIZATION_LEVEL = 0; 259 | GCC_PREPROCESSOR_DEFINITIONS = ( 260 | "DEBUG=1", 261 | "$(inherited)", 262 | ); 263 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 264 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 265 | GCC_WARN_UNDECLARED_SELECTOR = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 267 | GCC_WARN_UNUSED_FUNCTION = YES; 268 | GCC_WARN_UNUSED_VARIABLE = YES; 269 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 270 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 271 | MTL_FAST_MATH = YES; 272 | ONLY_ACTIVE_ARCH = YES; 273 | SDKROOT = iphoneos; 274 | }; 275 | name = Debug; 276 | }; 277 | 8442EE7E2394F4860021F5F8 /* Release */ = { 278 | isa = XCBuildConfiguration; 279 | buildSettings = { 280 | ALWAYS_SEARCH_USER_PATHS = NO; 281 | CLANG_ANALYZER_NONNULL = YES; 282 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 283 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 284 | CLANG_CXX_LIBRARY = "libc++"; 285 | CLANG_ENABLE_MODULES = YES; 286 | CLANG_ENABLE_OBJC_ARC = YES; 287 | CLANG_ENABLE_OBJC_WEAK = YES; 288 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 289 | CLANG_WARN_BOOL_CONVERSION = YES; 290 | CLANG_WARN_COMMA = YES; 291 | CLANG_WARN_CONSTANT_CONVERSION = YES; 292 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 293 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 294 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 295 | CLANG_WARN_EMPTY_BODY = YES; 296 | CLANG_WARN_ENUM_CONVERSION = YES; 297 | CLANG_WARN_INFINITE_RECURSION = YES; 298 | CLANG_WARN_INT_CONVERSION = YES; 299 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 300 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 301 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 302 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 303 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 304 | CLANG_WARN_STRICT_PROTOTYPES = YES; 305 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 306 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 307 | CLANG_WARN_UNREACHABLE_CODE = YES; 308 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 309 | COPY_PHASE_STRIP = NO; 310 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 311 | ENABLE_NS_ASSERTIONS = NO; 312 | ENABLE_STRICT_OBJC_MSGSEND = YES; 313 | GCC_C_LANGUAGE_STANDARD = gnu11; 314 | GCC_NO_COMMON_BLOCKS = YES; 315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 317 | GCC_WARN_UNDECLARED_SELECTOR = YES; 318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 319 | GCC_WARN_UNUSED_FUNCTION = YES; 320 | GCC_WARN_UNUSED_VARIABLE = YES; 321 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 322 | MTL_ENABLE_DEBUG_INFO = NO; 323 | MTL_FAST_MATH = YES; 324 | SDKROOT = iphoneos; 325 | VALIDATE_PRODUCT = YES; 326 | }; 327 | name = Release; 328 | }; 329 | 8442EE802394F4860021F5F8 /* Debug */ = { 330 | isa = XCBuildConfiguration; 331 | buildSettings = { 332 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 333 | CODE_SIGN_STYLE = Automatic; 334 | DEVELOPMENT_TEAM = 97Y98KA82X; 335 | INFOPLIST_FILE = YoungHookDemo/Info.plist; 336 | LD_RUNPATH_SEARCH_PATHS = ( 337 | "$(inherited)", 338 | "@executable_path/Frameworks", 339 | ); 340 | PRODUCT_BUNDLE_IDENTIFIER = net.Yonsm.YoungHookDemo; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | TARGETED_DEVICE_FAMILY = "1,2"; 343 | }; 344 | name = Debug; 345 | }; 346 | 8442EE812394F4860021F5F8 /* Release */ = { 347 | isa = XCBuildConfiguration; 348 | buildSettings = { 349 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 350 | CODE_SIGN_STYLE = Automatic; 351 | DEVELOPMENT_TEAM = 97Y98KA82X; 352 | INFOPLIST_FILE = YoungHookDemo/Info.plist; 353 | LD_RUNPATH_SEARCH_PATHS = ( 354 | "$(inherited)", 355 | "@executable_path/Frameworks", 356 | ); 357 | PRODUCT_BUNDLE_IDENTIFIER = net.Yonsm.YoungHookDemo; 358 | PRODUCT_NAME = "$(TARGET_NAME)"; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Release; 362 | }; 363 | /* End XCBuildConfiguration section */ 364 | 365 | /* Begin XCConfigurationList section */ 366 | 8442EE612394F4850021F5F8 /* Build configuration list for PBXProject "YoungHookDemo" */ = { 367 | isa = XCConfigurationList; 368 | buildConfigurations = ( 369 | 8442EE7D2394F4860021F5F8 /* Debug */, 370 | 8442EE7E2394F4860021F5F8 /* Release */, 371 | ); 372 | defaultConfigurationIsVisible = 0; 373 | defaultConfigurationName = Release; 374 | }; 375 | 8442EE7F2394F4860021F5F8 /* Build configuration list for PBXNativeTarget "YoungHookDemo" */ = { 376 | isa = XCConfigurationList; 377 | buildConfigurations = ( 378 | 8442EE802394F4860021F5F8 /* Debug */, 379 | 8442EE812394F4860021F5F8 /* Release */, 380 | ); 381 | defaultConfigurationIsVisible = 0; 382 | defaultConfigurationName = Release; 383 | }; 384 | /* End XCConfigurationList section */ 385 | }; 386 | rootObject = 8442EE5E2394F4850021F5F8 /* Project object */; 387 | } 388 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // YoungHookDemo 4 | // 5 | // Created by 郭春杨 on 2019/12/2. 6 | // Copyright © 2019 Yonsm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.mm for C++ test 3 | // YoungHookDemo 4 | // 5 | // Created by 郭春杨 on 2019/12/2. 6 | // Copyright © 2019 Yonsm. All rights reserved. 7 | 8 | #import "AppDelegate.h" 9 | //#import "CamoCall.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 18 | // Override point for customization after application launch. 19 | 20 | // NSLog(@"%@: %s", CFBridgingRelease( 21 | // CamoCallClassMessage("NSString", "stringWithCString:encoding:", "XXXX", NSUTF8StringEncoding) 22 | // ), "\x30"); 23 | return YES; 24 | } 25 | 26 | 27 | #pragma mark - UISceneSession lifecycle 28 | 29 | 30 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { 31 | // Called when a new scene session is being created. 32 | // Use this method to select a configuration to create the new scene with. 33 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; 34 | } 35 | 36 | 37 | - (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { 38 | // Called when the user discards a scene session. 39 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 40 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 41 | } 42 | 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // YoungHookDemo 4 | // 5 | // Created by 郭春杨 on 2019/12/2. 6 | // Copyright © 2019 Yonsm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SceneDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | #import "SceneDelegate.h" 2 | 3 | @interface SceneDelegate () 4 | 5 | @end 6 | 7 | @implementation SceneDelegate 8 | 9 | 10 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 11 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 12 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 13 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 14 | } 15 | 16 | 17 | - (void)sceneDidDisconnect:(UIScene *)scene { 18 | // Called as the scene is being released by the system. 19 | // This occurs shortly after the scene enters the background, or when its session is discarded. 20 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 21 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 22 | } 23 | 24 | 25 | - (void)sceneDidBecomeActive:(UIScene *)scene { 26 | // Called when the scene has moved from an inactive state to an active state. 27 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 28 | } 29 | 30 | 31 | - (void)sceneWillResignActive:(UIScene *)scene { 32 | // Called when the scene will move from an active state to an inactive state. 33 | // This may occur due to temporary interruptions (ex. an incoming phone call). 34 | } 35 | 36 | 37 | - (void)sceneWillEnterForeground:(UIScene *)scene { 38 | // Called as the scene transitions from the background to the foreground. 39 | // Use this method to undo the changes made on entering the background. 40 | } 41 | 42 | 43 | - (void)sceneDidEnterBackground:(UIScene *)scene { 44 | // Called as the scene transitions from the foreground to the background. 45 | // Use this method to save data, release shared resources, and store enough scene-specific state information 46 | // to restore the scene back to its current state. 47 | } 48 | 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // YoungHookDemo 4 | // 5 | // Created by 郭春杨 on 2019/12/2. 6 | // Copyright © 2019 Yonsm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // YoungHookDemo 4 | // 5 | // Created by 郭春杨 on 2019/12/2. 6 | // Copyright © 2019 Yonsm. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import "YoungHook.h" 12 | #import "YoungHookDemoCamo.h" 13 | 14 | // https://github.com/WebKit/webkit/blob/39a299616172a4d4fe1f7aaf573b41020a1d7358/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm#L1869 15 | _HOOK_MESSAGE(void, WKWebView, __layerTreeCommitComplete) 16 | { 17 | NSLog(@"%s, %@", __FUNCTION__, self); 18 | _WKWebView___layerTreeCommitComplete(self, sel); 19 | } 20 | 21 | // https://github.com/WebKit/webkit/blob/39a299616172a4d4fe1f7aaf573b41020a1d7358/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm#L4172 22 | _HOOK_CLASS(BOOL, WKWebView, handlesURLScheme_, NSString *urlScheme) 23 | { 24 | return _WKWebView_handlesURLScheme_(self, sel, urlScheme); 25 | } 26 | 27 | @implementation ViewController 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | // Do any additional setup after loading the view. 32 | 33 | WKProcessPool *pool = [[WKProcessPool alloc] init]; 34 | WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; 35 | config.processPool = pool; 36 | WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; 37 | webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 38 | //[webView loadHTMLString:@"Loading..." baseURL:[NSURL URLWithString:CAMO_https_www_apple_com]]; 39 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:CAMO_https_www_apple_com]]]; 40 | [self.view addSubview:webView]; 41 | 42 | //id browsingContextController = [webView browsingContextController]; 43 | //[NSClassFromString(@"WKBrowsingContextController") registerSchemeForCustomProtocol:@"https"]; 44 | 45 | CamoCallInit(); 46 | _Init_WKWebView_handlesURLScheme_(); 47 | _Init_WKWebView___layerTreeCommitComplete(); 48 | 49 | // DEMO1 50 | CAMO_NSString; CAMO_stringWithCString_encoding; CAMO_XXXX; 51 | NSLog(@"%@", CamoCallClassMessage(camo_NSString, camo_stringWithCString_encoding, camo_XXXX, NSUTF8StringEncoding)); 52 | 53 | //[WKWebView handlesURLScheme:[NSString stringWithCString:CamoDecrypt((__bridge CamoData *) webView) encoding:NSUTF8StringEncoding]]; 54 | //YHMsgSend(WKWebView, handlesURLScheme_, 55 | //objc_msgSend(WKWebView); 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/YoungHookDemoCamo.h: -------------------------------------------------------------------------------- 1 | // NSString 2 | #define CAMO_NSString char camo_NSString[9]; CamoStringDecode(camo_NSString, "\x46\x5a\x59\x79\x76\x5c\x60\x68", 8) 3 | // stringWithCString:encoding: 4 | #define CAMO_stringWithCString_encoding char camo_stringWithCString_encoding[28]; CamoStringDecode(camo_stringWithCString_encoding, "\x68\x6e\x67\x6f\x71\x77\x46\x6b\x67\x6a\x4e\x3d\x63\x5c\x64\x66\x6c\x10\x6c\x62\x64\x5f\x69\x5b\x5d\x63\x07", 27) 5 | // XXXX 6 | #define CAMO_XXXX char camo_XXXX[5]; CamoStringDecode(camo_XXXX, "\x5c\x5b\x5a\x59", 4) 7 | //@https://www.apple.com 8 | #define CAMO_https_www_apple_com CFBridgingRelease(CamoStringDecode2("\x7d\x60\x5f\x62\x62\x2a\x34\x33\x5a\x59\x58\x30\x68\x58\x57\x6a\x60\x2a\x64\x67\x64", 21)) 9 | -------------------------------------------------------------------------------- /YoungHookDemo/YoungHookDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // YoungHookDemo 4 | // 5 | // Created by 郭春杨 on 2019/12/2. 6 | // Copyright © 2019 Yonsm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | --------------------------------------------------------------------------------