- Published on
堆栈溢出初体验
- Authors
- Name
- wellsleep (Liu Zheng)
环境配置
- Kali Linux 4.8.0 (基于Debian 4.8.5),64位
- GCC 6.3.0 20170425
- GDB 7.11.1
- GDBGUI 网页前端 用于逃离gdb可怕的键盘操作
准备工作
源码
#include <stdio.h>
#include <string.h>
int hijack() //待注入的函数
{
printf("hijack!\n");
return 0;
}
int main(int argc, char* argv[])
{
char buf[256];
printf("buf at %p\n", buf);
strcpy(buf, argv[1]); //通过这里的溢出修改返回地址
printf("Input: %s\n", buf);
return 0;
}
编译选项
由于现在的OS和编译器对缓冲区溢出有了一定的防范,所以为了实验最基本的缓冲区溢出,必须关掉一些选项,包括:
关闭OS的虚拟地址随机化,默认值是2
#echo 0 > /proc/sys/kernel/randomize_va_space
调整编译选项
gcc -g -fno-stack-protector -z execstack -o book book.c
搭GDBGUI环境
(gdb) layout asm
(gdb) layout regs
开启更多分屏,但空间随之被压缩。由于刷新的问题屏幕可能乱七八糟,此时用Ctrl + L
重新刷新即可。
要调试起来的话一般是用b(reak) main
在main中设置一个断点,然后用r(un)
运行程序,到了断点的地方用c(ontinue)
或s(tep)i
或n(ext)i
来单步调试。注意si
和ni
对应汇编代码的下一行,如果是直接调C程序则用s
和n
即可。
要在某一行加断点使用b *0xfffffff7c
,而删除断点使用d(elete) n
,n对应断点编号。
所以GDB高手调起程序来是这个状态:
溢出实验
reference
- 典型的基于堆栈的缓冲区溢出
- 楼上的原文
- 64 Bits Linux Stack Based Buffer Overflow 其实讲基本溢出的攻击很多,但第一个属于手把手,讲的比较细,第二个是少数几个讲64位OS溢出的基础实验。由于64位OS的通用寄存器与32位的不同,因此作为上来一不小心选了64位作为平台的小白,歪果仁讲的更明白(相对而言)。
原理
在本文中,最基础的溢出原理就是使用`strcpy(dst,src)``时,由于不限定复制的长度,如果使用一个长度大于dst的src来运行此操作时,会出现dst后面的数据被复写。而如果dst后面的数据是堆栈中的重要寄存器值,比如返回地址(strcpy函数总是要返回给上级函数的嘛),那么经过巧妙构建的溢出数据,就可以修改程序的走向,引导到自己设定的邪恶的圈套中。
实现
更多的暗黑操作,是通过构建/bin/bash
的字符串,由程序中自带的system()
触发。之后还要研究如果开启了ASLR或其他缓解措施(比如va random或编译选项)是,如何溢出堆栈。路还很长哪~