关于进程地址空间中DLL加载的问题

M.S*_*sti 3 windows dll portable-executable

好吧,我读了几篇关于可移植可执行文件(PE)的Matt Pietrek的文章,比如:

另外,我已经阅读了关于这个主题的一些其他来源.要么是我忽略了某些部分,要么就是那里没有回答问题.

那么,这里有一些问题:

众所周知,在加载EXE时,Windows Loader从Importa地址表(IAT)读取导入的DLL列表,并将它们加载到进程地址空间.

  1. 进程地址空间是一个虚拟空间.DLL可能已经加载到某个物理空间中.对于像KERNEL32.dll或等的DLL,会发生这种情况USER32.dll.物理地址和虚拟地址之间有什么关系?加载器是仅分配页面并复制DLL,还是引用?

  2. 如果没有加载DLL,Loader是加载整个DLL,还是仅加载所需的函数?例如,如果您使用了函数foo()from bar.dll,那么加载器是否会将整个加载bar.dll到进程地址空间中?或者,它只是将foo代码加载到进程地址空间?

  3. 假设您的EXE文件使用驻留的函数MessageBox()from .您是否可以开发自定义,将其放在与EXE文件相同的目录中,并期望您的应用程序调用您的自定义而不是系统默认值?USER32.DLL%WINDIR%\system32\user32.dllUSER32.DLLMessageBoxMessageBox

Han*_*ant 6

Re 1:物理地址不起作用,这里涉及的所有内容都是虚拟内存.仅当虚拟内存页面映射到RAM(由页面错误触发)时才建立物理地址.许多基本DLL出现在几个进程中的相同虚拟内存地址中,例如kernel32.dll.这些过程只是共享相同的代码页(而不是数据).

Re 2:没有发生实际的'加载',使用的功能与支持内存映射文件的功能相同.这些页面的支持是DLL文件本身,而不是页面文件.在页面错误迫使Windows将文件从文件读入RAM之前,不会加载任何内容.但是,可以映射DLL的整个代码部分.

回复3:是的,那会有效.但是几乎不可能让它在实践中起作用,因为你必须为程序使用的所有 user32导出编写替换函数.包括其他Win32功能使用的那些,你无法知道.API挂钩是使用的典型技术,微软实验室的Detours是一个很好的技术.

Windows Internals第5版是一本很好的书,可以了解有关管道的更多信息.