660 likes | 683 Views
Learn about the heap exploits and research in Windows 2003, the most widely used Windows server OS. This talk covers the heap structure, exploitation techniques, and challenges faced in heap exploit development. Gain insights into safe unlinking, cookie checks, and heap management structures. Discover creative exploitation methods and understand the heap in motion concept.
E N D
HEAPS ABO UT HEAPS
This 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 -> Ben Hawkes BHUS08 Heap Explotation • How the heap works • FreelistsvsLookaside • Exploitation Techniques Heap Exploit Walkthrough • From start to finish
Windows 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
Heap 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
A 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.
The Heap In Motion After the allocation of three memory chunks, the heap layout now looks like this
The Heap In Motion Freeing a chunk in between two busy chunks, creates a Free Chunk
The Heap In Motion Free chunks that sit next to each other are joined (Coalesced) together.
Heap 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 FreeList[n] is populated Pointer to the first chunk in FreeList[0] FreeList[0] is used to store Free Chunks > 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
Heap Management Structure - Virtual Memory Allocation EBX is set to Base Address Check threshold Load BLINK ECX is @NewChunk Write @NewChunk to @BLINK+4 If the VirtualAllocatedBlocks->BLINK can be overwritten then the address of the NewChunk can be written to an arbitrary location
Heap Management Structure - FreeList Bitmap Bitmap is populated when chunk added to FreeList[n] 0-7 24-31 48-55 Bitmap is checked when looking for a FreeList[n] that fits the request If a match is found then the corresponding FreeList[n] is used for the allocation. If the Bitmap can be manipulated then a pointer to an empty FreeList[n] can be returned, allowing the overwrite of management structures. [nico]
Heap Management Structure - FreeList Bitmap FreeList[7] is populated FreeList[16] 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 FreeList[n] can be returned, allowing the overwrite of management structures. [nico]
Heap 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 FreeList[n] can be returned, allowing the overwrite of management structures. [nico]
Heap Management Structure – FreeList[n] FreeList[0] is similar to FreeList[n] but holds chunks > 1016 bytes Double Linked List connects free chunks together
Heap 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
Heap Management Structure – Lookaside[n] Lookaside[0] and Lookaside[1] are not used 48 byte structure
Lookaside Lists Lookaside Starts Empty This Value Gets Copied Copied To Here Chunk Removed From Top Of Lookaside Lookaside[n]->FLINK is corrupted Chunk Added To Top Of Lookaside Chunk Added To Top Of Lookaside Chunk Added To Top Of Lookaside About To Allocate From The Lookaside[n] 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 Lookaside[n]->FLINK with an arbitrary value to be returned at allocation.
Freelist[n] 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 Freelist[n]->BLINK will cause the address of the Free’d Chunk to be written to an arbitrary location
Freelist[n] Lists Freelist Searching • If a freelist[n] of requested size not available bitmap is used to find larger populated freelist[n] 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 freelist[n] to free to Manipulating Size Field • Allocation can control bitmap flipping • Free can have chunk free’d to different lookaside/freelist
Flipping 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
Free To Arbitrary Lookaside[n]/FreeList[n] Size Is Overwritten Cookie Is Left Intact Freeing To Lookaside[n] Freeing To Freelist[n] Coalescing Is A Problem That Needs To Be Dealt With Could This Be Useful When Filling In Gaps?
FreeList[0] - Free Load Freelist[0]->FLINK Populated Freelist[0] Check Size Is Larger Than Chunk Been Free’d Not Greater, Load Chunk->FLINK Check Size Is Great Than Chunk Been Free’d If It Is Greater Then Insert Chunk Exploitable Condition On Freelist[0] Insert
Exploiting FreeList[0] - Free An Overwritten Chunk In Freelist[0] Can Be Exploited To Write The Address Of The Chunk Being Freed To An Arbitrary Location Exploitable Condition On Freelist[0] Insert
Exploiting FreeList[0] - 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 Freelist[0] Insert
FreeList[0] - Allocate Load Freelist[0]->BLINK Load Freelist[0]->FLINK Populated Freelist[0] Check Size Is Large Enough For Request Too Small, Load Chunk->FLINK Check Size Is Large Enough For Request Large Enough, Return Chunk Check Size Is Large Enough For Request Exploitable Condition On Freelist[0] Allocate
Exploiting FreeList[0] - Searching Request Made For Size 0x0BF8 FLINK Points To Fake Chunk FLINK Points To Fake Chunk+8 Chunk Returned To Caller This Address Is In The Freelists = Requested Size (+1 block) Must Be Readable Must Be Readable Exploitable Condition On Freelist[0] Allocate - Searching
Allocation 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
Exploiting FreeList[0] - Relinking Request Made For Size Smaller Than Our Overwrite FLINK Points To Fake Chunk FLINK Points To Fake Chunk+8 Relink Chunk Address Written To 00360580 This Is The FrontEndHeap (Lookaside Base) > Relink Chunk Size Must Be Read/Write Exploitable Condition On Freelist[0] Allocate - Relinking
Splitting / 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 freelist[n] or freelist[0] • Size manipulated to put new chunk into arbitrary Freelist Can Skip By Setting As Last Chunk
Coalesced Chunks When Chunk Is Free’d 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
Preventing 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 > 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
Coalesced Chunks Chunk A Data Stored In BUSY Chunk Chunk B We Overflowing BUSY Chunk Keep The Flag Set To BUSY Chunk A Will Be Free’d And We Want To Prevent Coalescing
Coalesced 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 Free’d And We Want To Prevent Coalescing
Coalesced 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 Free’d And We Want To Prevent Coalescing
Preventing 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, doesn’t stop execution Move To Chunk Header Load Flag and Test If Busy
Example Removing Chunk From Lookaside Before Allocation Overwrite Flag After Allocation After Free()
Clearing 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
The 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?
Heap / 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 -> DATA EBP -> DATA ECX -> DATA EAX-> DATA
Heap / Stack Flipping Exploit Data Stack Registers Code Gets Executed Flipping Code
Heap / Stack Flipping Exploit Data New Stack Code That We Returned Into New Registers
Bypassing 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, memcpyshellcode 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
Bypassing 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
Bypassing 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(ExecuteFlags)); // 0x4
Bypassing DEP Perfect Instruction Set BUT! NtSetInformationProcess( NtCurrentProcess(), // (HANDLE)-1 ProcessExecuteFlags, // 0x22 &ExecuteFlags, // ptr to 0x2 sizeof(ExecuteFlags)); // 0x4 Requires [ESI+37] To Be Writable Correctly Set Stack
Heap 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
The Vulnerability Citrix ImaSrv.exe TCP Port 2512 or 2513 User-supplied -> Memory Allocation Undersized Allocation Overflow The Heap Buffer Citrix ImaSrv.exe TCP Port 2512 or 2513 User-supplied -> Memory Allocation Overflow The Heap Buffer
Reproducing 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
Reproducing 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.