├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── fishhook.c ├── fishhook.h └── fishhook.podspec /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to fishhook 2 | We want to make contributing to this project as easy and transparent as 3 | possible. 4 | 5 | ## Pull Requests 6 | We actively welcome your pull requests. 7 | 8 | 1. Fork the repo and create your branch from `master`. 9 | 2. If you've added code that should be tested, add tests. 10 | 3. If you've changed APIs, update the documentation. 11 | 4. Ensure the test suite passes. 12 | 5. Make sure your code lints. 13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 14 | 15 | ## Contributor License Agreement ("CLA") 16 | In order to accept your pull request, we need you to submit a CLA. You only need 17 | to do this once to work on any of Facebook's open source projects. 18 | 19 | Complete your CLA here: 20 | 21 | ## Issues 22 | We use GitHub issues to track public bugs. Please ensure your description is 23 | clear and has sufficient instructions to be able to reproduce the issue. 24 | 25 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe 26 | disclosure of security bugs. In those cases, please go through the process 27 | outlined on that page and do not file a public issue. 28 | 29 | ## License 30 | By contributing to fishhook, you agree that your contributions will be licensed 31 | under the LICENSE file in the root directory of this source tree. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fishhook 2 | 3 | __fishhook__ is a very simple library that enables dynamically rebinding symbols in Mach-O binaries running on iOS in the simulator and on device. This provides functionality that is similar to using [`DYLD_INTERPOSE`][interpose] on OS X. At Facebook, we've found it useful as a way to hook calls in libSystem for debugging/tracing purposes (for example, auditing for double-close issues with file descriptors). 4 | 5 | [interpose]: http://opensource.apple.com/source/dyld/dyld-210.2.3/include/mach-o/dyld-interposing.h "" 6 | 7 | ## Usage 8 | 9 | Once you add `fishhook.h`/`fishhook.c` to your project, you can rebind symbols as follows: 10 | ```Objective-C 11 | #import 12 | 13 | #import 14 | 15 | #import "AppDelegate.h" 16 | #import "fishhook.h" 17 | 18 | static int (*orig_close)(int); 19 | static int (*orig_open)(const char *, int, ...); 20 | 21 | int my_close(int fd) { 22 | printf("Calling real close(%d)\n", fd); 23 | return orig_close(fd); 24 | } 25 | 26 | int my_open(const char *path, int oflag, ...) { 27 | va_list ap = {0}; 28 | mode_t mode = 0; 29 | 30 | if ((oflag & O_CREAT) != 0) { 31 | // mode only applies to O_CREAT 32 | va_start(ap, oflag); 33 | mode = va_arg(ap, int); 34 | va_end(ap); 35 | printf("Calling real open('%s', %d, %d)\n", path, oflag, mode); 36 | return orig_open(path, oflag, mode); 37 | } else { 38 | printf("Calling real open('%s', %d)\n", path, oflag); 39 | return orig_open(path, oflag, mode); 40 | } 41 | } 42 | 43 | int main(int argc, char * argv[]) 44 | { 45 | @autoreleasepool { 46 | rebind_symbols((struct rebinding[2]){{"close", my_close, (void *)&orig_close}, {"open", my_open, (void *)&orig_open}}, 2); 47 | 48 | // Open our own binary and print out first 4 bytes (which is the same 49 | // for all Mach-O binaries on a given architecture) 50 | int fd = open(argv[0], O_RDONLY); 51 | uint32_t magic_number = 0; 52 | read(fd, &magic_number, 4); 53 | printf("Mach-O Magic Number: %x \n", magic_number); 54 | close(fd); 55 | 56 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 57 | } 58 | } 59 | ``` 60 | ### Sample output 61 | ``` 62 | Calling real open('/var/mobile/Applications/161DA598-5B83-41F5-8A44-675491AF6A2C/Test.app/Test', 0) 63 | Mach-O Magic Number: feedface 64 | Calling real close(3) 65 | ... 66 | ``` 67 | 68 | ## How it works 69 | 70 | `dyld` binds lazy and non-lazy symbols by updating pointers in particular sections of the `__DATA` segment of a Mach-O binary. __fishhook__ re-binds these symbols by determining the locations to update for each of the symbol names passed to `rebind_symbols` and then writing out the corresponding replacements. 71 | 72 | For a given image, the `__DATA` segment may contain two sections that are relevant for dynamic symbol bindings: `__nl_symbol_ptr` and `__la_symbol_ptr`. `__nl_symbol_ptr` is an array of pointers to non-lazily bound data (these are bound at the time a library is loaded) and `__la_symbol_ptr` is an array of pointers to imported functions that is generally filled by a routine called `dyld_stub_binder` during the first call to that symbol (it's also possible to tell `dyld` to bind these at launch). In order to find the name of the symbol that corresponds to a particular location in one of these sections, we have to jump through several layers of indirection. For the two relevant sections, the section headers (`struct section`s from ``) provide an offset (in the `reserved1` field) into what is known as the indirect symbol table. The indirect symbol table, which is located in the `__LINKEDIT` segment of the binary, is just an array of indexes into the symbol table (also in `__LINKEDIT`) whose order is identical to that of the pointers in the non-lazy and lazy symbol sections. So, given `struct section nl_symbol_ptr`, the corresponding index in the symbol table of the first address in that section is `indirect_symbol_table[nl_symbol_ptr->reserved1]`. The symbol table itself is an array of `struct nlist`s (see ``), and each `nlist` contains an index into the string table in `__LINKEDIT` which where the actual symbol names are stored. So, for each pointer `__nl_symbol_ptr` and `__la_symbol_ptr`, we are able to find the corresponding symbol and then the corresponding string to compare against the requested symbol names, and if there is a match, we replace the pointer in the section with the replacement. 73 | 74 | The process of looking up the name of a given entry in the lazy or non-lazy pointer tables looks like this: 75 | ![Visual explanation](http://i.imgur.com/HVXqHCz.png) -------------------------------------------------------------------------------- /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 | #if 0 85 | static int get_protection(void *addr, vm_prot_t *prot, vm_prot_t *max_prot) { 86 | mach_port_t task = mach_task_self(); 87 | vm_size_t size = 0; 88 | vm_address_t address = (vm_address_t)addr; 89 | memory_object_name_t object; 90 | #ifdef __LP64__ 91 | mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; 92 | vm_region_basic_info_data_64_t info; 93 | kern_return_t info_ret = vm_region_64( 94 | task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_64_t)&info, &count, &object); 95 | #else 96 | mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; 97 | vm_region_basic_info_data_t info; 98 | kern_return_t info_ret = vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object); 99 | #endif 100 | if (info_ret == KERN_SUCCESS) { 101 | if (prot != NULL) 102 | *prot = info.protection; 103 | 104 | if (max_prot != NULL) 105 | *max_prot = info.max_protection; 106 | 107 | return 0; 108 | } 109 | 110 | return -1; 111 | } 112 | #endif 113 | 114 | static void perform_rebinding_with_section(struct rebindings_entry *rebindings, 115 | section_t *section, 116 | intptr_t slide, 117 | nlist_t *symtab, 118 | char *strtab, 119 | uint32_t *indirect_symtab) { 120 | uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; 121 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); 122 | 123 | for (uint i = 0; i < section->size / sizeof(void *); i++) { 124 | uint32_t symtab_index = indirect_symbol_indices[i]; 125 | if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || 126 | symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { 127 | continue; 128 | } 129 | uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; 130 | char *symbol_name = strtab + strtab_offset; 131 | bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1]; 132 | struct rebindings_entry *cur = rebindings; 133 | while (cur) { 134 | for (uint j = 0; j < cur->rebindings_nel; j++) { 135 | if (symbol_name_longer_than_1 && strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { 136 | kern_return_t err; 137 | 138 | if (cur->rebindings[j].replaced != NULL && indirect_symbol_bindings[i] != cur->rebindings[j].replacement) 139 | *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; 140 | 141 | /** 142 | * 1. Moved the vm protection modifying codes to here to reduce the 143 | * changing scope. 144 | * 2. Adding VM_PROT_WRITE mode unconditionally because vm_region 145 | * API on some iOS/Mac reports mismatch vm protection attributes. 146 | * -- Lianfu Hao Jun 16th, 2021 147 | **/ 148 | err = vm_protect (mach_task_self (), (uintptr_t)indirect_symbol_bindings, section->size, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY); 149 | if (err == KERN_SUCCESS) { 150 | /** 151 | * Once we failed to change the vm protection, we 152 | * MUST NOT continue the following write actions! 153 | * iOS 15 has corrected the const segments prot. 154 | * -- Lionfore Hao Jun 11th, 2021 155 | **/ 156 | indirect_symbol_bindings[i] = cur->rebindings[j].replacement; 157 | } 158 | goto symbol_loop; 159 | } 160 | } 161 | cur = cur->next; 162 | } 163 | symbol_loop:; 164 | } 165 | } 166 | 167 | static void rebind_symbols_for_image(struct rebindings_entry *rebindings, 168 | const struct mach_header *header, 169 | intptr_t slide) { 170 | Dl_info info; 171 | if (dladdr(header, &info) == 0) { 172 | return; 173 | } 174 | 175 | segment_command_t *cur_seg_cmd; 176 | segment_command_t *linkedit_segment = NULL; 177 | struct symtab_command* symtab_cmd = NULL; 178 | struct dysymtab_command* dysymtab_cmd = NULL; 179 | 180 | uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); 181 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 182 | cur_seg_cmd = (segment_command_t *)cur; 183 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 184 | if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { 185 | linkedit_segment = cur_seg_cmd; 186 | } 187 | } else if (cur_seg_cmd->cmd == LC_SYMTAB) { 188 | symtab_cmd = (struct symtab_command*)cur_seg_cmd; 189 | } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { 190 | dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; 191 | } 192 | } 193 | 194 | if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || 195 | !dysymtab_cmd->nindirectsyms) { 196 | return; 197 | } 198 | 199 | // Find base symbol/string table addresses 200 | uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; 201 | nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); 202 | char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); 203 | 204 | // Get indirect symbol table (array of uint32_t indices into symbol table) 205 | uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); 206 | 207 | cur = (uintptr_t)header + sizeof(mach_header_t); 208 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 209 | cur_seg_cmd = (segment_command_t *)cur; 210 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 211 | if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && 212 | strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { 213 | continue; 214 | } 215 | for (uint j = 0; j < cur_seg_cmd->nsects; j++) { 216 | section_t *sect = 217 | (section_t *)(cur + sizeof(segment_command_t)) + j; 218 | if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { 219 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 220 | } 221 | if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { 222 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 223 | } 224 | } 225 | } 226 | } 227 | } 228 | 229 | static void _rebind_symbols_for_image(const struct mach_header *header, 230 | intptr_t slide) { 231 | rebind_symbols_for_image(_rebindings_head, header, slide); 232 | } 233 | 234 | int rebind_symbols_image(void *header, 235 | intptr_t slide, 236 | struct rebinding rebindings[], 237 | size_t rebindings_nel) { 238 | struct rebindings_entry *rebindings_head = NULL; 239 | int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); 240 | rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide); 241 | if (rebindings_head) { 242 | free(rebindings_head->rebindings); 243 | } 244 | free(rebindings_head); 245 | return retval; 246 | } 247 | 248 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { 249 | int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); 250 | if (retval < 0) { 251 | return retval; 252 | } 253 | // If this was the first call, register callback for image additions (which is also invoked for 254 | // existing images, otherwise, just run on existing images 255 | if (!_rebindings_head->next) { 256 | _dyld_register_func_for_add_image(_rebind_symbols_for_image); 257 | } else { 258 | uint32_t c = _dyld_image_count(); 259 | for (uint32_t i = 0; i < c; i++) { 260 | _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 261 | } 262 | } 263 | return retval; 264 | } 265 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /fishhook.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "fishhook" 3 | spec.version = "0.2" 4 | spec.license = { :type => "BSD", :file => "LICENSE" } 5 | spec.homepage = 'https://github.com/facebook/fishhook' 6 | spec.author = { "Facebook, Inc." => "https://github.com/facebook" } 7 | spec.summary = "A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS." 8 | spec.source = { :git => "https://github.com/facebook/fishhook.git", :tag => '0.2'} 9 | spec.source_files = "fishhook.{h,c}" 10 | spec.social_media_url = 'https://twitter.com/fbOpenSource' 11 | 12 | spec.ios.deployment_target = '6.0' 13 | end 14 | --------------------------------------------------------------------------------