繁体   English   中英

在汇编级别的此简约C代码中究竟发生了什么?

[英]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寄存器
  • 400649:将堆栈顶部的值(由%rsp中的值确定)复制到基本指针寄存器(似乎要由汇编程序确认:Push / pop寄存器?
  • 40064a:返回(操作系统使用%EAX中的内容作为返回码-所以我猜地址$ 0x0包含常数0?还是不是地址而是常数?)

40063b:将当前在基本指针寄存器中的地址放入堆栈段(该寄存器如何初始化?为什么这样做?)

您想保存基本指针,因为它可能被调用函数使用。

40063c:将值从堆栈指针寄存器复制到基本指针寄存器中(为什么?)

这为您提供了一个固定位置,该位置可能包含函数的参数。 它也可以用作任何局部变量的基址。

40063f:调用exploitableFunction(在汇编中“调用”一个函数到底是什么意思?这是什么情况?)

“调用”是指将返回地址(下一条指令的地址)压入堆栈,然后跳转到被调用函数的开头。

400644:将值从地址$ 0x0复制到EAX寄存器

实际上,它是return语句中的值0。

400649:将堆栈顶部的值(由%rsp中的值确定)复制到基本指针寄存器中(似乎由汇编程序确认:推/弹出寄存器?)

这将恢复我们保存在顶部的基本指针。 调用函数可能会假设我们这样做。

40064a:返回(操作系统使用%EAX中的内容作为返回码-所以我猜地址$ 0x0包含常数0?还是不是地址而是常数?)

这是从return 0开始的常量。 将EAX用作较小的返回值是一种常见的约定。

我找到了一个链接 ,该链接具有与您自己相似的代码,而且功能全面。

  • 40063b:将旧的基本指针推入堆栈以保存以备后用。 之所以进行推送,是因为这不是代码中的唯一过程。 其他过程将其称为。
  • 40063c:将堆栈指针的值复制到基本指针。 此后, %rbp指向main的堆栈框架的底部。
  • 40063f:调用地址0x4005f6的函数,将程序计数器压入堆栈,并将地址0x4005f6装入程序转换器,当函数返回时,发生弹出操作,将堆栈中已保存的地址返回到程序计数器0x400644
  • 400644:此指令将0复制到%eax ,x86调用约定规定函数的返回值存储在%eax
  • 400649:我们将旧的基本指针从堆栈中弹出,并将其存储回%rbp
  • 40064a:跳回返回地址,该地址也存储在堆栈帧中。 它指定程序的结尾。

同样,您也没有提到功能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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM