{"id":13605625,"url":"https://github.com/facebook/fishhook","last_synced_at":"2025-05-14T01:07:33.144Z","repository":{"id":38355440,"uuid":"11351927","full_name":"facebook/fishhook","owner":"facebook","description":"A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.","archived":false,"fork":false,"pushed_at":"2024-08-01T06:10:59.000Z","size":40,"stargazers_count":5267,"open_issues_count":38,"forks_count":973,"subscribers_count":229,"default_branch":"main","last_synced_at":"2025-03-17T11:53:43.674Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/facebook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-07-11T20:12:26.000Z","updated_at":"2025-03-16T03:25:34.000Z","dependencies_parsed_at":"2024-11-18T20:18:57.737Z","dependency_job_id":null,"html_url":"https://github.com/facebook/fishhook","commit_stats":{"total_commits":29,"total_committers":17,"mean_commits":"1.7058823529411764","dds":0.8620689655172413,"last_synced_commit":"aadc161ac3b80db07a9908851839a17ba63a9eb1"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Ffishhook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Ffishhook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Ffishhook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Ffishhook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/facebook","download_url":"https://codeload.github.com/facebook/fishhook/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245066675,"owners_count":20555427,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:01:00.909Z","updated_at":"2025-03-26T00:09:24.812Z","avatar_url":"https://github.com/facebook.png","language":"C","funding_links":[],"categories":["C","Foundation","Tools","OOM-Leaks-Crash","\u003ca id=\"58cd9084afafd3cd293564c1d615dd7f\"\u003e\u003c/a\u003e工具"],"sub_categories":["Dynamic Analysis Tools","逆向开发","\u003ca id=\"d0108e91e6863289f89084ff09df39d0\"\u003e\u003c/a\u003e新添加的"],"readme":"# fishhook\n\n__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).\n\n[interpose]: http://opensource.apple.com/source/dyld/dyld-210.2.3/include/mach-o/dyld-interposing.h \"\u003cmach-o/dyld-interposing.h\u003e\"\n\n## Usage\n\nOnce you add `fishhook.h`/`fishhook.c` to your project, you can rebind symbols as follows:\n```Objective-C\n#import \u003cdlfcn.h\u003e\n\n#import \u003cUIKit/UIKit.h\u003e\n\n#import \"AppDelegate.h\"\n#import \"fishhook.h\"\n \nstatic int (*orig_close)(int);\nstatic int (*orig_open)(const char *, int, ...);\n \nint my_close(int fd) {\n  printf(\"Calling real close(%d)\\n\", fd);\n  return orig_close(fd);\n}\n \nint my_open(const char *path, int oflag, ...) {\n  va_list ap = {0};\n  mode_t mode = 0;\n \n  if ((oflag \u0026 O_CREAT) != 0) {\n    // mode only applies to O_CREAT\n    va_start(ap, oflag);\n    mode = va_arg(ap, int);\n    va_end(ap);\n    printf(\"Calling real open('%s', %d, %d)\\n\", path, oflag, mode);\n    return orig_open(path, oflag, mode);\n  } else {\n    printf(\"Calling real open('%s', %d)\\n\", path, oflag);\n    return orig_open(path, oflag, mode);\n  }\n}\n \nint main(int argc, char * argv[])\n{\n  @autoreleasepool {\n    rebind_symbols((struct rebinding[2]){{\"close\", my_close, (void *)\u0026orig_close}, {\"open\", my_open, (void *)\u0026orig_open}}, 2);\n \n    // Open our own binary and print out first 4 bytes (which is the same\n    // for all Mach-O binaries on a given architecture)\n    int fd = open(argv[0], O_RDONLY);\n    uint32_t magic_number = 0;\n    read(fd, \u0026magic_number, 4);\n    printf(\"Mach-O Magic Number: %x \\n\", magic_number);\n    close(fd);\n \n    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n  }\n}\n```\n### Sample output\n```\nCalling real open('/var/mobile/Applications/161DA598-5B83-41F5-8A44-675491AF6A2C/Test.app/Test', 0)\nMach-O Magic Number: feedface \nCalling real close(3)\n...\n```\n\n## How it works\n\n`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.\n\nFor 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 `\u003cmach-o/loader.h\u003e`) 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-\u003ereserved1]`. The symbol table itself is an array of `struct nlist`s (see `\u003cmach-o/nlist.h\u003e`), 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.\n\nThe process of looking up the name of a given entry in the lazy or non-lazy pointer tables looks like this:\n![Visual explanation](http://i.imgur.com/HVXqHCz.png)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebook%2Ffishhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffacebook%2Ffishhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebook%2Ffishhook/lists"}