Vista ASLR is not on by default for image base addresses

This little tidbit seems to be missed in all of the press about Vista’s ASLR implementation: Vista ASLR (when speaking of randomizing image base addresses) does not apply to image bases by default. This is a sacrifice for application compatibility’s sake, in an effort to make fewer programs break “out of the box” on Vista. Most notably, this is the case even for images with base relocations.

Unfortunately, the mechanism to mark an executable image as “ASLR aware” (such that it can be freely rebased by Vista’s ASLR) is not at present documented. Furthermore, the linker version that is included with Visual Studio 2005 and the Windows Vista Platform SDK does not support the option necessary to mark as image as ASLR aware (though you could technically modify the image by hand with a hex editor or the like to enable it).

The WDK linker does support the new ASLR-enabling linker option, however (though it too does not appear to document it anywhere). You can find references to this new linker option in

!if defined(NO_DYNAMICBASE)
! if $(_NT_TOOLS_VERSION) >= 0x800
! else
! endif

Passing /dynamicbase to the WDK version of link.exe (8.00.50727.215) or later will set the 0x40 DllCharacteristics value in the PE header of the output binary. This corresponds to a newly-defined constant which is at present only documented briefly in the WDK version of ntimage.h:

     // DLL can move.

If this flag is set, then the base address of an image can be randomized by Vista’s ASLR; if the flag is clear, however, then no ASLR-style randomizations are performed to the image base address of a particular image (in this case, however, it is important to note that heap and stack allocations are still randomized – it is only the image base address that does not become randomized).

Now, virtually all of the Microsoft PE images that ship with the operating system are built with /dynamicbase, so they will take full advantage of Vista’s ASLR with respect to image base randomization. However, third party (ISV)-built programs will not, by default, gain all the benefits of ASLR due to this application compatibility sacrifice. This is where the potential problem is, as effectively all existing third party PE images will need to be recompiled to enable ASLR on image base addresses. (Technically, you could use link /edit with the WDK linker to do this without a rebuild, or hex edit binaries, but this is not a real solution in my mind. In Microsoft’s defense, many third-party .exe files are often built without base relocations, which means that even if Microsoft had enabled ASLR by default, many third party programs would still not be getting the full benefit. This does not, however, mean that I fully agree with their decision…)

I can understand where Microsoft is coming from with an application compatibility perspective as far as ASLR’s impact on poorly written programs (of which there are an abundance of in the Windows world), but it is a bit unfortunate that there is no real way to administratively enable ASLR globally, or at least administratively make it an opt-out instead of opt-in setting.

So, if you are an ISV, here’s a heads up to be on the lookout for a link.exe version shipping with Visual Studio that supports /dynamicbase. When such becomes available, I would highly recommend enabling /dynamicbase for all of your projects (so long as you aren’t doing anything terribly stupid in your programs, enabling image base randomizations should be fairly harmless in most cases). You should also mark your .exe files as /FIXED:NO such that they contain a relocation section. This, when combined with /dynamicbase, will allow your .exe files to be randomized by ASLR (just the same as with DLLs that have relocation information and are built with /dynamicbase).

Update: Visual Studio 2005 SP1 has shipped. This update to Visual Studio includes a newer version of the linker, which supports the /dynamicbase option described above. So, be sure to rebuild your programs with /dynamicbase and /fixed:no with VS 2005 SP1 in order to take full advantage of ASLR on Vista.

17 Responses to “Vista ASLR is not on by default for image base addresses”

  1. dispensa says:

    have you tried vs2k5 sp1 yet?

  2. I use Delphi compiler and cannot run Microsoft’s link.exe to set a new flag in the PE header to enable ASLR in Vista. Is therer any application that patches the PE header of the compiled EXE file to set the new flag to my application?

  3. Skywing says:

    You can still use the Microsoft linker to do that, after your PE image is built. Use link /edit /dynamicbase (or editbin /dynamicbase ). You”ll have to have a new-enough version of link.exe that supports /dynamicbase to do this, though.

  4. Thanks, I’ve used link.exe v8.00.50727.762 from Visual Studio 2005 SP1 and changed the PE bit using the command line option that you’ve suggested.

    Diff showed that the only change in the header are “DLL flags”, which became 0x0040.

    Stack now show different base each time I run the executable.

    Code base only changes when I reboot the machine.

    Entry points of Windows DLLs seem not not change at all. For example, GetProcAddress(GetModuleHandle(‘kernel32.dll’), ‘ExitProcess’) each time gives the value of 0x7700D85E, regardless the ASLR bit in the PE header.

    Why GetProcAddress always gives the same value, and why the image base only changes after I restart Windows Vista!?

    Thank you in advance!

  5. Skywing says:

    Image randomization is, as I recall, tied to the lifetime of the section object (which may last longer than the last user file reference). This is why you typically need to reboot (or perhaps delete and recreate the file in question) in order to get a new base randomization.

    This is a concession to performance, as having only one randomized image set greatly cuts down on the traditionally significant memory overhead that has normally been associated with many ASLR implementations in the past (when not dealing with position-independent code, anyway).

  6. Thank you! Is it intended by Microsoft that ASLR doesn’t affect the results of GetProcAddress? E.g. it always returns 0×7700D85E as an address for ExitProcess() API function. Does it mean that I can simply jump to 0×7700D85E to get this API function called? What is the point of ASLR then?

  7. Skywing says:

    The value returned by GetProcAddress can be thought of a 32-bit RVA from the image base of the associated module. So unless the module base has changed since the last time you recalled it (in the most common case, after a reboot), then you’ll get the same address back for a particular exported symbol.

  8. Thank you very much, Skywing!

    BTW, your blog is very interesting.

  9. Mike says:

    Hi, I have lots of question about ASLR:
    1. Original windows dlls from MS have been carefully build to diff address to avoid runtime relocation. After ASLR, is there big impact on performance? Do all these dll need to be relocated?
    2. After reboot, does any process have same address of some functiones from other dll ( such as ExitProcess). It is happned on WinXP. So if I can run a process on target machine, I still can inject some shellcode into other process like explore.exe, and the shellcode can call kernel function, address of which comes from former process. Is it true?

  10. Skywing says:

    1. Negligible performance impact. This is due to some clever tricks done on Microsoft’s part, and the fact that there is only ever one randomized instance of an image in-play on any given system at a time. Specifically, Vista ASLR takes care of the relocation problem by moving relocations from the user mode loader and into the memory manager. Vista now performs relocations on the fly as pages are in-paged from disk instead of doing them all up front. Relocations can be discarded if memory pressure forces otherwise un-modified pages to be removed, and then seemlessly reapplied during the in-paging process. This mechanism requires no additional storage to contain the relocated versions of images, and thus minimizes the negative performance impact of ASLR.

    2. This is only likely to occur for images which were either built without relocations or built without /dynamicbase. Note that there are only 256 possibilities, so with enough reboots it is probable that you’ll eventually see a duplicate.

  11. Mike says:

    Thanks for your reply! You are so nice. I still get confusion ideas:
    1. As my understanding, Dlls like kernel32.dll can have one copy of image in memory because it most likely is mapped to same address in those processes which use it. So the relocation will properly never happen. If relocation happens in one process, we will get new copy of dll(code changed) in memory and relocation takes time. So after using ASLR, whenever and wherever relocation happened, code are changed. Do you think it will take time and space to do that?
    2. For example, I build a Trojan with this switch. A victim got it. After reboot, my Trojan get to run. It want to inject shellcode into explore.exe. The shellcode has to do some system call, using functions in kernel32.dll for instance. Because image base address changes only after reboot, the Trojan can get function address from its own process and fix the function pointer in shellcode. Then the bad thing will happen. God bless the victim. :) Do you think it will happen?

  12. Skywing says:

    1. There is one randomization for a particular DLL per lifetime of the section object (typically, per boot). All processes will use the same randomization set if they load that DLL, which means it’ll try to put it at the same base address. Relocations for ASLR are performed only for physical pages being in-paged, so ASLR-relocated pages are typically shared between processes unless written to.
    2. Sure, that’s possible. Vista’s ASLR is only really designed to protect against remote attacks where it is not easy to determine the memory layout – against local attacks, where an attacker could load a DLL to find its randomization address, it’s not particularly effective (nor is it really designed to be in this case).

  13. Mike says:

    OK. I fully understand it. Thanks a lot.
    I ask those qustion because I wonder if following method is possible after ASLR.
    It seems it still can work in IA32.
    Thanks again.

  14. Amit says:

    How can I detect whether the given assembly is having the PE header “DLL flags” set to 0x0040

  15. nova says:

    @amit: one way, you can use the script with Immunity Debugger

    the script can be found here (you’ll need to make an account tho)