简体   繁体   English

如何实际共享Windows DLL?

[英]How are windows DLL actually shared?

By examing several DLLs I have in my windows machine (for instance KERNEL32.DLL) I've notice that none of their sections, not even the read only data section have the IMAGE_SCN_MEM_SHARED flag set. 通过检查我的Windows机器中的几个DLL(例如KERNEL32.DLL),我注意到它们的所有部分,甚至是只读数据部分都没有设置IMAGE_SCN_MEM_SHARED标志。

DLLs are mapped from the .dll file so only when you read a page of the file it is copied to physical memory but still, if the same page of let's say kernel32.dll is accessed by both process A and process B then the page will exist twice in physical memory. DLL是从.dll文件映射的,所以只有当你读取文件的页面时才会将它复制到物理内存中,但是,如果同一个页面让进程A和进程B都访问了kernel32.dll,那么页面将会在物理内存中存在两次。 I am asking for the veracity of this last statement. 我要求最后一句话的真实性。

If the .text or the .rodata segment where shared they would get copied to physical memory only onced, even when ASLR is enabled because what ASLR does is randomize the base of a module when it is first loaded (with corresponding relocations applied) but the next process that loads this module untill system restart will get the module at the same address so the .text and .rodata could be shared in the same manner. 如果.text或.rodata段共享它们将被仅复制到物理内存中,即使启用了ASLR,因为ASLR的作用是在模块首次加载时随机化模块的基础(应用相应的重定位)但是加载此模块的下一个进程直到系统重新启动将使模块处于相同的地址,因此.text和.rodata可以以相同的方式共享。

These are all assumptions I made, please correct me. 这些都是我做的假设,请指正。

Thanks! 谢谢!

The OS will definitely be able to map multiple virtual addresses to the same physical memory page, as long as the page content does not (need to) change [in different ways for different processes]. 操作系统肯定能够将多个虚拟地址映射到同一个物理内存页面,只要页面内容不(需要)[以不同方式更改不同进程]。 However, if the code uses an absolute address (either internally or externally to the DLL), for example a vtable/function pointers, pointers to global data (constant or non-constant) or simply function calls with absolute addresses, the address must be modified to match the actual address given by the OS to that section of memory. 但是,如果代码使用绝对地址(在DLL的内部或外部),例如vtable /函数指针,指向全局数据的指针(常量或非常量)或仅使用绝对地址的函数调用,则地址必须为修改为匹配操作系统给予该部分内存的实际地址。 This is called "relocation". 这称为“重新安置”。

So, at least in theory, you can share the same DLL even with address space randomization, it just requires a little more work from the compiler and/or programmer. 因此,至少在理论上,即使使用地址空间随机化,您也可以共享相同的DLL,它只需要编译器和/或程序员的更多工作。 In particular, it requires that there are no relocations (in large chunks of the code). 特别是,它要求没有重定位(在大块代码中)。 If the code has absolute addresses that are relocated based on the code-address, then it will need to have one copy per DLL. 如果代码具有基于代码地址重定位的绝对地址,则每个DLL需要一个副本。

I don't actually know how the OS deals with this. 我实际上并不知道操作系统如何处理这个问题。 A simple solution is obviously to randomize the address only once per DLL (until that particular DLL is unloaded), regardless of how many applications use the same DLL. 一个简单的解决方案显然是每个DLL只对一个地址进行随机化一次(直到该特定DLL被卸载),无论有多少应用程序使用相同的DLL。 It still makes it rather hard for an outsider to know what address the DLL is loaded at, since it will load at a different address each time it gets loaded the first time (and more importantly, it will not be a static value for ALL machines using the same version of OS, which would be the case without this feature). 它仍然让外人很难知道加载DLL的地址是什么,因为它会在每次第一次加载时加载到不同的地址(更重要的是,它不会是所有机器的静态值)使用相同版本的操作系统,没有此功能就是这种情况)。 It does, however, mean that long-running processes can be "inspected" by copying content from for example the stack that has known content. 然而,它确实意味着可以通过从例如具有已知内容的堆栈复制内容来“检查”长时间运行的进程。 Web servers, database servers and system services are typically long-running processes, and as such will have different addresses only when the system is "shut down" (or at least the long running process is restarted). Web服务器,数据库服务器和系统服务通常是长时间运行的进程,因此只有在系统“关闭”(或者至少重新启动长时间运行的进程)时才会有不同的地址。

The second, slightly trickier version is to check if a particular page (typically 4KB region of memory) has relocations, and share all the pages that have no relocation. 第二个稍微棘手的版本是检查特定页面(通常是4KB内存区域)是否具有重定位,并共享所有没有重定位的页面。 Relocated pages need to have one copy per base address. 重定位页面需要每个基址有一个副本。 It is typical to have "all references to external resources" in one block in DLL's (a "thunk section"), so the typical big part of a DLL wouldn't regardless of what the base address of the code, which means that is definitely a workable solution. 在DLL中的一个块(“thunk部分”)中通常具有“对外部资源的所有引用”,因此DLL的典型大部分不管代码的基址是什么,这意味着绝对是一个可行的解决方案

If neither of these schemes "work" in the OS, then you have to load the same DLL multiple times. 如果这些方案都没有在OS中“工作”,那么您必须多次加载相同的DLL。 This clearly works from the perspective of the OS anyway, as prior to ASLR, the base-address of the same DLL will need to be moved in case of two DLL's trying to load at the same address (for example DLL's produced by different vendors, that happen to pick the same base-address for the code, or the classic and common "I never gave a base address, so it uses the default address") - the OS will resolve such conflicts by changing the base address of the one loaded first. 无论如何,从操作系统的角度来看,这显然是有效的,因为在ASLR之前,如果两个DLL试图加载到同一地址(例如由不同供应商生成的DLL,则需要移动相同DLL的基地址),碰巧为代码选择相同的基地址,或者经典和常见的“我从未给过基地址,因此它使用默认地址”) - 操作系统将通过更改加载的一个基地址来解决此类冲突第一。

As to the meaning of IMAGE_SCN_MEM_SHARED , I would have thought that the developer would request this, where the sharing of pages in a DLL is done automatically. 至于IMAGE_SCN_MEM_SHARED的含义,我原以为开发人员会请求这个,其中DLL中的页面共享是自动完成的。 In other words IMAGE_SCN_MEM_SHARED will be set by the developer of a particular DLL or EXE to signify the content should be shared with other users of the same content, rather than "the OS can share it if it can be done without the user of the content noticing" (which is certainly the case for sharing code, and (writeable) data is typically not shared between DLL's. Read-only data, as long as it has no relocations, can of course implicitly be shared [the user of that content can not tell if it is shared or not]. 换句话说, IMAGE_SCN_MEM_SHARED将由特定DLL或EXE的开发者设置,以表示内容应该与相同内容的其他用户共享,而不是“如果可以在没有内容的用户的情况下完成操作系统,则操作系统可以共享它注意“(共享代码当然是这种情况,而且(可写)数据通常不在DLL之间共享。只读数据,只要它没有重定位,当然可以隐含地共享[该内容的用户可以不知道是否共享]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM