堆利用之unlink

2021-08-19 13:52:18 字數 2798 閱讀 2117

一 small bin,large bin等的記憶體結構

未分配的chunk

|  pre chunk size  |   size  |f|c|p|

|  fd       |         bk         |

presize: 前乙個塊的大小(如果前乙個塊是空閒的)

size:當前塊的大小

f標誌位:目前還沒有用

c標誌位:如果當前塊已被分配,置1;否則,置0

p標誌位:如果前乙個塊已被分配,置1,;否則,置0

二、unlink

久經辛苦終於看明白了。還是很精妙的。

unlink是free非fastbin時,會先檢查該chunk前乙個chunk是否為空閒,如果是空,則合併。

利用思路是溢位修改被free的chunk頭部的pre chunk size和size中的p位為0,導致合併空閒chunk。並在相鄰處偽造乙個chunk頭部。最終得到乙個任意位址寫。

例項說明

以how2heap的unsafe_unlink為例子說明,程式的注釋已經去掉

uint64_t *g_fake_chunk; //a

int main()

a unlink時檢查(f -> bk == p && b -> fd == p),需要乙個儲存著堆位址的空間,一般為乙個位址可知的變數

b 此時,記憶體分布如下:

g_fake_chunk------->    chunk0      |    0  |   size(0x90)  |        (addr)low

| 0(fd) |       0(bk)      |   

| 內容0x80byte       |

chunk1      |     0         |    size        |       

|    0(fd)   |   0(bk)      |   

| 內容0x80byte         | (addr)high

chunk0和chunk1是相鄰的。此外,g_fake_chunk指向chunk0

c d e三步驟後, chunk0的記憶體分布為

chunk0 | 0 |

|   0x90 |

chunk0內容 | 0 |   |---------------> g_fake_chunk-0x18| |

| 8 |         |   |---> g_fake_chunk-0x10| |

|     g_fake_chunk-0x18   |------|   | g_fake_chunk-0x8  | |

|     g_fake_chunk-0x10   |-----------------| g_fake_chunk | |

此步作用是為了能通過f -> bk == p && b -> fd == p檢查,具體在free中描述

f g步驟後,chunk1的頭部被修改為:

chunk1  |   0x80   |   size |p=0 |       

| 0(fd)    |       0(bk)    |   

| 0*0x80             |

這個修改表示,前一塊chunk沒有被使用,長度為0x80

h 重點來了,free非fastbin時,檢查前後chunk是否為空閒,如果是,會合併相鄰chunk。並做unlink。

為了清楚,再細畫一次此時的記憶體狀態。

chunk0 |   0    |

|     0x90    |

chunk0內容fake_chunk0         |   0    |    |------------> g_fake_chunk-0x18 | |

|       8     |    |   |---> g_fake_chunk-0x10 | |

| g_fake_chunk-0x18  |-----|   | g_fake_chunk-0x8   | |

| g_fake_chunk-0x10  |---------------| g_fake_chunk  | |

| 0x60位元組    | 0x60位元組是因為去掉了偽造的chunk頭部0x20剩下的

chunk1 | 0x80           | 

| size     |p=0 |       

|    0(fd)                 | 

| 0(bk)           |   

|    0*0x80             |

由於f g步驟後,chunk1的p位被竄改為0,認為前一塊為空,大小為0x80。

計算到前一塊的頭為chunk1-0x80,即chunk0內容位置,此塊空間是漏洞利用時可控的,且c d e三步驟時在在這裡偽造了乙個chunk頭。這裡稱呼它為fake_chunk0

此時執行unlink

unlink(p) //p即g_fake_chunk0

f = p -> fd;  //f = g_fake_chunk - 12

b = p -> bk;  //b = g_fake_chunk - 8

if (f -> bk == p && b -> fd == p)

此時,記憶體結構為

g_fake_chunk-0x18 |     |<---|

g_fake_chunk-0x10 |     |       |

g_fake_chunk-0x8   |     |       |

g_fake_chunk      |g_fake_chunk-12|-----|

i 因為這個位址並不是我們想要的任意位址,要實現任意位址寫,需要把g_fake_chunk覆蓋為任意位址

堆溢位利用

0x1 申請 0x2 使用 0x3 釋放 堆塊包括塊首與塊身 返回的指標指向 塊首是乙個堆塊頭部的幾個位元組,用來標識這個堆塊自身的資訊。未被占用的堆區 被占用的堆區 位於堆區的起始位置,堆表分為兩種空閒雙向鍊錶freelist 空表 128條 和快速單向鍊錶lookaside 快表 最多只有四項 ...

STL應用之大根堆小根堆

定義 priority queue 大根堆 priority queue,greater x 小根堆 訪問最值使用 top 堆自動把最值維護在堆最上層 刪除最值使用 pop 刪除後自動維護出乙個新堆 插入元素使用 push x 插入到元素該在的位置上 並自動維護堆有序 include include...

利用堆之優先佇列

利用上一節的最大堆,中間省略了很多該刪和修改的東西,總是時學習演算法嗎 懶了一些啊,o o include include struct heap int paraent int i int leftchild int i int rightchild int i void max heap int...