这个极简C代码在汇编级别上到底发生了什么?
我目前正在努力理解 C代码,用这个极简C代码在汇编级别上到底发生了什么?,c,assembly,C,Assembly,我目前正在努力理解 C代码,用cc-ggdb-exploitable.C-o-exploitable #include <stdio.h> void exploitableFunction (void) { char small[30]; gets (small); printf("%s\n", small); } main() { exploitableFunction(); return 0; } #包括 void可利用函数(void
cc-ggdb-exploitable.C-o-exploitable
#include <stdio.h>
void exploitableFunction (void) {
char small[30];
gets (small);
printf("%s\n", small);
}
main() {
exploitableFunction();
return 0;
}
#包括
void可利用函数(void){
半焦小[30];
得到(小);
printf(“%s\n”,小);
}
main(){
可利用函数();
返回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
0x0000000000040063B:推送%rbp
0x0000000000040063C:mov%rsp,%rbp
0x000000000040063f:callq 0x4005f6
0x00000000000400644:mov$0x0,%eax
0x0000000000400649:弹出%rbp
0x000000000040064a:retq
我认为它可以做到以下几点,但我真的不确定,如果我是对的/什么是对的,我想听听有汇编代码经验的人的意见
- 40063b:将当前在基指针寄存器中的地址放入堆栈段(该寄存器是如何初始化的?为什么要初始化?)
- 40063c:将堆栈指针寄存器中的值复制到基指针寄存器中(为什么?)
- 40063f:调用可利用函数(在程序集中“调用”函数到底意味着什么?这里发生了什么?)
- 400644:将值从地址$0x0复制到EAX寄存器
- 400649:将堆栈顶部的值(由%rsp中的值确定)复制到基指针寄存器中(似乎由确认)
- 40064a:返回(操作系统使用%EAX中的内容作为返回代码-因此我猜地址$0x0包含常量0?或者这不是地址而是常量?)
- 40063b:将旧的基指针推送到堆栈上以保存它以备将来使用。推送它是因为这不是代码中的唯一进程。其他一些过程称之为
- 40063c:将堆栈指针的值复制到基指针。在此之后,
指向%rbp
堆栈帧的底部主
- 40063f:调用address
中的函数,该函数将程序计数器推入堆栈,并将address0x4005f6
加载到程序上下文中,当函数返回时,发生pop操作,将堆栈中保存的地址返回到程序计数器,此处为0x4005f6
0x400644
- 400644:此指令将
复制到0
中,x86调用约定规定函数的返回值存储在%eax
%eax
- 400649:我们从堆栈中弹出旧的基指针,并将其存储回
%rbp
- 40064a:跳回返回地址,返回地址也存储在堆栈帧中。它指定程序的结束
可利用函数
。这里只有main
函数我找到了一个与您自己的代码类似的函数,并且有完整的解释
- 40063b:将旧的基指针推送到堆栈上以保存它以备将来使用。推送它是因为这不是代码中的唯一进程。其他一些过程称之为
- 40063c:将堆栈指针的值复制到基指针。在此之后,
指向%rbp
堆栈帧的底部主
- 40063f:调用address
中的函数,该函数将程序计数器推入堆栈,并将address0x4005f6
加载到程序上下文中,当函数返回时,发生pop操作,将堆栈中保存的地址返回到程序计数器,此处为0x4005f6
0x400644
- 400644:此指令将
复制到0
中,x86调用约定规定函数的返回值存储在%eax
%eax
- 400649:我们从堆栈中弹出旧的基指针,并将其存储回
%rbp
- 40064a:跳回返回地址,返回地址也存储在堆栈帧中。它指定程序的结束
可利用函数
。这里只有main
功能
40063b:将当前在基指针寄存器中的地址放入堆栈段(该寄存器是如何初始化的?为什么要初始化?)
您希望保存基指针,因为调用函数可能正在使用它 40063c:将堆栈指针寄存器中的值复制到基指针寄存器中(为什么?) 这为您提供了堆栈中的固定位置,其中可能包含函数的参数。它也可以用作任何局部变量的基址 40063f:调用可利用函数(在程序集中“调用”函数到底意味着什么?这里发生了什么?) “调用”意味着将返回地址(下一条指令的地址)推到堆栈上,然后跳到被调用函数的开头 400644:将值从地址$0x0复制到EAX寄存器 它实际上是return语句中的值0 400649:将堆栈顶部的值(由%rsp中的值确定)复制到基指针寄存器(似乎已由汇编器确认:Push/pop寄存器?) 这将恢复我们在顶部保存的基本指针。调用函数可能会假定我们这样做 40064a:返回(操作系统使用%EAX中的内容作为返回代码-因此我猜地址$0x0包含常量0?或者这不是地址而是常量?) 它是
返回0
中的常量。将EAX用于较小的返回值是一种常见的约定
40063b:将当前在基指针寄存器中的地址放入堆栈段(该寄存器是如何初始化的?为什么要初始化?)
您希望保存基指针,因为调用函数可能正在使用它 40063c:将堆栈指针寄存器中的值复制到bas中
; 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