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 Properly\n");
return 1;
}
实验室的一个步骤是确定分配给缓冲区的内存大小[24]。为此,我所做的是在 bof 函数上运行 gdb,我可以看到在我的系统上分配的内存是 0x20,即 32 位。
如果我改变缓冲区的大小,我可以运行 gdb 并找到分配的内存插槽。但是我应该能够知道在没有 gdb 的情况下会为 buffer[24] 分配多少内存吗?如果我更改为 buffer[8],我应该一眼就知道 32 位系统上的内存块是什么,还是它在系统上有所不同?如果我应该知道,有人可以解释一下。
解决方案
这取决于目标平台、编译器和编译标志。
例如,调试模式 ( -O0
) 中的 GCC 7.2 x86 在 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 个字节(天螺栓链接):
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
(godbolt 链接):
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
其他编译器可能有完全不同的结果。
在现实生活中,通过分析指令并计算函数返回地址的字节数,在汇编模式下会利用缓冲区溢出,因此源代码是什么或如何编译并不重要(无论如何,此信息通常不可用)。
推荐阅读
- hive - Hive 提取到本地驱动器错误的输出
- ios - UITableView:滑动 RowAction 取消选中的行
- react-native - 可触摸不透明度打破居中
- java - Spring Websockets:如何验证消息和接收客户端?
- php - 使用路由器重定向登录
- spring-boot - 未从 Spring Security Oauth2 中的授权代码中获取访问令牌?调用访问令牌失败给 ERR_TOO_MANY_REDIRECTS?
- r - R - 根据另一个数据框的多列中的值之间的关系创建具有值的矩阵
- unity3d - Unity3D获取OVRCameraRig的位置
- java - Spring Security 中如何让访客在不登录的情况下访问主页
- javascript - 如何使用 PHP 获得与我需要的完全相同的 JSON 格式?