Top Banner
UT HEAPS HEAPS ABO
66

UT HEAPS

Jan 27, 2016

Download

Documents

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 Freelists vs Lookaside - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: UT HEAPS

UT HEAPSHEAPS ABO

Page 2: UT HEAPS

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: Freelists vs Lookaside: Exploitation Techniques

Heap Exploit Walkthrough: From start to finish

This Talk Covers

Page 3: UT HEAPS

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

Windows Heap

Page 4: UT HEAPS

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

Heap Exploit Difficulties

Need To Get Creative In Exploitation Methods

Page 5: UT HEAPS

Initial Heap

Heap Management

Last Free Chunk Header

Last Free Chunk Space

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.

Page 6: UT HEAPS

Initial Heap

Heap Management

Last Free Chunk Header

Last Free Chunk Space

The Heap In Motion

Allocated A,B,C

Heap Management

Chunk A Header

Chunk A Space

Chunk B Header

Chunk B Space

Chunk C Header

Chunk C Space

Last Free Chunk Header

Last Free Chunk Space

After the allocation of three memory chunks, the heap layout now looks like this

Page 7: UT HEAPS

Initial Heap

Heap Management

Last Free Chunk Header

Last Free Chunk Space

The Heap In Motion

Allocated A,B,C

Heap Management

Chunk A Header

Chunk A Space

Chunk B Header

Chunk B Space

Chunk C Header

Chunk C Space

Last Free Chunk Header

Last Free Chunk Space

Free B

Heap Management

Chunk A Header

Chunk A Space

Free Chunk Header

Free Chunk Space

Chunk C Header

Chunk C Space

Last Free Chunk Header

Last Free Chunk Space

Freeing a chunk in

between two busy chunks,

creates a Free Chunk

Page 8: UT HEAPS

Initial Heap

Heap Management

Last Free Chunk Header

Last Free Chunk Space

The Heap In Motion

Allocated A,B,C

Heap Management

Chunk A Header

Chunk A Space

Chunk B Header

Chunk B Space

Chunk C Header

Chunk C Space

Last Free Chunk Header

Last Free Chunk Space

Free B

Heap Management

Chunk A Header

Chunk A Space

Free Chunk Header

Free Chunk Space

Chunk C Header

Chunk C Space

Last Free Chunk Header

Last Free Chunk Space

Free A

Heap Management

Free Chunk Header

Free Chunk Space

Chunk C Header

Chunk C Space

Last Free Chunk Header

Last Free Chunk Space

Free chunks that sit next to each other are joined (Coalesced) together.

Page 9: UT HEAPS

Heap Management StructureHeap Management

Address Value Description

00360000 Base Address

0036000C 00000002 Flags

00360010 00000000 ForceFlags

00360014 0000FE00 VirtualMemoryThreshold

00360050 00360050 VirtualAllocatedBlocks List

00360158 00000000 FreeList Bitmap

00360178 00361E90 FreeList[0]

00360180 00360180 FreeList[n]

00360578 00360608 HeapLockSection

0036057C 00000000 Commit Routine Ptr

00360580 00360688 FrontEndHeap

00360586 00000001 FrontEndHeapType

00360678 00361E88 Last Free Chunk

00360688 00000000 Lookaside[n]

All offsets are from the base of the Heap ObjectThese 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

MemoryA 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 bytesStart of double linked lists

to store Free ChunksPointer 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

Page 10: UT HEAPS

Heap Management Structure - Virtual Memory AllocationHeap Management

Address Value Description

00360014 0000FE00 VirtualMemoryThreshold

00360050 00360050 VirtualAllocatedBlocks List

00360050 FLINK

00360054 BLINK7C82AE14 CMP EDI,DWORD PTR DS:[EBX+14]7C82AE17 JBE ntdll.7C82A2FC...7C82AE8E LEA EAX,DWORD PTR DS:[EBX+50]...7C82AE97 MOV EDX,DWORD PTR DS:[EAX+4]...7C82AEA0 MOV DWORD PTR DS:[ECX],EAX7C82AEA2 MOV DWORD PTR DS:[ECX+4],EDX7C82AEA5 MOV DWORD PTR DS:[EDX],ECX7C82AEA7 MOV DWORD PTR DS:[EAX+4],ECX

EBX is set to Base AddressCheck threshold

Load BLINK

Write @NewChunk to @BLINK+4

ECX is @NewChunk

If the VirtualAllocatedBlocks->BLINK can be overwritten then the address of the NewChunk can be written to an arbitrary location

Page 11: UT HEAPS

Heap Management Structure - FreeList BitmapHeap Management

Address Value Description

00360158 00000000 FreeList Bitmap

7C82A291 LEA ESI,DWORD PTR DS:[EBX+EDX*4+158]...7C82A2A8 AND EAX,DWORD PTR DS:[ESI]...7C82A2B8 JNZ ntdll.7C82CB467C82A2BE TEST EAX,EAX7C82A2C0 JNZ ntdll.7C82C8C97C82A2C6 MOV EAX,DWORD PTR DS:[ESI]

Bitmap is checked when looking for a FreeList[n]

that fits the request

Bitmap is populated when chunk added to FreeList[n]

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]

80 00 00 02 00 00 80 00 00 00 00 00 00 00 00 00

0-7 24-31 48-55

Page 12: UT HEAPS

Heap Management Structure - FreeList BitmapHeap Management

Address Value Description

00360158 00000000 FreeList Bitmap

If the Bitmap can be manipulated then a pointer to an empty FreeList[n] can be returned, allowing the overwrite of management structures. [nico]

80 00 00 02 00 00 80 00 00 00 00 00 00 00 00 00

FreeList[7] is populated

FreeList[16] is empty

FreeLists

Address Value Description

003601B0 00364D78 FreeList[7]

... ... ...

003601F8 003601F8 FreeList[16]Request for block 16 will create a new block and

return it

Modify bitmap

Request for block 16 will return 003601F8

80 00 01 02 00 00 80 00 00 00 00 00 00 00 00 00

FreeLists

Address Value Description

003601B0 00364D78 FreeList[7]

... ... ...

003601F8 XXXXXXXX Overwrite

XXXXXXXX Overwrite

XXXXXXXX Overwrite

XXXXXXXX Overwrite

XXXXXXXX Overwrite

Page 13: UT HEAPS

Heap Management Structure - FreeList Bitmap

If the Bitmap can be manipulated then a pointer to an empty FreeList[n] can be returned, allowing the overwrite of management structures. [nico]

Part Of The Bitmap Loading Code

7C82C8AB MOVZX EAX,AH7C82C8AE MOVSX EAX,BYTE PTR DS:[EAX+7C82BAB8]7C82C8B5 ADD EAX,87C82C8B8 JMP ntdll.7C82C8307C82C8BD MOVSX EAX,BYTE PTR DS:[ECX+7C82BAB8]7C82C8C4 JMP ntdll.7C82C8307C82C8C9 LEA EDX,DWORD PTR DS:[EBX+178]7C82C8CF JMP ntdll.7C82C8087C82C8D4 SHR EAX,187C82C8D7 MOVSX EAX,BYTE PTR DS:[EAX+7C82BAB8]7C82C8DE ADD EAX,187C82C8E1 JMP ntdll.7C82C830

[ 7C82BAB8 ]A Static Pointer To A Bit Mask Table That Can Be Modified To Manipulate

The Bitmap Result

Page 14: UT HEAPS

Heap Management Structure – FreeList[n]Heap Management

Address Value Description

00360178 00361e90 FreeList[0]

00360180 00360180 FreeList[n]

FreeList[0] is similar to FreeList[n] but holds chunks > 1016 bytes

00360180 FLINK

00360184 BLINK

Free Chunk Header

Header Self Size Prev Size CK FL UN SI

Links FLINK BLINK

Free Chunk Header

Header Self Size Prev Size CK FL UN SI

Links FLINK BLINK

Double Linked List connects free

chunks together

Page 15: UT HEAPS

Heap Management Structure - Commit Routine PointerHeap Management

Address Value Description

0036057C 00000000 Commit Routine Ptr

7C833BF9 MOV ECX,DWORD PTR DS:[EAX+57C]7C833BFF TEST ECX,ECX7C833C01 JNZ ntdll.7C852C9E...7C852C9E PUSH EBX7C852C9F LEA EDX,DWORD PTR SS:[EBP+14]7C852CA2 PUSH EDX7C852CA3 PUSH EAX7C852CA4 CALL ECX

Initially set to nothing

Custom function() called when committing more

memory to the Heap

This is a static pointer that can be overwritten to gain execution control

Loaded into ECX and called

Page 16: UT HEAPS

Heap Management Structure – Lookaside[n]Heap Management

Address Value Description

00360688 00000000 Lookaside[n]

003606E8 Lookaside[2]

Lookaside[0] and Lookaside[1] are not used

48 byte structureLookaside List Header

Address Description

+00 Pointer To First Chunk

+04 Depth

+06 Max Depth

+08Allocation tracking for automatic Lookaside

Fine Tuning

+0C

+10

...

Lookaside Chunk Header

Header Self Size Prev Size CK FL UN SI

Links FLINK

Lookaside Chunk Header

Header Self Size Prev Size CK FL UN SI

Links FLINK

Page 17: UT HEAPS

Heap Chunks

Chunk On Lookaside

Header Self Size Prev Size CK FL UN SI

Links FLINK

Data

A Used Chunk

Header Self Size Prev Size CK FL UN SI

Data

Chunk On FreeList

Header Self Size Prev Size CK FL UN SI

Links FLINK BLINK

Data

Chunk Flags

00 Free

01 Busy

02 Extra Present

04 Fill Pattern

08 Virtual Alloc

10 Last Entry

20 FFU1

40 FFU2

80 No Coalesce

Page 18: UT HEAPS

Lookaside Lists

Lookaside[n]

FLINK 00000000

Lookaside Starts Empty

Address FLINK

003620D0 00000000

Lookaside[n]

FLINK 003620D0

Chunk Added To Top Of Lookaside

Address FLINK

003620E8 003620D0

Lookaside[n]

FLINK 003620E8

Chunk Added To Top Of Lookaside

Address FLINK

003620D0 00000000

Address FLINK

00362100 003620E8

Lookaside[n]

FLINK 00362100

Chunk Added To Top Of Lookaside

Address FLINK

003620E8 003620D0

Address FLINK

003620D0 00000000

About To Allocate From The Lookaside[n]

This Value Gets Copied

Address FLINK

00362100 003620E8

Lookaside[n]

FLINK 00362100

Address FLINK

003620E8 003620D0

Address FLINK

003620D0 00000000

Chunk Removed From Top Of Lookaside

Lookaside[n]

FLINK 003620E8

Address FLINK

003620E8 003620D0

Address FLINK

003620D0 00000000

Copied To Here

There is no Safe Unlinking or Cookie check for Lookaside ListsWell 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.

Overwrite the FLINK of the top chunk

Lookaside[n]

FLINK 003620E8

Address FLINK

003620E8 XXXXXXXX

Address FLINK

003620D0 00000000

Lookaside[n]->FLINK is corrupted

Lookaside[n]

FLINK XXXXXXXX

Page 19: UT HEAPS

Freelist[n] Lists

Lookaside[n]

FLINK 00000000

Freelist Starts Empty

Lookaside[n]

FLINK 003620D0

Lookaside[n]

FLINK 003620E8

Lookaside[n]

FLINK 00362100

Lookaside[n]

FLINK 00362100

Lookaside[n]

FLINK 003620E8

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

Lookaside[n]

FLINK 003620E8

Freelist[n]

Address FLINK BLINK

00360190 00360190 00360190

Address FLINK BLINK

00362130 00360190 00360190

Chunk Added To Bottom

Freelist[n]

Address FLINK BLINK

00360190 00362130 00362130

Address FLINK BLINK

00362160 00360190 00362130

Chunk Added To Bottom

Freelist[n]

Address FLINK BLINK

00360190 00362130 00362160

Address FLINK BLINK

00362130 00362160 00360190Chunk Removed

From Bottom

Freelist[n]

Address FLINK BLINK

00360190 00362130 00362130

Address FLINK BLINK

00362130 00360190 00360190

Freelist Is Empty

Page 20: UT HEAPS

Freelist[n] Lists

Freelist Searching: If a freelist[n] of requested size not availablebitmap 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

Header Self Size Prev Size CK FL UN SI

Page 21: UT HEAPS

Flipping Bitmap On Allocate

Size Is OverwrittenFLINK / BLINK Can Be

Overwritten

7C82C8E6 MOVZX ECX,WORD PTR DS:[ESI] ; Load Self Size7C82C8E9 MOV EDX,ECX..7C82C902 8DBC1A 58010000 LEA EDI,DWORD PTR DS:[EDX+EBX+158]

Calculate Bitmap

Bitmap Attack Explained Earlier

Chunk On FreeList

Header #### Prev Size CK FL UN SI

Links FLINK BLINK

Data

If Last Chunk On Freelist Then Bitmap Updated

If FLINK and BLINK Overwritten with Valid For Read and

FLINK == BLINKThen Bitmap Updated

Page 22: UT HEAPS

Free To Arbitrary Lookaside[n]/FreeList[n]

Size Is OverwrittenCookie Is Left Intact

Chunk To Be Freed

Header #### Prev Size CK FL UN SI

Data

7C829F1B MOVZX EAX,WORD PTR DS:[ESI] ; Load self size7C829F1E MOV DWORD PTR SS:[EBP-20],EAX7C829F21 CMP EAX,807C829F26 JNB ntdll.7C82A7BC7C829F2C PUSH DWORD PTR SS:[EBP+10]7C829F2F LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; Calculate Lookaside7C829F32 SHL EAX,47C829F35 ADD EAX,ECX7C829F37 PUSH EAX7C829F38 CALL ntdll.7C829F8F ; Push to Lookaside

Freeing To Lookaside[n]

Could This Be Useful When Filling In Gaps?

7C82A84C MOVZX EAX,WORD PTR SS:[EBP-20] ; Load selfsize7C82A850 LEA EBX,DWORD PTR DS:[EDI+EAX*8+178] ; Calculate 7C82A857 MOV DWORD PTR SS:[EBP-88],EBX7C82A85D CMP DWORD PTR DS:[EBX],EBX ; Check FreelistFreeing To

Freelist[n]

Coalescing Is A Problem That Needs To Be Dealt With

Page 23: UT HEAPS

FreeList[0] - Free

Address FLINK BLINK

00361E90 003622D0 00360178

Freelist[0]

Address FLINK BLINK

00360178 00361E90 00362B60

Address FLINK BLINK

003622D0 00362B60 00361E90

Address FLINK BLINK

00362B60 00360178 003622D0

Populated Freelist[0]

Load Freelist[0]->FLINK

Check Size Is Larger Than Chunk Been Free’dNot Greater, Load

Chunk->FLINK

Check Size Is Great Than Chunk Been Free’dIf It Is Greater Then

Insert Chunk

Exploitable Condition On Freelist[0] Insert

Page 24: UT HEAPS

Exploiting FreeList[0] - Free

Exploitable Condition On Freelist[0] Insert

7C82A982 CMP DX,WORD PTR DS:[EAX] ; Compare chunk size7C82A985 JA ntdll.7C82FDC4 ; To large move to next

7C82A98B LEA EAX,DWORD PTR DS:[ESI+8] ; Header of free’d chunk7C82A98E MOV DWORD PTR SS:[EBP-7C],EAX7C82A991 MOV EDX,DWORD PTR DS:[ECX+4] ; Load BLINK of current chunk7C82A994 MOV DWORD PTR SS:[EBP-84],EDX7C82A99A MOV DWORD PTR DS:[EAX],ECX ; Set free’d->FLINK == current7C82A99C MOV DWORD PTR DS:[EAX+4],EDX ; Set free’d->BLINK ==current->BLINK7C82A99F MOV DWORD PTR DS:[EDX],EAX ; Write @free’d to [current->BLINK]7C82A9A1 MOV DWORD PTR DS:[ECX+4],EAX ; Set current->BLINK == @free’d

An Overwritten Chunk In Freelist[0] Can Be Exploited To Write The Address Of The Chunk Being Freed To An Arbitrary Location

Page 25: UT HEAPS

Exploiting FreeList[0] - Free

Exploitable Condition On Freelist[0] Insert

Chunk To Be Freed @003622D0

8400 Prev Size CK FL UN SIOverwritten Chunk @00361E90

FFFF ???? ?? 02 ?? ??

FFFFFFFF 00360718

Place Where We Want To Write 003622D0Could Be A Function Table, This Is A Lookaside

Chunk To Be Freed @003622D0

8400 Prev Size CK FL UN SI

00361E90 00360718 Overwritten Chunk @00361E90

FFFF ???? ?? 02 ?? ??

FFFFFFFF 003622D0

Overwritten Lookaside Now PopulatedThree Requests And We Get Our Set Location

Chunk Is Inserted Before The Overwritting Chunk.

FLINK and BLINK updated

Page 26: UT HEAPS

FreeList[0] - Allocate

Address FLINK BLINK

00361E90 003622D0 00360178

Freelist[0]

Address FLINK BLINK

00360178 00361E90 00362B60

Address FLINK BLINK

003622D0 00362B60 00361E90

Address FLINK BLINK

00362B60 00360178 003622D0

Populated Freelist[0]

Load Freelist[0]->BLINK

Check Size Is Large Enough For Request

Load Freelist[0]->FLINK

Check Size Is Large Enough For RequestToo Small, Load Chunk->FLINK

Check Size Is Large Enough For RequestLarge Enough,

Return Chunk

Exploitable Condition On Freelist[0] Allocate

Page 27: UT HEAPS

Exploiting FreeList[0] - Searching

Exploitable Condition On Freelist[0] Allocate - Searching

Overwritten Chunk @003622C8

0100 ???? ?? ?? ?? ??

00360188 ????????

Fake Chunk @00360180

8001 3600 80 01 36 00

00360188 00360188

Must Be ReadableMust Be Readable= Requested Size

(+1 block)

Request Made For Size0x0BF8

FLINK Points To Fake Chunk

FLINK Points To Fake Chunk+8

Chunk Returned To CallerThis Address Is In The

Freelists

Page 28: UT HEAPS

Allocation Relinking

If Chunk Is Larger Than Request It Will Get Split

Chunk Header

Chunk Space

Chunk Header

Chunk Space

New Chunk Header

New Chunk Space

New Header Is Written Into The Existing Chunk

Space

Chunk Header

Chunk Space

New Chunk Header

New Chunk SpaceChunk Returned To

Caller

Chunk Inserted Into FreeLists

Page 29: UT HEAPS

Exploiting FreeList[0] - Relinking

Exploitable Condition On Freelist[0] Allocate - Relinking

Overwritten Chunk @003622C8

0202 ???? ?? ?? ?? ??

0036057C READ

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.....

Request Made For SizeSmaller Than Our Overwrite

Fake Chunk @00360574

7005 3600 08 06 36 00

???????? 00360688

Must Be Read/Write> Relink Chunk Size

FLINK Points To Fake Chunk

FLINK Points To Fake Chunk+8Relink Chunk Address

Written To 00360580

This Is The FrontEndHeap(Lookaside Base)

Page 30: UT HEAPS

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

Splitting / Resizing

7C82A3DB CMP EBX,1 ; Larger than one block difference7C82A3DE JE ntdll.7C82E5A47C82A3E4 MOV EAX,DWORD PTR SS:[EBP-48] ; Load requested size7C82A3E7 LEA EDI,DWORD PTR DS:[ESI+EAX*8] ; Move to create the new chunk..7C82A3F3 MOV BYTE PTR DS:[EDI+5],CL ; Store new flag7C82A3F6 MOV WORD PTR DS:[EDI+2],AX ; Store Prev Size..7C82A400 MOV WORD PTR DS:[EDI],BX ; Store new size7C82A403 TEST CL,10 ; Is chunk new LAST CHUNK7C82A406 JNZ ntdll.7C82A65E ; Jump if chunk is last chunk7C82A40C LEA EAX,DWORD PTR DS:[EDI+EBX*8] ; Move to NEXT chunk based on size7C82A40F MOV DWORD PTR SS:[EBP-50],EAX ; Will try and coalesce with next

Can Skip By Setting As Last Chunk

Page 31: UT HEAPS

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

Coalesced Chunks

7C82A6F6 JE SHORT ntdll.7C82A702 ; If prev size is 0 jump7C82A6F8 TEST BYTE PTR DS:[ESI+5],1 ; Is prev chunk BUSY?7C82A6FC JE ntdll.7C82CA7A ; If not then coalesce7C82A702 TEST BYTE PTR DS:[EDI+5],10 ; Is our chunk the last chunk?7C82A706 JNZ ntdll.7C82A7B3 ; If so can't coalesce7C82A70C MOV EAX,DWORD PTR SS:[EBP+10]7C82A70F MOV EAX,DWORD PTR DS:[EAX] ; Load our block size7C82A711 LEA ESI,DWORD PTR DS:[EDI+EAX*8] ; Move to next chunk7C82A714 TEST BYTE PTR DS:[ESI+5],1 ; Is next chunk BUSY?7C82A718 JNZ ntdll.7C82A7B3 ; Yup, so don't colaesce

Test Flag Of Previous

Chunk

Test Flag Of Next Chunk

Header Self Size Prev Size CK FL UN SI

Page 32: UT HEAPS

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

Preventing Coalesce

Page 33: UT HEAPS

Coalesced Chunks

???? ???? ?? ?? ?? ??

DATA

FFFF FFFF FF FF FF FF

DATA

Chunk AData Stored In

Chunk BWe Overflowing

BUSYChunk

BUSYChunk

Chunk A Will Be Free’d And We Want To

Prevent Coalescing

FFFF FFFF FF 01 FF FF

DATA

Keep The Flag Set To BUSY

Page 34: UT HEAPS

Coalesced Chunks

???? ???? ?? ?? ?? ??

DATA

FFFF FFFF FF FF FF FF

DATA

Chunk AData Stored In

Chunk BWe Overflowing

BUSYChunk

BUSYChunk

Chunk B Will Be Free’d And We Want To

Prevent Coalescing

FFFF FFFF FF 01 FF FF

DATA

0200 0200 FF FF FF FF

DATA

FFFF FFFF FF 01 FF FF

DATA

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

Page 35: UT HEAPS

Coalesced Chunks

???? ???? ?? ?? ?? ??

DATA

FFFF FFFF FF FF FF FF

DATA

Chunk AData Stored In

Chunk BWe Overflowing

BUSYChunk

BUSYChunk

Chunk B Will Be Free’d And We Want To

Prevent Coalescing

FFFF 0000 FF 10 FF FF

DATA

Set The Flag To Contain The Last

Chunk Flag

Page 36: UT HEAPS

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

Preventing A Free

Move To Chunk Header

Load Flag and Test If Busy

Page 37: UT HEAPS

Example Removing Chunk From Lookaside

Before Allocation

After Free()

Overwrite Flag

Self Size Prev Size CK FL UN SI

0300 0300 06 01 0E 00

Self Size Prev Size CK FL UN SI

0101 0101 01 02 01 01

After Allocation

Page 38: UT HEAPS

Top Chunk On A Lookaside Is Overwritten: Flags set to not BUSY, Flink set to 0x00000000

Clearing The Lookaside

Before Allocation

After Overwrite

Allocation And Free Will Clear The Lookaside List

Overwrite Flag And FLINK

Self Size Prev Size CK FL UN SI

0300 0300 06 01 0E 00

00362100

Self Size Prev Size CK FL UN SI

0101 0101 01 02 01 01

00000000

Page 39: UT HEAPS

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?

The Exploitation Process

Page 40: UT HEAPS

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

Heap / Stack Flipping

PUSH EBXPOP ESPPOP EBPRET

EBX -> DATA

LEAVERET

EBP -> DATA ECX -> DATA

MOV ESP,ECXRET 8

EAX-> DATA

XCHG EAX,ESPRET

Page 41: UT HEAPS

Heap / Stack Flipping

Flipping Code

Stack

Exploit Data

Registers

Code Gets Executed

Page 42: UT HEAPS

Heap / Stack Flipping

New Stack

Exploit Data

New RegistersCode That We Returned Into

Page 43: UT HEAPS

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

Bypassing DEP

Page 44: UT HEAPS

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

Page 45: UT HEAPS

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

Bypassing DEP

NtSetInformationProcess(NtCurrentProcess(), // (HANDLE)-1ProcessExecuteFlags, // 0x22&ExecuteFlags, // ptr to 0x2sizeof(ExecuteFlags)); // 0x4

Page 46: UT HEAPS

Bypassing DEP

Perfect Instruction Set

NtSetInformationProcess(NtCurrentProcess(), // (HANDLE)-1ProcessExecuteFlags, // 0x22&ExecuteFlags, // ptr to 0x2sizeof(ExecuteFlags)); // 0x4

Requires [ESI+37] To Be Writable

Correctly Set Stack

BUT!

Page 47: UT HEAPS

Step By Step: The vulnerability: Reproduction: Understanding the bug: Finding an overwrite: Find a pointer: Flipping the heap to stack: Bypassing DEP: The working

Heap Exploitation

Page 48: UT HEAPS

The Vulnerability

CitrixImaSrv.exe

TCP Port 2512 or 2513User-supplied -> Memory Allocation

Undersized AllocationOverflow The Heap Buffer

Citrix

TCP Port 2512 or 2513 User-supplied -> Memory AllocationImaSrv.exe

Overflow The Heap Buffer

Page 49: UT HEAPS

Usual Integer Overflow: Usual ‘packet size bug’

Usual Basic Fuzz Testwhile !crashed{

inc buffer lengthfill buffer with 0xFFsend to TCP 2512

}

Reproducing The Vulnerability

Length Of Data DATA

I Am Listening On TCP 2512

\xFF\xFF\xFF\xFF \xFF\xFF\xFF\xFF\xFF\xFF

Page 50: UT HEAPS

Reproducing The Vulnerability

A CrashA Crashntdll! RtlAllocateHeap

In the good ‘ol days, it would now be as easy as overwriting the UEF. But those days are over.

Page 51: UT HEAPS

Need To Trace From Start To Finish: bp WSARecv and send overflow again

Understanding The Bug

WSARecv

Stack

Buffer Size Buffer Address

Page 52: UT HEAPS

Need To Trace From Start To Finish: After WSARecv our buffer is loaded

Understanding The Bug

Page 53: UT HEAPS

Trace Through Code To Determine Paths: This code checks buffer sizes

Understanding The Bug

Load First DWORD Of Packet Into EAX

Compare Against Size Of Current Buffer

0x408Jump If Our Packet

Specified A Size Larger Than 0x408

Page 54: UT HEAPS

Trace Through Code To Determine Paths: Eventually get to here

Understanding The Bug

ESI == First DWORD From Packet

EAX == ESI + 3CIs Going To

Allocate A Buffer Of Size EAX

EAX == ESI + 3C

Page 55: UT HEAPS

But its not over yet: Trace down to ntdll!RTLAllocateHeap

Understanding The Bug

Allocate From Heap 00320000

Allocate 3B Bytes

Page 56: UT HEAPS

Still Thats Just An Undersized Buffer: Keep tracing the code

Understanding The Bug

Bunch Of Stuff Is Written Into The New Buffer

This Is A Custom Header And Is 0x3C Bytes Long

EAX Points To The Newly Allocated Buffer

Page 57: UT HEAPS

Finally....: A memmove instruction overflows the buffer

Understanding The Bug

New Buffer+3C

Packet Data

This Is The Size Of The Packet That We Sent

KABOOM!

Page 58: UT HEAPS

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

Understanding The Bug

Page 59: UT HEAPS

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

The Request LifeCycle

WSARecv()

RTLFreeHeap()

RTLAllocateHeap()

memmove()

Page 60: UT HEAPS

The Lookaside Lists

Lookaside[8] Has A Top Chunk That Sits After Lookaside[7] Top Chunk On All Runs

ANDThe Difference Is Greater Than 0x3C

0x0a871cc8 – 0x0a871c60= 0x680x0a871c38 – 0x0a871bd0

= 0x68

0x0a871d00 – 0x0a871c98= 0x68

Page 61: UT HEAPS

First Request : Request Lookaside[7]: Overwrite Lookaside[8]: Free Request

Problem: If we now had two allocations of Lookaside[8]: But we only have one

Solution: Set flag of top chunk of Lookaside[8] to be FREE: Then when free() is called it will be skipped

Lets Try It

Page 62: UT HEAPS

First Request : Request Lookaside[7]: Overwrite Lookaside[8]: Free Request

Second Request: Request Lookaside[8]: Top Chunk Is Popped: Free Request

Third Request: Request Lookaside[8], Our Address Is Returned

Lets Try It

Page 63: UT HEAPS

Function Pointer: Trace code looking for pointer: None found before WSARecv()

What Address To Overwrite

Lucky For Us That Winsock Uses Static Pointers

0x71C14044 Is A Static Pointer That Can Be Overwritten

EAX Points To Stack

Page 64: UT HEAPS

Winsock: Holds a structure

: Structure holds pointer to function pointer table on the default heap

Winsock Structure

Static Pointer To Handle

Load Address Of Pointer Table

‘Static Within Heap’

Call Function

Page 65: UT HEAPS

Pointer Table Address: 0x142360Set Lookaside Address: Need to account for header: Set lookaside to 0x01431D0Overwrite The Pointer Table: We now control executionSet The Stack: EAX points to the pointer table: EAX points to our data: Search for a heap/stack flipReturn Down The Stack: Return to Anti-DEP: Return to shellcode on pointer table

Exploiting The Bug

Heap/Stack Flip Local To Citrix DLLS

Page 66: UT HEAPS

Da GreetzAcknowledgement to those who shared

current information, some of which was used in this presentation

Nico Caddis

mxatone

Acknowledgement to those who have published past heap research

0dedShok

SotirovSandip Chaudhari

A. AnisimovN. Falliere

HalvarLitchfield

+ All Others