最后更新于:2022年6月25日 下午
动态链接预加载,可以用于偷梁换柱,英文名为 DLL injection
注意以下都是运行时替换,有时并不是我们想要的方式
首先创建一个 test 目录,在下面创建 Add.h
, Add.cpp
, fakeAdd.cpp
, main.cpp
,内容如下:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #pragma once int Add(int x, int y); int Sub(int x, int y);
#include "Add.h" int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; }
#include <iostream> struct Goodbye { Goodbye() {std::cout << "Fake Add start!\n";} ~Goodbye() {std::cout << "Goodbye!\n";} } goodbye; int Add(int x, int y) { return x * y; }
#include <bits/stdc++.h> #define cerr(x) std::cerr << (#x) << " is " << (x) << '\n' using LL = long long; #include "Add.hpp"
int main() { std::cin.tie(nullptr)->sync_with_stdio(false); std::cout << "Please input two integers:" << std::endl; int a, b; std::cin >> a >> b; std::cout << "a = " << a << ", b = " << b << std::endl; cerr(Add(a, b)); cerr(Sub(a, b)); return 0; }
|
For Mac
使用模板
1 2
| g++-11 preload.cpp -shared -fPIC -o preload.dylib DYLD_INSERT_LIBRARIES=./preload.dylib DYLD_FORCE_FLAT_NAMESPACE=1 <command>
|
示例
g++-11 Add.cpp -shared -fPIC -o Add.dylib
生成正常的 add 函数
g++-11 main.cpp -L. Add.dylib -o main
生成 main(可以通过 otools -L main
来查看是否真的链接上了)
./main
直接运行正常的加法处理程序
g++-11 fakeAdd.cpp -fPIC -shared -o fakeAdd.dylib
生成 fake 版本 add 函数
DYLD_INSERT_LIBRARIES=./fakeAdd.dylib DYLD_FORCE_FLAT_NAMESPACE=1 ./main
看效果
从这个例子可以看出,fakeAdd.dylib
有更高的优先级
For Linux
使用模板
1 2
| g++ preload.cpp -shared -fPIC -o preload.so LD_PRELOAD=./preload.so <command>
|
Linux 若链接进可执行程序,必须以 lib 开头以 .so
为后缀。若动态加载,可以不用以 lib 开头以 .so 为后缀
还可以使用 LD_LIBRARY_PATH
环境变量。或者在 VScode 中配置一下,参考 VScode-lldb 文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "version": "0.2.0", "configurations": [ { "type": "lldb", "request": "launch", "name": "a", "program": "${workspaceFolder}/a.out", "args": [], "cwd": "${workspaceFolder}", "env": { "LD_LIBRARY_PATH": "${workspaceFolder}/lib/", "sourceMap": { "/build/time/source/path" : "/current/source/path" }, }, }, ] }
|
示例
g++ Add.cpp -shared -fPIC -o libAdd.so
生成正常的 Add 函数
g++ main.cpp -L ./ -lAdd -o main
生成 main(可通过 ldd main
查看链接情况,发现 Add.so 未找到)
./main
直接运行正常的加法处理程序(会报错)
g++ fakeAdd.cpp -shared -fPIC -o libFakeAdd.so
LD_PRELOAD=./libFakeAdd.so ./main
(和上面一样会报错)
有四种处理报错的方式
export LD_LIBRARY_PATH=.
,什么都不用改,用完后 unset 一下即可(注意 fish 下 unset 无效)
- 在
./main
前加 LD_LIBRARY_PATH=.
- 将
libAdd.so
放到 /usr/lib
中
- 在
/etc/ld.so.config
中加入当前路径,再用 ldconfig
reload 一下
For windows
挖坑待补
参考资料