SlideShare una empresa de Scribd logo
1 de 189
Descargar para leer sin conexión
Windows Heap Exploitation
Angelboy
Windows Heap Exploitation
• Windows Memory Allocator

• NT heap

• BackEnd

• Exploitation

• FrontEnd

• LowFragmentationHeap

• Exploitation
Windows memory allocator
• Win 10 的 memory allocator 非常複雜,基本上主要有下列列兩兩種

• Nt Heap

• Default memory allocator

• SegmentHeap

• Win10 中全新的 memory allocator 機制

• 部分系統程式及 UWP 會使⽤用
Windows memory allocator
• Nt Heap 中⼜又可分

• 後端管理理器 (Back-End)

• 前端管理理器 (Front-End)

• LowFragmentationHeap

• 基本上是為了了不讓記憶體過於破碎,相同⼤大⼩小的記憶體區塊分配到⼀一定數
量量後就會使⽤用 (連續分配相同記憶體區塊 18 次)

• Size <= 0x4000
Windows memory allocator
• ⽬目前會以 win 10 (1809) 為主

• OS build - 17763.379

• 之後版本可能不⼀一定完全正確

• 結構常常改動很⼤大,有個概念念後,到新的發⾏行行版本,需要⾃自⼰己去追⼀一下結
構
Windows memory allocator
• Overview
Kernel32.dll
HeapAlloc
HeapFree
msvcrt140.dll
malloc
free
ntdll.dll
RtlAllocateHeap
RtlFreeHeap
ntdll.dll
RtlpAllocateHeap
RtlpFreeHeap
ntdll.dll
RtlpLowFragHeapAlloc
RtlpLowFragHeapFree
Kernel
Front-End
Back-End
Windows memory allocator
• 在 LFH 沒啟⽤用下,我們呼叫 malloc
Kernel32.dll
HeapAlloc
HeapFree
msvcrt140.dll
malloc
free
ntdll.dll
RtlAllocateHeap
RtlFreeHeap
ntdll.dll
RtlpAllocateHeap
RtlpFreeHeap
Kernel
Back-End
Windows memory allocator
• 啟⽤用 LFH 後,第⼀一次或 LFH 能⽤用的⽤用完時

會先跟 Back-End 要⼀一⼤大塊空間來來管理理
Kernel32.dll
HeapAlloc
HeapFree
msvcrt140.dll
malloc
free
ntdll.dll
RtlAllocateHeap
RtlFreeHeap
ntdll.dll
RtlpAllocateHeap
RtlpFreeHeap
ntdll.dll
RtlpLowFragHeapAlloc
RtlpLowFragHeapFree
Kernel
Front-End
Back-End
Windows memory allocator
• 啟⽤用 LFH 之後分配相同⼤大⼩小時,會直接給

Front-End 管理理
Kernel32.dll
HeapAlloc
HeapFree
msvcrt140.dll
malloc
free
ntdll.dll
RtlAllocateHeap
RtlFreeHeap
ntdll.dll
RtlpLowFragHeapAlloc
RtlpLowFragHeapFree
Front-End
Windows memory allocator
• HEAP 可分為

• Process Heap

• Default heap

• 整個 process 共享,呼叫 api 時會⽤用到

• 會存在 _PEB 結構中

• CRT 中的函式時也會⽤用到

• 存在 crt_heap
Windows memory allocator
• HEAP 可分為

• Private heap

• 另外創建的 heap

• HeapCreate
Windows memory allocator
• Core data structure

• _HEAP_ENTRY (chunk)

• Malloc 出來來的基本結構

• 在前後端分配器中,長相會不太⼀一樣,但都是同⼀一個名字
Windows memory allocator
• _HEAP_ENTRY (chunk)
data
chunk header
chunk header
data
_HEAP
chunk header
.
.
.
malloc return value
Windows memory allocator
• Core data structure

• _HEAP

• 整個 memory allocator 中最核⼼心的結構,⽤用來來管理理該 heap

• 每個 Heap 都會有⼀一個 _HEAP 通常在 heap 開頭
Windows memory allocator
• _HEAP

• EncodeFlagMask

• Heap 初始化後會設置為
0x100000 在判斷是否要 encode
該 heap 中 chunk 的 header

• Encoding (_HEAP_ENTRY)

• ⽤用來來與 chunk header 做 xor 的
cookies
…
EncodeFlagMask0x7c
0x80
0x138
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
0x150
0x198
FrontEndHeapUsageData0x1a8
…
Windows memory allocator
• _HEAP

• BlocksIndex (_HEAP_LIST_LOOKUP_)

• Back-End 中,重要的結構之⼀一,⽤用
來來管理理 Back-End 中的 chunk ,後
⾯面會詳細敘述

• FreeList (_HEAP_ENTRY)

• 串串接 Back-End 中的所有 free chunk
,類似 unsorted bin

• Sorted list
…
EncodeFlagMask0x7c
0x80
0x138
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
0x150
0x198
FrontEndHeapUsageData0x1a8
…
Windows memory allocator
• _HEAP

• FrontEndHeap

• 指向管理理 FrontEnd 的 Heap 的結構

• FrontEndHeapUsageData

• 指向⼀一個對應各⼤大⼩小 chunk 的陣列列

• 紀錄各種⼤大⼩小 chunk 使⽤用次數,到
達某個程度時會去 enable 該對應⼤大
⼩小 chunk 的 Front-End allocator
…
EncodeFlagMask0x7c
0x80
0x138
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
0x150
0x198
FrontEndHeapUsageData0x1a8
…
Windows memory allocator
• Nt Heap

• 後端管理理器 (Back-End)

• 前端管理理器 (Front-End)
Nt heap
• Nt Heap

• 後端管理理器 (Back-End)

• Data structure

• 分配機制
Windows memory allocator
• _HEAP_ENTRY (chunk)

• 分為三種狀狀況

• Allocated chunk

• Freed chunk

• VirtualAlloc chunk
Nt heap
• _HEAP_ENTRY (chunk)

• PreviousBlockPrivateData

• 基本上可為前⼀一塊 chunk 的 data,因
為 chunk 必須對⿑齊 0x10

• Size

• Chunk 的 size 但存入⽅方式並不是直接
存 size ⽽而是存 (size >>4) 後的值
User Data
PreviousBlockPrivateData
(8byte)
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Inused
Nt heap
• _HEAP_ENTRY (chunk)

• Flag

• 表⽰示該 chunk 是否 inused

• SmallTagIndex

• 前⾯面三個 byte 的 Checksum(三個
byte 做 xor),之後拿 header 出來來時會
驗證
User Data
PreviousBlockPrivateData
(8byte)
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Inused
Nt heap
• _HEAP_ENTRY (chunk)

• PreviousSize

• 相鄰的前⼀一塊 chunk 的 Size ,這邊ㄧ
樣是 (Size >> 4) 過後的數值

• SegmentOffset

• 某些情況下⽤用來來找 segment 的
User Data
PreviousBlockPrivateData
(8byte)
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Inused
Nt heap
• _HEAP_ENTRY (chunk)

• Unusedbyte

• 紀錄 user malloc 後所剩 chunk 的空間

• 可以⽤用來來判斷 chunk 的狀狀態判斷 chunk
是 FrontEnd or BackEnd

• User Data

• User 所使⽤用的區塊
User Data
PreviousBlockPrivateData
(8byte)
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Inused
Nt heap
• _HEAP_ENTRY (chunk)

• Flink

• 指向 linked list 中下⼀一塊 chunk

• Blink

• 指向 linked list 中上⼀一塊 chunk

• Unusedbyte 

• 恆為 0
User Data
PreviousBlockPrivateData
(8byte)
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
freed
Flink
Blink
Nt heap
• _HEAP_VIRTUAL_ALLOC_ENTRY (mmap
chunk)

• Flink

• 指向下⼀一塊 VirtualAlloc 出來來的 chunk

• Blink

• 指向上⼀一塊 VirtualAlloc 出來來的 chunk
User Data
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
inused
Flink
Blink
…
Nt heap
• _HEAP_VIRTUAL_ALLOC_ENTRY (mmap
chunk)

• Size

• 這邊的 size 指的是 unused size,且
沒有 shift 過

• Unusedbyte

• 恆為 4
User Data
Size (2byte)
Flag (1byte)
SmallTagIndex (1byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
inused
Flink
Blink
…
Nt heap
• FreeLists (_HEAP_ENTRY)

• 在 Free 完⼀一塊 chunk 後,會將該 chunk 放到 FreeLists 中,並會依照⼤大
⼩小決定插在 FreeLists 中的位置
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x110)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x160)
PreviousBlockPrivateData
Nt heap
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x110)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x160)
PreviousBlockPrivateDat
…
EncodeFlagMask0x7c
0x80
0x138
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
0x150
0x198
FrontEndHeapUsageData0x1a8
…
Flink
Blink
_HEAP
Nt heap
• Remark

• 關於 header encoding

• 所有的 chunk 都會經過 xor 過,在存 chunk header 時,會將整個
header^(_HEAP->Encoding) 在存入

• decode 時會驗證 check sum 確保沒被改掉

• 驗證⽅方式為 encode_header^(_HEAP->Encoding) 後的值,前 3 byte
xor 後和第 4 byte 比對
Nt heap
• BlocksIndex (_HEAP_LIST_LOOKUP)

• 主要⽤用來來管理理各種不同⼤大⼩小的 freed chunk 的結構,⽅方便便在配置記憶體
時,能快速的找到適合的 chunk
Nt heap
• BlocksIndex (_HEAP_LIST_LOOKUP)

• ExtendedLookup (_HEAP_LIST_LOOKUP)

• 指向下⼀一個 ExtendedLookup

• 通常下⼀一個會管理理更更⼤大塊 chunk 所⽤用的
結構

• ArraySize

• 該結構會管理理的,最⼤大 chunk 的⼤大⼩小,
通常為 0x80 (實際上是 0x800)
BlocksIndex
ExtendedLookup0x0
ArraySize0x8
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
0x10
0x14
BaseIndex0x18
ListHead
ListsInUseUlong
ListHint
0x20
0x28
0x30
Nt heap
• BlocksIndex (_HEAP_LIST_LOOKUP)

• ItemCount

• ⽬目前該結構所管理理的 chunk 數

• OutofRangeItems

• 超出該結構所管理理⼤大⼩小的 chunk 的
數量量
BlocksIndex
ExtendedLookup0x0
ArraySize0x8
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
0x10
0x14
BaseIndex0x18
ListHead
ListsInUseUlong
ListHint
0x20
0x28
0x30
Nt heap
• BlocksIndex (_HEAP_LIST_LOOKUP)

• BaseIndex

• 該結構所管理理的 chunk 的起始 index,
⽤用來來從 ListHint 找適合⼤大⼩小的 free
chunk ⽤用的,下⼀一個 BlocksIndex 將從
這個 index 的最⼤大值作為 BaseIndex

• ListHead (_HEAP_ENTRY)

• FreeList 的 Head
BlocksIndex
ExtendedLookup0x0
ArraySize0x8
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
0x10
0x14
BaseIndex0x18
ListHead
ListsInUseUlong
ListHint
0x20
0x28
0x30
Nt heap
• BlocksIndex (_HEAP_LIST_LOOKUP)

• ListsInUseUlong

• ⽤用在判斷 ListHint 中是否有適合⼤大⼩小的
chunk,是⼀一個 bitmap 

• ListHint 

• 重要結構,⽤用來來指向相對應⼤大⼩小的 chunk
array

• 其⽬目的就在於更更快速找到適合⼤大⼩小的 chunk

⼤大⼩小為 0x10 為⼀一個間隔
BlocksIndex
ExtendedLookup0x0
ArraySize0x8
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
0x10
0x14
BaseIndex0x18
ListHead
ListsInUseUlong
ListHint
0x20
0x28
0x30
…
EncodeFlagMask
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
FrontEndHeapUsageDat
…
_HEAP
BlocksIndex
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Flink
Blink
Chunk header (0x110)
PreviousBlockPrivate
Flink
Blink
Chunk header(0x160)
PreviousBlockPrivat
ListHint
Flink
Flink
Flink
ListHint[7]
ListHint[0x11]
ListHint[0x16]
000001…1…1000000000
ListsInUseUlong
Nt heap
• Nt Heap

• 後端管理理器 (Back-End)

• Data structure

• 分配機制
Nt heap
• Allocate (RtlpAllocateHeap)

• 基本上分為三種

• Size <= 0x4000

• 0x4000 < size <= 0xff000

• Size > 0xff000
Nt heap
• Allocate (RtlpAllocateHeap)

• Size <= 0x4000

• 基本上主要分配都會在 RtlpAllocateHeap

• 接著會去看該 size 對應到的 FrontEndHeapStatusBitmap 使否有啟⽤用 LFH

• 沒有的話會對對應到的 FrontEndHeapUsageData 加上 0x21

• 並且檢查值是否超過 0xff00 或者 & 0x1f 後超過 0x10

通過條件就會啟⽤用 LFH
Nt heap
• Allocate (RtlpAllocateHeap)

• Size <= 0x4000

• 接下來來會先看對應到的 ListHint 是否有值,會以 ListHint 中的 chunk 為優先

• 如果有適合剛好的 chunk 在 ListHint 上則移除 ListHint,並且會看該 chunk 的 Flink ⼤大⼩小是否
剛好也是同樣 size

• 是的話就將 LintHint 填上 Flink

• 不是則清空

• 最後則 unlink 該 chunk 把這塊 chunk 從 linked list 中移除返還給使⽤用者,並將 header xor
回去
Nt heap
• Allocate (RtlpAllocateHeap)

• Size <= 0x4000

• 如果沒有剛好適合的

• 從比較⼤大的 ListHint 中找,有找到比較⼤大的後如果該 chunk 將會從 ListHint 則移除之,
並看下⼀一塊 chunk size 有沒有剛好⼤大⼩小,有則補上,並且 unlink 將該 chunk 移除
freelist

• 最後將該 chunk 做切割,剩下的⼤大⼩小重新加入 Freelist ,如果可以放進 ListHint 就會放
進去

• 然後回傳切好的 chunk 給使⽤用者,這邊也會對切割後跟回傳使⽤用者的 chunk header xor
Nt heap
• Allocate (RtlpAllocateHeap)

• Size <= 0x4000

• 如果 FreeList 中都沒有

• 嘗試 ExtendHeap 加⼤大 heap 空間

• 再從 extend 出來來的 chunk 拿

• 接著後⾯面⼀一樣切割,放回 ListHint,xor header
Nt heap
• Allocate (RtlpAllocateHeap)

• 0x4000 < size <= 0xff000

• 除了了沒有對 LFH 相關的操作外,其餘都跟 0x4000 ⼀一樣
Nt heap
• Allocate (RtlpAllocateHeap)

• Size > 0xff000 (VirtualMemoryThreshold << 4)

• 直接使⽤用 ZwAllocateVirtualMemory

• 類似 mmap 直接給⼀一⼤大塊,並且會插入 _HEAP->VirtualAllocdBlocks
這個 linked list 中

• 這個 linked list 是串串接該 Heap VirtualAllocate 出來來的區段⽤用的
Nt heap
• Free (RtlpFreeHeap)

• 可分為

• Size <= 0xff000 

• Size > 0xff000
Nt heap
• Free (RtlpFreeHeap)

• Size <= 0xff000 

• 會先檢查 alignment、利利⽤用 unused byte 判斷該 chunk 狀狀態

• 如果是非 LFH 下,會對對應到的 FrontEndHeapUsageData 減 1

• 接著會判斷前後的 chunk 是否為 freed ,是的話就合併

• 此時會把可以合併的 chunk 做 unlink ,並從 ListHint 移除

• 移除⽅方式與前⾯面相同,看看下⼀一塊是不是同樣⼤大⼩小,是的話補上 ListHint
Nt heap
• Free (RtlpFreeHeap)

• Size <= 0xff000 

• 合併完後, update size & prevsize ,然後會看看是不是最前跟最後,
是就插入,不⾏行行插入就從 ListHint 中插入,並且 update ListHint,插入
時也會對 linked list 做檢查

• 但這檢查不會 abort

• 其原因主要因為不做 unlink 寫入
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Free(Q)
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Find Prevchunk
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Prevchunk =
Chunk address
-
(prevsize << 4)
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Find Prevchunk
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Prevchunk =
chunk addr - 0x70
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Decode prevchunk

header
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check checksum
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
SmallTagInex ==

(size & 0xff)
xor
(size >> 8)
xor
Flag
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check checksum
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
7 ==

0x7^0x0^0x0
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check

linked list
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
P->Flink->Blink == 

P->Blink->Flink == 

P
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Find 

BlocksIndex
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Find suitable 

BlocksIndex
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
Check
P->size < ArraySize
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check

ListHint
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
Check
ListHint[7] ==
Prevchunk
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check

ListHint
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
Check
prevchunk->Flink ==
ListHead
成立的話會準備 update

ListHint
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check

ListHint[7]->Flink
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
decode
prevchunk->Flink
And check
the checksum
由於前⼀一張 slide 不成立
要去驗 Flink 的 size

ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check

ListHint[7]->Flink
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
Size == 

prevchunk->Flink->size
如果相等,直接將 ListHint
換成下⼀一塊

ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Update

ListHint[7]
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
ListHint[7] =

prevchunk->Flink
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Unlink

prevchunk
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x7)
Flag (0x0)
SmallTagIndex (0x7)
Prevchunk->Blink->Flink

= Prevchunk->Flink

Prevchunk->Flink->Blink
= Prevchunk->Blink
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Update

prevchunk

and next chunk
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x7)
Prevchunk->size =

0x11 + Prevchunk->size(7)
R->Prevsize = 0x18
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Check

next chunk
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x7)
檢查下⼀一塊 chunk

使否 freed
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Find suitable

BlocksIndex

For P
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x7)
Check

P->Size < ArraySize
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Search

insert

point
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x7)
Check

P->size <
ListHead->Blink->Size

P->size <
ListHead->Flink->Size
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Insert

linked list
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x7)
Check

S->Blink->Flink

== S
If not pass it will not 

abort

But it will not unlink
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Update

ListHint
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x7)
If LintHint[0x18] == NULL

LintHint[0x18] = P
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
FlinkListHint[0x18]
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Update

header
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0x18)
Flag (0x0)
SmallTagIndex (0x18)
SmallTagIndex = 

(size >> 8) ^

(size & 0xff) ^

Flag
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
FlinkListHint[0x18]
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Flink
Blink
Chunk header(0x110)
PreviousBlockPrivat
FlinkListHint[7]
Flink
Blink
Chunk header(0x70)
PreviousBlockPrivat
merge chunk
P
Q
R
S
Encode

header
Size (0x11)
Flag (0x1)
SmallTagIndex (0x10)
Prevsize (0x7)
Size (0xda)
Flag (0xab)
SmallTagIndex (0x41)
P->header ^

_HEAP->Encoding
P
Flink
Blink
Chunk header (0x180)
PreviousBlockPrivate
FlinkListHint[0x18]
Nt heap
• Free (RtlpFreeHeap)

• Size > 0xff000 

• 檢查該 chunk 的 linked list 並從 _HEAP->VirtualAllocdBlocks 移除

• 接著使⽤用 RtlpSecMemFreeVirtualMemory 將 chunk 整個 munmap 掉
Back-End Exploitation
• Unlink

• 基本上與 Linux 中的 unlink 很類似,繞過⽅方法也差不多

• 簡⽽而⾔言之就是利利⽤用從 linked listed 移除 node 的⾏行行為來來做有限制的寫入

• 要注意的是在會 decode 的地⽅方,都要讓他正常 decode

• 也就是 check sum 要過

• 另外⼀一點是 Flink 及 Blink 並不是指向 chunk 開頭,⽽而是直接指向 User data 部分,也就是
不太需要做偏移偽造 chunk

• 所以找到⼀一個指向該 userdata 的 pointer 讓他繞過 double linked list 的驗證就好了了
Back-End Exploitation
• Unlink

• Q->Blink->Flink = Q->Flink

• Q->Flink->Blink = Q->Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x110)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x160)
PreviousBlockPrivateData
QP R
Back-End Exploitation
• Unlink

• Q->Blink->Flink = Q->Flink

• Q->Flink->Blink = Q->Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x110)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x160)
PreviousBlockPrivateData
QP R
Back-End Exploitation
• Unlink

• Q->Blink->Flink = Q->Flink

• Q->Flink->Blink = Q->Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x110)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x160)
PreviousBlockPrivateData
QP R
Back-End Exploitation
• Unlink

• Q->Blink->Flink = Q->Flink

• Q->Flink->Blink = Q->Blink
Flink
Blink
Chunk header (0x70)
PreviousBlockPrivateData
Flink
Blink
Chunk header (0x160)
PreviousBlockPrivateData
QP R
A
A
Chunk header (0x110)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
UAF
T
A
A
A
Chunk header (0x110)
PreviousBlockPrivate
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
Free(Q)
T
A
Q
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
A
ListHead
QListHint[0x11]
free(S)
Update ListHint
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
A
S
SListHint[0x11]
Q
ListHead
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
A
S
SListHint[0x11]
Q
ListHead
Let’s corrupt the heap !
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
free(P)
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
Check next chunk 

is free
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
Decode 

chunk Q
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead(&Q-8)->Blink
==
(&Q)->Flink
== Q
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead(&Q-8)->Blink
==
(&Q)->Flink
== Q
Flink
Blink
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead(&Q-8)->Blink
==
(&Q)->Flink
== Q
Flink
Blink
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead*(&Q)
==
*(&Q)
== Q
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead*(&Q)
==
*(&Q)
== Q
Pass the check !!
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
Find 

BlockIndex
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
Check

ListHint[0x11]
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead由於 S != Q

所以不會對 ListHint

做任何處理理
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
Data Pointer
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
Unlink !!
Q->Blink->Flink
= Q->Flink
Flink
Blink
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
&Q - 8
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHeadUnlink !!
Q = &Q-8
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
&Q - 8
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHead
Unlink !!
Q->Flink->Blink
= Q->Blink
Flink
Blink
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHeadUnlink !!
Q = &Q
S
A
Chunk header (0x110)
PreviousBlockPrivate
Q
Chunk header (0x110)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
P
Q
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
&Q - 8
&Q
SListHint[0x11]
Q
ListHeadUpdate 

chunk size
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHeadUpdate 

chunk size
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
Search insert point
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHeadFind the last one
And decode it
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
P
Find the first one
And decode it
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
我們要插在 A 前
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
Check

A->Blink->Flink
== A
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
Check

Q->Flink
== A
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHeadFailed

不過不會 abort
只是不會 insert
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
Update 

ListHint
P
S
A
Chunk header (0x220)
PreviousBlockPrivate
Chunk header(0x50)
PreviousBlockPrivat
S
Chunk header(0x110)
PreviousBlockPrivat
R
S
P
&Q
R
S
T
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
BlockIndex
ListHint
T
A
SListHint[0x11]
Q
ListHead
P
PListHint[0x22]
Back-End Exploitation
• Edit Q

• 我們可以把 Q 周圍的 pointer 寫掉

• 最後可達成任意記憶體讀寫
P
&Q
R
S
T
Back-End Exploitation
• Edit Q

• 我們可以把 Q 周圍的 pointer 寫掉

• 最後可達成任意記憶體讀寫

• 可對 Target 1 - 4 做寫入
P
Target 1
Target 2
Target 3
Target 4
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• ntdll.dll

• PebLdr

• binary address

• Kernel32.dll
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• kernelbase

• KERNELBASE!BasepFilterInfo

• Stack address
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• ntdll.dll

• _HEAP_LOCK

• _HEAP->LockVariable.Lock

• CriticalSection->DebugInfo

• 指向 ntdll
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• ntdll!PebLdr

• _PEB_LDR_DATA

• 可找出所有 DLL 的位置

• 不過缺點是最後⼀一兩兩個 byte 可能是 0

• 可先找出 binary base 從 IAT 找 kernel32
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• BinaryBase

• 從 IAT 找出 Kernel32 位置
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• Kernel32

• 重要 dll 很多常⽤用 function 都在這 (CreateFile, ReadFile,WriteFile) 

• IAT

• 獲得 kernelbase.dll 位置
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• kernelbase

• KERNELBASE!BasepFilterInfo

• 指向 Heap 上的結構

• 裡⾯面有⾼高機率會有 stack pointer

• https://j00ru.vexillium.org/2016/07/disclosing-stack-data-from-the-default-
heap-on-windows/
Back-End Exploitation
• After arbitrary memory reading and writing

• Leak

• 如果 BasepFilterInfo 中沒有 stack address

• 因 BasepFilterInfo 內容會有 stack address 是因為未初始化因素,所
以有機會沒有 stack address

• 可以從 PEB 往前或往後算 1 個 page ,通常會是 TEB 位置,上⾯面繪
有 stack 尾段的位置,可以藉由該位置找出 retrun address
Back-End Exploitation
• After arbitrary memory reading and writing

• Write 

• Return address

• Control RIP

• ROP to VirtualProtect/VirtualAlloc

• Jmp to shellcode
Windows memory allocator
• Nt Heap

• 後端管理理器 (Back-End)

• 前端管理理器 (Front-End)
Windows memory allocator
• Nt Heap

• 前端管理理器 (Front-End)

• ⽬目前 win10 主要使⽤用

• LowFragmentationHeap

• 在非 Debug 下才會 enable

• Size < 0x4000
Windows memory allocator
• Nt Heap

• 前端管理理器 (Front-End)

• Data Structure

• 分配機制
Windows memory allocator
• Nt Heap

• 前端管理理器 (Front-End)

• Data Structure

• 分配機制
LFH
• FrontEndHeap (_LFH_HEAP)

• HEAP (_HEAP)

• 指向對應到的 _HEAP

• Buckets (_HEAP_BUCKET)

• ⽤用來來尋找配置⼤大⼩小對應到 Block ⼤大⼩小
的陣列列結構
…
Heap0x18
0x2a4
…
Buckets
SegmentInfoArray
…
…
LocalData
0x4a8
0xcc0
LFH
• FrontEndHeap (_LFH_HEAP)

• SegmentInfoArray
(_HEAP_LOCAL_SEGMENT_INFO)

• _HEAP_LOCAL_SEGMENT_INFO array,
不同⼤大⼩小對應到不同的 Segment_info 結
構,主要管理理對應到的 Subsegment 的資訊

• LocalData (_HEAP_LOCAL_DATA)

• 其中有個欄欄位指向 LFH 本⾝身,通常⽤用來來找
回 LFH
…
Heap0x18
…
Buckets
SegmentInfoArray
…
…
LocalData
0x2a4
0x4a8
0xcc0
LFH
• Buckets (_HEAP_BUCKET)

• BlockUnits

• 要分配出去的⼀一個 block ⼤大⼩小 >> 4

• SizeIndex

• 使⽤用者需要的⼤大⼩小 >> 4
BlockUnits
Buckets
SizeIndex
…
BlockUnits
SizeIndex
…
…
…
Buckets[0]
Buckets[1]
LFH
• SegmentInfoArray
(_HEAP_LOCAL_SEGMENT_INFO)

• LocalData (_HEAP_LOCAL_DATA)

• 對應到 _LFH_HEAP->LocalData ⽅方便便
從 SegmentInfo 找回 _LFH_HEAP

• BucketIndex

• 對應到的 BucketIndex
LocalData
SegmentInfoArray[x]
ActiveSubsegment
CachedItems
…
BucketIndex
…
LFH
• SegmentInfoArray
(_HEAP_LOCAL_SEGMENT_INFO)

• ActiveSubsegment (_HEAP_SUBSEGMENT)

• 極為重要結構

• 對應到分配出去的 Subsegment

• 其⽬目的在於管理理 Userblock

• 記錄了了剩餘多少 chunk 

• 該 Userblock 最⼤大分配數等等
SegmentInfoArray[x]
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
LFH
• SegmentInfoArray
(_HEAP_LOCAL_SEGMENT_INFO)

• CachedItems (_HEAP_SUBSEGMENT)

• _HEAP_SUBSEGMENT array

• 存放對映到該 SegmentInfo 且還有可
以分配 chunk 給 user 的Subsegment 

• 當 ActiveSubsegment ⽤用完時,會從
這邊填充,置換掉 ActiveSubsegment
SegmentInfoArray[x]
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
LFH
…
Heap
…
…
…
LocalData
0x18
0x2a4
0x4a8
0xcc0
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
…
EncodeFlagMask
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
FrontEndHeapUsageData
…
_HEAP
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
LFH
• ActiveSubsegment (_HEAP_SUBSEGMENT)

• LocalInfo
(_HEAP_LOCAL_SEGMENT_INFO)

• 指回對應到的
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
ActiveSubsegment
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
0x0
0x8
0x20
0x24
0x28
0x2a
LFH
• ActiveSubsegment (_HEAP_SUBSEGMENT)

• UserBlock (_HEAP_USERDATA_HEADER)

• LFH 的記憶體分配池

• 也就是要分配出去的 Chunk (Block)
所在位置

• 開頭會有些 metadata 管理理這些 chunk

• 重要結構
LocalInfo
ActiveSubsegment
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
0x0
0x8
0x20
0x24
0x28
0x2a
LFH
• ActiveSubsegment (_HEAP_SUBSEGMENT)

• AggregateExchg (_INTERLOCK_SEQ)

• ⽤用來來管理理對應到的 UserBlock 中還有
多少 freed chunk

• LFH ⽤用這個判斷是否還從該
UserBlock 分配

• 同時也有 Lock 的作⽤用
LocalInfo
ActiveSubsegment
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
0x0
0x8
0x20
0x24
0x28
0x2a
LFH
• ActiveSubsegment (_HEAP_SUBSEGMENT)

• BlockSize

• 在該 UserBlock 中每個 Block (chunk)的⼤大⼩小

• BlockCount

• 在該 UserBlock 中 Block 的總數

• SizeIndex

• 該 UserBlock 對應到的 SizeIndex
LocalInfo
ActiveSubsegment
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
0x0
0x8
0x20
0x24
0x28
0x2a
LFH
• AggregateExchg (_INTERLOCK_SEQ)

• Depth

• 該 UserBlock 所剩下的 Freed chunk 數量量

• Lock

• 就是 Lock
AggregateExchg
Depth0x0
Hint (15bit)
Lock (1bit)
0x8
LFH
• UserBlock (_HEAP_USERDATA_HEADER)

• SubSegment

• 指回對應的 Subsegment

• EncodeOffsets

• ⽤用來來驗證 chunk header 是否有被改過

• BusyBitmap

• 記錄該 UserBlock 哪些 chunk 有在⽤用的
bitmap
SubSegment
UserBlock
…
EncodedOffsets
BusyBitmap
0x8
0x18
0x20
chunk header
chunk header
chunk header
LFH
• UserBlock (_HEAP_USERDATA_HEADER)

• Block (chunk)

• LFH 回傳給使⽤用者的 chunk
SubSegment
UserBlock
…
EncodedOffsets
BusyBitmap
0x8
0x18
0x20
chunk header
chunk header
chunk header
LFH
• _HEAP_ENTRY (chunk)

• SubSegmentCode

• Encode 過的 metadata ⽤用來來推回
userblock 的位置

• PreviousSize

• 該 chunk 在 UserBlock 中的 index
User Data
PreviousBlockPrivateData
(8byte)
SubSegmentCode (4byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Inused
LFH
• _HEAP_ENTRY (chunk)

• Unusedbyte

• Unusedbyte & 0x80 is true
User Data
PreviousBlockPrivateData
(8byte)
SubSegmentCode (4byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Inused
LFH
• _HEAP_ENTRY (chunk)

• Unusedbytes

• 恆為 0x80

• ⽤用來來判斷是否為 LFH 的 Free chunk
User Data
PreviousBlockPrivateData
(8byte)
SubSegmentCode (4byte)
PreviousSize (2byte)
SegmentOffset (1byte)
Unusedbyte (1byte)
Freed
LFH
• Remark

• 關於 EncodedOffsets

• 在 UserBlock 初始化時設置,其算法為下⾯面四個值的 xor

• (sizeof(userblock header) | (BlockUnit*0x10 << 16))

• LFHkey

• Userblock address

• _LFH_HEAP address
LFH
• Remark

• 關於 LFH header encoding

• 所有的 chunk header 在初始化時都會經過 xor 過,算法為下⾯面個值的 xor

• _HEAP address

• LFHkey

• Chunk address >> 4

• ((chunk address) - (UserBlock address)) << 12
LFH
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Windows memory allocator
• Nt Heap

• 前端管理理器 (Front-End)

• Data Structure

• 分配機制
Windows memory allocator
• Nt Heap

• 前端管理理器 (Front-End)

• 初始化

• 在 FrontEndHeapUsageData[x] & 0x1f > 0x10 時,下⼀一次的 allocate 會對 LFH 做出初始化 

• 會先 ExtendFrontEndUsageData 及增加更更⼤大的 BlocksIndex (0x80-0x400)

• 建立 FrontEndHeap

• 初始化 SegmentInfoArrays[idx]

• 接下來來在 allocate 相同⼤大⼩小的 chunk 就會開始使⽤用 LFH
Windows memory allocator
• LFH(初始化)

• malloc(0x40) * 16
FrontEndHeapUsageData
…
0x210
此時可 enable LFH 範圍為
index 0x0 - 0x80
Windows memory allocator
• LFH(初始化)

• malloc(0x40) (第 17 次)
FrontEndHeapUsageData
…
0x231 0x231 & 0x1f > 0x10
Windows memory allocator
• LFH(初始化)
FrontEndHeapUsageData
…
0x231
heap->CompatibilityFlag |= 0x20000000
設置上這個 flag 後
下次 allocate 時會去初始化LFH

Windows memory allocator
…
EncodeFlagMask
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
FrontEndHeapUsageData
…
_HEAP
FrontEndHeapUsageData
0x231
BlocksIndex
ExtendedLookup
ArraySize
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex
ListHead
ListsInUseUlong
ListHint
Windows memory allocator
• LFH(初始化)

• malloc(0x40) (第 18 次)

• ExtendFrontEndUsageData 及增加更更⼤大的 BlocksIndex
(0x80-0x400) ,並設置對應的 bitmap

• 並在該對應的 FrontEndHeapUsageData 寫上對應的
index,此時可 enable LFH 範圍變為 (idx: 0-0x400)

• 建立並初始化 FrontEndHeap (mmap)

• 初始化 SegmentInfoArrays[idx]

• 在 SegmentInfoArrays[BucketIndex] 填上 segmentInfo
FrontEndHeapUsageData
…
0x4
Windows memory allocator
…
EncodeFlagMask
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
FrontEndHeapUsageData
…
_HEAP
FrontEndHeapUsageData
0x251 0x4
BlocksIndex
ExtendedLookup
ArraySize(0x80)
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex (0x0)
ListHead
ListsInUseUlong
ListHint
BlocksIndex
ExtendedLookup
ArraySize (0x400)
…
ItemCount (4 bytes)
OutofRangeItems (4 bytes)
BaseIndex (0x80)
ListHead
ListsInUseUlong
ListHint
Windows memory allocator
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
…
EncodeFlagMask
Encoding
…
BlocksIndex
…
FreeList
…
FrontEndHeap
…
FrontEndHeapUsageData
…
_HEAP
FrontEndHeapUsageData
0x251 0x4
Windows memory allocator
• LFH(初始化)

• malloc(0x40) (第 19 次)

• Allocate Userblock 並初始化

• 設置對應的 chunk 

• 設置對應的 ActiviteSubsegment

• 隨機返回其中的⼀一個 chunk
Userblock metadata
Chunk 00
Chunk 01
…
Chunk MaxBlockCount
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Windows memory allocator
• LFH

• Allocate (RtlpLowFragHeapAllocFromContext)

• 先看看 ActiveSubsegment 中是否有可分配的 chunk

• 從 ActiveSubsegment->depth 判斷

• 如果沒有則會從 CachedItem 找,有找到的話會把 ActiveSubsegment
換成 CachedItem 中的 SubSegment
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Find SegementIfoArray by bucket->SizeIndex
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Find SegementIfoArray by bucket->SizeIndex
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Check ActiveSubsegment
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Check ActiveSubsegment
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Check ArgregateExchg.Depth not 0
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Check ArgregateExchg.Depth not 0
…
Heap
…
…
…
LocalData
Buckets[x]
SegmentInfoArray[x]
BlockUnits
SizeIndex
…
_LFH_HEAP
_HEAP_BUCKET
_HEAP_LOCAL_SEGMENT_INFO
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
LocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
Check Userblock
Windows memory allocator
• LFH

• Allocate (RtlpLowFragHeapAllocFromContext)

• 取得 RtlpLowFragHeapRandomData[x] 上的直

• 下⼀一次會從 RtlpLowFragHeapRandomData[x+1] 取

• x 為 1 byte ,當下次輪輪回 x 則會 x = rand() %256 繼續取

• RtlpLowFragHeapRandomData 為⼀一個 random 256 byte 的陣列列

• 範圍為 0x0 - 0x7f
Windows memory allocator
• LFH

• Allocate (RtlpLowFragHeapAllocFromContext)

• 最獲得的 index 為 

• RtlpLowFragHeapRandomData[x]*maxidx >> 7 

• 如果 collision 則往後取最近的

• 檢查 (unused byte & 0x3f) !=0 (表⽰示 chunk 是 freed)

• 最後設置 index 及 unused byte 就返回給使⽤用者
….
….
….
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_HEAP_USERDATA_HEADER
• Get an index

• RtlpLowFragHeapRandomData[x]*maxidx >> 7

• 檢查該 index 對映到的 bitmap 是否為 0

• 是 0 則返回對映的 bitmap

• 非 0 擇取最近的下⼀一個
chunk header
….
….
….
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_HEAP_USERDATA_HEADER
• 算出來來的 index 發現已⽤用過

• 會取下⼀一個

• 並設置對映的 bitmap
chunk header
….
….
….
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_HEAP_USERDATA_HEADER
• 算出來來的 index 發現已⽤用過

• 會取下⼀一個

• 並設置對映的 bitmap
chunk header
Windows memory allocator
• LFH

• Free (RtlFreeHeap)

• Update unused byte in chunk header

• Find the index of the Chunk and reset Userblock->BusyBitmap

• Update ActiveSubsegment->AggregateExchg

• 如果 Free 的 chunk 不屬於當前 ActiveSubsegment 則會看看能不能放
進 cachedItems ,可以放就放進去
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
• Free

• ⽤用 chunk header 尋找
UserBlock
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
• Free

• ⽤用 chunk header 尋找
UserBlock

• 找回對映的 SubSegment
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
• Free

• ⽤用 chunk header 尋找
UserBlock

• 找回對映的 SubSegment

• 設置 unused byte = 0x80

• 清除對映的 bitmap

• Update AggregateExchg
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
• Free

• ⽤用 chunk header 尋找
UserBlock

• 找回對映的 SubSegment

• 設置 unused byte = 0x80

• 清除對映的 bitmap

• Update AggregateExchg
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
Depth
Hint (15bit)
Lock (1bit)
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_INTERLOCK_SEQ
_HEAP_USERDATA_HEADER
• Free

• ⽤用 chunk header 尋找
UserBlock

• 找回對映的 SubSegment

• 設置 unused byte = 0x80

• 清除對映的 bitmap

• Update AggregateExchg
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_HEAP_USERDATA_HEADERLocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
_HEAP_SUBSEGMENT
Depth (1)
Hint (15bit)
Lock (1bit)
_INTERLOCK_SEQ
CachedItems
ActiveSubsegmet
不等於 Free 掉 chunk 的

SubSegment
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
_HEAP_SUBSEGMENT
SubSegment
…
EncodedOffsets
BusyBitmap
chunk header
chunk header
chunk header
_HEAP_USERDATA_HEADERLocalData
ActiveSubsegment
CachedItems
…
BucketIndex
…
LocalInfo
UserBlock
…
AggregateExchg
BlockSzie
BlockCount
…
SizeIndex
…
_HEAP_SUBSEGMENT
Depth (1)
Hint (15bit)
Lock (1bit)
_INTERLOCK_SEQ
CachedItems
CachedItems[0]
LFH Exploitation
• Reuse attack

• 假設我們有 Use after free 的漏洞洞

• 但因為 LFH 的隨機性,導致無法預側下⼀一塊 chunk 會在哪,使得我們
很難利利⽤用

• 這時可以填滿 Userblock 的⽅方式,在 free 掉其中⼀一塊,那麼下次該
chunk 必定會拿到同⼀一塊,我們可以利利⽤用這個特性,拿到 overlap
chunk 做進⼀一步利利⽤用
LFH Exploitation
• normal case

• malloc(sizeof(A))
Userblock header
LFH Exploitation
• normal case

• malloc(sizeof(B))
Userblock header
fptr
LFH Exploitation
• normal case

• free(A)
Userblock header B
fptr
LFH Exploitation
• normal case

• malloc(sizeof(A))
Userblock header B
fptr
LFH Exploitation
• normal case

• malloc(sizeof(B))
Userblock header B
fptr
LFH Exploitation
• normal case

• malloc(sizeof(B))
Userblock header B
fptr
Hard to use
LFH Exploitation
• Reuse attack 

• malloc(sizeof(A))
Userblock header
LFH Exploitation
• Reuse attack 

• malloc(sizeof(B)) x 6
Userblock header
fptr
LFH Exploitation
• Reuse attack 

• free(A)
Userblock header
B
B B B
fptr B B
LFH Exploitation
• Reuse attack 

• malloc(sizeof(B))
Userblock header
B
B B B
fptr B B
LFH Exploitation
• Reuse attack 

• A->fptr
Userblock header
B
B B B
fptr B B
LFH Exploitation
• Reuse attack 

• A->fptr
Userblock header
B
B B B
fptr B B
Hijack the control flow !
Reference
• https://github.com/saaramar/
35C3_Modern_Windows_Userspace_Exploitation

• http://illmatics.com/Understanding_the_LFH.pdf

• https://github.com/saaramar/Deterministic_LFH
Thank you for listening
!189
angelboy@chroot.org @scwuaptx
!189

Más contenido relacionado

La actualidad más candente

Pwning in c++ (basic)
Pwning in c++ (basic)Pwning in c++ (basic)
Pwning in c++ (basic)Angel Boy
 
DeathNote of Microsoft Windows Kernel
DeathNote of Microsoft Windows KernelDeathNote of Microsoft Windows Kernel
DeathNote of Microsoft Windows KernelPeter Hlavaty
 
Binary exploitation - AIS3
Binary exploitation - AIS3Binary exploitation - AIS3
Binary exploitation - AIS3Angel Boy
 
Tcache Exploitation
Tcache ExploitationTcache Exploitation
Tcache ExploitationAngel Boy
 
Linux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledgeLinux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledgeAngel Boy
 
Sigreturn Oriented Programming
Sigreturn Oriented ProgrammingSigreturn Oriented Programming
Sigreturn Oriented ProgrammingAngel Boy
 
You didnt see it’s coming? "Dawn of hardened Windows Kernel"
You didnt see it’s coming? "Dawn of hardened Windows Kernel" You didnt see it’s coming? "Dawn of hardened Windows Kernel"
You didnt see it’s coming? "Dawn of hardened Windows Kernel" Peter Hlavaty
 
Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Angel Boy
 
Windows Kernel Exploitation : This Time Font hunt you down in 4 bytes
Windows Kernel Exploitation : This Time Font hunt you down in 4 bytesWindows Kernel Exploitation : This Time Font hunt you down in 4 bytes
Windows Kernel Exploitation : This Time Font hunt you down in 4 bytesPeter Hlavaty
 
ROP 輕鬆談
ROP 輕鬆談ROP 輕鬆談
ROP 輕鬆談hackstuff
 
syzkaller: the next gen kernel fuzzer
syzkaller: the next gen kernel fuzzersyzkaller: the next gen kernel fuzzer
syzkaller: the next gen kernel fuzzerDmitry Vyukov
 
台科逆向簡報
台科逆向簡報台科逆向簡報
台科逆向簡報耀德 蔡
 
Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniqueAngel Boy
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolveAngel Boy
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程Weber Tsai
 
[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long
[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long
[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin LongCODE BLUE
 
Modern Kernel Pool Exploitation: Attacks and Techniques
Modern Kernel Pool Exploitation: Attacks and TechniquesModern Kernel Pool Exploitation: Attacks and Techniques
Modern Kernel Pool Exploitation: Attacks and TechniquesMichael Scovetta
 

La actualidad más candente (20)

Pwning in c++ (basic)
Pwning in c++ (basic)Pwning in c++ (basic)
Pwning in c++ (basic)
 
Kernel Pool
Kernel PoolKernel Pool
Kernel Pool
 
DeathNote of Microsoft Windows Kernel
DeathNote of Microsoft Windows KernelDeathNote of Microsoft Windows Kernel
DeathNote of Microsoft Windows Kernel
 
Binary exploitation - AIS3
Binary exploitation - AIS3Binary exploitation - AIS3
Binary exploitation - AIS3
 
Tcache Exploitation
Tcache ExploitationTcache Exploitation
Tcache Exploitation
 
Linux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledgeLinux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledge
 
Sigreturn Oriented Programming
Sigreturn Oriented ProgrammingSigreturn Oriented Programming
Sigreturn Oriented Programming
 
You didnt see it’s coming? "Dawn of hardened Windows Kernel"
You didnt see it’s coming? "Dawn of hardened Windows Kernel" You didnt see it’s coming? "Dawn of hardened Windows Kernel"
You didnt see it’s coming? "Dawn of hardened Windows Kernel"
 
Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation
 
Windows Kernel Exploitation : This Time Font hunt you down in 4 bytes
Windows Kernel Exploitation : This Time Font hunt you down in 4 bytesWindows Kernel Exploitation : This Time Font hunt you down in 4 bytes
Windows Kernel Exploitation : This Time Font hunt you down in 4 bytes
 
ROP 輕鬆談
ROP 輕鬆談ROP 輕鬆談
ROP 輕鬆談
 
syzkaller: the next gen kernel fuzzer
syzkaller: the next gen kernel fuzzersyzkaller: the next gen kernel fuzzer
syzkaller: the next gen kernel fuzzer
 
台科逆向簡報
台科逆向簡報台科逆向簡報
台科逆向簡報
 
Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit Technique
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolve
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程
 
[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long
[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long
[CB16] DeathNote of Microsoft Windows Kernel by Peter Hlavaty & Jin Long
 
WSL Reloaded
WSL ReloadedWSL Reloaded
WSL Reloaded
 
Modern Kernel Pool Exploitation: Attacks and Techniques
Modern Kernel Pool Exploitation: Attacks and TechniquesModern Kernel Pool Exploitation: Attacks and Techniques
Modern Kernel Pool Exploitation: Attacks and Techniques
 
x86
x86x86
x86
 

Similar a Windows 10 Nt Heap Exploitation (Chinese version)

D2 t2 steven seeley - ghost in the windows 7 allocator
D2 t2   steven seeley - ghost in the windows 7 allocatorD2 t2   steven seeley - ghost in the windows 7 allocator
D2 t2 steven seeley - ghost in the windows 7 allocator_mr_me
 
Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016
Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016
Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016DataStax
 
Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...
Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...
Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...Spark Summit
 
Engineering fast indexes
Engineering fast indexesEngineering fast indexes
Engineering fast indexesDaniel Lemire
 
Presentation on Heap Sort
Presentation on Heap Sort Presentation on Heap Sort
Presentation on Heap Sort Amit Kundu
 
Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018
Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018
Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018Codemotion
 
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_heRecon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_heLiang Chen
 
Computer Introduction
Computer IntroductionComputer Introduction
Computer IntroductionSpy Seat
 
Advance computer architecture
Advance computer architectureAdvance computer architecture
Advance computer architecturesuma1991
 
Hash Functions FTW
Hash Functions FTWHash Functions FTW
Hash Functions FTWsunnygleason
 
Code and memory optimization tricks
Code and memory optimization tricksCode and memory optimization tricks
Code and memory optimization tricksDevGAMM Conference
 
Code and Memory Optimisation Tricks
Code and Memory Optimisation Tricks Code and Memory Optimisation Tricks
Code and Memory Optimisation Tricks Sperasoft
 
A survey on Heap Exploitation
A survey on Heap Exploitation A survey on Heap Exploitation
A survey on Heap Exploitation Alireza Karimi
 
Lightning Talk: MongoDB Sharding
Lightning Talk: MongoDB ShardingLightning Talk: MongoDB Sharding
Lightning Talk: MongoDB ShardingMongoDB
 
Jurczyk windows kernel reference count vulnerabilities. case study
Jurczyk   windows kernel reference count vulnerabilities. case studyJurczyk   windows kernel reference count vulnerabilities. case study
Jurczyk windows kernel reference count vulnerabilities. case studyDefconRussia
 
Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...
Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...
Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...Spark Summit
 
Compromising Linux Virtual Machines with Debugging Mechanisms
Compromising Linux Virtual Machines with Debugging MechanismsCompromising Linux Virtual Machines with Debugging Mechanisms
Compromising Linux Virtual Machines with Debugging MechanismsRussell Sanford
 

Similar a Windows 10 Nt Heap Exploitation (Chinese version) (20)

D2 t2 steven seeley - ghost in the windows 7 allocator
D2 t2   steven seeley - ghost in the windows 7 allocatorD2 t2   steven seeley - ghost in the windows 7 allocator
D2 t2 steven seeley - ghost in the windows 7 allocator
 
Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016
Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016
Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2016
 
Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...
Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...
Engineering Fast Indexes for Big-Data Applications: Spark Summit East talk by...
 
Engineering fast indexes
Engineering fast indexesEngineering fast indexes
Engineering fast indexes
 
Bloom filters
Bloom filtersBloom filters
Bloom filters
 
Presentation on Heap Sort
Presentation on Heap Sort Presentation on Heap Sort
Presentation on Heap Sort
 
Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018
Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018
Managing your Black Friday Logs - Antonio Bonuccelli - Codemotion Rome 2018
 
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_heRecon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
 
Computer Introduction
Computer IntroductionComputer Introduction
Computer Introduction
 
Advance computer architecture
Advance computer architectureAdvance computer architecture
Advance computer architecture
 
Hash Functions FTW
Hash Functions FTWHash Functions FTW
Hash Functions FTW
 
Code and memory optimization tricks
Code and memory optimization tricksCode and memory optimization tricks
Code and memory optimization tricks
 
Code and Memory Optimisation Tricks
Code and Memory Optimisation Tricks Code and Memory Optimisation Tricks
Code and Memory Optimisation Tricks
 
A survey on Heap Exploitation
A survey on Heap Exploitation A survey on Heap Exploitation
A survey on Heap Exploitation
 
Lightning Talk: MongoDB Sharding
Lightning Talk: MongoDB ShardingLightning Talk: MongoDB Sharding
Lightning Talk: MongoDB Sharding
 
Why learn Internals?
Why learn Internals?Why learn Internals?
Why learn Internals?
 
Jurczyk windows kernel reference count vulnerabilities. case study
Jurczyk   windows kernel reference count vulnerabilities. case studyJurczyk   windows kernel reference count vulnerabilities. case study
Jurczyk windows kernel reference count vulnerabilities. case study
 
Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...
Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...
Deep Dive into Project Tungsten: Bringing Spark Closer to Bare Metal-(Josh Ro...
 
Compromising Linux Virtual Machines with Debugging Mechanisms
Compromising Linux Virtual Machines with Debugging MechanismsCompromising Linux Virtual Machines with Debugging Mechanisms
Compromising Linux Virtual Machines with Debugging Mechanisms
 
Lecture 25
Lecture 25Lecture 25
Lecture 25
 

Último

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 

Último (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 

Windows 10 Nt Heap Exploitation (Chinese version)

  • 2. Windows Heap Exploitation • Windows Memory Allocator • NT heap • BackEnd • Exploitation • FrontEnd • LowFragmentationHeap • Exploitation
  • 3. Windows memory allocator • Win 10 的 memory allocator 非常複雜,基本上主要有下列列兩兩種 • Nt Heap • Default memory allocator • SegmentHeap • Win10 中全新的 memory allocator 機制 • 部分系統程式及 UWP 會使⽤用
  • 4. Windows memory allocator • Nt Heap 中⼜又可分 • 後端管理理器 (Back-End) • 前端管理理器 (Front-End) • LowFragmentationHeap • 基本上是為了了不讓記憶體過於破碎,相同⼤大⼩小的記憶體區塊分配到⼀一定數 量量後就會使⽤用 (連續分配相同記憶體區塊 18 次) • Size <= 0x4000
  • 5. Windows memory allocator • ⽬目前會以 win 10 (1809) 為主 • OS build - 17763.379 • 之後版本可能不⼀一定完全正確 • 結構常常改動很⼤大,有個概念念後,到新的發⾏行行版本,需要⾃自⼰己去追⼀一下結 構
  • 6. Windows memory allocator • Overview Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpAllocateHeap RtlpFreeHeap ntdll.dll RtlpLowFragHeapAlloc RtlpLowFragHeapFree Kernel Front-End Back-End
  • 7. Windows memory allocator • 在 LFH 沒啟⽤用下,我們呼叫 malloc Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpAllocateHeap RtlpFreeHeap Kernel Back-End
  • 8. Windows memory allocator • 啟⽤用 LFH 後,第⼀一次或 LFH 能⽤用的⽤用完時
 會先跟 Back-End 要⼀一⼤大塊空間來來管理理 Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpAllocateHeap RtlpFreeHeap ntdll.dll RtlpLowFragHeapAlloc RtlpLowFragHeapFree Kernel Front-End Back-End
  • 9. Windows memory allocator • 啟⽤用 LFH 之後分配相同⼤大⼩小時,會直接給
 Front-End 管理理 Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpLowFragHeapAlloc RtlpLowFragHeapFree Front-End
  • 10. Windows memory allocator • HEAP 可分為 • Process Heap • Default heap • 整個 process 共享,呼叫 api 時會⽤用到 • 會存在 _PEB 結構中 • CRT 中的函式時也會⽤用到 • 存在 crt_heap
  • 11. Windows memory allocator • HEAP 可分為 • Private heap • 另外創建的 heap • HeapCreate
  • 12. Windows memory allocator • Core data structure • _HEAP_ENTRY (chunk) • Malloc 出來來的基本結構 • 在前後端分配器中,長相會不太⼀一樣,但都是同⼀一個名字
  • 13. Windows memory allocator • _HEAP_ENTRY (chunk) data chunk header chunk header data _HEAP chunk header . . . malloc return value
  • 14. Windows memory allocator • Core data structure • _HEAP • 整個 memory allocator 中最核⼼心的結構,⽤用來來管理理該 heap • 每個 Heap 都會有⼀一個 _HEAP 通常在 heap 開頭
  • 15. Windows memory allocator • _HEAP • EncodeFlagMask • Heap 初始化後會設置為 0x100000 在判斷是否要 encode 該 heap 中 chunk 的 header • Encoding (_HEAP_ENTRY) • ⽤用來來與 chunk header 做 xor 的 cookies … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 …
  • 16. Windows memory allocator • _HEAP • BlocksIndex (_HEAP_LIST_LOOKUP_) • Back-End 中,重要的結構之⼀一,⽤用 來來管理理 Back-End 中的 chunk ,後 ⾯面會詳細敘述 • FreeList (_HEAP_ENTRY) • 串串接 Back-End 中的所有 free chunk ,類似 unsorted bin • Sorted list … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 …
  • 17. Windows memory allocator • _HEAP • FrontEndHeap • 指向管理理 FrontEnd 的 Heap 的結構 • FrontEndHeapUsageData • 指向⼀一個對應各⼤大⼩小 chunk 的陣列列 • 紀錄各種⼤大⼩小 chunk 使⽤用次數,到 達某個程度時會去 enable 該對應⼤大 ⼩小 chunk 的 Front-End allocator … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 …
  • 18. Windows memory allocator • Nt Heap • 後端管理理器 (Back-End) • 前端管理理器 (Front-End)
  • 19. Nt heap • Nt Heap • 後端管理理器 (Back-End) • Data structure • 分配機制
  • 20. Windows memory allocator • _HEAP_ENTRY (chunk) • 分為三種狀狀況 • Allocated chunk • Freed chunk • VirtualAlloc chunk
  • 21. Nt heap • _HEAP_ENTRY (chunk) • PreviousBlockPrivateData • 基本上可為前⼀一塊 chunk 的 data,因 為 chunk 必須對⿑齊 0x10 • Size • Chunk 的 size 但存入⽅方式並不是直接 存 size ⽽而是存 (size >>4) 後的值 User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  • 22. Nt heap • _HEAP_ENTRY (chunk) • Flag • 表⽰示該 chunk 是否 inused • SmallTagIndex • 前⾯面三個 byte 的 Checksum(三個 byte 做 xor),之後拿 header 出來來時會 驗證 User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  • 23. Nt heap • _HEAP_ENTRY (chunk) • PreviousSize • 相鄰的前⼀一塊 chunk 的 Size ,這邊ㄧ 樣是 (Size >> 4) 過後的數值 • SegmentOffset • 某些情況下⽤用來來找 segment 的 User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  • 24. Nt heap • _HEAP_ENTRY (chunk) • Unusedbyte • 紀錄 user malloc 後所剩 chunk 的空間 • 可以⽤用來來判斷 chunk 的狀狀態判斷 chunk 是 FrontEnd or BackEnd • User Data • User 所使⽤用的區塊 User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  • 25. Nt heap • _HEAP_ENTRY (chunk) • Flink • 指向 linked list 中下⼀一塊 chunk • Blink • 指向 linked list 中上⼀一塊 chunk • Unusedbyte • 恆為 0 User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) freed Flink Blink
  • 26. Nt heap • _HEAP_VIRTUAL_ALLOC_ENTRY (mmap chunk) • Flink • 指向下⼀一塊 VirtualAlloc 出來來的 chunk • Blink • 指向上⼀一塊 VirtualAlloc 出來來的 chunk User Data Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) inused Flink Blink …
  • 27. Nt heap • _HEAP_VIRTUAL_ALLOC_ENTRY (mmap chunk) • Size • 這邊的 size 指的是 unused size,且 沒有 shift 過 • Unusedbyte • 恆為 4 User Data Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) inused Flink Blink …
  • 28. Nt heap • FreeLists (_HEAP_ENTRY) • 在 Free 完⼀一塊 chunk 後,會將該 chunk 放到 FreeLists 中,並會依照⼤大 ⼩小決定插在 FreeLists 中的位置 Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData
  • 29. Nt heap Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateDat … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 … Flink Blink _HEAP
  • 30. Nt heap • Remark • 關於 header encoding • 所有的 chunk 都會經過 xor 過,在存 chunk header 時,會將整個 header^(_HEAP->Encoding) 在存入 • decode 時會驗證 check sum 確保沒被改掉 • 驗證⽅方式為 encode_header^(_HEAP->Encoding) 後的值,前 3 byte xor 後和第 4 byte 比對
  • 31. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • 主要⽤用來來管理理各種不同⼤大⼩小的 freed chunk 的結構,⽅方便便在配置記憶體 時,能快速的找到適合的 chunk
  • 32. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • ExtendedLookup (_HEAP_LIST_LOOKUP) • 指向下⼀一個 ExtendedLookup • 通常下⼀一個會管理理更更⼤大塊 chunk 所⽤用的 結構 • ArraySize • 該結構會管理理的,最⼤大 chunk 的⼤大⼩小, 通常為 0x80 (實際上是 0x800) BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  • 33. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • ItemCount • ⽬目前該結構所管理理的 chunk 數 • OutofRangeItems • 超出該結構所管理理⼤大⼩小的 chunk 的 數量量 BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  • 34. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • BaseIndex • 該結構所管理理的 chunk 的起始 index, ⽤用來來從 ListHint 找適合⼤大⼩小的 free chunk ⽤用的,下⼀一個 BlocksIndex 將從 這個 index 的最⼤大值作為 BaseIndex • ListHead (_HEAP_ENTRY) • FreeList 的 Head BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  • 35. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • ListsInUseUlong • ⽤用在判斷 ListHint 中是否有適合⼤大⼩小的 chunk,是⼀一個 bitmap • ListHint • 重要結構,⽤用來來指向相對應⼤大⼩小的 chunk array • 其⽬目的就在於更更快速找到適合⼤大⼩小的 chunk
 ⼤大⼩小為 0x10 為⼀一個間隔 BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  • 36. … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageDat … _HEAP BlocksIndex ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Flink Blink Chunk header (0x110) PreviousBlockPrivate Flink Blink Chunk header(0x160) PreviousBlockPrivat ListHint Flink Flink Flink ListHint[7] ListHint[0x11] ListHint[0x16] 000001…1…1000000000 ListsInUseUlong
  • 37. Nt heap • Nt Heap • 後端管理理器 (Back-End) • Data structure • 分配機制
  • 38. Nt heap • Allocate (RtlpAllocateHeap) • 基本上分為三種 • Size <= 0x4000 • 0x4000 < size <= 0xff000 • Size > 0xff000
  • 39. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • 基本上主要分配都會在 RtlpAllocateHeap • 接著會去看該 size 對應到的 FrontEndHeapStatusBitmap 使否有啟⽤用 LFH • 沒有的話會對對應到的 FrontEndHeapUsageData 加上 0x21 • 並且檢查值是否超過 0xff00 或者 & 0x1f 後超過 0x10
 通過條件就會啟⽤用 LFH
  • 40. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • 接下來來會先看對應到的 ListHint 是否有值,會以 ListHint 中的 chunk 為優先 • 如果有適合剛好的 chunk 在 ListHint 上則移除 ListHint,並且會看該 chunk 的 Flink ⼤大⼩小是否 剛好也是同樣 size • 是的話就將 LintHint 填上 Flink • 不是則清空 • 最後則 unlink 該 chunk 把這塊 chunk 從 linked list 中移除返還給使⽤用者,並將 header xor 回去
  • 41. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • 如果沒有剛好適合的 • 從比較⼤大的 ListHint 中找,有找到比較⼤大的後如果該 chunk 將會從 ListHint 則移除之, 並看下⼀一塊 chunk size 有沒有剛好⼤大⼩小,有則補上,並且 unlink 將該 chunk 移除 freelist • 最後將該 chunk 做切割,剩下的⼤大⼩小重新加入 Freelist ,如果可以放進 ListHint 就會放 進去 • 然後回傳切好的 chunk 給使⽤用者,這邊也會對切割後跟回傳使⽤用者的 chunk header xor
  • 42. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • 如果 FreeList 中都沒有 • 嘗試 ExtendHeap 加⼤大 heap 空間 • 再從 extend 出來來的 chunk 拿 • 接著後⾯面⼀一樣切割,放回 ListHint,xor header
  • 43. Nt heap • Allocate (RtlpAllocateHeap) • 0x4000 < size <= 0xff000 • 除了了沒有對 LFH 相關的操作外,其餘都跟 0x4000 ⼀一樣
  • 44. Nt heap • Allocate (RtlpAllocateHeap) • Size > 0xff000 (VirtualMemoryThreshold << 4) • 直接使⽤用 ZwAllocateVirtualMemory • 類似 mmap 直接給⼀一⼤大塊,並且會插入 _HEAP->VirtualAllocdBlocks 這個 linked list 中 • 這個 linked list 是串串接該 Heap VirtualAllocate 出來來的區段⽤用的
  • 45. Nt heap • Free (RtlpFreeHeap) • 可分為 • Size <= 0xff000 • Size > 0xff000
  • 46. Nt heap • Free (RtlpFreeHeap) • Size <= 0xff000 • 會先檢查 alignment、利利⽤用 unused byte 判斷該 chunk 狀狀態 • 如果是非 LFH 下,會對對應到的 FrontEndHeapUsageData 減 1 • 接著會判斷前後的 chunk 是否為 freed ,是的話就合併 • 此時會把可以合併的 chunk 做 unlink ,並從 ListHint 移除 • 移除⽅方式與前⾯面相同,看看下⼀一塊是不是同樣⼤大⼩小,是的話補上 ListHint
  • 47. Nt heap • Free (RtlpFreeHeap) • Size <= 0xff000 • 合併完後, update size & prevsize ,然後會看看是不是最前跟最後, 是就插入,不⾏行行插入就從 ListHint 中插入,並且 update ListHint,插入 時也會對 linked list 做檢查 • 但這檢查不會 abort • 其原因主要因為不做 unlink 寫入
  • 48. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Free(Q) Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7)
  • 49. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find Prevchunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Prevchunk = Chunk address - (prevsize << 4)
  • 50. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find Prevchunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Prevchunk = chunk addr - 0x70
  • 51. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Decode prevchunk
 header Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7)
  • 52. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check checksum Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) SmallTagInex ==
 (size & 0xff) xor (size >> 8) xor Flag
  • 53. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check checksum Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) 7 ==
 0x7^0x0^0x0
  • 54. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 linked list Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) P->Flink->Blink == 
 P->Blink->Flink == 
 P
  • 55. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find 
 BlocksIndex Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7)
  • 56. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find suitable 
 BlocksIndex Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Check P->size < ArraySize
  • 57. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Check ListHint[7] == Prevchunk
  • 58. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Check prevchunk->Flink == ListHead 成立的話會準備 update
 ListHint
  • 59. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint[7]->Flink Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) decode prevchunk->Flink And check the checksum 由於前⼀一張 slide 不成立 要去驗 Flink 的 size

  • 60. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint[7]->Flink Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Size == 
 prevchunk->Flink->size 如果相等,直接將 ListHint 換成下⼀一塊

  • 61. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 ListHint[7] Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) ListHint[7] =
 prevchunk->Flink
  • 62. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Unlink
 prevchunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Prevchunk->Blink->Flink
 = Prevchunk->Flink
 Prevchunk->Flink->Blink = Prevchunk->Blink
  • 63. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 prevchunk
 and next chunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Prevchunk->size =
 0x11 + Prevchunk->size(7) R->Prevsize = 0x18 P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  • 64. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 next chunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) 檢查下⼀一塊 chunk
 使否 freed P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  • 65. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find suitable
 BlocksIndex
 For P Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check
 P->Size < ArraySize P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  • 66. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Search
 insert
 point Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check
 P->size < ListHead->Blink->Size
 P->size < ListHead->Flink->Size P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  • 67. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Insert
 linked list Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check
 S->Blink->Flink
 == S If not pass it will not 
 abort
 But it will not unlink P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  • 68. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 ListHint Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) If LintHint[0x18] == NULL
 LintHint[0x18] = P P Flink Blink Chunk header (0x180) PreviousBlockPrivate FlinkListHint[0x18]
  • 69. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 header Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x18) SmallTagIndex = 
 (size >> 8) ^
 (size & 0xff) ^
 Flag P Flink Blink Chunk header (0x180) PreviousBlockPrivate FlinkListHint[0x18]
  • 70. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Encode
 header Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0xda) Flag (0xab) SmallTagIndex (0x41) P->header ^
 _HEAP->Encoding P Flink Blink Chunk header (0x180) PreviousBlockPrivate FlinkListHint[0x18]
  • 71. Nt heap • Free (RtlpFreeHeap) • Size > 0xff000 • 檢查該 chunk 的 linked list 並從 _HEAP->VirtualAllocdBlocks 移除 • 接著使⽤用 RtlpSecMemFreeVirtualMemory 將 chunk 整個 munmap 掉
  • 72. Back-End Exploitation • Unlink • 基本上與 Linux 中的 unlink 很類似,繞過⽅方法也差不多 • 簡⽽而⾔言之就是利利⽤用從 linked listed 移除 node 的⾏行行為來來做有限制的寫入 • 要注意的是在會 decode 的地⽅方,都要讓他正常 decode • 也就是 check sum 要過 • 另外⼀一點是 Flink 及 Blink 並不是指向 chunk 開頭,⽽而是直接指向 User data 部分,也就是 不太需要做偏移偽造 chunk • 所以找到⼀一個指向該 userdata 的 pointer 讓他繞過 double linked list 的驗證就好了了
  • 73. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  • 74. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  • 75. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  • 76. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  • 77. A A Chunk header (0x110) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint UAF T A
  • 78. A A Chunk header (0x110) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint Free(Q) T A
  • 79. Q A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A A ListHead QListHint[0x11] free(S) Update ListHint
  • 80. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A A S SListHint[0x11] Q ListHead
  • 81. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A A S SListHint[0x11] Q ListHead Let’s corrupt the heap !
  • 82. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead free(P)
  • 83. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Check next chunk 
 is free
  • 84. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Decode 
 chunk Q
  • 85. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead(&Q-8)->Blink == (&Q)->Flink == Q
  • 86. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead(&Q-8)->Blink == (&Q)->Flink == Q Flink Blink
  • 87. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead(&Q-8)->Blink == (&Q)->Flink == Q Flink Blink
  • 88. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead*(&Q) == *(&Q) == Q
  • 89. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead*(&Q) == *(&Q) == Q Pass the check !!
  • 90. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Find 
 BlockIndex
  • 91. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Check
 ListHint[0x11]
  • 92. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead由於 S != Q
 所以不會對 ListHint
 做任何處理理
  • 93. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Unlink !! Q->Blink->Flink = Q->Flink Flink Blink
  • 94. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q - 8 R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadUnlink !! Q = &Q-8
  • 95. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q - 8 R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Unlink !! Q->Flink->Blink = Q->Blink Flink Blink
  • 96. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadUnlink !! Q = &Q
  • 97. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadUpdate 
 chunk size
  • 98. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadUpdate 
 chunk size P
  • 99. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Search insert point P
  • 100. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadFind the last one And decode it P
  • 101. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead P Find the first one And decode it
  • 102. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead 我們要插在 A 前 P
  • 103. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Check
 A->Blink->Flink == A P
  • 104. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Check
 Q->Flink == A P
  • 105. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadFailed
 不過不會 abort 只是不會 insert P
  • 106. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Update 
 ListHint P
  • 107. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead P PListHint[0x22]
  • 108. Back-End Exploitation • Edit Q • 我們可以把 Q 周圍的 pointer 寫掉 • 最後可達成任意記憶體讀寫 P &Q R S T
  • 109. Back-End Exploitation • Edit Q • 我們可以把 Q 周圍的 pointer 寫掉 • 最後可達成任意記憶體讀寫 • 可對 Target 1 - 4 做寫入 P Target 1 Target 2 Target 3 Target 4
  • 110. Back-End Exploitation • After arbitrary memory reading and writing • Leak • ntdll.dll • PebLdr • binary address • Kernel32.dll
  • 111. Back-End Exploitation • After arbitrary memory reading and writing • Leak • kernelbase • KERNELBASE!BasepFilterInfo • Stack address
  • 112. Back-End Exploitation • After arbitrary memory reading and writing • Leak • ntdll.dll • _HEAP_LOCK • _HEAP->LockVariable.Lock • CriticalSection->DebugInfo • 指向 ntdll
  • 113. Back-End Exploitation • After arbitrary memory reading and writing • Leak • ntdll!PebLdr • _PEB_LDR_DATA • 可找出所有 DLL 的位置 • 不過缺點是最後⼀一兩兩個 byte 可能是 0 • 可先找出 binary base 從 IAT 找 kernel32
  • 114. Back-End Exploitation • After arbitrary memory reading and writing • Leak • BinaryBase • 從 IAT 找出 Kernel32 位置
  • 115. Back-End Exploitation • After arbitrary memory reading and writing • Leak • Kernel32 • 重要 dll 很多常⽤用 function 都在這 (CreateFile, ReadFile,WriteFile) • IAT • 獲得 kernelbase.dll 位置
  • 116. Back-End Exploitation • After arbitrary memory reading and writing • Leak • kernelbase • KERNELBASE!BasepFilterInfo • 指向 Heap 上的結構 • 裡⾯面有⾼高機率會有 stack pointer • https://j00ru.vexillium.org/2016/07/disclosing-stack-data-from-the-default- heap-on-windows/
  • 117. Back-End Exploitation • After arbitrary memory reading and writing • Leak • 如果 BasepFilterInfo 中沒有 stack address • 因 BasepFilterInfo 內容會有 stack address 是因為未初始化因素,所 以有機會沒有 stack address • 可以從 PEB 往前或往後算 1 個 page ,通常會是 TEB 位置,上⾯面繪 有 stack 尾段的位置,可以藉由該位置找出 retrun address
  • 118. Back-End Exploitation • After arbitrary memory reading and writing • Write • Return address • Control RIP • ROP to VirtualProtect/VirtualAlloc • Jmp to shellcode
  • 119. Windows memory allocator • Nt Heap • 後端管理理器 (Back-End) • 前端管理理器 (Front-End)
  • 120. Windows memory allocator • Nt Heap • 前端管理理器 (Front-End) • ⽬目前 win10 主要使⽤用 • LowFragmentationHeap • 在非 Debug 下才會 enable • Size < 0x4000
  • 121. Windows memory allocator • Nt Heap • 前端管理理器 (Front-End) • Data Structure • 分配機制
  • 122. Windows memory allocator • Nt Heap • 前端管理理器 (Front-End) • Data Structure • 分配機制
  • 123. LFH • FrontEndHeap (_LFH_HEAP) • HEAP (_HEAP) • 指向對應到的 _HEAP • Buckets (_HEAP_BUCKET) • ⽤用來來尋找配置⼤大⼩小對應到 Block ⼤大⼩小 的陣列列結構 … Heap0x18 0x2a4 … Buckets SegmentInfoArray … … LocalData 0x4a8 0xcc0
  • 124. LFH • FrontEndHeap (_LFH_HEAP) • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • _HEAP_LOCAL_SEGMENT_INFO array, 不同⼤大⼩小對應到不同的 Segment_info 結 構,主要管理理對應到的 Subsegment 的資訊 • LocalData (_HEAP_LOCAL_DATA) • 其中有個欄欄位指向 LFH 本⾝身,通常⽤用來來找 回 LFH … Heap0x18 … Buckets SegmentInfoArray … … LocalData 0x2a4 0x4a8 0xcc0
  • 125. LFH • Buckets (_HEAP_BUCKET) • BlockUnits • 要分配出去的⼀一個 block ⼤大⼩小 >> 4 • SizeIndex • 使⽤用者需要的⼤大⼩小 >> 4 BlockUnits Buckets SizeIndex … BlockUnits SizeIndex … … … Buckets[0] Buckets[1]
  • 126. LFH • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • LocalData (_HEAP_LOCAL_DATA) • 對應到 _LFH_HEAP->LocalData ⽅方便便 從 SegmentInfo 找回 _LFH_HEAP • BucketIndex • 對應到的 BucketIndex LocalData SegmentInfoArray[x] ActiveSubsegment CachedItems … BucketIndex …
  • 127. LFH • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • ActiveSubsegment (_HEAP_SUBSEGMENT) • 極為重要結構 • 對應到分配出去的 Subsegment • 其⽬目的在於管理理 Userblock • 記錄了了剩餘多少 chunk • 該 Userblock 最⼤大分配數等等 SegmentInfoArray[x] LocalData ActiveSubsegment CachedItems … BucketIndex …
  • 128. LFH • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • CachedItems (_HEAP_SUBSEGMENT) • _HEAP_SUBSEGMENT array • 存放對映到該 SegmentInfo 且還有可 以分配 chunk 給 user 的Subsegment • 當 ActiveSubsegment ⽤用完時,會從 這邊填充,置換掉 ActiveSubsegment SegmentInfoArray[x] LocalData ActiveSubsegment CachedItems … BucketIndex …
  • 130. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • LocalInfo (_HEAP_LOCAL_SEGMENT_INFO) • 指回對應到的 _HEAP_LOCAL_SEGMENT_INFO LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  • 131. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • UserBlock (_HEAP_USERDATA_HEADER) • LFH 的記憶體分配池 • 也就是要分配出去的 Chunk (Block) 所在位置 • 開頭會有些 metadata 管理理這些 chunk • 重要結構 LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  • 132. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • AggregateExchg (_INTERLOCK_SEQ) • ⽤用來來管理理對應到的 UserBlock 中還有 多少 freed chunk • LFH ⽤用這個判斷是否還從該 UserBlock 分配 • 同時也有 Lock 的作⽤用 LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  • 133. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • BlockSize • 在該 UserBlock 中每個 Block (chunk)的⼤大⼩小 • BlockCount • 在該 UserBlock 中 Block 的總數 • SizeIndex • 該 UserBlock 對應到的 SizeIndex LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  • 134. LFH • AggregateExchg (_INTERLOCK_SEQ) • Depth • 該 UserBlock 所剩下的 Freed chunk 數量量 • Lock • 就是 Lock AggregateExchg Depth0x0 Hint (15bit) Lock (1bit) 0x8
  • 135. LFH • UserBlock (_HEAP_USERDATA_HEADER) • SubSegment • 指回對應的 Subsegment • EncodeOffsets • ⽤用來來驗證 chunk header 是否有被改過 • BusyBitmap • 記錄該 UserBlock 哪些 chunk 有在⽤用的 bitmap SubSegment UserBlock … EncodedOffsets BusyBitmap 0x8 0x18 0x20 chunk header chunk header chunk header
  • 136. LFH • UserBlock (_HEAP_USERDATA_HEADER) • Block (chunk) • LFH 回傳給使⽤用者的 chunk SubSegment UserBlock … EncodedOffsets BusyBitmap 0x8 0x18 0x20 chunk header chunk header chunk header
  • 137. LFH • _HEAP_ENTRY (chunk) • SubSegmentCode • Encode 過的 metadata ⽤用來來推回 userblock 的位置 • PreviousSize • 該 chunk 在 UserBlock 中的 index User Data PreviousBlockPrivateData (8byte) SubSegmentCode (4byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  • 138. LFH • _HEAP_ENTRY (chunk) • Unusedbyte • Unusedbyte & 0x80 is true User Data PreviousBlockPrivateData (8byte) SubSegmentCode (4byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  • 139. LFH • _HEAP_ENTRY (chunk) • Unusedbytes • 恆為 0x80 • ⽤用來來判斷是否為 LFH 的 Free chunk User Data PreviousBlockPrivateData (8byte) SubSegmentCode (4byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Freed
  • 140. LFH • Remark • 關於 EncodedOffsets • 在 UserBlock 初始化時設置,其算法為下⾯面四個值的 xor • (sizeof(userblock header) | (BlockUnit*0x10 << 16)) • LFHkey • Userblock address • _LFH_HEAP address
  • 141. LFH • Remark • 關於 LFH header encoding • 所有的 chunk header 在初始化時都會經過 xor 過,算法為下⾯面個值的 xor • _HEAP address • LFHkey • Chunk address >> 4 • ((chunk address) - (UserBlock address)) << 12
  • 143. Windows memory allocator • Nt Heap • 前端管理理器 (Front-End) • Data Structure • 分配機制
  • 144. Windows memory allocator • Nt Heap • 前端管理理器 (Front-End) • 初始化 • 在 FrontEndHeapUsageData[x] & 0x1f > 0x10 時,下⼀一次的 allocate 會對 LFH 做出初始化 • 會先 ExtendFrontEndUsageData 及增加更更⼤大的 BlocksIndex (0x80-0x400) • 建立 FrontEndHeap • 初始化 SegmentInfoArrays[idx] • 接下來來在 allocate 相同⼤大⼩小的 chunk 就會開始使⽤用 LFH
  • 145. Windows memory allocator • LFH(初始化) • malloc(0x40) * 16 FrontEndHeapUsageData … 0x210 此時可 enable LFH 範圍為 index 0x0 - 0x80
  • 146. Windows memory allocator • LFH(初始化) • malloc(0x40) (第 17 次) FrontEndHeapUsageData … 0x231 0x231 & 0x1f > 0x10
  • 147. Windows memory allocator • LFH(初始化) FrontEndHeapUsageData … 0x231 heap->CompatibilityFlag |= 0x20000000 設置上這個 flag 後 下次 allocate 時會去初始化LFH

  • 149. Windows memory allocator • LFH(初始化) • malloc(0x40) (第 18 次) • ExtendFrontEndUsageData 及增加更更⼤大的 BlocksIndex (0x80-0x400) ,並設置對應的 bitmap • 並在該對應的 FrontEndHeapUsageData 寫上對應的 index,此時可 enable LFH 範圍變為 (idx: 0-0x400) • 建立並初始化 FrontEndHeap (mmap) • 初始化 SegmentInfoArrays[idx] • 在 SegmentInfoArrays[BucketIndex] 填上 segmentInfo FrontEndHeapUsageData … 0x4
  • 150. Windows memory allocator … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageData … _HEAP FrontEndHeapUsageData 0x251 0x4 BlocksIndex ExtendedLookup ArraySize(0x80) … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex (0x0) ListHead ListsInUseUlong ListHint BlocksIndex ExtendedLookup ArraySize (0x400) … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex (0x80) ListHead ListsInUseUlong ListHint
  • 152. Windows memory allocator • LFH(初始化) • malloc(0x40) (第 19 次) • Allocate Userblock 並初始化 • 設置對應的 chunk • 設置對應的 ActiviteSubsegment • 隨機返回其中的⼀一個 chunk Userblock metadata Chunk 00 Chunk 01 … Chunk MaxBlockCount
  • 154. Windows memory allocator • LFH • Allocate (RtlpLowFragHeapAllocFromContext) • 先看看 ActiveSubsegment 中是否有可分配的 chunk • 從 ActiveSubsegment->depth 判斷 • 如果沒有則會從 CachedItem 找,有找到的話會把 ActiveSubsegment 換成 CachedItem 中的 SubSegment
  • 162. Windows memory allocator • LFH • Allocate (RtlpLowFragHeapAllocFromContext) • 取得 RtlpLowFragHeapRandomData[x] 上的直 • 下⼀一次會從 RtlpLowFragHeapRandomData[x+1] 取 • x 為 1 byte ,當下次輪輪回 x 則會 x = rand() %256 繼續取 • RtlpLowFragHeapRandomData 為⼀一個 random 256 byte 的陣列列 • 範圍為 0x0 - 0x7f
  • 163. Windows memory allocator • LFH • Allocate (RtlpLowFragHeapAllocFromContext) • 最獲得的 index 為 • RtlpLowFragHeapRandomData[x]*maxidx >> 7 • 如果 collision 則往後取最近的 • 檢查 (unused byte & 0x3f) !=0 (表⽰示 chunk 是 freed) • 最後設置 index 及 unused byte 就返回給使⽤用者
  • 164. …. …. …. SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADER • Get an index • RtlpLowFragHeapRandomData[x]*maxidx >> 7 • 檢查該 index 對映到的 bitmap 是否為 0 • 是 0 則返回對映的 bitmap • 非 0 擇取最近的下⼀一個 chunk header
  • 165. …. …. …. SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADER • 算出來來的 index 發現已⽤用過 • 會取下⼀一個 • 並設置對映的 bitmap chunk header
  • 166. …. …. …. SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADER • 算出來來的 index 發現已⽤用過 • 會取下⼀一個 • 並設置對映的 bitmap chunk header
  • 167. Windows memory allocator • LFH • Free (RtlFreeHeap) • Update unused byte in chunk header • Find the index of the Chunk and reset Userblock->BusyBitmap • Update ActiveSubsegment->AggregateExchg • 如果 Free 的 chunk 不屬於當前 ActiveSubsegment 則會看看能不能放 進 cachedItems ,可以放就放進去
  • 168. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • ⽤用 chunk header 尋找 UserBlock
  • 169. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • ⽤用 chunk header 尋找 UserBlock • 找回對映的 SubSegment
  • 170. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • ⽤用 chunk header 尋找 UserBlock • 找回對映的 SubSegment • 設置 unused byte = 0x80 • 清除對映的 bitmap • Update AggregateExchg
  • 171. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • ⽤用 chunk header 尋找 UserBlock • 找回對映的 SubSegment • 設置 unused byte = 0x80 • 清除對映的 bitmap • Update AggregateExchg
  • 172. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • ⽤用 chunk header 尋找 UserBlock • 找回對映的 SubSegment • 設置 unused byte = 0x80 • 清除對映的 bitmap • Update AggregateExchg
  • 173. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADERLocalData ActiveSubsegment CachedItems … BucketIndex … LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT Depth (1) Hint (15bit) Lock (1bit) _INTERLOCK_SEQ CachedItems ActiveSubsegmet 不等於 Free 掉 chunk 的
 SubSegment
  • 174. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADERLocalData ActiveSubsegment CachedItems … BucketIndex … LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT Depth (1) Hint (15bit) Lock (1bit) _INTERLOCK_SEQ CachedItems CachedItems[0]
  • 175. LFH Exploitation • Reuse attack • 假設我們有 Use after free 的漏洞洞 • 但因為 LFH 的隨機性,導致無法預側下⼀一塊 chunk 會在哪,使得我們 很難利利⽤用 • 這時可以填滿 Userblock 的⽅方式,在 free 掉其中⼀一塊,那麼下次該 chunk 必定會拿到同⼀一塊,我們可以利利⽤用這個特性,拿到 overlap chunk 做進⼀一步利利⽤用
  • 176. LFH Exploitation • normal case • malloc(sizeof(A)) Userblock header
  • 177. LFH Exploitation • normal case • malloc(sizeof(B)) Userblock header fptr
  • 178. LFH Exploitation • normal case • free(A) Userblock header B fptr
  • 179. LFH Exploitation • normal case • malloc(sizeof(A)) Userblock header B fptr
  • 180. LFH Exploitation • normal case • malloc(sizeof(B)) Userblock header B fptr
  • 181. LFH Exploitation • normal case • malloc(sizeof(B)) Userblock header B fptr Hard to use
  • 182. LFH Exploitation • Reuse attack • malloc(sizeof(A)) Userblock header
  • 183. LFH Exploitation • Reuse attack • malloc(sizeof(B)) x 6 Userblock header fptr
  • 184. LFH Exploitation • Reuse attack • free(A) Userblock header B B B B fptr B B
  • 185. LFH Exploitation • Reuse attack • malloc(sizeof(B)) Userblock header B B B B fptr B B
  • 186. LFH Exploitation • Reuse attack • A->fptr Userblock header B B B B fptr B B
  • 187. LFH Exploitation • Reuse attack • A->fptr Userblock header B B B B fptr B B Hijack the control flow !
  • 189. Thank you for listening !189 angelboy@chroot.org @scwuaptx !189