动态链接库DLL

1、Windows应用程序编程接口提供的所有函数都包含在DLL中,三个重要DLL:

Kernel32.dll:包含的函数用来管理内存、进程和线程;

User32.dll:包含的函数用来执行与用户界面相关的任务,如创建窗口和发送消息;

GDI32.dll:包含的函数用来绘制图像和显示文字。

2、如果编译器看到一个变量、函数或C++类是用_declspec(dllexport)修饰的,那么她就知道应该在生成的DLL模块中导出该变量、函数或C++类。

3、extern ”C“修饰符用来告诉编译器不要对变量名或函数名进行改编,这样用C、C++或任何编程语言编写的可执行模块都可以访问该变量或函数。

4、为了让线程能够调用DLL模块中的一个函数,我们必须将DLL的文件映像映射到调用线程所在进程的地址空间中,可以通过两种达到该目的:

隐式链接:直接让应用程序的源代码引用DLL中所包含的符号,使得加载程序会在应用程序运行的时候隐式地载入(并链接)所需的DLL;

显示链接:应用程序在运行的过程中,线程调用LoadLibrary(Ex)将DLL载入到进程的地址空间中,并调用GetProcAddress来与想要的输出符号进行链接。

5、FreeLibrary或FreeLibraryAndExitThread:显式地卸载DLL模块

6、每个DLL在进程中有一个与之对应的使用计数,LoadLibrary递增该计数,FreeLibrary递减该计数。如果同一个进程的线程再调用LoadLibrary来载入同一个DLL文件映像时,系统不会再次将DLL的文件映像映射到进程的地址空间中,只会将对应的使用计数递增。

7、GetModuleFileName:获取DLL的全路径,第一个参数为空时,返回应用程序的可执行文件的文件名。

8、DllMain:DLL的入口点函数,用来执行一些与进程或线程有关的初始化和清理工作。

9、进程的主线程将调用每个DLL的DllMain函数,并传入DLL_PROCESS_ATTACH值,如果任何一个DLL的DllMain函数返回FALSE,初始化失败,那么系统会把所有的文件映像从地址空间清除,终止整个进程。显式载入DLL时,调用LoadLibrary的线程会调用DLL的DllMain函数,并传入DLL_PROCESS_ATTACH值,若返回FALSE,则撤销对DLL文件映像的映射,并让LoadLibrary返回NULL。

10、当系统将一个DLL从进程的地址空间中撤销映射,会调用DLL的DllMain函数,并传入DLL_PROCESS_DETACH值。只有当每个DLL都处理完DLL_PROCESS_DETACH通知后,操作系统才会真正的终止进程。

11、当进程创建一个新线程时,系统会检查所有已经被映射到进程的地址空间的DLL,并用DLL_THREAD_ATTACH来调用每个DLL的DllMain函数。新创建的线程负责执行所有DLL的DllMain函数中的代码,执行相关的初始化。

12、系统调用ExitThead终止线程时,系统会让该进程用DLL_THREAD_DETACH来调用所有已映射DLL的DllMain函数。

 若调用TerminateProcess终止进程/线程,系统将不会用DLL_PROCESS_DETACH / DLL_THREAD_DETACH来调用DLL的DllMain函数,这意味着已映射到进程地址空间中的任何DLL将没有机会执行任何清理代码,可能导致数据丢失。

13、DllMain函数只应该执行简单的初始化,避免在DllMain中调用LoadLibrary和FreeLibrary,并且不要在DllMain中调用WaitForSingleObject函数。

14、DLL重定向:强制操作系统的加载程序首先从应用程序的目录中载入模块。必须将一个文件放到应用程序的目录中,该文件的文件名必须是xxxxx.local,如SuperApp.exe.local。

15、构建可执行模块时,链接器会将模块的首选基地址设为0x00400000,对于DLL模块,则为0x10000000。

16、线程局部存储区TLS:将数据与一个正在执行的指定线程关联起来。

 

 

 

 

 

 

上一篇:Windows核心编程——dllmain和dll劫持


下一篇:python shellcode分析