通过 dyld-interposing 实现C/C++代码注入
苹果系统的链接器/usr/lib/dyld 提供了一个叫dyld-interposing的功能(从 Mac OS X 10.4 开始),可以在程序启动时替换掉某个函数的实现。这个功能可以用来实现代码注入(详见:《Mac OS X Internals: A Systems Approach》- Amit Singh - 第二章 2.6.3.4 dyld interposing)
举个栗子
比如,我们可以在程序运行时,替换掉malloc函数的实现:
1 | // malloc_trace.c |
1 | // test.c |
1 | $ cc -dynamiclib -o libmalloctrace.dylib malloc_trace.c -install_name libmalloctrace.dylib |
ps. 不能在替换函数(replacement)中使用会调用被替换函数(replacee)的其它函数。比如printf()内部可能会使用malloc()则trace_malloc中不能调用printf,不然死给你看~
头文件<mach-o/dyld-interposing.h>来自 dyld 源码:https://github.com/apple-oss-distributions/dyld/blob/dyld-1042.1/include/mach-o/dyld-interposing.h
其中宏 DYLD_INTERPOSE 的定义:
1 |
|
malloc_trace.c 展开后的代码如下:
1 | static struct { |
这段代码声明了一个_interpose_malloc的结构体,replacement成员指向trace_malloc函数,replacee成员指向malloc函数。
并通过__attribute__编译配置将这个结构体放到了 Mach-O 产物的 __DATA,__interpose段中。
用 otool 查看:
1 | $ otool -l libmalloctrace.dylib | grep -A 5 __interpose |
__DATA,__interpose段的大小为0x10,也就是16字节,正好是代码中_interpose_malloc结构体的大小。
也可以使用 MachOView 查看:

在程序加载dylib时,dyld 会解析它的__DATA,__interpose段,找到所有的struct { uintptr_t replacement; uintptr_t replacee; };结构体,然后将replacee成员指向的函数替换成replacement成员指向的函数。
详见源码:RuntimeState::buildInterposingTables()
使用__DATA,__interpose段实现函数替换是静态替换,在程序启动时(dylib被加载时)就替换了。
曾经还有一种方式是动态替换,使用dyld的私有函数dyld_dynamic_interpose,在程序运行时替换函数,详见<mach-o/dyld_priv.h>。不过经过测试,已经失效了~~
使用环境变量 DYLD_PRINT_INTERPOSING=1,可以打印出被替换函数的替换信息:
1 | $ DYLD_PRINT_INTERPOSING=1 DYLD_INSERT_LIBRARIES=libmalloctrace.dylib ./test |
有什么用?
你可能疑惑通过dyld-interposing实现代码注入有什么用?
- 方便调试(比如实现
malloc的内存泄漏检测) - api trace(比如实现
openglapi trace) - hook dylib api (比如实现 hot-reload)
- …
Prevent dyld-interposing?
阻止dyld加载 DYLD_INSERT_LIBRARIES:添加链接参数-Wl,-add_empty_section,__RESTRICT,__restrict (详见:ProcessConfig::Security::getAMFI 、Header::isRestricted() )
Refs
- Mac OS X Internals: A Systems Approach
- dyld源码
- Mach-O linking and loading tricks
- Code Injection with Dyld Interposing
- https://github.com/DerekSelander/symbol-interposing
iOS 上有没有类似的功能?
fishhook 用于替换 Mach-O 二进制文件中符号的库,可以在 iOS 上实现类似的功能。
Author: Yrom
Link: https://yrom.net/blog/2023/10/19/dyld-interposing/
License: 知识共享署名-非商业性使用 4.0 国际许可协议