[英]What exactly happens in this minimalistic C code on assembly level?
我目前正在尝试了解编写缓冲区溢出漏洞-面向初学者的教程 。
使用cc -ggdb exploitable.c -o exploitable
编译的C代码
#include <stdio.h>
void exploitableFunction (void) {
char small[30];
gets (small);
printf("%s\n", small);
}
main() {
exploitableFunction();
return 0;
}
似乎有汇编代码
0x000000000040063b <+0>: push %rbp
0x000000000040063c <+1>: mov %rsp,%rbp
0x000000000040063f <+4>: callq 0x4005f6 <exploitableFunction>
0x0000000000400644 <+9>: mov $0x0,%eax
0x0000000000400649 <+14>: pop %rbp
0x000000000040064a <+15>: retq
我认为它可以做到以下几点,但是我对此不确定,我想听听有汇编代码经验的人说的对/对。
40063b:将当前在基本指针寄存器中的地址放入堆栈段(该寄存器如何初始化?为什么这样做?)
您想保存基本指针,因为它可能被调用函数使用。
40063c:将值从堆栈指针寄存器复制到基本指针寄存器中(为什么?)
这为您提供了一个固定位置,该位置可能包含函数的参数。 它也可以用作任何局部变量的基址。
40063f:调用exploitableFunction(在汇编中“调用”一个函数到底是什么意思?这是什么情况?)
“调用”是指将返回地址(下一条指令的地址)压入堆栈,然后跳转到被调用函数的开头。
400644:将值从地址$ 0x0复制到EAX寄存器
实际上,它是return语句中的值0。
400649:将堆栈顶部的值(由%rsp中的值确定)复制到基本指针寄存器中(似乎由汇编程序确认:推/弹出寄存器?)
这将恢复我们保存在顶部的基本指针。 调用函数可能会假设我们这样做。
40064a:返回(操作系统使用%EAX中的内容作为返回码-所以我猜地址$ 0x0包含常数0?还是不是地址而是常数?)
这是从return 0
开始的常量。 将EAX用作较小的返回值是一种常见的约定。
我找到了一个链接 ,该链接具有与您自己相似的代码,而且功能全面。
%rbp
指向main
的堆栈框架的底部。 0x4005f6
的函数,将程序计数器压入堆栈,并将地址0x4005f6
装入程序转换器,当函数返回时,发生弹出操作,将堆栈中已保存的地址返回到程序计数器0x400644
0
复制到%eax
,x86调用约定规定函数的返回值存储在%eax
%rbp
同样,您也没有提到功能exploitableFunction
的汇编代码。 这只是main
功能
函数条目保存bp并将sp移入bp。 现在将使用bp寻址功能的所有参数。 这是一个标准的cdecl约定(在Intel汇编程序中):
; int example(char *s, int i)
push bp ; save the caller's value of bp
mov bp,sp ; set-up our base pointer to the stack-frame
sub sp, 16 ; room for automatic variables
mov ax,dword ptr [bp+8] ; ax has *s
mov bx,dword ptr [bp+12] ; bx has i
... ; do your thing
mov ax, dword ptr[result] ; function return in ax
pop bp ; restore caller's base-pointer
ret
调用此函数时,编译器将参数压入堆栈,然后调用该函数。 返回后,它将清理堆栈:
; i= example(myString, k);
mov ax, [bp+16] ; this gets a parameter of the curent function
push ax ; this will be parameter i
mov ax, [bp-16] ; this gets a local variable
push ax ; this is parameter s
call example
add sp,8 ; remove the pushed parameters from the stack
mov dword ptr [i], ax ; save return value - always in ax
不同的编译器可以使用不同的约定来传递寄存器中的参数,但是我认为以上是C语言中使用cdecl进行调用的基础。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.