Professional Documents
Culture Documents
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
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
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()
Need To
Get Creative
In Exploitation
Methods
: Windows
Vista
and Windows
Server
2008
A Heap In Motion
Initial Heap
Heap
Management
Last Free
Chunk Header
Last Free
Chunk Space
Initial Heap
Heap
Management
Last Free
Chunk Header
Last Free
Chunk Space
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
Initial Heap
Heap
Management
Last Free
Chunk Header
Last Free
Chunk Space
Allocated
A,B,C
Heap
Management
Free B
Heap
Management
Chunk A Header
Chunk A
Header
Chunk A Space
Chunk A Space
Free Chunk
Header
Chunk B
Header
Free Chunk
Space
Chunk B Space
Chunk C Header
Chunk C
Header
Chunk C Space
Chunk C Space
Last Free
Freeing a
chunk in
between
two busy
chunks,
creates a
Free Chunk
Initial Heap
Heap
Management
Last Free
Chunk Header
Last Free
Chunk Space
Allocated
A,B,C
Heap
Management
Free B
Free A
Heap
Management
Heap
Management
Chunk A Header
Free Chunk
Header
Chunk A
Header
Chunk A Space
Chunk A Space
Free Chunk
Header
Chunk B
Free Chunk
Header Free chunks
that sit
Space
Chunk B Space
next to each other are
joinedChunk
(Coalesced)
C Header
together.
Chunk C
Chunk C Space
Header
Chunk C Space
Last Free
Free Chunk
Space
Chunk C
Header
Chunk C Space
Last Free
Chunk Header
Last Free
Chunk Space
These
Flags
All
offsets
arehold
from
as
thesettings
base ofsuch
the Heap
The
maximum
size
isDebug,
Exceptionof
Object
an allocation
before a
Raising, and
Virtual
Memory
A four
Linked
listDWORD
of Heap
blocks
Executable
allocation
is bit
bitmask
with
allocated
fromeach
Virtual
Pointer
to
the first
performed
set
if the
Memory
chunk
in FreeList[0]
corresponding
FreeList[0]
is used
Start
of double
linked
FreeList[n]
is to
Pointer
toFree>
store
Free
Chunks
lists
to
store
populated
Pointer to Function()
CriticalSection
that is
1016
bytes
Chunks
thatto
is lock
called
when
used
the
heap
Pointer
to
the
front
theduring
heap ischanges
expanded
endmore
allocator.
and
pages
Pointer
Flag
to the
stores
Last
This
iscommitted
a that
pointer
the
Start
of
the 48 to
byte
settings
FreeLookaside
Chunk
about
in the
the
Lookaside
list headers
front end
heap
allocator
003600
00
Value
Description
Base Address
003600
0C
0000000 Flags
2
003600
10
0000000 ForceFlags
0
003600
14
0000FE0 VirtualMemoryThresh
0
old
003600
50
0036005 VirtualAllocatedBlock
0
s List
003601
58
003601
78
00361E9 FreeList[0]
0
003601
80
0036018 FreeList[n]
0
003605
78
0036060 HeapLockSection
8
Address
Value
Description
003600
14
0000FE0 VirtualMemoryThresh
0
old
003600
50
0036005 VirtualAllocatedBlock
FLINK
0
s0036005
List
0
Bitmap is populated
when chunk added to
FreeList[n]
8
0
0
0
0-7
0
0
0
2
2431
0
0
0
0
8
0
4855
003601
58
0
0
0
0
0
0
Value
Description
0
0
0
0
0
0
0
0
00
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]
FreeList[7] is
populated
8
0
0
0
0
0
1
0
2
0
0
003601
58
0
0
8
0
FreeList[16] is
Modify bitmap
empty
0
0
0
0
0
0
Value
0
0
0
0
0
0
0
0
00
FreeLists
Address
003601
B0
Description
...
003601
F8
Value
Description
00364D FreeList[7]
78
...
...
XXXXXX
003601 Overwrite
FreeList[16]
XX
F8
XXXXXX Overwrite
XX
FreeList[0] is similar
to FreeList[n] but
holds chunks > 1016
bytes
Address
Value
003601
78
00361e9 FreeList[0]
0
003601
80
0036018 FreeList[n]
0036018
0
0
0036018
4
Self
Size
Prev
Size
CK
FLINK
FL
U
N
Links
Self
Size
Prev
Size
FLINK
FLINK
BLINK
SI
BLINK
Description
CK
FL
U
N
BLINK
SI
Double Linked
List connects
free chunks
together
Custom function()
called when
committing more
memory to the Heap
Address
003605
7C
Value
Description
Lookaside[0] and
Lookaside[1] are not
used
Lookaside List Header
Addres
s
+04
Depth
+06
Max Depth
+08
...
Description
0000000 Lookaside[n]
0
003606
48 byte
E8
Lookaside[2]
structure
Lookaside Chunk Header
Pointer To First
Chunk
+10
003606
88
Value
Description
+00
+0C
Address
Allocation
tracking for
automatic
Lookaside Fine
Tuning
Header
Links
Self
Size
Prev
Size
CK
FL UN
SI
FLINK
Lookaside Chunk Header
Header
Links
Self
Size
Prev
Size
FLINK
CK
FL UN
SI
Heap Chunks
A Used Chunk
Header
Self
Size
Prev
Size
CK
Chunk Flags
FL UN
SI
Data
Chunk On Lookaside
Header
Links
Self
Size
Prev
Size
CK
FL UN
SI
FLINK
Data
Chunk On FreeList
Header
Links
Data
Self
Size
Prev
Size
FLINK
CK
FL UN
BLINK
SI
00
Free
01
Busy
02
Extra Present
04
Fill Pattern
08
Virtual Alloc
10
Last Entry
20
FFU1
40
FFU2
80
No Coalesce
Lookaside Lists
Lookaside
Starts Empty
Chunk
Lookaside[n]Chunk
Removed
Added
From
>FLINK
To Top
Topis
Of
Of
Lookaside
corrupted
Lookaside
About To Allocate
Overwrite the FLINK of
From The
the top chunk
Lookaside[n]
Lookaside[n]
FLINK
0000000
0036210
003620E
XXXXXX
003620
D0
XX
0
8
Address
FLINK
003621 003620E
003620
0000000
XXXXXX
003620
D0
00
E8
D0
XX
0
8
Address
FLINK
This
Copied
Value
To
GetsHere
Copied
003620 0000000
003620
D0
E8
D0
0
Address
FLINK
003620
D0
0000000
0
Freelist[n] Lists
Freelist
Freelist
Starts
Is
Empty
Chunk Added
To Bottom
Chunk
Chunk Added
Removed
To Bottom
From Bottom
Freelist[n]
Lookaside[n]
Address
FLINK
BLINK
FLINK
0000000
0036210
003620E
003620
D0
0
8
003601 003621
003601
003601
003621
90
90
30
90
60
30
Address
FLINK
BLINK
003621
30
Address
003601
003621
60
90
FLINK
003601
90
BLINK
003621
60
003601
90
003621
30
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
Header
Self
Prev
CK FL UN SI
: Free can have chunk
freed
to
different
Size
Size
lookaside/freelist
Chunk On FreeList
Header
####
Links
Prev
Size
FLINK
CK
FL UN
SI
BLINK
Data
7C82C8E6 MOVZX ECX,WORD PTR DS:[ESI]
; Load
Self Size
7C82C8E9 MOV EDX,ECX
..
7C82C902 8DBC1A 58010000 LEA EDI,DWORD PTR DS:
If Last Chunk[EDX+EBX+158]
On Freelist Then Bitmap
Updated
Calculate
Bitmap
Size Is Overwritten
Cookie Is Left Intact
Header
####
Prev
Size
CK
FL UN
SI
Data
Freeing To
Freeing To
Lookaside[n
Freelist[n]
]
7C82A84C MOVZX
7C829F1B
MOVZX EAX,WORD
EAX,WORD PTR
PTR DS:[ESI]
SS:[EBP-20] ; Load
self size
selfsize
7C829F1E MOV
7C82A850
LEA EBX,DWORD
DWORD PTR PTR
SS:[EBP-20],EAX
DS:[EDI+EAX*8+178] ;
7C829F217C82A857
Calculate
CMP EAX,80
MOV DWORD PTR SS:[EBP-88],EBX
7C829F26 JNB
7C82A85D
CMPntdll.7C82A7BC
DWORD PTR DS:[EBX],EBX
; Check
7C829F2C PUSH DWORD PTR SS:[EBP+10]
Freelist
7C829F2F
LEA Is
EAX,DWORD
DS:[EAX+EAX*2]
Coalescing
A ProblemPTR
That
Needs To Be Dealt ;
Calculate Lookaside
With
7C829F32 SHL EAX,4
7C829F35 ADD EAX,ECX
7C829F37 PUSH EAX
7C829F38 CALL ntdll.7C829F8F
; Push to
Lookaside
FreeList[0] - Free
Freelist[0]
Populate
d
Freelist[
0]
Address
FLINK
BLINK
003601
78
Address
00361E
90
FLINK
00362B
60
BLINK
00361E
90
Address
003622
D0
FLINK
003601
78
BLINK
003622
D0
Address
00362B
60
FLINK
00361E
90
BLINK
00362B
60
003601
78
003622
D0
Load Freelist[0]>FLINK
Check Size Is Larger
Not
Load
ThanGreater,
Chunk Been
Chunk->FLINK
Freed
Check Size Is Great
Chunk Been
IfThan
It Is Greater
Then
Freed
Insert
Chunk
Prev
Prev
Size
Size
00361E90
CK
FL
FL UN
UN
SI
00360718
FFFF
????
??
FFFFFFFF
02
??
003622D0
00360718
??
FreeList[0] - Allocate
Freelist[0]
Populate
d
Freelist[
0]
Address
FLINK
BLINK
003601
78
Address
00361E
90
FLINK
00362B
60
BLINK
00361E
90
Address
003622
D0
FLINK
003601
78
BLINK
003622
D0
Address
00362B
60
FLINK
00361E
90
BLINK
00362B
60
003601
78
003622
D0
Load Freelist[0]>BLINK
>FLINK
Check Size Is Large
Too For
Small,
Enough
Request
Load Chunk->FLINK
Check Size Is Large
LargeFor
Enough,
Enough
Request
Return Chunk
Check Size Is Large
Enough For Request
Chunk Returned To
Caller
This Address Is In
The Freelists
Overwritten Chunk
@003622C8
0100
????
00360188
??
??
??
????????
FLINK Points To
Fake
FakeChunk+8
Chunk
Fake Chunk @00360180
8001
3600
00360188
= Requested Size
(+1 block)
??
80
01
36
00
00360188
Must Be Readable
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
Overwritten Chunk
@003622C8
0202
????
??
0036057C
??
??
??
READ
XXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXX
FLINK Points To
XXXXX.....
Fake
FakeChunk+8
Chunk
3600
????????
08
06
36
00360688
Must Be
Read/Write
00
Splitting / Resizing
Coalesced Chunks
Preventing Coalesce
Coalesced Chunks
????
????
??
??
??
??
Chunk A
Data Stored In
DATA
BUSY
Chunk
FFFF
BUSY
Chunk
Chunk A Will Be
Freed And We
Want To Prevent
Coalescing
FFFF
FF
DATA
01
FF
FF
FF
Chunk B
We
Overflowing
Coalesced Chunks
????
????
??
??
??
??
Chunk A
Data Stored In
DATA
BUSY
Chunk
FFFF
FFFF
FF
01
FF
FF
FF
FF
FF
01
FF
FF
DATA
0200
FFFF
BUSY
Chunk
0200
FFFF
FF
DATA
FFFF
Chunk B Will Be
Freed And We
Want To Prevent
Coalescing
FFFF
FF
DATA
Chunk B
We
Overflowing
Coalesced Chunks
????
????
??
??
??
??
Chunk A
Data Stored In
DATA
BUSY
Chunk
FFFF
BUSY
Chunk
Chunk B Will Be
Freed And We
Want To Prevent
Coalescing
0000
FFFF
FF
DATA
10
FF
FF
FF
Chunk B
We
Overflowing
Preventing A Free
Prev
Size
CK
FL UN
SI
Self
Size
Prev
Size
CK
FL UN
SI
0300
0300
06
01
00
0101
0101
01
02
01
After
Allocation
After Free()
0E
01
Prev
Size
CK
FL UN
SI
Self
Size
Prev
Size
CK
FL UN
SI
0300
0300
06
01
00
0101
0101
01
02
01
00362100
0E
00000000
After
Overwrite
Allocation And Free Will Clear The Lookaside List
01
The Steps
: Exploit the heap
: Overwrite a function pointer or other to gain
execution
: Flip the heap onto the stack to get ret-tolibc style control
: Turn off Data Execution Protection (DEP)
: Return to shellcode
Exploit The Heap
: Application dependant
Overwrite A Function Pointer
: Application dependant?
Exploit Data
Stack
Registers
Code Gets
Executed
Flipping Code
Exploit Data
New Registers
New Stack
Code That We Returned
Into
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, 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
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!
Requires [ESI+37] To Be
Writable
Correctly Set Stack
NtSetInformationProcess(
NtCurrentProcess(), //
(HANDLE)-1
ProcessExecuteFlags, //
0x22
&ExecuteFlags, // ptr to 0x2
sizeof(ExecuteFlags)); // 0x4
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
Citrix
ImaSrv.exe
TCP Port 2512 or 2513
User-supplied -> Memory
Allocation
Undersized Allocation
Overflow The Heap Buffer
ImaSrv.e
User-suppliedxe
-> Memory
Allocation
DATA
\
xFF\xFF\xFF\xFF\xFF\xF
F
I Am
Listening
On TCP
2512
Buffer Size
Buffer Address
Compare Against
Size Of Current
Buffer 0x408
DWORD From
Packet
EAX == ESI
+ 3C
Is Going To
Allocate A
Buffer Of Size
EAX
Allocate 3B Bytes
Bunch Of Stuff Is
Written Into The New
Buffer
This Is A Custom
Header And Is 0x3C
Bytes Long
Finally....
: A memmove instruction overflows the buffer
New
Buffer+3C
Packet Data
KABOOM!
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
RTLAllocateHea
p()
WSARecv()
memmove()
RTLFreeHeap()
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
0x0a871c38
0x0a871bd0
= 0x68
0x0a871cc8
0x0a871c60
= 0x68
0x0a871d00
0x0a871c98
= 0x68
Lets Try It
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
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
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
Winsock Structure
Winsock
: Holds a structure
Static
Pointer To
Handle
Call Function
Da Greetz
Acknowledgement to those who shared
current information, some of which was used
in this presentation
Nico
Caddis
mxatone
0ded
Shok
Sotirov
Sandip Chaudhari
A. Anisimov
N. Falliere
Halvar
Litchfield
+ All Others