vivotek
这次换个口味,试试arm的摄像头。
固件下载及提取
1 | unzip CC8160-VVTK-0100d.flash.zip |
固件仿真
- 用户模式
已知漏洞存在于httpd中,因此直接运行此程序,发现ld不是arm架构的,因为这是之前复现路由器漏洞时的ld,因此是mips架构的。
由于程序会默认从根目录寻找ld文件,因此我们可以使用下面这个命令改变暂时改变根目录来解决这个问题
1 | cp /usr/bin/qemu-arm-static ./qemu |
没有/dev/null文件,创建在./dev文件夹下创建null文件
再次运行
根据错误信息定位到该程序具体代码,发现原因是缺少/etc/conf.d/boa/boa.conf
文件,但该文件是配置文件,不知道其中的内容,因此利用find $PATH -name boa.conf
命令查找到该文件
同时发现./etc/conf.d
是指向../mnt/flash/etc/conf.d
的文件只需要将boa.conf文件放入指向的文件夹即可。
再次运行,依旧报错,同样的,定位字符串找到报错的语句,查看交差引用,发现并没有谁调用这个函数,坏了,一股不安涌上心头,没事,找找其他人有没有遇到这种问题,嘶~,他们咋都没出现这个问题,又是我的问题?😢
ida提示没有函数调用该函数,根据经验判断可能存在某种虚表,通过偏移进行函数的调用的,因此就从上面的打开boa.conf文件操作后开始寻找这个虚表,寻找过程很枯燥,就是点开每个函数,查看是否有(a1)(argv)类似这样的以变量作为函数的,很快就找到了满足条件的函数,我们查看调用该函数的函数,很快便找到虚表。
根据sub_FFC8()
的参数,发现产生错误的原因在boa.conf中,查看该文件中的内容,并根据报错锁定到了下图,文件中提示如果不想打开该文件就设置成/dev/null
且不要使用注释
1 | - MimeTypes /etc/conf.d/boa/mime.types |
再次运行,依旧报错
根据报错定位到下图,原因是因为我们的主机名和固件中的主机名不同导致错误其中,gethostname()
是获取进程所在主机的主机名,gethostbyname()
是通过域名\主机名获取IP地址
因此,只需将$PATH/etc/hosts中主机名改为自己的主机名即可
再次运行,可以看见执行成功
- 系统模式
本来准备使用qemu配置真实的环境,但奈何找不到供qemu使用的arm内核镜像,其他人博客里的链接也都失效了,找了一天没找到,放弃,差点就准备自己买个摄像头emmmm
漏洞分析
该漏洞分析较为简单,因strncpy()的第三个参数是我们输入的长度,并且没有对长度进行检查,因此会造成溢出。但仔细一想为啥会这样写,Content-Length:
后一般都是数字,而数字一般的长度都很短,本以为后面会有对dest
进行处理的函数如,atoi()等,但并没有发现。
虽然说漏洞处的逻辑简单,但确保从_start()
执行到该漏洞函数处的过程却是十分复杂的,跟剥洋葱差不多,分析起来也十分的头疼,函数套函数套函数套函数……
漏洞调试
1 | #第一个终端中输入 |
调试发现程序会执行到exit(),发现该程序需要我们输入参数,必须要包括-d
在内,这样dword_31930
才会被置为0,才能不执行exit()。
因此,添加参数过后,我们继续调试,当断点下在0x1cd54
时,便卡在了continuing这里,从该断点往前读代码寻找问题语句,发现问题出在select()
,该函数检查套接字是否已经准备好读/写,因此,我们需要向127.0.0.1:80
发送数据。
因此我们另起一个终端输入nc 127.0.0.1 80
并且发送数据即可进行后面的调试了。这里便是我们构造的payload的输入点。
漏洞利用
利用cyclic确定偏移,为52
同时,程序开了NX保护,因此不能将shellcode写入栈中。
因此我们利用ROP来执行system函数,首先查看libc中的system函数的源码很好,没有fork(),可以在用户态下执行。
利用延迟绑定获得libc基地址,从libc中获得gadget,同时函数的抵用规则也十分简单,先将pc
寄存器push
到栈中,返回函数时在pop
回来,因此可直接覆盖pc
寄存器,其中gadget可以利用ROPgadget --binary ./lib/libc.so.0 --only "pop"
获得,同时,因为是strncpy函数造成的溢出,所以地址不能存在\x00
.
经调试,程序流执行到了system函数,发现dword_586BC
是0,因此不能获得shell
笔者也换了种思路,因为system是调用execve执行的,因此只要将execve的第二个和第三个参数都设为指向0的地址,在调用SVC #0
即可,但找了很久没有找到可以改变r2寄存器的gadget,很神奇,其他寄存器都有,就r2没有,当我想看看还有谁调用了execve时,突然看见了如下图的汇编代码,可以通过构造r3来控制r2
但很可惜,构造成功了也还是报错😭
完整exp:
1 | from pwn import * |
不过system函数没有执行成功的原因因该和mips架构时的原因差不多,需要启动qemu系统模式才能执行。