Mechanism of glibcmalloc • Allocated chunk DATA prev_size size N M P P:PREV_INUSED M:IS_MMAPPED N:NON_MAIN_ARENA
13.
Mechanism of glibcmalloc • freed chunk • prev_size • size • fd : point to next chunk ( 包含 bin ) • 這邊指的是 linked list 中的 next chunk,⽽而非連續記憶體中的 chunk • bk : point to last chunk ( 包含 bin ) • 這邊指的是 linked list 中的 last chunk,⽽而非連續記憶體中的 chunk • fd_nextsize : point to next large chunk(不包含 bin) • bk_nextsize : point to last large chunk (不包含 bin)
14.
Mechanism of glibcmalloc • freed chunk DATA prev_size size N M P P:PREV_INUSED M:IS_MMAPPED N:NON_MAIN_ARENA fd bk
15.
Mechanism of glibcmalloc • top chunk • 第⼀一次 malloc 時就會將 heap 切成兩兩塊 chunk,第⼀一塊 chunk 就是分配出 去的 chunk ,剩下的空間視為 top chunk,之後要是分配空間不⾜足時將會由 top chunk 切出去 • prev_size • size • 顯⽰示 top chunk 還剩下多少空間
16.
Mechanism of glibcmalloc • bin • linked list • 為了了讓 malloc 可以更更快找到適合⼤大⼩小的 chunk,因此在 free 掉⼀一個 chunk 時,會把該 chunk 根 據⼤大⼩小加入適合的 bin 中 • 根據⼤大⼩小⼀一共會分為 • fast bin • small bin • large bin • unsorted bin
17.
Mechanism of glibcmalloc • fast bin • a singly linked list • chunk size < 144 byte • 不取消 inuse flag • 依據 bin 中所存的 chunk ⼤大⼩小,在分為 10 個 fast bin 分別為 size 0x20,0x30,0x40… • LIFO • 當下次 malloc ⼤大⼩小與這次 free ⼤大⼩小相同時,會從相同的 bin 取出,也就是會取到相 同位置的 chunk
18.
• fast bin Mechanismof glibc malloc 0x128 0 0xddaa …… 0 ….. 0x20size 0x30 0x40 …. 0x70 …. prev_size size = 0x20 fd = null bk = null data data prev_size size = 0x40 fd = null bk = null data data 0x128 0xddaa fast bin array
19.
• fast bin Mechanismof glibc malloc 0x20size 0x30 0x40 …. 0x70 …. prev_size size = 0x20 fd = null bk = null data data prev_size size = 0x40 fd = null bk = null data data 0x128 0xddaa free(0x466) fast bin array 0x128 0 0xddaa …… 0 …..
20.
Mechanism of glibcmalloc • fast bin 0x20size 0x30 0x40 …. 0x70 …. prev_size size = 0x20 fd = null bk = null data data prev_size size = 0x40 fd = ddaa bk = null data data prev_size size = 0x40 fd = null bk = null data data 0x128 0x456 0xddaa fast bin array 0x128 0 0x456 …… 0 …..
21.
Mechanism of glibcmalloc • fast bin 0x20size 0x30 0x40 …. 0x70 …. prev_size size = 0x20 fd = null bk = null data data prev_size size = 0x40 fd = ddaa bk = null data data prev_size size = 0x40 fd = null bk = null data data 0x128 0x456 0xddaa malloc(0x30) fast bin array 0x30 為使⽤用這所需⼤大⼩小,分配需加上 chunk header 所以分配到 0x40 的 chunk 0x128 0 0x456 …… 0 …..
22.
• fast bin Mechanismof glibc malloc 0x20size 0x30 0x40 …. 0x70 …. prev_size size = 0x20 fd = null bk = null data data prev_size size = 0x40 fd = null bk = null data data 0x128 0xddaa fast bin array 0x128 0 0xddaa …… 0 …..
23.
Mechanism of glibcmalloc • unsorted bin • circular doubly linked list • 當 free 的 chunk ⼤大⼩小⼤大於等於 144 byte 時,為了了效率,glibc 並不會⾺馬 上將 chunk 放到相對應的 bin 中,就會先放到 unsorted bin • ⽽而下次 malloc 時將會先找找看 unsorted bin 中是否有適合的 chunk , 找不到才會去對應得 bin 中尋找, 此時會順便便把 unsorted bin 的 chunk 放到對應的 bin 中,但 small bin 除外,為了了效率,反⽽而先從 small bin 找
24.
Mechanism of glibcmalloc • small bin • circular doubly linked list • chunk size < 1024 byte • FIFO • 根據⼤大⼩小在分成 62 個⼤大⼩小不同的 bin • 0x20,0x30…0x60,0x70,0x90,……1008
25.
Mechanism of glibcmalloc • large bin • circular doubly linked list (sorted list) • chunk size >= 1024 • freed chunk 多兩兩個欄欄位 fd_nextsize 、bk_nextsize 指向前⼀一塊跟後⼀一塊 large chunk • 根據⼤大⼩小在分成 63 個 bin 但⼤大⼩小不再是⼀一固定⼤大⼩小增加 • 前 32 個 bin 為 0x400+64*i • 32 - 48 bin 為 0x1380 + 512*j • ....依此類推 • 不再是每個 bin 中的 chunk ⼤大⼩小都固定,每個 bin 中存著該範圍內不同⼤大⼩小的 bin 並在存的過程中進⾏行行 sort ⽤用來來加快 search 的 速度,⼤大的 chunk 會放在前⾯面,⼩小的 chunk 會放在後⾯面 • FIFO
26.
Mechanism of glibcmalloc • last remainder chunk • 在 malloc ⼀一塊 chunk 時,如果有找到比較⼤大的 chunk 可以給 user 會做 split 將 chunk 切成兩兩部分,多的那⼀一部分會成為⼀一塊 chunk 放到 last remander 中,unsortbin 也會存這⼀一塊 • 當下次 malloc 時,如果 last remainder chunk 夠⼤大,則會繼續從 last remainder 切出來來分配給 user
27.
Mechanism of glibcmalloc • unsorted bin, small bin , large bin (chunk array) 0x123 &bin2 &bin14 …… &bin64 0xdead …… 1bin_index 2 14 63 64 …. fd 126…. …. ….73 0x789 &bin2 &bin14 …… &bin64 0xbeef ……bk prev_size size = 144 fd = 0x789 bk = &bin1 data data prev_size size = 196 fd = &bin1 bk = 0x123 data data 0x123 0x789 prev_size size = 1152 fd = 0xbeef bk = &bin73 fd_nextsize bk_nextsize data prev_size size = 1140 fd = &bin73 bk = 0xdead fd_nextsize bk_nextsize data 0xdead 0xbeef
28.
Mechanism of glibcmalloc • main arena header • malloc_state • 存有所有的 bin 、 top chunk 等資訊 • 位於 libc 的 bss 段中
Mechanism of glibcmalloc prev_size = 0x90 size = 0x90 prev_size = 0 size = 0x91 prev_size = 0 size = 0x90 fd = &small bin bk = &small bin p 0x4b000 0x4b000 0x4b000 small bin unsorted bin free(p) &unsortbin &unsortbin
33.
Mechanism of glibcmalloc prev_size = 0x90 size = 0x90 prev_size = 0 size = 0x91 prev_size = 0 size = 0x90 fd = &small bin bk = &small bin p 0x4b000 unsorted bin 先利利⽤用 size 找到下 ⼀一塊 chunk p - 0x10 + 0x90 0x4b000 0x4b000 &unsortbin &unsortbin small bin
34.
Mechanism of glibcmalloc prev_size = 0x90 size = 0x90 prev_size = 0 size = 0x91 prev_size = 0 size = 0x90 fd = &small bin bk = &small bin p 0x4b000 unsorted bin 利利⽤用 inuse bit 檢查是否有被 free 過 0x4b000 0x4b000 &unsortbin &unsortbin small bin
35.
Mechanism of glibcmalloc prev_size = 0x90 size = 0x90 prev_size = 0 size = 0x91 prev_size = 0 size = 0x90 fd = &small bin bk = &small bin p 0x4b000 unsorted bin 檢查上⼀一塊 是否為 freed 0x4b000 0x4b000 &unsortbin &unsortbin small bin
36.
Mechanism of glibcmalloc prev_size = 0x90 size = 0x90 prev_size = 0 size = 0x91 prev_size = 0 size = 0x90 fd = &small bin bk = &small bin p 0x4b000 unsorted bin 利利⽤用 prev_size 找到上⼀一塊 chunk p - 0x10 - 0x90 0x4b000 0x4b000 &unsortbin &unsortbin small bin
37.
Mechanism of glibcmalloc prev_size = 0x90 size = 0x90 prev_size = 0 size = 0x91 prev_size = 0 size = 0x90 fd = null bk = null p &smallbin &smallbinm 0x4b000 small bin &unsortbin &unsortbin unsorted bin 進⾏行行 unlink 將上⼀一塊 chunk 從 bin 中移除
38.
Mechanism of glibcmalloc prev_size = 0x120 size = 0x90 prev_size = 0 size = 0x120 fd = null bk = null p 0x4b000 small bin unsorted bin merge &smallbin &smallbinm &unsortbin &unsortbin
39.
Mechanism of glibcmalloc prev_size = 0x120 size = 0x90 prev_size = 0 size = 0x120 fd = &unsorted bin bk = &unsorted bin p 0x4b000 small bin unsorted bin 加入 unsorted bin 中 &smallbin &smallbinm 0x4b000 0x4b000
Use after free •Assume there exists a dangling ptr • p is a pointer of movement • free(p)
45.
Use after free •Assume there exists a dangling ptr • p is a pointer of movement • free(p) // p is dangling ptr • q = (*struct stu)malloc(sizeof(stu)) • 此時因為 fast bin 的關係使 p == q
46.
Use after free •Assume there exists a dangling ptr • p is a pointer of movement • free(p) // p is dangling ptr • q = (*struct stu)malloc(sizeof(stu)) • 此時因為 fast bin 的關係使 p == q • set id = 0x616161616161
47.
Use after free •Assume there exists a dangling ptr • p is a pointer of movement • free(p) // p is dangling ptr • q = (*struct stu)malloc(sizeof(stu)) • 此時因為 fast bin 的關係使 p == q • set id = 0x616161616161 • p.playctf()
48.
Use after free •Assume there exists a dangling ptr • p is a pointer of movement • free(p) // p is dangling ptr • q = (*struct stu)malloc(sizeof(stu)) • 此時因為 fast bin 的關係使 p == q • set id = 0x616161616161 • p.playctf() rip = 0x616161616161
49.
Outline • Glibc memoryallocator Overview • Use After Free • Heap Overflow • Appendix - Detection in Glibc
Heap overflow • usingunlink (modern) • bypass the detection • there’re a pointer r point to data of the second chunk. prev_size = 0 size = 0x91 prev_size = 0 size = 0x80 prev_size = 0 size = 0x91 q r
71.
Heap overflow • usingunlink (modern) • bypass the detection • there’re a pointer r point to data of the second chunk. • overflow and forge chunks. prev_size = 0 size = 0x80 prev_size = 0 size = 0x80 prev_size = 0 size = 0x81 fd = &bin bk = &bin q rfake prev_size = 0x90 fake size = 0x80 fake fd = &r-0x18 fake bk = &r-0x10 fake prev_size2=0x80 size = 0x90 fake chunk
72.
Heap overflow • usingunlink (modern) • bypass the detection • there’re a pointer r point to data of the second chunk. • overflow and forge chunks. • you can see the pointer r is point to the fake chunk prev_size = 0 size = 0x80 prev_size = 0 size = 0x80 prev_size = 0 size = 0x81 fd = &bin bk = &bin fake prev_size = 0x90 fake size = 0x80 fake fd = &r-0x18 fake bk = &r-0x10 fake prev_size2=0x80 size = 0x90 r q
Heap overflow • Usingmalloc maleficarum • The House of Mind • The House of Prime • The House of Spirit • The House of Force • The House of Lore
88.
The House ofSpirit • stack overflow • 當 stack overflow 不夠蓋到 ret 時 • 利利⽤用 stack overflow 蓋過要 free 的 ptr 並偽造 chunk • 須針對 prev_size 及 size 做處理理,通過檢查 • using fastbin • 當下次 malloc 時 就會取得偽造的 chunk
89.
The House ofSpirit • 可以做 information leak • 也可加⼤大 stack overflow 的距離 • 要先算算看在 stack 中取下⼀一塊 chunk 的 size 是否合法為 0x10 的倍數, size 的取決是很重要的 • 32 bit 為 0x8 倍數
90.
The House ofSpirit • Assume exist free(p) • read(0,buf,size) • read 不夠長到可以蓋 ret fake_size_2 … ret ebp … … *p dddd eeee buf q size
91.
The House ofSpirit • overflow *p fake chunk fake_size_2 … ret ebp … … *q fake_size fake prev_size buf q
92.
The House ofSpirit • overflow *p • free(p) -> free(q) fake chunk fake_size_2 … ret ebp … … *q fake_size fake prev_size buf q
93.
The House ofSpirit • overflow *p • free(q) • 下⼀一塊 size 要合法 fake_size_2 … ret ebp … … *q fake_size fake prev_size buf q
94.
The House ofSpirit • overflow *p • free(q) • malloc(fake_size-16) • it will return q fake_size fake_size_2 … ret ebp … … *q fake_size fake prev_size buf q
95.
The House ofSpirit • overflow *p • free(q) • malloc(fake_size-16) • it will return q • read(0,q,fake_size-16) fake_size_2 … ret ebp … … *q fake_size fake prev_size buf q
96.
The House ofSpirit • overflow *p • free(q) • malloc(fake_size-16) • it will return q • read(0,q,fake_size-16) overflow fake_size_2 … aaaa aaaa aaaa aaaa aaaa fake_size fake prev_size buf q
97.
The House ofForce • malloc 從 top 分配空間時,top 位置會以當前位置+分配 chunk ⼤大⼩小,作為 新的 top 位置 • nb = malloc 時 user 所需⼤大⼩小 • new top = old top + nb + sizeof(chunk header)
98.
The House ofForce • malloc(nb) prev_size data top chunk size prev_size top_size
99.
The House ofForce • malloc(nb) • 檢查 top_size 是否夠分配給使⽤用者 • top_size - nb > 0 ? • true : 從 top 分配 • false : 使⽤用 mmap or 擴⼤大 heap 空間 prev_size data top chunk size prev_size top_size
100.
The House ofForce • malloc(nb) • new top = old top + nb + sizeof(chunk header) prev_size data top chunk size prev_size top_size
101.
The House ofForce • malloc(nb) • new top = old top + nb + sizeof(chunk header) • new_top_size = top_size - (nb+sizeof(chunk header) prev_size data old top size prev_size nb + sizeof(header) new topprev_size new_top_size data nb + sizeof(header)
102.
The House ofForce • heap overflow 蓋過 top chunk 的 size,變成⼀一個很⼤大的值 • 下次 malloc 時,malloc ⼀一個很⼤大的數字(nb),然後 arena header 中的 top chunk 的位置會改變 • new top chunk = old top + nb + sizeof(header) • nb 可以是負的,因為傳進去會被⾃自動轉成很⼤大的數字,只要讓 fake size - nb > 0 就會讓 glibc 以為 top 還有空間可以給,因 nb 是負的,所以 top 會往前,造 成 overlap • 這樣下次 malloc 的位置將會是 new top chunk 的位置
103.
The House ofForce prev_size data prev_size top chunk size size data prev_size size
104.
The House ofForce 0 function ptr 0 top chunk 0x41 0x41 data 0 0x20f81
105.
• Overflow • topsize -> a large value The House of Force 0 function ptr 0 top chunk 0x41 0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff
106.
• Overflow • topsize -> a large value • malloc(nb) • new top chunk = old top + nb + 16 • nb = new top - old top - 16 The House of Force 0 function ptr 0 top chunk 0x41 0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff
107.
• Overflow • topsize -> a large value • malloc(nb) • new top chunk = old top + nb + 16 • nb = -(0x40+0x40) - 0x10 = -0x90 = - 144 The House of Force 0 function ptr 0 top chunk 0x41 0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff new top
108.
• Overflow • topsize -> a large value • malloc(-144) • check • 0xffffffffffffffff - (-144) > 0 The House of Force 0 function ptr 0 top chunk 0x41 0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff new top
109.
• Overflow • topsize -> a large value • malloc(-144) • malloc(0x30) The House of Force 0 function ptr 0 top chunk 0x79 0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff
110.
• Overflow • topsize -> a large value • malloc(-144) • malloc(0x30) • call function ptr The House of Force 0 aaaaaaaa 0 top chunk 0x41 0x79-0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff
111.
• Overflow • topsize -> a large value • malloc(-144) • malloc(0x30) • call function ptr The House of Force 0 aaaaaaaa 0 top chunk 0x79 0x41 aaaaaaaa aaaaaaaa aaaaaaaa 0xffffffffffffffff Control RIP