2011-12-13 90 views
3

我正在查看我的一個類的練習考試,我只是不明白問題的某些方面,所以也許你會幫助我(可能真的很容易,如果你知道x86 )。在x86彙編代碼中追蹤堆棧

所以它在這裏的問題8: http://www.coe.utah.edu/~cs4400/schedule/exam3.F10.pdf

而解決的辦法是在這裏: http://www.coe.utah.edu/~cs4400/schedule/exam3_solns.F10.pdf \

我只是不明白的值是如何在溶液中獲得。讓我跑通過I如何解讀爲此堆棧:

08048510 <callfoo>: 
08048510: 55  pushl %ebp    # old frame pointer is pushed to the stack 
08048511: 89 e5 movl %esp,%ebp   # frame pointer = stack pointer 
08048513: 83 ec 08 subl $0x8,%esp   # allocates 8 bytes for stack 
08048516: 83 c4 f4 addl $0xfffffff4,%esp # this I believe allocates 4 bytes to the stack?? 
08048519: 68 9c 85 04 08 pushl $0x804859c # push string address 
0804851e: e8 d1 ff ff ff call 80484f4 <foo> # call foo, which takes the string address as param1 
08048523: 89 ec movl %ebp,%esp   # (after foo) does similar to return out of function 
08048525: 5d  popl %ebp 
08048526: c3  ret 

080484f4 <foo>: 
080484f4: 55  pushl %ebp     # push old frame pointer 
080484f5: 89 e5 movl %esp,%ebp    # frame pointer = stack pointer 
080484f7: 83 ec 18 subl $0x18,%esp    # allocate 24 bytes 
080484fa: 8b 45 08 movl 0x8(%ebp),%eax   # moves the param1 (string pointer) into eax 
080484fd: 83 c4 f8 addl $0xfffffff8,%esp  # allocates 8 more bytes (?) 
08048500: 50  pushl %eax     # push x # pushes param1 to stack 
08048501: 8d 45 fc leal 0xfffffffc(%ebp),%eax # adds 12 to the frame pointer, puts it in eax(?) 
08048504: 50  pushl %eax     # push buf (which apparently is located in eax and 0xc(%ebp) 
08048505: e8 ba fe ff ff call 80483c4 <strcpy> # copies the string from param1 into buf 
0804850a: 89 ec movl %ebp,%esp    # puts stack pointer into ebp 
0804850c: 5d  popl %ebp     # pops ebp (returns back to other function) 
0804850d: c3  ret 

(一),所以這樣做之後,我想我可以有點看如何BUF [0] = 0x64636261。 char是一個字節,並且是小端,也可以這樣讀取:buf [0] = 0x61626364(儘管我不知道我的教授是否會接受該答案)。 但是,我不明白buf [2]如何等於0x080400690x69000408。它有最後一個字符,然後是空字符,但0408是什麼? (b)我不知道如何獲得(b)或(c)。我甚至可以在哪裏獲得esp的值是要找出在foo的開始處放入ebp的值?總的來說,我只是困惑於最後兩個......幫助? :(

+0

提示:Ctrl-F 0804;) – Diadistis

+0

對,我得到了那個連接,我不認爲我會假設buf會100%包含地址的開始部分的內存。因此我不會在測試中做這件事。 (b)(c)就此而言更令人困惑,我只是不知道他們在哪裏得到這些地址。 :/ – fvertk

+1

當foo在0804851e被調用時,下一條指令(返回地址)被壓入堆棧(08048523)。 Foo將8個字節分配給堆棧,然後寫入10個字節,從而部分覆蓋堆棧上的返回地址。 – Diadistis

回答

3

似乎有很多的堆棧指針在此代碼回事多餘的操作,但所有真正重要的是,buf變量在ebp-4你可以看到,從順序:

leal 0xfffffffc(%ebp),%eax 
pushl %eax 
call 80483c4 <strcpy> 

0xfffffffc爲-4,所以leal 0xfffffffc(%ebp),%eax套EAX到所述存儲器位置ebp-4的地址。然後,該值被壓入堆棧作爲第一個參數,以strcpy,由於傳遞給strcpy第一個參數爲buf,我們知道buf的地址是ebp-4

現在考慮如何調用foo來構建堆棧。

首先按指令pushl $0x804859c推送字符串地址。

0804859c # string pointer 

然後,當函數foo被調用時,調用(08048523)之後的指令的地址被壓入堆棧作爲返回地址。

08048523 # return address 

然後在foo裏面,ebp被保存在堆棧中。這可能是任何事情。

???????? # saved ebp 

然後ebp被設置爲esp,所以它現在指向前一個ebp被保存的位置。

現在因爲我們知道buf在ebp-4,這意味着堆棧中的下一個項目將是buf。在堆棧上分配的空間比subladdl指令所需的空間多得多,但我們關心的是bufebp-4。所以,我們關心這個樣子的堆棧的一部分:

0804859c # string pointer 
08048523 # return address 
???????? # saved ebp  <- ebp points here 
???????? # buff[0]  <- ebp-4 points here 

所以,現在當您複製「ABCDEFGHI」成迷會發生什麼?由於機器是小端,所以這些雙字將從右到左填滿。您在該字符串中有9個字符加上一個空終止符,因此您將覆蓋buff[0]的所有四個字節,保存的ebp的所有四個字節,然後覆蓋返回地址的兩個字節。

所以你的籌碼,現在看起來是這樣的:

0804859c # string pointer 
08040069 # return address 
68676665 # saved ebp  <- ebp points here 
64636261 # buff[0]  <- ebp-4 points here 

從這一點,它應該是相當明顯發生了什麼答案的各種問題的。

由於棧在內存中向下構建,因此buff[1]buff[2]位於堆棧表示中的buff[0]的正上方,正如我已經展示的那樣。所以,你可以看到各種BUFF值只是:

buff[0] = 0x64636261 
buff[1] = 0x68676665 
buff[2] = 0x08040069 

然後立即在ret指令之前,我們有以下兩個指令:

movl %ebp,%esp 
popl ebp 

第一臺ESP到EBP的當前值,所以它會指向堆棧中保存上一個ebp的位置。但是,查看堆棧表示,可以看到該值現在已被68676665覆蓋。所以當你彈出ebp時,這就是你將要獲得的價值。

%ebp = 0x68676665 

同樣,當函數返回時,它會嘗試和彈出堆棧中的返回地址,但你可以再次從堆棧中表示,原來的返回地址已被部分覆蓋看到。因此在ret指令eip之後立即彈出08040069

$eip = 0x08040069 

而且,我想,回答你所有的問題。

我意識到這個問題現在已經有幾年了,但它並沒有被封閉,也沒有被接受的答案,所以也許這個解釋對某些人來說可能還是有用的。

+0

我只是在瀏覽我的老問題和哇,你是一個紳士和學者。 – fvertk