Title: UT HEAPS
1UT HEAPS
HEAPS ABO
2This Talk Covers
- Windows 2003
- Windows 2003 SP2
- Still most widely used windows server OS
- Still not a lot of heap exploits released
- Still not a lot of heap research released
- Vista -gt Ben Hawkes BHUS08
- Heap Explotation
- How the heap works
- Freelists vs Lookaside
- Exploitation Techniques
- Heap Exploit Walkthrough
- From start to finish
3Windows Heap
- Multiple Heaps
- Process has default heap
- Can create separate heaps for different uses
- Some loaded .dll create their own heap
- Some .dlls hold pointer to the heap they use
- State Of The Heap
- Server restart
- Service restart
- First request
- Long time live, multiple previous requests
- Things That Matter
- Everything, IP address, server name, day of the
week
4Heap Exploit Difficulties
- Safe Unlinking
- On unlink, coalesce, relink from freelist
- Causes the link/unlink to fail if addresses
readable - Raises a handled exception, execution proceeds
- Chunk address still returned to caller
- Cookie Check
- Cookie checked on free
- Invalid cookie prevents relinking of chunk
- HeapSetInformation()
- HeapEnableTerminateOnCorruption()
- Windows Vista and Windows Server 2008
Need To Get Creative In Exploitation Methods
5A Heap In Motion
The heap object initially starts as an empty
contiguous block of memory. Two structures are
written into the heap. The Heap Management
structure contains information regarding the heap
object, and tracks the heap chunks. There is
always one Free Chunk in the heap object and it
points to the free space at the end of the heap.
6The Heap In Motion
After the allocation of three memory chunks, the
heap layout now looks like this
7The Heap In Motion
Freeing a chunk in between two busy chunks,
creates a Free Chunk
8The Heap In Motion
Free chunks that sit next to each other are
joined (Coalesced) together.
9Heap Management Structure
All offsets are from the base of the Heap Object
These Flags hold settings such as isDebug,
Exception Raising, and Executable Heap
The maximum size of an allocation before a
Virtual Memory allocation is performed
Linked list of blocks allocated from Virtual
Memory
A four DWORD bitmask with each bit set if the
corresponding FreeListn is populated
Pointer to the first chunk in FreeList0 FreeList
0 is used to store Free Chunks gt 1016 bytes
Start of double linked lists to store Free Chunks
Pointer to CriticalSection that is used to lock
the heap during changes
Pointer to Function() that is called when the
heap is expanded and more pages committed
Pointer to the front end allocator. This is a
pointer to the Lookaside
Flag that stores settings about the front end
allocator
Pointer to the Last Free Chunk in the heap
Start of the 48 byte Lookaside list headers
10Heap Management Structure - Virtual Memory
Allocation
EBX is set to Base Address Check threshold
Load BLINK
ECX is _at_NewChunk
Write _at_NewChunk to _at_BLINK4
If the VirtualAllocatedBlocks-gtBLINK can be
overwritten then the address of the NewChunk can
be written to an arbitrary location
11Heap Management Structure - FreeList Bitmap
Bitmap is populated when chunk added to
FreeListn
0-7
24-31
48-55
Bitmap is checked when looking for a FreeListn
that fits the request
If a match is found then the corresponding
FreeListn is used for the allocation.
If the Bitmap can be manipulated then a pointer
to an empty FreeListn can be returned, allowing
the overwrite of management structures. nico
12Heap Management Structure - FreeList Bitmap
FreeList7 is populated
FreeList16 is empty
Modify bitmap
Request for block 16 will create a new block and
return it
Request for block 16 will return 003601F8
If the Bitmap can be manipulated then a pointer
to an empty FreeListn can be returned, allowing
the overwrite of management structures. nico
13Heap Management Structure - FreeList Bitmap
Part Of The Bitmap Loading Code
7C82BAB8 A Static Pointer To A Bit Mask Table
That Can Be Modified To Manipulate The Bitmap
Result
If the Bitmap can be manipulated then a pointer
to an empty FreeListn can be returned, allowing
the overwrite of management structures. nico
14Heap Management Structure FreeListn
FreeList0 is similar to FreeListn but holds
chunks gt 1016 bytes
Double Linked List connects free chunks together
15Heap Management Structure - Commit Routine Pointer
Custom function() called when committing more
memory to the Heap
Initially set to nothing
Loaded into ECX and called
This is a static pointer that can be overwritten
to gain execution control
16Heap Management Structure Lookasiden
Lookaside0 and Lookaside1 are not used
48 byte structure
17Heap Chunks
18Lookaside Lists
Lookaside Starts Empty
This Value Gets Copied
Copied To Here
Chunk Added To Top Of Lookaside
Chunk Added To Top Of Lookaside
Chunk Added To Top Of Lookaside
Chunk Removed From Top Of Lookaside
Lookasiden-gtFLINK is corrupted
About To Allocate From The Lookasiden
Overwrite the FLINK of the top chunk
There is no Safe Unlinking or Cookie check for
Lookaside Lists Well known attack is to overwrite
the FLINK of a chunk on a Lookaside. This will
populate the Lookasiden-gtFLINK with an
arbitrary value to be returned at allocation.
19Freelistn Lists
Freelist Starts Empty
Freelist Is Empty
Chunk Added To Bottom
Chunk Added To Bottom
Chunk Removed From Bottom
Safe Unlinking and Cookie checks will prevent
Unlinking Overwriting the Freelistn-gtBLINK
will cause the address of the Freed Chunk to be
written to an arbitrary location
20Freelistn Lists
- Freelist Searching
- If a freelistn of requested size not available
- bitmap is used to find larger populated
freelistn - Chunk Size
- Size field of the chunk header used as offset to
bitmap - Bitmap is updated on allocate/free if needed
- Size field is used to calculate freelistn to
free to - Manipulating Size Field
- Allocation can control bitmap flipping
- Free can have chunk freed to different
lookaside/freelist
21Flipping Bitmap On Allocate
Size Is Overwritten FLINK / BLINK Can Be
Overwritten
If Last Chunk On Freelist Then Bitmap Updated
Calculate Bitmap
If FLINK and BLINK Overwritten with Valid For
Read and FLINK BLINK Then Bitmap Updated
Bitmap Attack Explained Earlier
22Free To Arbitrary Lookasiden/FreeListn
Size Is Overwritten Cookie Is Left Intact
Freeing To Lookasiden
Freeing To Freelistn
Coalescing Is A Problem That Needs To Be Dealt
With
Could This Be Useful When Filling In Gaps?
23FreeList0 - Free
Load Freelist0-gtFLINK
Populated Freelist0
Check Size Is Larger Than Chunk Been Freed
Not Greater, Load Chunk-gtFLINK
Check Size Is Great Than Chunk Been Freed
If It Is Greater Then Insert Chunk
Exploitable Condition On Freelist0 Insert
24Exploiting FreeList0 - Free
An Overwritten Chunk In Freelist0 Can Be
Exploited To Write The Address Of The Chunk Being
Freed To An Arbitrary Location
Exploitable Condition On Freelist0 Insert
25Exploiting FreeList0 - Free
Chunk Is Inserted Before The Overwritting Chunk.
FLINK and BLINK updated
Place Where We Want To Write 003622D0 Could Be A
Function Table, This Is A Lookaside
Overwritten Lookaside Now Populated Three
Requests And We Get Our Set Location
Exploitable Condition On Freelist0 Insert
26FreeList0 - Allocate
Load Freelist0-gtBLINK
Load Freelist0-gtFLINK
Populated Freelist0
Check Size Is Large Enough For Request
Too Small, Load Chunk-gtFLINK
Check Size Is Large Enough For Request
Large Enough, Return Chunk
Check Size Is Large Enough For Request
Exploitable Condition On Freelist0 Allocate
27Exploiting FreeList0 - Searching
Request Made For Size 0x0BF8
FLINK Points To Fake Chunk
FLINK Points To Fake Chunk8
Chunk Returned To Caller This Address Is In The
Freelists
Requested Size (1 block)
Must Be Readable
Must Be Readable
Exploitable Condition On Freelist0 Allocate -
Searching
28Allocation Relinking
If Chunk Is Larger Than Request It Will Get Split
Chunk Returned To Caller
New Header Is Written Into The Existing Chunk
Space
Chunk Inserted Into FreeLists
29Exploiting FreeList0 - Relinking
Request Made For Size Smaller Than Our Overwrite
FLINK Points To Fake Chunk
FLINK Points To Fake Chunk8
Relink Chunk Address Written To 00360580 This Is
The FrontEndHeap (Lookaside Base)
gt Relink Chunk Size
Must Be Read/Write
Exploitable Condition On Freelist0 Allocate -
Relinking
30Splitting / Resizing
- When Allocated Chunk Is To Large
- Checked when allocation from other list
- Chunk is cut to size, New header is written
- Chunk is inserted to freelistn or freelist0
- Size manipulated to put new chunk into arbitrary
Freelist
Can Skip By Setting As Last Chunk
31Coalesced Chunks
- When Chunk Is Freed To Freelist
- Size field is used to locate previous and next
chunk - Requires valid FLINK/BLINK on chunks to colaesce
- An overflow can control all of this to prevent
coalesce
Test Flag Of Previous Chunk
Test Flag Of Next Chunk
32Preventing Coalesce
- How To Prevent A Coalesce
- Set the chunk being freed prev size to ZERO
- Set the chunk being freed FLAG to last chunk
- Set the chunk being freed self size gt 0xFE00
- Set the prev/next chunks flag to PASS the BUSY
check - Control the size to fake the prev/next chunks
location - Why Prevent A Coalesce()
- Coalescing an overwritten chunk normally blows up
- Linking, resizing, and relinking is very complex
33Coalesced Chunks
Chunk A Data Stored In
BUSY Chunk
Chunk B We Overflowing
BUSY Chunk
Keep The Flag Set To BUSY
Chunk A Will Be Freed And We Want To Prevent
Coalescing
34Coalesced Chunks
Chunk A Data Stored In
BUSY Chunk
Chunk B We Overflowing
BUSY Chunk
Create Two Fake Chunks And Set Size In Header Of
Chunk B To Point To The Fake Chunks Flag Set To
Busy
Create Two Fake Chunks And Set Size In Header Of
Chunk B To Point To The Fake Chunks Flag Set To
Busy
Chunk B Will Be Freed And We Want To Prevent
Coalescing
35Coalesced Chunks
Chunk A Data Stored In
BUSY Chunk
Chunk B We Overflowing
BUSY Chunk
Set The Flag To Contain The Last Chunk Flag
Chunk B Will Be Freed And We Want To Prevent
Coalescing
36Preventing A Free
- How To Prevent A Free
- Set the chunks flag to FAIL the BUSY check
- Why Prevent A Free()
- Remove chunk from Lookaside
- Can be overwritten before allocation
- Remove chunk from Freelist
- Flag gets reset on allocation
- Bypass Cookie Check
- Will cause a heap exception, doesnt stop
execution
Move To Chunk Header
Load Flag and Test If Busy
37Example Removing Chunk From Lookaside
Before Allocation
Overwrite Flag
After Allocation
After Free()
38Clearing The Lookaside
- Top Chunk On A Lookaside Is Overwritten
- Flags set to not BUSY, Flink set to 0x00000000
Before Allocation
Overwrite Flag And FLINK
After Overwrite
Allocation And Free Will Clear The Lookaside List
39The Exploitation Process
- The Steps
- Exploit the heap
- Overwrite a function pointer or other to gain
execution - Flip the heap onto the stack to get ret-to-libc
style control - Turn off Data Execution Protection (DEP)
- Return to shellcode
- Exploit The Heap
- Application dependant
- Overwrite A Function Pointer
- Application dependant?
40Heap / Stack Flipping
- What Is Heap/Stack Flipping
- Exploit data is on the heap
- For fine grained control, it needs to be on the
stack - Requirements
- Pointer to exploit data on stack, in a register,
in reg /- n - Locate instructions to manipulate pointer and pop
esp, ret - Overwrite function pointer to return to
instructions - Populate ESP With The Pointer To Exploit Data
EBX -gt DATA
EBP -gt DATA
ECX -gt DATA
EAX-gt DATA
41Heap / Stack Flipping
Exploit Data
Stack
Registers
Code Gets Executed
Flipping Code
42Heap / Stack Flipping
Exploit Data
New Stack
Code That We Returned Into
New Registers
43Bypassing DEP
- Entirely Ret-to-Libc
- Entire shellcode in borrowed instructions
- Inject into process that is not DEP enabled
- Very difficult
- HeapCreate()
- Create new heap with HEAP_CREATE_ENABLE_EXECUTE
- Allocate new chunk, memcpy shellcode across
- Doable, but sounds like a lot of work
- Registry
- 'Image File Execution Options
- Would turn it off on a restart
- Not really very helpful
44Bypassing DEP
- SetProcessDEPPolicy()
- Not available on 2003
- Copy Shellcode To RWE Memory Page
- Copy shellcode and then return to address
- VirtualProtect()
- Use the PAGE_EXECUTE_READWRITE flag to reset heap
- Return to shellcode
45Bypassing DEP
- VirtualAlloc()
- Allocate new memory with PAGE_EXECUTE_READWRITE
- Address is returned in EAX
- Copy shellcode and return to it
- NtSetInformationProcess()
- Skape and Skywing ret-to-libc to deactivate DEP
- Easier on windows 2003
NtSetInformationProcess( NtCurrentProcess(), //
(HANDLE)-1 ProcessExecuteFlags, //
0x22 ExecuteFlags, // ptr to 0x2 sizeof(Execute
Flags)) // 0x4
46Bypassing DEP
Perfect Instruction Set
BUT!
NtSetInformationProcess( NtCurrentProcess(), //
(HANDLE)-1 ProcessExecuteFlags, //
0x22 ExecuteFlags, // ptr to 0x2 sizeof(Execute
Flags)) // 0x4
Requires ESI37 To Be Writable Correctly Set
Stack
47Heap Exploitation
- Step By Step
- The vulnerability
- Reproduction
- Understanding the bug
- Finding an overwrite
- Find a pointer
- Flipping the heap to stack
- Bypassing DEP
- The working
48The Vulnerability
Citrix ImaSrv.exe TCP Port 2512 or
2513 User-supplied -gt Memory Allocation Undersized
Allocation Overflow The Heap Buffer
Citrix
ImaSrv.exe
TCP Port 2512 or 2513
User-supplied -gt Memory Allocation
Overflow The Heap Buffer
49Reproducing The Vulnerability
- Usual Integer Overflow
- Usual packet size bug
- Usual Basic Fuzz Test
- while !crashed
-
- inc buffer length
- fill buffer with 0xFF
- send to TCP 2512
-
I Am Listening On TCP 2512
50Reproducing The Vulnerability
A Crash
A Crash
ntdll! RtlAllocateHeap
In the good ol days, it would now be as easy as
overwriting the UEF. But those days are over.
51Understanding The Bug
WSARecv
- Need To Trace From Start To Finish
- bp WSARecv and send overflow again
Stack
Buffer Size
Buffer Address
52Understanding The Bug
- Need To Trace From Start To Finish
- After WSARecv our buffer is loaded
53Understanding The Bug
- Trace Through Code To Determine Paths
- This code checks buffer sizes
Load First DWORD Of Packet Into EAX
Compare Against Size Of Current Buffer 0x408
Jump If Our Packet Specified A Size Larger Than
0x408
54Understanding The Bug
- Trace Through Code To Determine Paths
- Eventually get to here
ESI First DWORD From Packet
EAX ESI 3C
EAX ESI 3C
Is Going To Allocate A Buffer Of Size EAX
55Understanding The Bug
- But its not over yet
- Trace down to ntdll!RTLAllocateHeap
Allocate From Heap 00320000
Allocate 3B Bytes
56Understanding The Bug
- Still Thats Just An Undersized Buffer
- Keep tracing the code
EAX Points To The Newly Allocated Buffer
Bunch Of Stuff Is Written Into The New
Buffer This Is A Custom Header And Is 0x3C Bytes
Long
57Understanding The Bug
- Finally....
- A memmove instruction overflows the buffer
New Buffer3C
Packet Data
KABOOM!
This Is The Size Of The Packet That We Sent
58Understanding The Bug
- The Result
- We can cause the allocation of a size 0x01
0x03B - We can overflow the chunk with 0x408 bytes
- The Limitations
- Can only allocate chunk 2 through to 9
- That range is FFFFFFC5 0x01 Chunk 2
- To FFFFFFFF 0x3b Chunk 9
- The first 0x3C bytes are not controlled by us due
to the custom header
59The Request LifeCycle
- So Now What?
- We know we can cause an allocation of a lower
chunk - Lets look at the Lookaside lists at the time of
the allocation
RTLAllocateHeap()
WSARecv()
memmove()
RTLFreeHeap()
60The Lookaside Lists
0x0a871cc8 0x0a871c60 0x68
0x0a871c38 0x0a871bd0 0x68
0x0a871d00 0x0a871c98 0x68
Lookaside8 Has A Top Chunk That Sits After
Lookaside7 Top Chunk On All Runs AND The
Difference Is Greater Than 0x3C
61Lets Try It
- First Request
- Request Lookaside7
- Overwrite Lookaside8
- Free Request
- Problem
- If we now had two allocations of Lookaside8
- But we only have one
- Solution
- Set flag of top chunk of Lookaside8 to be FREE
- Then when free() is called it will be skipped
62Lets Try It
- First Request
- Request Lookaside7
- Overwrite Lookaside8
- Free Request
- Second Request
- Request Lookaside8
- Top Chunk Is Popped
- Free Request
- Third Request
- Request Lookaside8, Our Address Is Returned
63What Address To Overwrite
- Function Pointer
- Trace code looking for pointer
- None found before WSARecv()
Lucky For Us That Winsock Uses Static Pointers
EAX Points To Stack
0x71C14044 Is A Static Pointer That Can Be
Overwritten
64Winsock Structure
- Winsock
- Holds a structure
- Structure holds pointer to function pointer table
on the default heap
Static Pointer To Handle
Load Address Of Pointer Table Static Within Heap
Call Function
65Exploiting The Bug
- Pointer Table Address
- 0x142360
- Set Lookaside Address
- Need to account for header
- Set lookaside to 0x01431D0
- Overwrite The Pointer Table
- We now control execution
- Set The Stack
- EAX points to the pointer table
- EAX points to our data
- Search for a heap/stack flip
- Return Down The Stack
- Return to Anti-DEP
- Return to shellcode on pointer table
Heap/Stack Flip Local To Citrix DLLS
66Da Greetz
Acknowledgement to those who have published past
heap research 0ded Shok Sotirov Sandip
Chaudhari A. Anisimov N. Falliere Halvar Litchfiel
d All Others
Acknowledgement to those who shared current
information, some of which was used in this
presentation Nico Caddis mxatone
Delphic