c-缓冲区溢出漏洞实验室



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

这是利用的代码:

/* 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 Properlyn");
return 1;
}

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

如果我改变缓冲区的大小,我可以运行gdb并找到分配的内存插槽。但是,如果没有gdb,我应该能够告诉缓冲区[24]将分配多少内存吗?如果我改为缓冲区[8],我应该一眼就知道32位系统上的内存块是什么吗?还是它会因系统而异?如果我知道的话,有人能解释一下怎么做吗。

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

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

示例:(导螺杆连杆(

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链接(:

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((导螺杆连杆(:

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((导螺杆连杆(:

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

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

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