Win32学习7
25、动态链接库
①什么是动态链接库?
动态链接库(Dynamic Link Library,缩写为 DLL) ,是微软公司在微软 Windows操作系统中,实现共享函数库概念的一种方式。 这些库函数的扩展名是”.dll"、".ocx" (包含ActiveX控制的库)。
相较于静态链接库是和exe打包在同一模块一块儿存在,动态链接库是独立存在的,当真正使用exe 的时候才会将dll加载。如果不用的话也不会主动加载。所以因此,dll不会将exe 的体积变大。
②创建动态链接库
<1> extern "C"_declspec(dllexport)调用约定返回类型函数名(参数列表); <2>使用.def文件: EXPORTS 函数名 @编号 函数名 @编号 NONAME
使用序号导出的好处: 名字是一段程序就精华的注释,通过名字可以直接猜测到函数的功能。通过使用序号,可以达到隐藏的目的
③使用动态链接库
步骤1: //定义函数指针 如: typedef int (stdcall *lpPlus)(int,int); typedef int (stdcall lpSub)(int,int) 步骤2: //声明函数指针变量如: IpPlus myPlus; IpSub mySub; 步骤3: //动态加载dll到内存中,如: HINSTANCE hModule=LoadLibrary("DIDemo.dll"); 步骤4: //获取函数地址,如: myPlus = (IpPlus)GetProcAddress(hModule, "Plus"); mySub=(lpSub)GetProcAddress(hModule, (char)0x10); 步骤5: //调用函数,如: int a = myPlus(10,2); int b = mySub(10,2); 步骤6: //释放动态链接库,如: FreeLibrary(hModule);
动态链接库可以随时动态加载也可以随时释放,相较于静态链接库更为灵活。
26、隐式链接
动态链接库的有点在于随时想使用这个dll的时候都可以调用这个dll,但是也有缺点,使用这个dll的时候需要获取这个dll 的地址,如果需要多个dll 的话,就需要获取多个dll 的地址,这样的话,就比较的麻烦。这种称为显式链接。
①隐式链接
步骤1:将*.dl *.lib放到工程目录下面 步骤2:将#pragma comment(lib,"DLL名.lib")添加到调用文件中 步骤3:加入函数的声明 _declspec(dllimport)stdcall int Plus (int x,int y); declspec(dllimport)__stdcall int Sub (int x,int y); 注意: extern "C"declspec(dllexport)调用约定返回类型函数名(参数列表); extern "C"_declspec(dllimport)调用约定返回类型函数名(参数列表);
隐式链接不再需要自己去利用函数如 GetProcAddress 去获取函数地址,编译器就会自动帮我们找到函数的地址。且动态链接库都是间接调用的函数,即函数并非同exe一块儿,不会占据exe 的大小。
②隐式链接的实现
隐式链接实际上是将函数的地址存放在了exe 的导入表中,当需要调用这个函数的时候,exe就会从导入表中取得这个地址并进行调用。
③ DLL 的优点
④DLLMain函数
BOOL WINAPI DIMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID IpvReserved // reserved
);
exe 和 dll 不仅有导入表和导出表的区别。还有入口函数和执行时间的区别。
这个DllMain 不同于 main 函数只执行一次,这个DllMain 可能会执行多次。然后是参数不一样,三个参数中第三个一般来说用不到,只用着重了解前两个,前两个参数,第一个参数主要是指当前的这个dll被加载到什么位置了。第二个参数是指这个dll被加载上的原因。而我们通过查询可以知道dll 被调用可以有四种情况:
-
DLL_PROCESS_ATTACH (LoadLibrary)
-
DLL_PROCESS_DETACH (FreeLibrary)
-
DLL_THREAD_ATTACH
-
DLL_THREAD_DETACH 一和二指的是一般的程序进行加载和释放dll会调用这个入口函数;三和四两种情况指的是在创建线程的时候加载和释放dll也会调用这个入口函数。也可以理解成同一个进程多次调用的时候参数会是三和四。
27、远程线程
①线程
<1>线程是附属在进程上的执行实体,是代码的执行流程。 <2>代码必须通过线程才能执行。 即使是一个空的main函数都是一个线程。
无论是main函数中还是在自己创建的别的线程中都可以,但是只要想要执行代码,就必须要将代码放在线程中才能够正确的执行。
②创建远程线程
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId
);
下面是一个实例代码:
BOOL MyCreateRenoteThread(DWORD duProcessID,DWORD dwProcAddr)
{
HANDLE hProcess;
DWORD dwThreadID;
dwThreadID = 0;
hProcess = 0;
//1.获取进程句柄
hProcess =OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessID);
if(hProcess == NULL)
{
OutputDebugString("OpenProcess Errort \n");
return FALSE;
}
//2.创建远程线程
CreateRemoteThread(hProcess,NULL, 0, duProcAddr ,NULL ,0,&dwThreadID);
if(hThread == NULL)
{
OutputDebugString("CreateRenoteThread Error! \n");
CloseHandle (hProcess);
return FALSE;
}
//3.关闭
CloseHandle(hThread);
CloseHandle(hProcess);
return true;
}
28、远程线程注入
实际上远程线程,操纵的进程B,实际上仍是调用的自己的进程中的线程,并非A进程中的。而如果我们能够通过注入来让B进程调用我们A进程的代码,这样就可以实现真正的操控了。
①什么是注入?
所谓注入就是在第三方进程不知道或者不允许的情况下将模块或者代码 写入对方进程空间,并设法执行的技术。 在安全领域, “注入”是非常重要的一种技术手段,注入与反注入也一直 处于不断变化的,而且也愈来愈激烈的对抗当中。 已知的注入方式: 远程线程注入、APC注入、消息钩子注入、注册表注入、导入表注入、输入法注入等等。
②远程线程注入的流程:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?