DLL virtual address
DLL을 만드는 이유중 하나는,
동일 DLL이 차지하는 메모리 공간을 서로 다른 프로세스들이 공유할 수 있기 때문이다.
각 프로세스들이 나름대로의 가상주소 위치로 DLL 코드를 매핑하겠지만
그 가상주소들은 동일한 실 메모리 페이지들을 가리킨다..??

이렇게 생각하고 있었는데, 실상은 좀 다른 모양이다.

Windows DLL은 PE 헤더에 (링크할때 설정 가능한) prefered base address를 담고 있는데,
이 가상메모리 주소로 로드되는 경우에만 다른 프로세스와 메모리 페이지가 공유 가능한 듯 하다.
DLL 로드할때 해당 베이스주소가 이미 다른 DLL 등에 의해 사용중이면
어쩔 수 없이 다른 가상주소 위치로 읽어들이는 재배치(relocation)가 일어나게 되고
이 경우 점프명령어 주소수정이 일어나는 코드페이지들은 CoW(Copy on Write) 프로텍션에 의해
새 물리페이지로 복사이전 되므로 해당 코드페이지들은 더이상 타 프로세스와 공유되지 않음.

(Windows에서 이렇다는 것이고, 아마 Linux에서는 .so(Shared Object)를 만들때 PIC로 만들어지므로
 프로세스마다 서로 다른 가상주소로 매핑된 .so 코드 페이지들도 서로 공유되는 모양이다.
참고: https://en.wikipedia.org/wiki/Position-independent_code
position-independent code (PIC) or position-independent executable (PIE) is a body of machine code that, being placed somewhere in the primary memory, executes properly regardless of its absolute address. PIC is commonly used for shared libraries, so that the same library code can be loaded in a location in each program address space where it does not overlap with other memory in use (for example, other shared libraries))

따라서 DLL을 링크할때 다른 DLL들과 충돌하지 않도록 적절히 베이스주소를 설정해줘야 메모리 공유가 이뤄지겠는데
문제는, 아무 생각없이 사용자 DLL을 만들어 링크하면 베이스 주소가 기본값(0x10000000)으로 설정되므로
사용자 DLL이 여러개 로드될 경우 재배치가 일어날 수밖에 없다는 것.


Modify the Base Addresses for a DLL Files Series
    https://www.codeproject.com/Articles/35829/Modify-the-Base-Addresses-for-a-DLL-Files-Series

A Dynamic-link library created in Microsoft Visual C++ has default base address 0x10000000 (Visual C# has default base address 0x400000). That means, when the process starts, the system loader tries to load the DLL to this address in the process memory. However, if a number of DLLs have the same base address, only one of them is loaded to its default address. For all other DLLs, the loader makes the relocation: changes the memory addresses in DLL commands according to the new base address where the DLL is loaded. This process is also known as DLL collisions.


Loading Applications and DLLs
    https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection

DLLs are created with a default base address. Every process that uses a DLL will try to load the DLL within its own address space at the default virtual address for the DLL. If multiple applications can load a DLL at its default virtual address, they can share the same physical pages for the DLL. If for some reason a process cannot load the DLL at the default address, it loads the DLL elsewhere.


If relocated DLLs cannot share pages, then doesn’t ASLR cause all pages to be non-shared?
    https://devblogs.microsoft.com/oldnewthing/20160413-00/?p=93301

구식 DLL들은 재배치(relocate)될 경우 프로세스간 메모리 공간 공유가 이뤄지지 않는다.
그럼 ASLR 켜진 상태로 링크된 DLL들은 로드할 때 적재주소가 랜덤화되므로 공유가 불가능한가 하면, 그렇지 않다.
DLL을 최초 로드할 때 랜덤화된 상태가 이후 다른 프로세스에서 DLL을 로드할 때 재활용되면서
메모리페이지가 공유되는 모양이다.

The solution is that when a DLL is loaded, ASLR chooses a random destination address, but it then remembers that address for future use, and if another process loads the DLL, the kernel will try to use the same destination address for the DLL in that other process. This means that if two processes load a DLL, that DLL will probably get the same destination address in both processes, which establishes one of the prerequisites for sharing.


Six Facts about Address Space Layout Randomization on Windows
    https://www.fireeye.com/blog/threat-research/2020/03/six-facts-about-address-space-layout-randomization-on-windows.html

by 시험さま | 2021/03/08 12:30 | 컴퓨터 | 트랙백 | 덧글(0)
트랙백 주소 : http://chanik.egloos.com/tb/4194550
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

< 이전페이지 다음페이지 >