前言
DLL(Dynamic Link Library,动态链接库)是 Windows 下的一种可执行模块,
可以被多个程序同时加载使用。可以导出函数
常见用途:
封装公共函数(比如数学库、图形库)
插件系统(比如浏览器插件)
逆向工程与注入(CTF、安全研究中常用)
DLL基础:
DllMain:
dll没有
main或WinMain。它有一个可选的
DllMain入口点函数。这个函数不是给普通用户调用的,而是操作系统加载器在特定事件发生时(DLL 被加载、卸载、进程创建线程、线程结束)自动调用的。它的主要目的是进行初始化和清理工作(例如,创建/销毁全局对象、初始化线程本地存储 TLS)。如果不需要这些,完全可以不实现
DllMain。
1 |
|
导出函数,有两种方式:
写.def文件
1 | ; mylib.def |
然后在编译时链接这个文件。这种方式可以精确控制导出函数的名字和序号。
使用关键字(更常见)
可在如下所示的函数声明中使用 __declspec(dllexport) 关键字。
1 | __declspec(dllexport) double WINAPI my_C_export(double x) |
必须在声明的最左侧添加 __declspec(dllexport) 关键字。 这种方法的优点是该函数不需要在 DEF 文件中列出,并且导出状态与定义一致。
如果要避免使用 C++ 名称修饰来提供 C++ 函数,必须按如下方式声明函数。
1 | extern "C" |
链接器将使该函数显示为 my_undecorated_Cpp_export,即源代码中显示的名称,没有任何修饰。
编写一个dll并编译
mydll.h
1 |
|
这里我们下面的源文件是.c,所以不加extern “C”
mydll.c
1 |
|
编译指令:
1 | gcc -shared -o mydll.dll mydll.c -Wl,--out-implib,libmydll.a |
解释一下参数:
-shared:告诉 gcc 生成动态链接库-o mydll.dll:输出 DLL 文件-Wl,--out-implib,libmydll.a:同时生成一个静态导入库(方便别人链接)
这里的静态导入库的作用是可以把dll和exe合成一个文件。方便发布,一般我们直接gcc -shared -o mydll.dll mydll.c就可以
main.c(测试函数)
1 |
|
运行结果:
1 | sum=30 |
DLL调试:
dll调试如果用vscode的话太逆天,掌握不好注入器和被注入exe之间的关系,用vs就很轻松
右键我们的文件夹,点最下面的属性

然后配置类型需要改成动态库.dll

在调试的行那,右边的命令放要注入的exe路径,然后在我们的dll对应的.c文件那直接像正常的.c文件那样下断点就可以了

然后直接运行这个dll对应的.c源程序,在exe文件的进程空间导入dll文件(dll注入或loadlibrary)后,我们就可以正常调试了