【问题标题】:Buffer overflow vulnerability lab缓冲区溢出漏洞实验室
【发布时间】:2020-07-13 00:20:17
【问题描述】:

我正在通过实验室演示缓冲区溢出漏洞利用。我有它的工作,但有一个领域我不太了解,我希望有人可以为我解释。

这是带有漏洞利用的代码:

/* Vunlerable program: stack.c */
/* You can get this program from the lab’s website */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
  char buffer[24];
  /* The following statement has a buffer overflow problem */
  strcpy(buffer, str); ➀
  return 1;
}
int main(int argc, char **argv)
{
  char str[517];
  FILE *badfile;
  badfile = fopen("badfile", "r");
  fread(str, sizeof(char), 517, badfile);
  bof(str);
  printf("Returned Properly\n");
  return 1;
}

实验的一个步骤是确定分配给缓冲区的内存大小[24]。为此,我在 bof 函数上运行 gdb,我可以看到在我的系统上分配的内存是 0x20,即 32 位。

如果我改变缓冲区的大小,我可以运行 gdb 并找到分配的内存插槽。但是我应该能够知道在没有 gdb 的情况下会为 buffer[24] 分配多少内存吗?如果我更改为 buffer[8],我应该一眼就知道 32 位系统上的内存块是什么,还是它在系统上有所不同?如果我应该知道,谁能解释一下。

【问题讨论】:

  • 分配给缓冲区的大小取决于编码:UTF-8, UTF-16, UTF-32, character encoding, ...地址根据您的系统以 32 位或 64 位表示
  • 我在 32 位 ubuntu 16.04 上运行它。有了这些信息,就可以知道将分配给缓冲区的内存 [24] 还是最好使用 gdb 之类的东西来计算内存大小。

标签: c ubuntu buffer-overflow


【解决方案1】:

这取决于目标平台、编译器和编译标志。

例如,调试模式下的 GCC 7.2 x86 (-O0) 在 16 字节边界上对齐堆栈帧并分配帧指针 (ebp)。

示例:(godbolt link)

bof(char*):
        push    ebp                   ; -4
        mov     ebp, esp           
        sub     esp, 40               ; -40
        sub     esp, 8                ; -8
        push    DWORD PTR [ebp+8]     ; -4
        lea     eax, [ebp-32]         ; 32 bytes to top of stack frame
        push    eax                   ; -4
        call    strcpy                ; stack is aligned to 16 bytes (-64)
        add     esp, 16
        mov     eax, 1
        leave
        ret

对 (-O2) 进行优化后,帧指针被省略,但堆栈仍按 16 字节对齐 (godbolt link):

bof(char*):
        sub     esp, 52               ; -52
        push    DWORD PTR [esp+56]    ; -4
        lea     eax, [esp+20]         ; 36 bytes to top of stack frame
        push    eax                   ; -4
        call    strcpy                ; stack is aligned to 16 bytes (-64)
        mov     eax, 1
        add     esp, 60
        ret

强制 4 字节堆栈对齐 (-O2 -mpreferred-stack-boundary=2) (godbolt link):

bof(char*):
        sub     esp, 24               ; -24
        push    DWORD PTR [esp+28]    ; -4
        lea     eax, [esp+4]          ; 24 bytes to top of stack frame
        push    eax                   ; -4
        call    strcpy
        mov     eax, 1
        add     esp, 32
        ret

开启堆栈保护器 (-O2 -fstack-protector-all) (godbolt link):

bof(char*):
        sub     esp, 52                      ; -52
        mov     eax, DWORD PTR gs:20
        mov     DWORD PTR [esp+36], eax      ; stack check value at -16 (-52+36)
        xor     eax, eax
        push    DWORD PTR [esp+56]           ; -4
        lea     eax, [esp+16]                ; 40 bytes to top of stack frame, leaving exactly 24 bytes to check value
        push    eax
        call    strcpy
        add     esp, 16
        mov     edx, DWORD PTR [esp+28]
        xor     edx, DWORD PTR gs:20
        jne     .L5
        mov     eax, 1
        add     esp, 44
        ret
.L5:
        call    __stack_chk_fail

其他编译器可能有完全不同的结果。

在现实生活中,通过分析指令并计算函数返回地址的字节数,在汇编模式下会利用缓冲区溢出,因此源代码是什么或如何编译并不重要(此信息通常不可用无论如何)。

【讨论】:

    猜你喜欢
    • 2013-02-01
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    相关资源
    最近更新 更多