关于DLL加载进程地址空间的问题 [英] Questions Regarding DLL Loading in a Process Address Space
问题描述
- 深入了解Win32便携式可执行文件格式,第1部分和第2部分
- 关于链接器的MSJ文章
- 关于COFF格式的MSJ文章
<另外,我已经阅读了关于这个问题的其他一些资料。或者我忽略了一些部分,或者问题没有在那里回答。
所以,这里是问题:
$ b $已知当加载EXE时,Windows Loader会从Importa Address Table(IAT)中读取导入的DLL的列表,并将其加载到进程地址空间。
-
进程地址空间是一个虚拟空间。 DLL可能已经加载到某些物理空间中。对于像
KERNEL32.dll
或USER32.dll
这样的DLL,会发生这种情况。物理和虚拟地址之间的关系是什么?加载器只是分配页面并复制DLL,还是进行引用? -
如果没有加载DLL,Loader会加载整个DLL,还是仅需要功能?例如,如果您从
bar.dll
中使用函数foo()
,则加载器将加载整个bar.dll
进入进程的地址空间?或者,是否将foo
的代码加载到进程地址空间? -
假设您的EXE文件使用来自
USER32.DLL
的函数MessageBox()
,它位于%WINDIR% \system32\user32.dll
。您可以开发一个自定义的USER32.DLL
,将其放在与EXE文件相同的目录中,并期望您自定义的MessageBox
被您的应用程序调用,而不是系统的默认值MessageBox
?
Re 1:物理地址不起作用,这里涉及的一切都是虚拟内存。物理地址仅在虚拟内存页面映射到RAM时被页面错误触发而建立。许多基本的DLL在几个进程中出现在同一个虚拟内存地址,如kernel32.dll。这些过程只是共享相同的代码页(而不是数据)。
Re 2:没有实际的加载发生,所使用的功能是同一个支持内存的功能映射文件。这些页面的后台是DLL文件本身,而不是分页文件。直到页面错误迫使Windows将文件从页面读入RAM为止,才会加载任何内容。但是是的,DLL的整个代码段被映射。
Re 3:是的,这将工作。但是,实际上这是不可能的,因为您将不得不为您的程序使用的user32导出写入所有的替换函数。包括其他Win32功能使用的功能,您不能知道。 API钩子是使用的典型技术,微软实验室的曲折是一个很好的例子。
Windows内部版本5是一本很好的书,可以了解有关管道的更多信息。 >
Well, I read several of Matt Pietrek's articles on Portable Executable (PE) files, like:
- An In-Depth Look into the Win32 Portable Executable File Format, Part 1 and Part 2
- MSJ article on linkers
- MSJ article on COFF format
In addition, I have read a few other sources on the subject. It is either me overlooking some parts, or the questions aren't answered there.
So, here are the questions:
It is known that, when loading an EXE, the Windows Loader reads the list of imported DLL's from the Importa Address Table (IAT), and loads them into the process address space.
The process address space is a virtual space. The DLL may have already loaded into some physical space. This happens for DLLs like
KERNEL32.dll
orUSER32.dll
. What is the relation between the physical and virtual address? Does the loader just allocate pages and copy the DLL, or does it make references?If a DLL is not loaded, does the Loader load the whole DLL, or just the functions needed? For instance, if you used function
foo()
frombar.dll
, does the loader load the wholebar.dll
into the process address space? Or, does it just load thefoo
's code into the process address space?Assume your EXE file uses function
MessageBox()
fromUSER32.DLL
, which resides in%WINDIR%\system32\user32.dll
. Can you develop a customizedUSER32.DLL
, put it in the same directory as your EXE file, and expect that your customizedMessageBox
is called by your app instead of the system'd defaultMessageBox
?
Re 1: physical addresses play no role, everything involved here is virtual memory. The physical address is only established when a virtual memory page gets mapped into RAM, triggered by a page fault. Many basic DLLs appear at the same virtual memory address in several processes, like kernel32.dll. The processes simply share the same pages of code (not data).
Re 2: no actual 'loading' takes place, the feature used is the same one that supports memory mapped files. The backing of these pages is the DLL file itself, not the paging file. Nothing gets loaded until a page fault forces Windows to read the page from the file into RAM. But yes, the entire code section of the DLL gets mapped.
Re 3: yes, that would work. But it is next to impossible to make it work in practice since you will have to write replacement functions for all the user32 exports that your program uses. Including the ones that other Win32 functions use, you cannot know. API hooking is the typical technique used, Detours from Microsoft Labs is a good one.
Windows Internals edition 5 is an excellent book to learn more about the plumbing.
这篇关于关于DLL加载进程地址空间的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!