00:00:00.708-->00:00:05.708 [Applause] >>Good Morning, welcome to Def Con. Today I will talk about a topic, uhh kernel- 00:00:08.208-->00:00:15.042 macOS and iOS Kernel Debugging and Heap Feng Shui. Here is the outline. First, I will introduce 00:00:15.042-->00:00:21.417 myself and what is the kernel. Then I will introduce how to do kernel debugging on MacOS and 00:00:21.417-->00:00:26.417 iOS then I will use these debugging techniques to debug a real kernel heap overflow, last 00:00:29.833-->00:00:36.750 but not least I will, I will introduce two methods to do Heap Feng Shui. Okay, let’s start. 00:00:36.750-->00:00:41.750 So, who am I? My name is Min Zheng, you can call me Spark. Umm I’m a security expert at 00:00:45.167-->00:00:50.167 AliBaba and I am a PhD in CUHK, and I am a member of Blue Lotus and Insight-labs. I work in 00:00:52.958-->00:00:57.958 FireEye, Baidu and Tencent before. Our team have achieved a private jail breaking of iOS 9, 00:01:01.333-->00:01:06.333 and we will show more details in the future. Ummm, here is my weebler and twitter.. you can 00:01:09.708-->00:01:15.208 follow me and ask me questions on that. This work has a coauthor called Xiagyu Liu- he 00:01:15.208-->00:01:20.708 is my colleague and he is a security engineer at AliBaba. I also want a special thanks to my 00:01:20.708-->00:01:25.708 friends which helped me in this work. Uh so, the topic is Kernel Debugging. What is the Kernel? 00:01:29.000-->00:01:34.833 The kernel is actually the XNU. XNU is the computer system operating system kernel 00:01:34.833-->00:01:39.833 developed by Apple. It is open source software as part of the Darwin operating system. It has 00:01:42.375-->00:01:47.375 abbreviation called, X is Not Unix. We know that XNU for macOS is open source. It can be 00:01:51.958-->00:01:56.958 compiled and debugged. However, XNU for iOS is not open source. You cannot compile it and debug 00:02:01.042-->00:02:07.958 it officially, but most implementations is same as macOS. However, we can use some 00:02:07.958-->00:02:12.958 tricks to do Kernel Debugging for iOS too and I will introduce it later. Let’s talk about macOS 00:02:16.625-->00:02:21.625 debugging first. A wise man once said to do a good job, one must sharpen one’s tool. Uh so we 00:02:26.542-->00:02:32.917 need to buy some equipments. First, we need two MacBooks or one MacBook with Virtual 00:02:32.917-->00:02:39.333 Machine. [clears throat] The system version can be different, which means you can debug iOS 10 00:02:39.333-->00:02:44.333 point 10 or iOS 10 point 11 also you need to buy some ummm converters or keyboards. 00:02:50.250-->00:02:55.250 Thunderbolt to FireWire, FireWire cable. After we have the equipment, we need to 00:02:58.875-->00:03:03.875 install KDK on the two MacBooks, umm for for the for the host MacBook we need to execute a 00:03:07.583-->00:03:12.583 command called FWKDP for the debugged MacBook we need to copy the kernel dot development of 00:03:14.875-->00:03:20.958 KDK to the System/Library/Kernels/ folder in the debug MacBook and then 00:03:20.958-->00:03:26.167 execute the following command. This command will set the environment and reboot the 00:03:26.167-->00:03:31.167 debug, the debugged MacBook. Uh, after rebooting the host MacBook can start debugging with command 00:03:36.292-->00:03:41.292 LLDP, KDP-remote localhost, know that we can get kernel slides immediately it is very useful 00:03:43.500-->00:03:48.500 for us to debug the kernel. Uh also we can use some.. com..some command like image list to get 00:03:50.833-->00:03:57.292 the kernel address of partial kernel extensions. Note we can only get partial kernel 00:03:57.292-->00:04:03.208 extensions, if we want to get all the kernel extensions we need some other ways. Uh just 00:04:03.208-->00:04:08.208 ilk JDB we can use X slash NX to read the data in the kernel. Also, we have three ways to set 00:04:13.083-->00:04:18.083 the breaks point in the kernel. Um by using uh by we can use B uh asterisk address to set the 00:04:22.625-->00:04:27.625 break point in the RRDB. We need to use the offset of the kernel cache plus the kernel slides to 00:04:30.500-->00:04:35.500 calculate the address. Another way to pause the debugging machine is to use a shortcut 00:04:38.083-->00:04:43.083 key. You can use command plus alt plus control plus shift the plus ESC all at once. And it 00:04:45.458-->00:04:50.458 will pause the debug machine immediately. Uh we can also set breakpoints in the XNU source 00:04:53.917-->00:04:58.917 code zeroing dollar three. Print information note that you use this way to debug the kernel you 00:05:03.083-->00:05:08.083 need to recompile the kernel then put it in the debug machine. Uh also we can use 00:05:11.875-->00:05:16.875 command script, the importer. This command to load the present script in the kernel. In the 00:05:19.917-->00:05:25.250 RRDB. It is very useful because this script path help me get a lot of information about the 00:05:25.250-->00:05:30.250 kernel. Forget them you can the print to print the zone.. the zone information and uh you can 00:05:34.333-->00:05:39.333 use show z free list release tool to show the relevant information in the free list. Uh 00:05:42.792-->00:05:47.750 there's another command called showed all kernel extensions. This commander can get all the 00:05:47.750-->00:05:54.667 kernel addresses of the kernel extension. In addition, you can implement your own peasant 00:05:54.667-->00:05:59.667 script. Um you can find some examples in the KDKs peasant folder. Okay. So uh let's talk 00:06:07.958-->00:06:12.958 about iOS kernel debugging. We know that there's no official tools for iOS kernel debugging 00:06:16.542-->00:06:23.500 but we can use some tricks to do that. Um before we debug the iOS kernel we need to get the 00:06:23.500-->00:06:30.458 kernel.. kernel cache. Alright Mac iOS, we needed to decrypt the kernel cache. Before iOS 00:06:30.458-->00:06:36.917 turned the kernel cache were encrypted. You can find the key in the Wiki uh iPhone Wiki 00:06:36.917-->00:06:42.292 website and then decrypt the kernel cache. After iOS turns there's no encryption but 00:06:42.292-->00:06:47.292 there's some code so we need to unzip the kernel and uh decode the kernel using a major four 00:06:49.583-->00:06:54.583 tool. After that you can extract the kernel.. kernel information through Joker and IDA. Uh note 00:06:59.500-->00:07:06.000 that there's no break point in iOS so the most common way to get the registered value is to 00:07:06.000-->00:07:11.000 is use the penny the use the panic log um some thing to pay attention is um if there are too 00:07:15.000-->00:07:20.000 many panic logs in your phone's system it will stop generating the panic log. So if you want to 00:07:22.708-->00:07:27.708 debug your iOS.. iOS system, you need to delete the panic logs if there are too many. So you can 00:07:30.042-->00:07:35.042 use two measure to do this. One if for jail break the iOS and another is for un jail break the 00:07:37.333-->00:07:42.333 iOS. Uh although there's no KDK in iOS we can still use kernel task port to do arbitrary kernel 00:07:47.750-->00:07:52.750 memory read and write through to userland API. One is called Mark VM read another is called Mark 00:07:55.250-->00:08:00.250 VM Write. But what if we don't have the task for PID Patch for no jail break. What do we do? 00:08:04.667-->00:08:09.667 Well you need first you need a kernel vulnerability uh then you can use its vulnerability to get 00:08:12.167-->00:08:18.833 the kernels task port. Then you can restore this kernel task port into the hostess special 00:08:18.833-->00:08:25.750 port. Then you can use uh userland API called the host to get the special to get the 00:08:25.750-->00:08:30.750 kernel task port in the userland and then you can use Mark VM Read and Mark VM Write to do the 00:08:33.750-->00:08:38.750 kernel reading and writing in the userland. Uh after getting the kernel task the next step is 00:08:41.750-->00:08:48.625 to figure out the kernel text space and slide. In uh um so there are two ways to get it 00:08:48.625-->00:08:53.625 because there are only two hundred and fifty six potential [cough] locations for the kernel 00:08:55.750-->00:09:00.750 slide. But they in arm64 it's not easy we need to do something first create an OS object in 00:09:03.458-->00:09:08.458 kernel. Then we need to find its vtable pointer which points to the kernels base region. Then we 00:09:10.875-->00:09:17.333 search backwards from the vtable address until we find the kernel header. Uh the source code can 00:09:17.333-->00:09:22.333 be referred to the iOS kernel utilities project. Hmm, after getting the kernel slide, we can 00:09:26.500-->00:09:31.500 get the root privilege for our applications for the kernel read and write. Hmm and then we can 00:09:34.958-->00:09:39.958 use off set plus kernel slide to find the object address of related post in memory. It is 00:09:42.417-->00:09:47.417 very useful to debug the mark port in the XML system. So now I will show how to use debug 00:09:53.708-->00:09:58.708 techniques to debug a real kernel overflow. Uh this one ability this is the Mach Voucher 00:10:04.083-->00:10:09.083 uh extract attribute recipe trap. Uh this is uh new function added in iOS ten and iOS and 00:10:12.583-->00:10:17.583 MacOS ten point twelve. So that's why there's no jailbreak for iOS nine point three point 00:10:21.375-->00:10:26.375 five because uh this function does not exist in that version. It's a new function in iOS ten. 00:10:29.125-->00:10:34.125 And this Mach trap can be called inside the sandbox so we can we can detect the kernel in inside 00:10:37.542-->00:10:42.542 the sandbox. This function we are first call use calling to get the recipe size from the 00:10:45.500-->00:10:50.500 userland and save this size to the S Z then we use key log to allocate SZ size a member of 00:10:55.958-->00:11:00.958 blog memory with this size and then it will be copying to copy the data from the userland to 00:11:04.333-->00:11:11.125 the kernel. However the developer forgot that the recipe size was a userland point 00:11:11.125-->00:11:16.125 userland pointer and then it use it as a size value in the copying. We know that a userland 00:11:18.792-->00:11:23.792 pointer may be very large than the size value so it may cause an overflow. If we want to debug 00:11:28.833-->00:11:33.833 this vulnerability then we can set the break points before and after copy-copying IO. And they 00:11:36.208-->00:11:41.208 are address are calculated through the overset in the kernel cache plus the kernel 00:11:43.292-->00:11:48.292 slide. Uh so you can as you can see before people can overflow we can find the flag of dead 00:11:53.417-->00:11:58.417 beef. The dead beef means this this blog of memory are not used but as the next blog of memory 00:12:01.667-->00:12:06.667 is used with F F F. After after we trigger the F overflow we can find the first log is full of 00:12:12.458-->00:12:17.458 our our data with A. And then the next blog of memory by our first blog of memory uh it 00:12:24.667-->00:12:29.667 overflowed. It started to bind with character B. So now we have the ability to overflow 00:12:34.333-->00:12:39.333 arbitrary content of data but we need to find a way to do the kernel read and write. So we 00:12:42.958-->00:12:47.958 need to do some Feng Shui. Um there's two ways to do hip hip Feng Shui in iOS ten and MAC OS 00:12:50.625-->00:12:55.625 ten point twelve. Uh I already introduced the first one. We know that in iOS ten and Mac OS 00:12:59.708-->00:13:04.708 ten point twelve we can not use the classic VM Map copy techniques to do the heap Feng 00:13:07.000-->00:13:12.000 Shui. By changing the VM map size because Apple added the new um mitigation that uh they will 00:13:15.417-->00:13:22.250 check the freeing into the wrong zone attack which means if you change the size of the VM copy 00:13:22.250-->00:13:27.250 the kernel will panic. So we need to find a way to avoid that. Uh luckily Beer in Google 00:13:30.875-->00:13:35.875 Project Zero proposed a new way to do heap functions zero the preallocate Mach port. The basic 00:13:38.333-->00:13:43.333 idea is to use Mach Port alloc full IPC k message objects in the kernel memory. The memory uh 00:13:46.250-->00:13:51.250 the object contends a size field we can corrupt and it doesn't have any pointer so we not 00:13:55.042-->00:14:00.042 corrupt any pointer in the kernel memory so we will not be panicked. Uh by using the 00:14:02.250-->00:14:07.250 exception port we can send and receive the data in the kernel memory. And this data we can we 00:14:10.375-->00:14:15.375 are not be freed it's very important. And the data we used to send is the crashed is 00:14:18.000-->00:14:23.750 registered value of the cached thread. So if we want to send the information to the kernel we 00:14:23.750-->00:14:28.750 need to create a thread and set the registered value. We want to send and then crush the thread 00:14:32.083-->00:14:37.083 the data will be sended to the to the address to IPC can message objects plus IKM size 00:14:40.792-->00:14:45.792 minus one oh four. SO why is the number one oh four. We can use kernel debugging to figure out 00:14:49.667-->00:14:55.375 it. First we use kernel debugging to figure out the address of pre-alloc port buffer 00:14:55.375-->00:15:00.958 in the memory. then we can trigger the execution and send the data to the kernel. After 00:15:00.958-->00:15:07.500 that we can use kernel debugging machine like kernel reader to get the data to inspect the data 00:15:07.500-->00:15:12.500 of the buffer. As you can see we find the location of the data in the buffer is D three C. Because 00:15:17.417-->00:15:22.417 we set the value of the IKM size to E 4 O, uh therefore we can one oh four at last. So that's 00:15:27.125-->00:15:32.125 why the number is one oh four. Um so now we when we get the object to do the heap functions 00:15:35.917-->00:15:40.917 the next step is to rearrange the kernel memory. First we allocate 2-->000 prealloc ports un 00:15:43.042-->00:15:48.042 to ensure the following imports are continuous continuously. And then the attacker can 00:15:50.542-->00:15:55.542 generate.. can allocate three ports. One if the holder. The second is first port and the 00:15:58.250-->00:16:03.250 third is second port. Both of them uh are in the zone of two thou.. uh four thousand and 00:16:09.583-->00:16:14.583 ninety six. Then we then the attacker can free the holder and use the overflow vulnerability 00:16:18.375-->00:16:23.375 to overflow the first port. Um, it the the over overflow data contains the IKM size and other 00:16:28.917-->00:16:33.917 fields of the IKM object. Um the key point is to set the IKM size to one one oh four. So why is 00:16:39.083-->00:16:44.417 one one oh four, we can do a simple calculation that the first the address of the first 00:16:44.417-->00:16:49.417 port plus one one oh four minus one oh four. Uh it will be the address of the second port. 00:16:52.167-->00:16:57.167 Which means we can control the second port through the first port. Uh so if we can control 00:17:01.833-->00:17:07.333 the second the data of the second port, the next step is to get the address of the second 00:17:07.333-->00:17:12.333 port. Which means we need heap information link. So how to do that. The first thing is the 00:17:14.875-->00:17:19.875 attacker give you the first port to give the second port a valid header. If the second port has a 00:17:22.250-->00:17:27.250 valid header, you send, you send the data to the second port. The second port is IKM next and IKM 00:17:29.958-->00:17:35.792 perverse will be set to point to itself. Which means if you received the data from the 00:17:35.792-->00:17:41.875 kernel to get the data of the second porter you can figure out the kernel location of the said 00:17:41.875-->00:17:46.875 port of the kernel memory. After getting the heap address the next step is to get the kernel 00:17:50.125-->00:17:55.125 slide. Um but uh before we do that we need to safely free the second port. The reason is if 00:17:58.750-->00:18:05.375 you don't do that the system will be panicked because the.. the kernel detects from memory 00:18:05.375-->00:18:10.375 corruption. After freeing the second port the attacker can allocate use their client to 00:18:13.042-->00:18:18.042 hold the spot of the second port. Then the attacker can get the user client object through 00:18:22.667-->00:18:27.667 the first spot. Uh note that the first eight byte of the kernel of userland.. user client object 00:18:30.833-->00:18:35.833 is the vtable address so which means you can use vtable address in the kernel cache compare with 00:18:40.750-->00:18:46.833 the. with this dynamic vtable address then we can calculate the kernel slide. In this case, 00:18:46.833-->00:18:51.833 the kernel slide is one BC zero, zero, zero, zero, zero. After that the attacker can uh 00:18:55.875-->00:19:00.875 generate uh create a rope chain which can be used to do the kernel arbitrary kernel memory 00:19:03.542-->00:19:08.542 read, He use.. he can use OS centralized with the uh with UUID copy. This way the attacker 00:19:11.667-->00:19:16.667 can copy the data from any address to the kernel buffer piece plus four eight. And then 00:19:19.333-->00:19:24.333 use the first port to get this data back to the user mode. If we reverse the X one and the X 00:19:28.875-->00:19:33.875 zero we can get kernel memory write because one is to do the read another is to do the write. 00:19:36.583-->00:19:41.583 Uh so, we can rope chains. The next step is the trigger this rope chains through the IO 00:19:48.458-->00:19:54.833 connect that gets service. This method that will invoke, get method class return and then the 00:19:54.833-->00:19:59.833 release method. So we can create a fake vtable- vtable and send it to the second port. Then we 00:20:02.833-->00:20:08.500 can use IO connect get service to trigger the rope chain. Uh we mentioned it before to do the 00:20:08.500-->00:20:14.167 kernel read and write. Uh when we get the ability of kernel read and write we can do kernel 00:20:14.167-->00:20:19.167 patch. Uh the latest in kernel patch tech.. technique can be referred to as yalu. Uh note 00:20:21.208-->00:20:27.750 that this this tradition Feng Shui is not sta..stable because it it need to do multiple times 00:20:27.750-->00:20:32.750 and it use the a lot of rope chains. Uh it only have a fifty percent successful rate. Uh so 00:20:36.042-->00:20:41.042 if we want to get if want we want to have uh high success- successful rate we need to use 00:20:44.792-->00:20:49.792 Port Feng Shui. So what is Port. We know that Mach Message is the most frequently IPC mechanism in 00:20:53.083-->00:20:58.083 X and U. And we can use complicated to send out of LAN Ports to the kernel which means 00:21:00.625-->00:21:05.625 we can send the ports object to the kernel. And in this case, I.. we will send thirty two Mach 00:21:10.792-->00:21:15.792 Port to the kernel and uh each each port use the eight bytes. And eight byte multiplied by 32 00:21:20.792-->00:21:25.792 is 256. So the data will be sended to the zone 256. Uh note that the out of LAN Ports saved 00:21:31.833-->00:21:36.833 in the mach message is the IPC object pointer. And the pointer can be pointed to the user mode 00:21:39.292-->00:21:44.292 address therefore the attacker can overflow this those pointers and modify the pointer to point 00:21:46.833-->00:21:51.833 to a user mode and then we can control this port in user mode and uh create a fake task for 00:21:54.167-->00:21:59.167 this fake port as well. So, uh how to overflow the right port. The right port is key. So we 00:22:06.500-->00:22:13.333 need to do some Feng Shui to rearrange the kernel memory. The first thing we should do is to 00:22:13.333-->00:22:19.875 send lots of OL pod to the kernel. To ensure the new allocated blogs are continuous. 00:22:19.875-->00:22:24.875 And then the attacker receives some message in the middle to dig some slot. Then the attacker 00:22:29.000-->00:22:34.000 sends some message again to me because the overflow point at the middle of the slot. After 00:22:36.542-->00:22:41.542 that the attacker can trigger the overflow vulnerability at the overflow point. Then we 00:22:44.375-->00:22:49.375 receive all the port from the kernel and check the value of the port. As we mentioned we 00:22:51.833-->00:22:56.833 send the data port to the kernel with F F F F. If the value changes to some other value 00:23:00.250-->00:23:05.250 which means this port is overflowed by us and we can we can control this port in 00:23:07.750-->00:23:12.750 userland. So if we can control a port in the kernel what we can use this port to do arbitrary 00:23:15.292-->00:23:20.292 kernel memory read. How to do that. We need to set the io bits of the fake IPC object to uh 00:23:23.625-->00:23:28.625 IKOT task and craft a fake task for the fake port by setting the value at uh the fake task plus 00:23:32.917-->00:23:37.917 uh the process of the attacker can do arbitrary memory read. It is very- it is a-amazing because 00:23:42.083-->00:23:47.625 the fun-function doesn't change the validation of the task and they're just the return of the 00:23:47.625-->00:23:52.625 valid of the address. As you can see in this function uh the the int where port name to task to 00:23:55.500-->00:24:00.500 get the fake task and the fake task is controlled by us. The it will use get PST task info to 00:24:03.833-->00:24:08.833 get the information and uh the function. So the function will use A one plus three eight oh to 00:24:11.500-->00:24:16.500 get the to get the data on the address. And this address is controlled by us. Also it will 00:24:19.000-->00:24:25.208 use the process CAD to get the information on the A one plus one oh, and this address is also 00:24:25.208-->00:24:30.208 controlled by us. So we can get this so we can get any address uh in the data in any address 00:24:35.417-->00:24:40.417 and we get the kernel.. kernel arbitrary read ability. Then we can dump the kernel the IPC 00:24:42.500-->00:24:47.500 object and the kernel task to our fake IPC object and the and the copy it to our fake IPC 00:24:49.833-->00:24:56.083 object and the fake task. Then we can use the userland API called Task to get special port 00:24:56.083-->00:25:01.083 to get the kernel task port. Then we can use this kernel task port to do.. to call two API. 00:25:05.125-->00:25:10.125 One is VM.. Mach VM read and one is Mach VM Write to arbitrary read and write. So here is the 00:25:15.333-->00:25:20.333 conclusion. Uh in we we talked about the kernel debugging. It is very useful for us to do 00:25:22.958-->00:25:28.708 kernel exploit development and uh we introduced two heap function techniques. One is 00:25:28.708-->00:25:34.500 traditional heap function because it needs rope chains to do kernel memory read and write. 00:25:34.500-->00:25:40.708 And it needs multi times, so it's not stable. For Port Feng Shui, it doesn't need any 00:25:40.708-->00:25:46.667 gadgets and it only use this structure. It's stable. Uh with the highest success.. highest 00:25:46.667-->00:25:51.667 successful rate. But it's very easy for airport to fix it. So that's all for my talk, thank 00:25:53.708-->00:26:00.458 you for your listening. [Applause] Do you have any questions? [Applause] Sorry, I 00:26:00.458-->00:26:02.333 take a long time.