亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標題: Linux堆棧溢出的經(jīng)典問題,歡迎圍觀!大牛前進 [打印本頁]

作者: GoldenSoldier    時間: 2009-11-25 18:33
標題: Linux堆棧溢出的經(jīng)典問題,歡迎圍觀!大牛前進
原帖請見:http://blog.chinaunix.net/u/26166/showart.php?id=198375

我的環(huán)境是redhant 9 ,2.4的核。由于對Linux環(huán)境下堆棧的不熟悉,所以就這個例子,做了一些哦測試。
我的代碼:
  1. #include<stdio.h>

  2. void attack()
  3. {
  4. int attack=1;
  5. printf("hi,attacked!\n");
  6. }
  7. void yaya()
  8. {
  9. int yaya=1;
  10. printf("hi,yaya is my wife\n");
  11. }
  12. void foo()
  13. {
  14. int c_foo=1;
  15.   *(& c_foo +2)=(int)attack;
  16. }

  17. void main(){
  18. int a_main=1;
  19. a_main=(int)yaya;
  20. foo();
  21. }
復(fù)制代碼


然后,gdb下觀察結(jié)果:
main函數(shù)的反匯編:


yaya函數(shù)的反匯編


attack函數(shù)的反匯編:


foo函數(shù)的反匯編:


在main的堆棧中,a_main的值從1變?yōu)閥aya函數(shù)的入口地址0x08048347,而進入foo函數(shù)之后,本來0xbfffe2cc存放的是main返回的地址0x0804839f,但是改為attack函數(shù)的入口地址0x08048328。
這樣就會導(dǎo)致main函數(shù)無法正常返回。


下面是我畫的堆棧示意圖,請指教:


從函數(shù)foo返回后,就進入了attack函數(shù)了。

打印“hi,attacked!”成功!
接著,返回段錯誤。

我的問題:為什么yaya函數(shù)沒有執(zhí)行,就出現(xiàn)了段錯誤?
照文章中所述的,yaya函數(shù)的入口地址0x08048347已經(jīng)放在了0xbfffe2d4,為什么eip會訪問不到么?


[ 本帖最后由 GoldenSoldier 于 2009-11-26 09:17 編輯 ]
作者: GoldenSoldier    時間: 2009-11-25 19:10
上面有個圖發(fā)沖了
在下面修正一下:

作者: fox144215    時間: 2009-11-25 20:49
你cat /proc/$(pid)/maps看下0x08048347是屬于哪個段的
作者: GoldenSoldier    時間: 2009-11-25 21:07
標題: 回復(fù) #3 fox144215 的帖子
>>你cat /proc/$(pid)/maps看下0x08048347是屬于哪個段的

不懂你的意思。
0x08048347是屬于代碼段啊
作者: mik    時間: 2009-11-25 21:56
原帖由 GoldenSoldier 于 2009-11-25 18:33 發(fā)表
原帖請見:http://blog.chinaunix.net/u/26166/showart.php?id=198375

我的環(huán)境是redhant 9 ,2.4的核。由于對Linux環(huán)境下堆棧的不熟悉,所以就這個例子,做了一些哦測試。
我的代碼:
#include

void a ...


圍觀

你沒看懂 dump 出來的 main() 代碼嗎?

已經(jīng)很清楚了。
作者: GoldenSoldier    時間: 2009-11-25 22:03
原帖由 mik 于 2009-11-25 21:56 發(fā)表


圍觀

你沒看懂 dump 出來的 main() 代碼嗎?

已經(jīng)很清楚了。


本人菜鳥一個
請指教,我想知道為什么yaya函數(shù)沒有執(zhí)行
作者: mik    時間: 2009-11-25 22:20
標題: 回復(fù) #6 GoldenSoldier 的帖子
你這個 yaya() 地址并沒有接著 attack() 后面
作者: kouu    時間: 2009-11-25 22:26
沒看明白0xbfffe2d0上面存放的0x42130a14是怎么來的, 從attack函數(shù)返回后應(yīng)該是跳到這個地址上了...
LZ代碼中, main函數(shù)里面的那句i=(int)yaya是怎么回事? 代碼還有蹊蹺?

[ 本帖最后由 kouu 于 2009-11-25 22:47 編輯 ]
作者: GoldenSoldier    時間: 2009-11-26 08:42
原帖由 mik 于 2009-11-25 22:20 發(fā)表
你這個 yaya() 地址并沒有接著 attack() 后面


謝謝你的關(guān)注!
你的意思是不是0xbfffe2d0地址里面不是yaya函數(shù)的入口地址?
作者: GoldenSoldier    時間: 2009-11-26 08:47
原帖由 kouu 于 2009-11-25 22:26 發(fā)表
沒看明白0xbfffe2d0上面存放的0x42130a14是怎么來的, 從attack函數(shù)返回后應(yīng)該是跳到這個地址上了...
LZ代碼中, main函數(shù)里面的那句i=(int)yaya是怎么回事? 代碼還有蹊蹺?


我也是初學(xué)者,我也不知道為什么0xbfffe2d0上面存放的0x42130a14,這是gdb你看到的。
從字面上來看,沒有和我函數(shù)的任何的局部變量產(chǎn)生關(guān)系(即 非任何局部變量的值),我懷疑是和printf有關(guān)的,猜得。

main函數(shù)里面的那句i=(int)yaya是筆誤,應(yīng)該是a_main= (int)yaya,不好意思。源代碼已經(jīng)修正過。慚愧
a_main= (int)yaya是為了讓yaya函數(shù)執(zhí)行而已。
但是沒想到中間還有個0xbfffe2d0(0x42130a14),不解。

[ 本帖最后由 GoldenSoldier 于 2009-11-26 09:19 編輯 ]
作者: ljk19841115    時間: 2009-11-26 09:23
void main(){
int a_main=1;
i=(int)yaya;
foo();
}

樓主代碼有問題哈~ i 和 a_main??
作者: GoldenSoldier    時間: 2009-11-26 09:29
原帖由 GoldenSoldier 于 2009-11-25 18:33 發(fā)表
原帖請見:http://blog.chinaunix.net/u/26166/showart.php?id=198375

我的環(huán)境是redhant 9 ,2.4的核。由于對Linux環(huán)境下堆棧的不熟悉,所以就這個例子,做了一些哦測試。
我的代碼:
#include

void a ...


謝謝mik的提醒:“你這個 yaya() 地址并沒有接著 attack() 后面


剛改了一下代碼:
  1. a_main=(int)yaya;
  2. 改為:*(& a_main -1)=(int)yaya;
復(fù)制代碼

現(xiàn)在可以成功的運行yaya函數(shù)了,但是最后還是返回段錯誤。

最后還是不明白,為什么在main函數(shù)的反匯編中,esp為什么減去0x8?
main只有一個局部變量a_main啊,而且看后面的匯編,也沒有用到0xbfffe2d0啊。(esp減去0x4就夠用了么:em11: )
請教!



[ 本帖最后由 GoldenSoldier 于 2009-11-26 21:09 編輯 ]
作者: GoldenSoldier    時間: 2009-11-26 09:32
原帖由 ljk19841115 于 2009-11-26 09:23 發(fā)表
void main(){
int a_main=1;
i=(int)yaya;
foo();
}

樓主代碼有問題哈~ i 和 a_main??

已經(jīng)修正過了,貼出的代碼是錯了。但在gcc編譯的代碼還是對的。謝謝!
作者: ljk19841115    時間: 2009-11-26 13:56
這里假設(shè)在進入函數(shù)之前,棧是16字節(jié)對齊的話,那么,進入函數(shù)后,EIP和EBP被壓入堆棧后,棧地址最末4位二進制位必定是1000,esp -8則恰好使后4位地址二進制位為0000?磥恚@也是為保證棧16字節(jié)對齊的

http://blog.csdn.net/yayong/archive/2004/11/07/170842.aspx
作者: fox144215    時間: 2009-11-26 14:49
原帖由 GoldenSoldier 于 2009-11-25 18:33 發(fā)表
原帖請見:http://blog.chinaunix.net/u/26166/showart.php?id=198375

我的環(huán)境是redhant 9 ,2.4的核。由于對Linux環(huán)境下堆棧的不熟悉,所以就這個例子,做了一些哦測試。
我的代碼:
#include

void a ...


如圖,該地址屬于代碼段,權(quán)限r(nóng)_xp,你應(yīng)該知道是什么原因了

作者: kouu    時間: 2009-11-26 15:44
標題: 回復(fù) #15 fox144215 的帖子
“該地址”指的是前面說的yaya函數(shù)的入口地址0x08048347吧? 然后呢? 恕本人愚頓,沒能領(lǐng)悟……
作者: fox144215    時間: 2009-11-26 16:51
*(& c_foo +2),是這個地址
作者: GoldenSoldier    時間: 2009-11-26 20:15
原帖由 ljk19841115 于 2009-11-26 13:56 發(fā)表
這里假設(shè)在進入函數(shù)之前,棧是16字節(jié)對齊的話,那么,進入函數(shù)后,EIP和EBP被壓入堆棧后,棧地址最末4位二進制位必定是1000,esp -8則恰好使后4位地址二進制位為0000。看來,這也是為保證棧16字節(jié)對齊的

htt ...

非常感謝你的幫助,看了這篇文章,獲益匪淺啊。

文章提到,為了保證16字節(jié)的對齊,EBP最后一位(16進制)必須是8,所以ESP(ESP-8)就為0了。
我很希望這是對的,但是我所看到的卻不是啊。
比如下圖中:(注意下面的圖標注都是原來的,將就看一下吧啊

ESP的尾數(shù)為0100(二進制),4(16進制)。
這又如何解釋呢?

另外:
下圖中ESP減去0x4,又作何解釋么?


還有,在Linux一站式學(xué)習(xí)中的圖http://learn.akae.cn/media/ch19s01.html

ESP和EBP的尾數(shù)也并為有上面提到的規(guī)律。浚ā16字節(jié)對齊”)

最后,我知道GCC是4字節(jié)對齊的(sizeof結(jié)構(gòu)體可知),和這個“16字節(jié)對齊”,二者有什么關(guān)系么?

[ 本帖最后由 GoldenSoldier 于 2009-11-26 20:22 編輯 ]
作者: mik    時間: 2009-11-26 20:53
原帖由 fox144215 于 2009-11-26 14:49 發(fā)表


如圖,該地址屬于代碼段,權(quán)限r(nóng)_xp,你應(yīng)該知道是什么原因了
237447



這和 LZ 的錯誤有什么關(guān)系呢?
作者: mik    時間: 2009-11-26 21:00
原帖由 GoldenSoldier 于 2009-11-26 20:15 發(fā)表

非常感謝你的幫助,看了這篇文章,獲益匪淺啊。

文章提到,為了保證16字節(jié)的對齊,EBP最后一位(16進制)必須是8,所以ESP(ESP-8)就為0了。
我很希望這是對的,但是我所看到的卻不是啊。
比如下圖中: ...


對于用戶程序的入口函數(shù),即:main(), gcc 一般作 16 bytes 對齊。其它函數(shù),不作 16 bytes 對齊
作者: GoldenSoldier    時間: 2009-11-26 21:08
原帖由 mik 于 2009-11-26 21:00 發(fā)表


對于用戶程序的入口函數(shù),即:main(), gcc 一般作 16 bytes 對齊。其它函數(shù),不作 16 bytes 對齊


非常感謝你的幫助!

受教了,原來如此!
不知mik大牛如何知道這么多,問一下有這方面的書籍或者技術(shù)資料參考一下么?
謝謝

另外,mik知道可以如何對上述代碼進行修改,使得main函數(shù)可以正常返回么?
請不吝賜教


[ 本帖最后由 GoldenSoldier 于 2009-11-26 21:53 編輯 ]
作者: kouu    時間: 2009-11-26 21:22
原帖由 mik 于 2009-11-26 20:53 發(fā)表



這和 LZ 的錯誤有什么關(guān)系呢?


呵呵, 這位老兄比較深藏不露, 發(fā)了幾次問, 最終還是沒弄清楚他要表達什么...

mik兄的回復(fù)... 學(xué)習(xí)了~
作者: mik    時間: 2009-11-26 22:03
原帖由 GoldenSoldier 于 2009-11-26 21:08 發(fā)表


非常感謝你的幫助!

受教了,原來如此!
不知mik大牛如何知道這么多,問一下有這方面的書籍或者技術(shù)資料參考一下么?
謝謝

另外,mik知道可以如何對上述代碼進行修改,使得main函數(shù)可以正常返回么? ...


我不是牛人

牛人可不是隨便就能叫的。
作者: mik    時間: 2009-11-26 22:12
原帖由 GoldenSoldier 于 2009-11-26 21:08 發(fā)表


非常感謝你的幫助!

受教了,原來如此!
不知mik大牛如何知道這么多,問一下有這方面的書籍或者技術(shù)資料參考一下么?
謝謝

另外,mik知道可以如何對上述代碼進行修改,使得main函數(shù)可以正常返回么? ...


在你的代碼里,你要使用 main() 正常退出,

必須把 調(diào)用 foo() 時的返回地址交由 yaya() 函數(shù)來返回

void foo()
{
       int c_foo = 1;

      int yaya_ret = (int) *(& c_foo + 2);
      *(& c_foo + 2) = (int)attack;
      *(& c_foo + 3) = (int)yaya;
      *(& c_foo + 4) = (int)yaya_ret;
  
}

void main(){
   /*  int a_main=1; */
   /* a_main=(int)yaya; */

    foo();
}

}
作者: mik    時間: 2009-11-26 22:20
標題: 回復(fù) #21 GoldenSoldier 的帖子
像你這些代碼,是很笨拙的

通過 “利用局部變量偏移量改變” 返回地址的方法是很笨拙的
作者: GoldenSoldier    時間: 2009-11-27 14:50
原帖由 mik 于 2009-11-26 22:20 發(fā)表
像你這些代碼,是很笨拙的

通過 “利用局部變量偏移量改變” 返回地址的方法是很笨拙的


嘿嘿,版主教訓(xùn)的是!
我是新手學(xué)習(xí),只能先以后難吧,我就是先理解一下Linux堆棧的細節(jié)而已。

>>通過 “利用局部變量偏移量改變” 返回地址的方法是很笨拙的
還有其他的好的方法?
誠心請教一下
拜。(莫不是內(nèi)嵌匯編?)

作者: GoldenSoldier    時間: 2009-11-27 15:25
原帖由 mik 于 2009-11-26 22:12 發(fā)表


在你的代碼里,你要使用 main() 正常退出,

必須把 調(diào)用 foo() 時的返回地址交由 yaya() 函數(shù)來返回

void foo()
{
       int c_foo = 1;

      int yaya_ret = (int) *(& c_foo + 2);
      * ...

明白你的意思了 ,就是把存儲a_main的地址里的內(nèi)容換成main函數(shù)返回的地址。
我嘗試了一下,見下:
  1. void foo()
  2. {
  3.   int c_foo=1;
  4.   int main_ret=(int)*(& c_foo +2);
  5.   *(& c_foo +2)=(int)attack;
  6.   *(& c_foo +4)= (int) main_ret;
  7. }
復(fù)制代碼
其他的代碼都沒變。
這樣就OK了,最后測試通過,沒有出現(xiàn)段錯誤! 嘿嘿

[ 本帖最后由 GoldenSoldier 于 2009-11-27 15:27 編輯 ]
作者: 學(xué)與思    時間: 2009-11-27 17:41
unsigned long get_ebp(void)
{
        __asm__("movl %ebp, %eax");
}


要想學(xué)會這個匯編必不可少

[ 本帖最后由 學(xué)與思 于 2009-11-27 17:42 編輯 ]
作者: 學(xué)與思    時間: 2009-11-27 18:06
不過對于你這個問題,更好的辦法是利用函數(shù)的第一個參數(shù)的地址來獲取函數(shù)的返回地址的地址
作者: ypyf3000    時間: 2009-11-30 00:20
四不像
作者: famdestiny    時間: 2009-12-04 19:25
mark一下
作者: wolfired    時間: 2009-12-12 13:15
yaya執(zhí)行了哦
作者: rainballdh    時間: 2009-12-16 23:31
看了MIK得方法,我也嘗試了一下:
#include<stdio.h>

void attack()
{
    int attack=1;
    printf("hi,attacked!\n");
}
void yaya()
{
    int yaya=1;
    printf("hi,yaya is my wife\n");
}
void foo()
{
    int c_foo=1;
    int addr = *(&c_foo+2);
    *(& c_foo +2)=(int)attack;
    *(&c_foo + 3)=addr;
}

void main(){
    int a_main=1;
    int addr = *(&a_main+2);
    *(& a_main+2)=(int)yaya;
    *(& a_main+3)=addr;
    foo();
}
作者: qurongyao_linux    時間: 2010-02-10 15:50
void foo()

{

int c_foo=1;

  *(& c_foo +2)=(int)attack;

}
修改了foo入棧前保存的環(huán)境,當然會跳到attack那里,你把它改成main,它還會跳到main那里
作者: qurongyao_linux    時間: 2010-02-10 15:51
不過你能寫這么清楚,牛人




歡迎光臨 Chinaunix (http://www.72891.cn/) Powered by Discuz! X3.2