1. 程式人生 > 其它 >Dance In Heap(三):一些堆利用的方法(中)

Dance In Heap(三):一些堆利用的方法(中)

0x00 前面的話

在前一篇堆的利用方法裡面,我們簡單的提了一下UAF,並主要對從 bin 中釋放 chunk 的操作,即 unlink 巨集、unsortedbin attack,進行了利用。那麼在本篇中,我們主要討論如何將對一個對一個chunk進行復用來進行某種攻擊。

在這裡面我們要當心,chunk size的計算是個需要小心的地方,因為這裡包括了 prev_size的複用,以及根據不同系統考慮的對齊情況,還有 chunk 的size位表示的是包括chunk header在內的size,而實際可用的size與此不同,它是減去chunk header後的大小。

本篇文章目錄

0x01 fastbin attack
0x02 overlapping chunk 1
0x03 overlapping chunk 2
0x04 小結

0x01 fastbin attack

還記不記得我們在第一篇中那個介紹 fastbin 中 dobule free的例子

#include <stdio.h>
#include <stdlib.h>
int main() {
    char *a=malloc(24);
    char *b=malloc(24);
    free(a);
    free(b);
    free(a);
}

這個執行是沒有問題的,但是想象一下,這樣做之後,現在的 fastbin 中是什麼樣子

  -------     -------     -------     -------    -------
 | 頭結點 |-> |   a   |-> |   b   |-> |   a   |->|  null |
  -------     -------     -------     -------    -------

其中的指向關係由chunk的 fd 指標標識。此時我們再從 fastbin中 malloc 出一個 chunk

c = malloc(24);

此時的 fastbin

  -------     -------     -------     -------
 | 頭結點 |-> |   b   |-> |   a   |-> |  null |
  -------     -------     -------     -------

現在我們得到了一個chunk,並且這個 chunk 同時在 fastbin中也存在,那麼此時如果我們修改 c 的 fd 指標位置為任意地址,那麼 fastbin 中 a 的指向也會發生改變

  -------     -------     -------     -------
 | 頭結點 |-> |   b   |-> |   a   |-> |任意地址|
  -------     -------     -------     -------

我們之後連續 malloc 兩次

malloc(24);
malloc(24);

現在的 fastbin

  -------     -------
 | 頭結點 |-> |任意地址|
  -------     -------

那我們再次 malloc 時,就可以在任意地址建立一個 chunk 了,但是要注意的是,我們在之前提到過,從 fastbin 中取出 chunk 的時候會對 chunk 的size 做檢查,也就是這個任意位置的 chunk 的 size 位必須構造。我們可以在棧中構造

int stack = 0x30 // 24 + header = 0x28 ,0x10 對齊後 0x30

這個變數作為size位,我們可以將任意地址填充為 &stack - 8,然後 malloc 之後會返回這個地址的 chunk,在棧中變數無法溢位時,我們可以向 chunk 裡面寫入資料來造成棧溢位。

d = malloc(24);
d[20] = 0xdeadbeef //控制rip

fastbin attack 中令人興奮的一點是,它不需要對 chunk 進行溢位就可以進行攻擊,這在一些對輸入長度檢查嚴格的地方可以得到奇妙的應用。

0x02 overlapping chunk 1

幸運的是,並不是所有的程式都會對輸入長度有嚴格的約束,當我們能夠溢位到下一個 chunk 時,我們可以修改它的 size 位來造成 chunk 的覆蓋。

首先,我們建立三個chunk,考慮 prev_size 的複用和 0x10位元組對齊,我們將 malloc(0x100-8), 系統會給我們(0x100-8)+0x10-0x8,即0x100(0x10對齊)的空間,實際可用的空間正好是0x100-8,並沒有多分配,而要是malloc(0x100)的話,你會看到實際可用的空間是0x108(這個不是必須的,只是向大家強調一下 chunk 大小的計算)

a = malloc(0x100-8);
b = malloc(0x100-8);
c = malloc(0x100-8);

然後 free 掉 b,b就會放到 unsortedbin 中 ,這個bin只有一個連結串列,並不對size進行區分,所以我們可以放入0x100的chunk,修改為size為0x180後就可以拿出0x180的chunk

free(b);

然後我們利用a溢位到b的size位

*(a+0xf8) = 0x181 // 0x01標識a為inuse狀態

現在我們malloc一個0x180的 chunk,系統就會將從b開始的0x180大小的空間返還,這其中包括c

d = malloc(0x180-8);

ok,現在我們就可以更改利用d更改c中的內容,如果c中包含某個函式指標,我們也可以去改變它,當然

0x03 overlapping chunk 2

我們在前面先釋放再修改size來獲得了一個覆蓋掉後面chunk 的 chunk,那麼如果我們先修改size為一個大值,然後free會怎樣呢?

首先我們建立4個chunk

a = malloc(0x100-8);
b = malloc(0x100-8);
c = malloc(0x100-8);
d = malloc(0x100-8);// 第四個為了防止被top chunk 合併,以及應對 free的檢查

我們通過a溢位到b的size

*(a+0xf8) = 0x201 // 0x1為inuse標識

我們這裡講b的size擴大到了c,由於free時需要檢查下一個chunk的size,所以我們預留了d,並且防止free後直接與top chunk合併,之後我們free掉b,然後再次malloc就又包括了c

free(p);
e = malloc(0x200-8);

然後就可以可以像0x02一樣去利用。

0x04 小結

除了這些之外,我們還可以根據不同的條件去構造不同的chunk複用,像是隻利用一個位元組溢位(off-by-one)來使chunk size減小,以此來構造的poison_null_byte 漏洞等等。瞭解chunk複用的原理,就是去改變 size 位來使系統對錯誤的長度進行 malloc、free,這就是我們的目的。