Windows Vista Beta 2 includes a new defense against buffer overrun exploits called address space layout randomization. Not only is it in Beta 2, it’s on by default too. Now before I continue, I want to level set ASLR. It is not a panacea, it is not a replacement for insecure code, but when used in conjunction with other technologies, which I will explain shortly, it is a useful defense because it makes Windows systems look “different” to malware, making automated attacks harder.
So what is ASLR? In short, when you boot a Windows Vista Beta 2 computer, we load system code into different locations in memory. This helps defeat a well-understood attack called “return-to-libc”, where exploit code attempts to call a system function, such as the socket() function in wsock32.dll to open a socket, or LoadLibrary in kernel32.dll to load wsock32.dll in the first place. The job of ASLR is to move these function entry points around in memory so they are in unpredictable locations. In the case of Windows Vista Beta 2, a DLL or EXE could be loaded into any of 256 locations, which means an attacker has a 1/256 chance of getting the address right. In short, this makes it harder for exploits to work correctly.
Think: “Where’s Waldo()?”
For example, earlier today my laptop reported the following:
I then rebooted the machine, and my laptop reported the following:
As you can see, various DLLs are loaded at different addresses and this makes it harder for exploit code to locate and therefore take advantage of functionality inside these DLLs. Not impossible, just harder.
What really raises the bar however, is the combination of various defenses we now have in Windows Vista, including:
This is a compile-time option in Visual C++ (on by default) that adds stack-based buffer overrun detection. It also juggles around some of the function arguments and the function stack variable to make some classes of attack harder to pull off. Virtually all Windows Vista binaries are compiled with this, and we are now in our fourth iteration of /GS!
When /GS is triggered, the application is terminated.
This is a linker option that writes the addresses of exception handlers to the PE header of the executable, and when an exception is raised, the OS checks the exception handler address against the list in the PE header, and if the address is not in the list, something corrupted the exception handler address so the OS kills the process.
Data Execution Protection (aka NX)
This requires CPU as well as operating system support. Most (read: all) buffer overruns come into a vulnerable application as data, and then that data is executed. NX can prevent the exploit working by marking data segments as No-Execute, in other words, you can’t run data. When the WMF flaw was found, I wrote a small malicious WMF file that popped, “oops!” on the desktop. When I ran this on my computer at home, an AMD 64FX based computer that supports NX, Windows shut the image viewer down when I read my WMF file because the operating system detected an attempt to run data.
Function Pointer Obfuscation
Long-lived function pointers are targets for attack because (a) they are long lived (!) and (b) they point to functions that are called at some point by the code. In Windows Vista we encode numerous long-lived pointers, and only un-encode them when the pointer is needed. You can read more about this functionality in a prior blog post “Protecting against Pointer Subterfuge (Kinda!)”
The net of this is ASLR is seen as just another defense, and it’s on by default in Windows Vista Beta 2. I think the latter point is important, we added ASLR pretty late in the game, but we decided that adding it to beta 2 and enabling it by default was important so we can understand how well it performs in the field. By this I mean what the compatibility implications are, and to give us time to fine tune ASLR before we finally release Windows Vista.
Please remember, this is work in progress!
I’ll write more about ASLR and some other defenses in the coming weeks. Please let us know what you think.