Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Agenda
Practical Windows heap internals How to exploit Win2K WinXP SP1 heap overflows 3rd party (me ) assessment of WinXP SP2 improvements How to exploit WinXP SP2 heap overflows Summary
Default Heap
Heaps Count
0x70000 0x170000
Free Lists
Lookaside List
1400 16
2000 16
2000
2408
48
48
2
3 4 5 6
16
48
48
Self Size
Segment Index
Flags
Overflow direction
Self Size
Segment Index
Flags
Next chunk
Previous chunk
C
Step 3: Buffer removed from free list
A + B Coalesced
A C
A + B + C Coalesced
A
Step 4: Buffer placed back on the free list
4-to-n-byte Overwrite
Using a 4-byte overwrite to indirectly cause an overwrite of an arbitrary-n bytes
PEB Header
0x7ffdf130
~1k of payload
4-to-n-byte overwrite:
Heap Exploitation
Questions?
This technique we just covered is very reliably, providing success almost every time on all Win2K (all service packs) and WinXP (up to SP2)
On to XP SP2.
XP Service Pack 2
Effects on Heap Exploitation
XP Service Pack 2
PEB Randomization
In theory, it could have a big impact on heap exploitation though not in reality Prior to XP SP2, it used to always be at the highest page available (0x7ffdf000) The first (and ONLY the first) TEB is also randomized They seem to never be below 0x7ffd4000
XP Service Pack 2
PEB Randomization Does it make any difference? Not much, randomization is definitely a misnomer If 2 threads are present: We can write to 0x7ffdf000-0x7ffdffff, and 2 other pages between 0x7ffd4000-0x7ffdefff If 3 threads are present: 0x7ffde000-0x7ffdffff 2 other pages between 0x7ffd4000-0x7ffdefff If 11 threads are present: 100% success, no empty pages
XP Service Pack 2
PEB Randomization Summary Provides little protection for Any application that have m workers per n connections (IIS? Exchange?) Any service in dllhost/services/svchost or any other active surrogate process
XP Service Pack 2
Heap header cookie
XP SP2 Header *reminder: overflow direction
Self Size
New Cookie
Flags
Unused bytes
Segment Index
Current Header
Self Size
Segment Index
Flags
XP Service Pack 2
Heap header cookie calculation If ((AddressOfChunkHeader / 8) XOR Chunk>Cookie XOR Heap->Cookie != 0) CORRUPT
Since the cookie has only 8-bits, it has 2^8 = 256 possible keys Well randomly guess the security cookie, on average, 1 of every 256 attempts
XP Service Pack 2
On the normal WinXP SP2 system, corrupting a chunk will do nothing Since we only overwrite the Flink/Blink of the chunk, we corrupt no other chunks Thus we can keep trying until we run out of memory
XP Service Pack 2
Summary so far
At this point, we see that we can with enough time trivially defeat all the other protection mechanisms. On to safe unlinking
XP Service Pack 2
Safe Unlinking
Safe unlinking means that RemoveListEntry(B) will make this check: (B->Flink)->Blink == B && (B->Blink)->Flink == B In other words: C->Blink == B && A->Flink == B Can it be evaded? Yes, in one particular case.
Header to free
XP Service Pack 2
UnSafe-Unlinking FreeList Overwrite Technique
p = HeapAlloc(n); FillLookaside(n); HeapFree(p); EmptyLookaside(n); Overwrite p[0] (somewhere on the heap) with: p->Flags = Busy (to prevent accidental coalescing) p ->Flink = (BYTE *)&ListHead[(n/8)+1] - 4 p ->Blink = (BYTE *)&ListHead[(n/8)+1] + 4 HeapAlloc(n); // defeats safe unlinking (ignore result) p = HeapAlloc(n); // defeats safe unlinking // p now points to &ListHead[(n/8)].Blink
XP Service Pack 2
Defeating Safe Unlinking (before overwrite)
ListHead[n-1] ListHead[n] ListHead[n+1]
[4] Blink [0] Flink [4] Blink [0] Flink [0] Flink [4] Blink
FreeChunk
XP Service Pack 2
Defeating Safe Unlinking: Step 1 (Overwrite)
ListHead[n-1] ListHead[n] ListHead[n+1]
[4] Blink [0] Flink [4] Blink [0] Flink [0] Flink [4] Blink
FreeChunk
FreeChunk->Flink->Blink) == *(*(FreeChunk+0)+4)
Both point to FreeChunk, unlink proceeds!
XP Service Pack 2
Defeating Safe Unlinking: Step 2 (1st alloc)
ListHead[n-1] ListHead[n] ListHead[n+1]
XP Service Pack 2
Defeating Safe Unlinking: Step 3 (2nd alloc)
ListHead[n-1] ListHead[n] ListHead[n+1]
Returns pointer to &ListHead[n-1].Blink Now the FreeLists point to whatever data the user puts in it
XP Service Pack 2
Questions?
XP Service Pack 2
Unsafe-Unlinking FreeList Overwrite Technique For vulnerabilities where you can control the allocation size, safe unlinking can be evadable. But is this reliable? Hardly.
XP Service Pack 2
Unsafe-Unlinking FreeList Overwrite Technique (cont) We have to flood the heap with this repeating 8 byte sequence: [FreeListHead-4][FreeListHead+4] And hope the Chunks Flink/Blink pair is within the range we can overflow But there is an even easier method
XP Service Pack 2
Chunk-on-Lookaside Overwrite Technique In fact on XP SP2, there is an even easier method Lookasides lists take precedence over free lists This is quite convenient because Lookaside lists (singly linked) are easier to exploit than the free lists (doubly linked)
XP Service Pack 2
Chunk-on-Lookaside Overwrites HeapAlloc checks the lookaside before the free list There is no check to see if the cookie was overwritten since it was freed It is a singly-linked list, thus the safe unlinking check doesnt apply Result: a clean exploitation technique (albeit with brute-forcing required)
XP Service Pack 2
Chunk-on-Lookaside Overwrites (Technique Summary)
// We need at least 2 entries on lookaside a_n[0] = HeapAlloc(n) a_n[1] = HeapAlloc(n) HeapFree(a_n[1]) HeapFree(a_n[0]) Overwrite a_n[0] (somewhere on the heap) with: a_n[0].Flags = Busy (to prevent accidental coalescing) a_n[0].Flink = AddressWeWant HeapAlloc(n) // discard, this returns a_n[0] p = HeapAlloc(n) p now points to AddressWeWant
XP Service Pack 2
Chunk-on-Lookaside Overwrite - Success rate? Reqiures overwriting a chunk already freed to the lookaside If an attacker overflows a buffer repeatedly, how often will he/she need to before succeeding?
XP Service Pack 2
Chunk-on-Lookaside Overwrite Empirical results
64K heap with 1 segment All chunk sizes sizes between 8-1024 bytes Max overflow size = 1016 bytes Random number of allocs between 10-1000 Free probability of 50%
Took an average of 84 allocations to be within overflow range It will take at least 2 overwrites (one to overwrite a function pointer, one to place shellcode)
XP Service Pack 2
Chunk-on-Lookaside Overwrite Empirical results Application specific function pointer and writable location for shellcode:
84*2 = 168 attempts to execute shellcode
XP Service Pack 2
Chunk-on-Lookaside Overwrite Summary To exploit a non-application specific heap exploit will take 2000+ attempts to do it reliably But now ask yourself how long does it take generate 2000 heap overwrite attempts? Lets be overly conservative and assume 5 minutes That will really slow down a worm But will it help you if someone is specifically trying to hack your machine?
XP Service Pack 2
Low Fragmentation Heap (LFH) Looks really solid kudos to its author Uses 32-bit cookie Obscures address of Lookaside list heads:
ChunkSizes = *((DWORD *)Chunk) // (ChunkSize<<16|PrevChunkSize) pLookasideEntry = (DWORD)Chunk / 8 pLookasideEntry ^= Lookaside->Key pLookasideEntry ^= ChunkSizes pLookasideEntry ^= RtlpLFHKey
XP Service Pack 2
Low Fragmentation Heap (LFH) The RtlpLFHKey is a show stopper:
push call mov lea push call imul push mov eax _RtlRandomEx@4 _RtlpLFHKey, eax eax, [ebp+var_4] eax _RtlRandomEx@4 eax, _RtlpLFHKey esi _RtlpLFHKey, eax
XP Service Pack 2
Low Fragmentation Heap (LFH)
Must be enabled manually (via NTDLL!RtlSetHeapInformation or KERNEL32!HeapSetInformation) It is used for chunks < 16K It is not used by anything on XP SP2 Professional What irony
Summary
Win2K WinXP SP1 Fixed heap base and fixed PEB allow for writing very stable exploits Overwriting FreeList/Lookaside list heads gives us the ability to overwrite any writable address with 1K of data
Summary
WinXP SP2 Decreases reliability (more bruteforcing is necessary) But with enough time, exploitation will still succeed XP SP2 will really slow worm propagation, but not help a targeted victim ...
Summary
WinXP SP2 Heap corruption handling is weak PEB randomization is weak Safe unlinking is evadable Non-LFH cookie checks are weak LFH looks good
Summary
Solutions Use low fragmentation heap by default
Just be sure it is the lowest address on the heap Most machines have 1GB+ RAM these days If I have an application with 50 corrupt chunks in 60 seconds, I want to know someone is owning me
Summary
The eventual death of 4 byte overwrites Whether an attacker can predict the ChunkSize/PrevSize or not, he/she wont be able to predict a larger security cookie (like LFH has). Heap exploits will focus more on attacking application data on the heap (not the heap itself)