Bypassing Windows ASLR by determining the library address using shared pages - windows

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

Related

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

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.

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.

Is DLL loaded in kernel mode or user mode?

I was asked such a question in an interview:
In windows, suppose there is an exe which depends on some dlls, when you start
the exe, and then the dependent dlls will be loaded, are these dlls
loaded in kernel mode or user mode?
I am not quite sure about the question, not the mention the answer - could you help to explain?
Thanks.
I'm not an expert about how Windows internally works, but for what i know the correct answer is user mode, simply because only the processes related to your Operative System are admitted in the kernel space http://en.wikibooks.org/wiki/Windows_Programming/User_Mode_vs_Kernel_Mode
Basically if it's not an OS process, it's going to be allocated in the user space.
The question is very imprecise/ambiguous. "In Windows" suggests something but isn't clear what. Likely the interviewer was referring to the Win32 subsystem - i.e. the part of Windows that you usually get to see as an end-user. The last part of the question is even more ambiguous.
Now while process and section objects (in MSDN referred to as MMF, loaded PE images such as .exe and .dll and .sys) are indeed kernel objects and require some assistance from the underlying executive (and memory manager etc) the respective code in the DLL (including that in DllMain) will behave exactly the same as for any other user mode process, when called from a user mode process. That is, each thread that is running code from the DLL will transition to kernel mode to make use of OS services eventually (opening files, loading PE files, creating events etc) or do some stuff in user mode whenever that is sufficient.
Perhaps the interviewer was even interested in the memory ranges that are sometimes referred to as "kernel space" and "user space", traditionally at the 2 GB boundary for 32bit. And yes, DLLs usually end up below the 2 GB boundary, i.e. in "user space", while other shared memory (memory mapped files, MMF) usually end up above that boundary.
It is even possible that the interviewer fell victim to a common misunderstanding about DLLs. The DLL itself is merely a dormant piece of memory, it isn't running anything on its own ever (and yes, this is also true for DllMain). Sure, the loader will take care of all kinds of things such as relocations, but in the end nothing will run without being called explicitly or implicitly (in the context of some thread of the process loading the DLL). So for all practical purposes the question would require you to ask back.
Define "in Windows".
Also "dlls loaded in kernel mode or user mode", does this refer to the code doing the loading or to the end result (i.e. where the code runs or in what memory range it gets loaded)? Parts of that code run in user mode, others in kernel mode.
I wonder whether the interviewer has a clear idea of the concepts s/he is asking about.
Let me add some more information. It seems from the comments on the other answer that people have the same misconception that exists about DLLs also about drivers. Drivers are much closer to the idea of DLLs than to that of EXEs (or ultimately "processes"). The thing is that a driver doesn't do anything on its own most of the time (though it can create system threads to change that). Drivers are not processes and they do not create processes.
The answer is quite obviously User mode for anybody who does any kind of significant application development for windows. Let me explain two things.
DLL
A dynamic link library is closely similar to a regular old link library or .lib. When your application uses a .lib it pastes in function definitions just after compile time. You typically use a .lib to store API's and to modify the functions with out having to rebuild the whole project, just paste new .lib with same name over the old and as long as the interface(function name and parameters) hasn't changed it still works. Great modularity.
A .dll does exactly the same thing however it doesn't require re-linking or any compilation. You can think of a .dll as essentially a .lib which gets compiled to an .exe just the same as applications which use it. Simply put the new .dll which shares the name and function signatures and it all just works. You can update your application simply by replacing .dlls. This is why most windows software consists of .dlls and a few exe's.
The usage of a .dll is done in two ways
Implicit linking
To link this way if you had a .dll userapplication.dll you would have an userapplication.lib which defines all the entry points in the dll. You simply link to the static link library and then include the .dll in the working directory.
Explicit linking
Alernatively you can programmatically load the .dll by first calling LoadLibrary(userapplication.dll) which returns a handle to your .dll. Then GetProcAddress(handle, "FunctionInUserApplicationDll") which returns a function pointer you can use. This way your application can check stuff before attempting to use it. c# is a little different but easier.
USER/KERNEL MODES
Windows has two major modes of execution. User mode and Kernel modes (kernel further divided into system and sessions). For user mode the physical memory address is opaque. User mode makes use of virtual memory which is mapped to real memory spaces. User mode driver's are coincidentally also .dll's. A user mode application typically gets around 4Gb of virtual addressing space to work with. Two different applications can not meaningfully use those address because they are with in context of that application or process. There is no way for a user mode application to know it's physical memory address with out falling back to kernel mode driver. Basically everything your used to programming (unless you develop drivers).
Kernel mode is protected from user mode applications. Most hardware drivers work in the context of kernel mode and typically all windows api's are broken into two categories user and kernel. Kernel mode drivers use kernel mode api's and do not use user mode api's and hence don't user .dll's(You can't even print to a console cause that is a user mode api set). Instead they use .sys files which are drivers and essentially work exactly the same way in user mode. A .sys is an pe format so basically an .exe just like a .dll is like an .exe with out a main() entry point.
So from the askers perspective you have two groups
[kernel/.sys] and [user/.dll or .exe]
There really isn't .exe's in kernel because the operating system does everything not users. When system or another kernel component starts something they do it by calling DriverEntry() method so I guess that is like main().
So this question in this sense is quite simple.

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