[英]Reserved stack space in assembly doesn' t seem to match the c code
我有以下代碼示例:
int main(int argc, char **argv) {
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
exit(0);
}
拆卸程序會導致類似於以下內容:
1. 0x08048250 <main+0>: push %ebp
2. 0x08048251 <main+1>: mov %esp,%ebp
3. 0x08048253 <main+3>: and $0xfffffff0,%esp
4. 0x08048256 <main+6>: sub $0x20,%esp
5. 0x08048259 <main+9>: movl $0x80a6f68,0x18(%esp)
6. 0x08048261 <main+17>: movl $0x0,0x1c(%esp)
7. 0x08048269 <main+25>: mov 0x18(%esp),%eax
8. 0x0804826d <main+29>: movl $0x0,0x8(%esp)
9. 0x08048275 <main+37>: lea 0x18(%esp),%edx
10. 0x08048279 <main+41>: mov %edx,0x4(%esp)
11. 0x0804827d <main+45>: mov %eax,(%esp)
12. 0x08048280 <main+48>: call 0x804f5c0 <execve>
13. 0x08048285 <main+53>: movl $0x0,(%esp)
14. 0x0804828c <main+60>: call 0x8048af0 <exit>
我試圖了解程序集:
在第4行,減少了stackpointer以便為局部變量分配空間,但是我不明白為什么它保留32個字節(0x20 = 32個字節)? 據我了解,它只需要分配:
我也看到一些數據存儲在與堆棧指針偏移的位置,但似乎並沒有使用所有空間。
有人可以解釋一下這個組裝嗎? 我在將C代碼映射到給定的匯編指令時遇到麻煩。 特別是由於保留空間的長度似乎與c代碼不匹配。
我對以下內容特別感興趣:
謝謝!
關於“它只需要分配”:
“ 4個字節的指針名稱”-不太正確。 name是一個由兩個指針組成的數組,因此2 * 4 = 8個字節(假設您使用的是32位指針,那是它的樣子)。
“字符串“ / bin / sh”為8個字節-不會在堆棧上。它將在二進制文件的其他位置(可能是.rodata段,即只讀數據),因此不會占用任何堆棧空間。
“ NULL是否還會占用空間?” -NULL(可能是,除非您有一個錯誤的C編譯器)的值為0。“ value”本身不能占用堆棧空間,但是如果堆棧上有一個值為NULL的變量,則您會發現零。堆棧。
“ argc和argv [etc]”-可以說是這些函數調用的堆棧框架的一部分,但是它們是由調用者初始化的,因此不能通過減少%esp來保留。
“似乎並沒有使用所有空間”-由於對齊,通常是正確的。 考慮:
struct {
char ch;
int *ptr;
};
對於這種結構情況,我們將有一個字節的char,然后是三個字節的padding,以便正確對齊ptr,然后是四個字節的ptr。 (如果指針是64位,則填充7個字節。)如果在堆棧上分配這些結構之一,則將有3個(或7個)“未使用”的堆棧字節。
但是,在這種情況下,編譯器在堆棧上為初始“ sub ...%esp”指令中的execve()調用的參數創建了空間,這是一個很小的優化。
第3行:對齊:在16字節邊界上對齊%esp。 (對於任何人都足夠。)第4行:創建一些堆棧空間。 其中一些是局部變量。 當將函數調用放在一起時,編譯器會將它的其他一些字節用於臨時空間。
第9行:(有效地)將字符串“ / bin / sh”放入%edx。 該字符串的地址位於二進制文件中的0x80a6f68位置(將.rodata加載到的位置)。 第5行將值0x80a6f68放入(%esp + 0x18)。 第9行將*(%esp + 0x18),即*(char **)0x80a6f68放入%edx。
第11行:(%esp)實際上是指針引用:* esp = eax。 它將eax寄存器的值放入* esp,即堆棧指針正上方的四個字節。 eax的值在第7行中定義。
第13行:將* esp設置為0x00000000。 由於我們隨后調用exit(),因此將exit的第一個參數(即* esp)設置為0。
name
是2個指針的數組。 這將占用8或16個字節,具體取決於您的平台是32位還是64位。
字符串/bin/sh
完全不在堆上,而是在已初始化的數據段中; 為了完整起見, \\0
確實需要空間。
argc
和argv
將作為參數傳遞到堆棧中。
第3行將堆棧指針對齊為16個字節的倍數
第19行實際上是說“讓edx
為0x18加上esp
的值”; lea
是“加載有效地址”; 認為它是一個mov
,而不是執行內存加載,而是返回將從其加載內存的地址。
上線11和13中, (esp)
是指該位置的內容通過指向esp
。
我承認我的匯編器有點生銹。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.