Does Windows map DLLs to the same virtual address in different processes? - windows

Say two processes are using Kernel32.dll, does Windows map the DLLs to the same virtual address space in both processes? If not, how does paging mechanism end up using the same physical address where the DLL is in fact loaded for both processes? I tried finding this info in the windows internals book but didn't find anything

TL;DR: No, it might be loaded somewhere else in another process.
Ntdll and Kernel32 are special and always load at the same address so it is better to focus on something else, Shell32 for example.
A dll has what is known as a preferred base address and this is stored in the PE header (ImageBase). The loader will first attempt to load the dll at this address. If that address range is free then loading will succeed with no extra work required.
If the address is not free then the loader has to load it somewhere else. Loading at a different address usually requires relocation information and if this was removed during linking (/FIXED) then loading will fail! If there was space somewhere else to load the dll, the loader will use the relocation information to patch the given locations in the dll with the new base address. Because dlls are loaded as copy-on-write, this will cause extra memory usage compared to loading at the preferred address since each memory page that needed a patch is now a private copy in the process. This means that the answer to your question is no, a dll might not load at the same address in a different process if that process already has something else loaded there.
So far I have only talked about the loader. The loader is implemented in Ntdll as normal usermode code and is not involved with how a file mapped into memory actually works. Memory mapped files (known as Sections internally in NT) is a co-operation between the operating system kernel and the CPU hardware. This is a whole topic in of itself but the important thing to know is that physical memory and the page/swap file mechanism is completely disconnected from how a usermode process accesses its virtual memory pages. The kernel can map a physical memory page to zero, one, or multiple places in a processes virtual memory and the CPU will automatically translate when a virtual page is accessed by the process.
As a final note, ASLR does complicate things a little bit but the "offset" only changes on reboot and should not have an impact on this specific question in current implementations. In theory Windows could change this in the future and always load things at different addresses in different processes but this is unlikely to happen because of the copy-on-write downsides.

Related

Is the same DLL guaranteed to be mapped to the same virtual address in every process using it?

I'm studying Windows system internals and the question is just a guess.
I learn that DLL is a form of shared libraries, so at least the code section of the same DLL is shared between processes using it. (By adding the same page entries into the page table of these processes) The code section usually has something like jump tables, which need to be relocated (i.e. write the run-time virtual address to fix the pointer) before it's ready to be executed.
Assume that the same DLL aa.dll is mapped in two different processes at different virtual addresses. (e.g. a.exe 0x00400000 b.exe 0x00410000) The same pointer (at .text+0x100) will be fixed into different addresses. (e.g. a.exe 0x00400100 b.exe 0x004100100). So we have to make a copy of the code section and change it to adapt one process. Then how can the code section be shared?
Am I right?
Answering my own question. The first time a DLL is loaded, Windows would try to load it at the Preferred address which would not require relocation (i.e. fixing addresses due to the fact that code segment is located at x). If it cannot be loaded at the preferred address, it would be allocated virtual pages at a free address backed up by the DLL file itself (not swap file) but marked as Copy-On-Write. Now Windows has to go and fix up the assembly code using the relocation table. Hopefully only a small percentage of code needs to be fixed up and each code segment that is changed would be copied on write and put into physical memory somewhere.
Each time a process cannot load a DLL at the preferred address, I believe this process would happen. This is why sometimes popular DLLs need to be rebased so that their preferred addresses don't conflict.

Does ASLR mean rebasing dlls isn't required?

Am I right in thinking there is no point in rebasing our dlls during our build if we use ASLR as the dlls will be rebased again anyway when the kernel comes to load them?
I am concerned that our application is often used on Terminal Services machines. So, if rebasing occurs at load time, we could end up with dlls being rebased for each process they are loaded into (there would be one process per session). And this would result in more memory usage and paging than we want to pay for. Do I need to be concerned?
I've found the following blog post that says the rebasing only happens once and it is system wide: Matt Evans - Enabling ASLR for memory savings?. I haven't seen any other references about this, so just wanted to be sure if I use ASLR and don't rebase during our build I won't cause memory problems on a Terminal Services box?
So based on my reading you should not have a problem. ASLR causes the the dll's to be loaded to semi random memory address and should not just start rebasing for every process. If you want to check memory use of dll's there is a free tool called MassiveRebase that lets you dynamically load two dll's and view info about their memory use. The was designed to view changes that aslr may have on memory.
The tool and more about it can be found here: http://www.tmurgent.com/appv/index.php/en/resources/tools/137-massive-rebase
Hope this helps.
Rebasing is still helpful. When the operating system loads, it applies a fixed random value to the DLL base.
The result is that the location a DLL is loaded to, is typical for a single boot, but different between machines and boots.
This means that a given DLL in lots of processes can be shared between processes, as all its code data is shared with the same value.
When a DLL is moved because it's address space is taken, it has to modify the fixups, and less of the DLL is shared, increasing system load.
If your DLL is not shared, then it does not affect resources.
The cost of fixing up a DLL used to be cheaper if it was loaded to the correct place, not sure if that is true for ASLR, but may still save resource loading time.

Bypassing Windows ASLR by determining the library address using shared pages

I am quite familiar with ASLR, but today I heard a new interesting fact about the implementation of ASLR in Windows.
In order to optimize performance if process A and B load the same dll Windows will only load it once to physical memory and both processes will share the same instance via shared pages.
This is old news .. But the interesting part is that both process A and B will load the shared library in the same virtual address (why ??).
It seems to me that any local attack (e.g. privilege escalation) can easily bypass ASLR by the following way:
1. Create a new dummy process
2. Check the address of dlls of interest (kernel32, user32 ..)
3. Attack the privileged process and bypass ASLR with the information from step 2.
I have done some simple tests using Olly and found that shared libraries are indeed loaded in the same virtual address.
If this is really the case, is ASLR useless for local exploitation ?
You are correct, ASLR is little defense against a local attacker. It is primarily designed to thwart hard-coded addresses in remote exploits.
Edit: Some details in my previous answer were incorrect, though the point above still stands. An ASLR-enabled DLL's base address is actually a function of both: (1) a random offset chosen by Windows from a set of 256 possible values at boot time; and (2) the order in which the DLL is loaded, which for known DLLs is randomized by the Session Manager during system startup. Knowing just the random offset is therefore not sufficient to compute the base address of an arbitrary ASLR'd DLL. However, if you are able to directly observe the address of a target DLL in shared memory, as you describe, then all bets are off anyway.
Sources:
http://www.symantec.com/avcenter/reference/Address_Space_Layout_Randomization.pdf
Windows Internals, 6th Edition

Effect of changing page protection inside the code section of a DLL?

I want to change the protection for the memory pages of a hole function inside a Dll to be no more executable.
Does this affect other processes which mapped the same dll into virtual address space?
TL;DR: No, it doesn't.
The NX bit works at the virtual/page level. Each process has their own virtual address space, and cannot directly affect another process' address space (barring shared memory).
Different processes can share mapped pages of a DLL. If one process alters a page, copy-on-write kicks in and that process gets a unique copy of the page, the other processes' view(s) of the DLL are unaffected.
For more information on NX, see Intel® 64 and IA-32 Architectures
Software Developer’s Manual (Volume 3A linked, 7 volumes total).
Also, here is an older but still relevant Microsoft article on copy-on-write protection.

Microsoft's ASLR is weird

I watched a ASLRed dll images's based address for 32bit Process.
It's not a fully randomization. It just randomizated 1/2 probability.
For example, once I load a dll then the image is loaded on 0x12345678.
And I load the image again, the image is loaded on 0x23456789.(Base address is changed!)
But I load the image again
0x12345678
0x23456789
0x12345678
0x23456789
...
Why they did implement like this?
Is it for a crash report's frequency?(For getting same crash addresses of re-deployed dlls)
This is by design. Normally, Windows selects a preferred base address for an ASLR DLL when the DLL is first loaded, and then it keeps using that address until the system is rebooted. That way the DLL will be mapped at the same address in every process that loads it, allowing code pages to be shared.
However, if a DLL has been unloaded from every process, the system may sometimes select a different base address the next time the DLL is loaded. It does this to reduce virtual address space fragmentation, not for security reasons. This is what seems to be happening in your case.
It's documented as being at one of 1 of 256 possible starting addresses.
But i didn't think it even applied to a process, but to shared DLL's.
ASLR: is not on by default for process images. It's an opt-in thing, for compatiblity.(3)
Address Space Layout Randomization
(ASLR)
ASLR moves executable images into
random locations when a system boots,
making it harder for exploit code to
operate predictably. For a component
to support ASLR, all components that
it loads must also support ASLR. For
example, if A.exe consumes B.dll and
C.dll, all three must support ASLR. By
default, Windows Vista and later will
randomize system DLLs and EXEs, but
DLLs and EXEs created by ISVs must opt
in to support ASLR using the
/DYNAMICBASE linker option.
ASLR also randomizes heap and stack
memory:
When an application creates a heap in
Windows Vista and later, the heap
manager will create that heap at a
random location to help reduce the
chance that an attempt to exploit a
heap-based buffer overrun succeeds.
Heap randomization is enabled by
default for all applications running
on Windows Vista and later.
When a
thread starts in a process linked with
/DYNAMICBASE, Windows Vista and later
moves the thread's stack to a random
location to help reduce the chance
that a stack-based buffer overrun
exploit will succeed.
Had installed new Win8 RC x64 yesterday.
Watch out!
Kernel32.dll (64-bit version) have different base address in different processes (in single session, of course). Only ntdll.dll base address remains constant. I had to change the code, you can no longer rely on the permanent address Loadlibrary.

Resources