2015-04-15 35 views
0

我最近自學電腦系統。我不明白二進制彈子實驗室階段2的代碼。我輸入1 2 3 4 5 6作爲輸入-0x20混亂(%ebp)

這些通道是幹什麼的? 這個-0x20是怎麼來的?它的目的是什麼?

0x08048bab <+7>: lea -0x20(%ebp),%eax 
0x08048bae <+10>: mov %eax,0x4(%esp) 

這些代碼來自

Dump of assembler code for function phase_2: 

0x08048ba4 <+0>: push %ebp 
0x08048ba5 <+1>: mov %esp,%ebp 
0x08048ba7 <+3>: push %ebx 
0x08048ba8 <+4>: sub $0x34,%esp 
0x08048bab <+7>: lea -0x20(%ebp),%eax 
0x08048bae <+10>: mov %eax,0x4(%esp) 
0x08048bb2 <+14>: mov 0x8(%ebp),%eax 
0x08048bb5 <+17>: mov %eax,(%esp) 
0x08048bb8 <+20>: call 0x804928d <read_six_numbers> 
0x08048bbd <+25>: cmpl $0x0,-0x20(%ebp) 
0x08048bc1 <+29>: jns 0x8048be3 <phase_2+63> 
0x08048bc3 <+31>: call 0x804924b <explode_bomb> 
0x08048bc8 <+36>: jmp 0x8048be3 <phase_2+63> 
0x08048bca <+38>: mov %ebx,%eax 
0x08048bcc <+40>: add -0x24(%ebp,%ebx,4),%eax 
0x08048bd0 <+44>: cmp %eax,-0x20(%ebp,%ebx,4) 
0x08048bd4 <+48>: je  0x8048bdb <phase_2+55> 
0x08048bd6 <+50>: call 0x804924b <explode_bomb> 
0x08048bdb <+55>: inc %ebx 
0x08048bdc <+56>: cmp $0x6,%ebx 
0x08048bdf <+59>: jne 0x8048bca <phase_2+38> 
0x08048be1 <+61>: jmp 0x8048bea <phase_2+70> 

2.

我覺得

mov 0xc(%ebp),%eax 

越來越投入。

我試過x/s $ ebp + oxc,它打印這個字符串\ 350 \ 366 \ 377 \ 277 \ b \ 367 \ 377 \ 277> \ 223 \ 004 \ b {\ 246 \ 004 \ b。 那是什麼?我真的很難理解這是幹什麼的?我試圖在每個內存地址中打印出價值,但沒有幫助。

當我試圖在cmp $ 0x5,%eax之前打印出x/d $ eax時,它顯示無法訪問地址爲0x0的內存。

Dump of assembler code for function read_six_numbers: 
0x0804928d <+0>: push %ebp 
0x0804928e <+1>: mov %esp,%ebp 
0x08049290 <+3>: sub $0x28,%esp 
0x08049293 <+6>: mov 0xc(%ebp),%eax 
0x08049296 <+9>: lea 0x14(%eax),%edx 
0x08049299 <+12>: mov %edx,0x1c(%esp) 
0x0804929d <+16>: lea 0x10(%eax),%edx 
0x080492a0 <+19>: mov %edx,0x18(%esp) 
0x080492a4 <+23>: lea 0xc(%eax),%edx 
0x080492a7 <+26>: mov %edx,0x14(%esp) 
0x080492ab <+30>: lea 0x8(%eax),%edx 
0x080492ae <+33>: mov %edx,0x10(%esp) 
0x080492b2 <+37>: lea 0x4(%eax),%edx 
0x080492b5 <+40>: mov %edx,0xc(%esp) 
0x080492b9 <+44>: mov %eax,0x8(%esp) 
0x080492bd <+48>: movl $0x804a64b,0x4(%esp) 
0x080492c5 <+56>: mov 0x8(%ebp),%eax 
0x080492c8 <+59>: mov %eax,(%esp) 
0x080492cb <+62>: call 0x8048860 <[email protected]> 
0x080492d0 <+67>: cmp $0x5,%eax 
0x080492d3 <+70>: jg  0x80492da <read_six_numbers+77> 
0x080492d5 <+72>: call 0x804924b <explode_bomb> 
+3

'sub $ 0x34,%esp'指令在堆棧上創建了一些像局部變量這樣的東西。 'lea -0x20(%ebp),%eax'指令將這個暫存空間中一個位置的地址加載到'eax'中。 –

回答

1

正如Michael所說,sub $0x34,%esp爲局部變量創建空間。由於mov %esp,%ebp先前複製了%esp%ebp,該分配的空間也可以相對於從%ebp-0x34直至%ebp範圍內的%ebp來尋址。 %ebp-0x20是一個局部變量的地址,在這種情況下它的大小爲6的整數數組的基地址(即int numbers[6];)此地址被裝入%eax並隨後寫入到堆棧:

0x08048bab <+7>: lea -0x20(%ebp),%eax 
0x08048bae <+10>: mov %eax,0x4(%esp) 

的適用的調用約定指定參數應該在堆棧上傳遞。因此,這是將地址作爲第二個參數傳遞給下面的函數調用。第一個是在%esp

0x08048bb2 <+14>: mov 0x8(%ebp),%eax 
0x08048bb5 <+17>: mov %eax,(%esp) 
0x08048bb8 <+20>: call 0x804928d <read_six_numbers> 

注意,傳入的參數的當前功能也堆棧上,並且可以使用從%ebp正偏移,開始從8.這樣得到解決,上面的代碼經過第一傳入的參數作爲第一個參數到read_six_numbers。全部放在一起,到目前爲止的代碼可能是這個樣子:

void phase_2(char* text) 
{ 
    int numbers[6]; 
    read_six_numbers(text, numbers); 
    ... 
} 

看着read_six_numbers我們可以看到,它獲取傳入的參數,併爲sscanf一堆的輸出參數:

void read_six_numbers(char* text, int* numbers) 
{ 
    if (sscanf(text, "%d %d %d %d %d %d", numbers, numbers + 1, 
      numbers + 2, numbers + 3, numbers + 4, numbers + 5) != 6) 
     explode_bomb(); 
} 

我相信你可以看到這是如何在彙編代碼中完成的。

+0

感謝您的回答。我看到,-0x20(%ebp)在任何輸入中都沒有讀取,只是爲read_six_numbers函數指定int [6]的指針。非常感謝你,我花了幾乎整夜的時間去了解那裏發生了什麼。對於我的第二個問題,cmp $ 0x5,%eax,$ eax應該是sscanf函數的返回值。爲什麼我無法打印%eax?我試過x/s $ eax,它顯示<地址0x0越界>和x/d $ eax,它也顯示無法訪問地址0x0處的內存。我期望它應該打印出來6. –

+0

'x'是用於檢查內存的,但是當時的eax只是一個數字。你可以使用'p(rint)'命令,即。 'p $ eax'。 – Jester

0

EBP指向堆棧幀的「底部」。所以當你需要把東西放入堆棧時,你可以從EBP中減去它。

因此,在您的示例中,它將地址「EBP - 0x20」並將結果存儲在EAX中。