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

好吧,我读了几篇关于可移植可执行文件(PE)的Matt Pietrek的文章,比如: 深入研究Win32可移植可执行文件格式,第1部分和第2部分 MSJ关于连接子的文章 MSJ关于COFF格式的文章 另外,我已经阅读了关于这个主题的一些其他来源。要么是我忽略了某些部分,要么就是那里没有回答问题。 那么,这里有一些问题: 众所周知,在加载EXE时,Windows Loader从Importa地址表(IAT)读取导入的DLL列表,并将它们加载到进程地址空间。 进程地址空间是一个虚拟空间。 DLL可能已经加载到某个物理空间中。对于像
KERNEL32.dll
USER32.dll
这样的DLL会发生这种情况。物理地址和虚拟地址之间有什么关系?加载器是仅分配页面并复制DLL,还是引用? 如果没有加载DLL,Loader是加载整个DLL,还是仅加载所需的函数?例如,如果你使用
bar.dll
中的函数
foo()
,加载程序是否将整个
bar.dll
加载到进程地址空间?或者,它只是将
foo
的代码加载到进程地址空间中吗? 假设你的EXE文件使用
USER32.DLL
中的函数
MessageBox()
,它位于
%WINDIR%system32user32.dll
。你可以开发一个定制的
USER32.DLL
,把它放在与你的EXE文件相同的目录中,并期望你的应用程序调用你的自定义
MessageBox
而不是系统默认的
MessageBox
?     
已邀请:
Re 1:物理地址不起作用,这里涉及的所有内容都是虚拟内存。物理地址仅在虚拟内存页面映射到RAM时由页面错误触发而建立。许多基本DLL出现在几个进程中的相同虚拟内存地址中,例如kernel32.dll。这些过程只是共享相同的代码页(而不是数据)。 Re 2:没有发生实际的'加载',使用的功能与支持内存映射文件的功能相同。这些页面的支持是DLL文件本身,而不是页面文件。在页面错误迫使Windows将文件从文件读入RAM之前,不会加载任何内容。但是,可以映射DLL的整个代码部分。 回复3:是的,那会有效。但是几乎不可能让它在实践中起作用,因为你必须为程序使用的所有user32导出编写替换函数。包括其他Win32功能使用的那些,你无法知道。 API挂钩是使用的典型技术,微软实验室的Detours是一个很好的技术。 Windows Internals第5版是一本很好的书,可以了解有关管道的更多信息。     
1)当您创建新进程时,NT内核加载程序为进程分配空间并映射指定位置上的所有PE部分。然后NT加载器查看导入表,在进程内存中加载DLL并在必要时更正指针(称为重定位)。 2)Loader在进程地址空间中加载整个DLL。 3)是的,它将使用EXE所在目录中的
user32.dll
。看到这个链接。但是作为位于
user32.dll
的大多数WinAPI函数,您的自定义dll必须导出很多它们。     

要回复问题请先登录注册