WEBVTT 00:00:00.099 --> 00:00:15.129 34c3 preroll music 00:00:15.129 --> 00:00:19.695 Herald Angel: And now I want to introduce our first speaker and the topic he's 00:00:19.695 --> 00:00:27.844 talking about. iOS kernel exploitation archaeology. A kernel exploit from late 00:00:27.844 --> 00:00:35.231 2013 early 2014 will be digged out and analyzed proper archaeology all the 00:00:35.231 --> 00:00:43.165 digging... digging and analysis is done by argp here to my left on the stage and give 00:00:43.165 --> 00:00:46.586 him a big round of applause. And the stage is yours, thanks. 00:00:46.586 --> 00:00:47.882 Applause 00:00:47.882 --> 00:00:58.883 argp: Thanks for the introduction. First of all, thank you all for being here. As 00:00:58.883 --> 00:01:03.899 the person that did the introduction told you this is going to be an archeology talk 00:01:03.899 --> 00:01:09.939 so I apologize in advance if it's not that interesting for you. So we'll talk about a 00:01:09.939 --> 00:01:16.310 bit older stuff rather than new things. Okay so a bit a few things about myself. 00:01:16.851 --> 00:01:20.923 Actually, I think from all these things, the most important are the the Phrack 00:01:20.923 --> 00:01:26.830 papers, right? So, yeah. Let's ignore all the other stuff okay? So, what I'm going 00:01:26.830 --> 00:01:35.059 to talk about. I'm going to talk about the evasi0n7 kernel exploit. Now evasi0n7 was 00:01:35.059 --> 00:01:42.060 a jailbreak it was released by the evad3rs on the 22nd of December 2013. It supported 00:01:42.060 --> 00:01:50.210 iOS7 to iOS7.1 beta 3. That's not the 7.1 stable release, right? So that's a 00:01:50.210 --> 00:01:55.759 beta. And this supported all devices at that time including the iPhone 5s which 00:01:55.759 --> 00:02:03.999 was the first 64-bit device except the Apple TV. So, I decided to reverse 00:02:03.999 --> 00:02:08.900 engineer the kernel exploit of the jailbreak focused just on that. Because I 00:02:08.900 --> 00:02:14.170 was really interested, not so much in the bug itself, which was as we will see not 00:02:14.170 --> 00:02:18.805 very complicated. But I was really interested to understand the exploitation 00:02:18.805 --> 00:02:25.970 techniques that the evad3rs used. So, I started reversing it, and I understanding 00:02:25.970 --> 00:02:32.329 it, and at some point I just said I'm just gonna do a reimplementation of the kernel 00:02:32.329 --> 00:02:37.030 exploit. So, this talk is basically my notes on this whole process. And, of 00:02:37.030 --> 00:02:42.390 course, it's not a jailbreak walkthrough, right? And I'm going to specifically focus 00:02:42.390 --> 00:02:50.042 on the various problems I encountered during this task and how I overcame them. 00:02:50.042 --> 00:02:58.250 And hopefully it's going to give you some helpful takeways for if you do iOS kernel 00:02:58.250 --> 00:03:05.459 research nowadays. Okay, so, the general outline is I'm going to say a few things 00:03:05.459 --> 00:03:11.730 about the version 7 to setup the stage. And then I'm going to explain the kernel 00:03:11.730 --> 00:03:18.971 bug itself. And, then I'm going to talk in length about my debugging setup. And, I 00:03:18.971 --> 00:03:26.136 think that's a very important step that usually phone or embedded talks 00:03:26.136 --> 00:03:29.860 exploitation talks don't analyze that much, and I think it's a really important 00:03:29.860 --> 00:03:36.220 part. Because usually having a working the debugging set up is, basically, maybe half 00:03:36.220 --> 00:03:41.080 the job of doing a reliable exploit. Then I'm going to do to talk about my 00:03:41.080 --> 00:03:46.520 reimplementation of the exploit, and hopefully, at the end, we're gonna have 00:03:46.520 --> 00:03:53.870 some things to take away or maybe not. We will see. Okay so it was the evasi0n7 00:03:53.870 --> 00:03:59.300 jailbreak was released about 4 years ago. And that's the archaeology in the title. 00:03:59.300 --> 00:04:04.830 That's ancient history right? And if you were following the jailbreak community, 00:04:04.830 --> 00:04:12.120 you might remember this huge drama around this jailbreak, initially, with geohot and 00:04:12.120 --> 00:04:17.160 if he was planning or not to release it before the evad3rs. And who he was 00:04:17.160 --> 00:04:22.860 planning to sell it to, and some leaked discussion that he had with some of that 00:04:22.860 --> 00:04:31.070 he was offering money to buy. And geohot, his jailbreak supposedly using 00:04:31.070 --> 00:04:37.773 some of the bugs the evad3rs were using so this is a huge drama. And then after the 00:04:37.773 --> 00:04:43.320 evasi0n7 jailbreak released, like maybe a few hours ago, people realize that if your 00:04:43.320 --> 00:04:54.220 phone had a Chinese locale then the jailbreak was installing a piracy app. So, 00:04:54.220 --> 00:04:57.440 that was basically a third-party app that 00:04:57.440 --> 00:05:00.660 was taking you to an app store not operated 00:05:00.660 --> 00:05:05.210 by Apple but by TaiG that had some pirated versions of the real applications on the 00:05:05.210 --> 00:05:12.700 App Store. And, of course, that also create like a huge drama, this practice. 00:05:13.695 --> 00:05:17.660 Okay, so a lot of things were said about the jailbreak at that time and about the 00:05:17.660 --> 00:05:23.820 TaiG pirate App Store. But what I really set apart was this tweet. And the really 00:05:23.820 --> 00:05:28.030 important thing that I like about this tweet is, that it doesn't really make 00:05:28.030 --> 00:05:31.430 sense. So he says that we have to decide to remotely disable the default 00:05:31.430 --> 00:05:35.285 installation of TaiG in China for further investigations of the piracy. So that 00:05:35.285 --> 00:05:40.740 whole thing doesn't make sense. So you mean, you didn't know what was happening? 00:05:40.740 --> 00:05:45.490 You didn't bundle it with a jailbreak? Are you going to disable it for new 00:05:45.490 --> 00:05:50.040 installations? And then, what does remotely then mean exactly? So what about 00:05:50.040 --> 00:05:56.290 the people that already had the apps, the piracy app. How are you going to disable 00:05:56.290 --> 00:06:04.520 that? Is that what remotely refers to? So that's an excellent tweet I think. Okay, 00:06:04.520 --> 00:06:11.370 so some point after the evasi0n7 jailbreak was released geohot did a writeup on the 00:06:11.370 --> 00:06:19.151 userland part of it. So, he analyzed how the userland part worked and he stopped at 00:06:19.151 --> 00:06:27.690 the point of gaining root and basically, he mentioned in his writeup that the 00:06:27.690 --> 00:06:33.185 evasi0n7 untethered binary, which basically what was good doing the kernel 00:06:33.185 --> 00:06:40.260 exploit, was obfuscated. And as we will see this was indeed the case and as far as 00:06:40.260 --> 00:06:46.038 I know that's the first jailbreak that used the deliberate obfuscation. I don't 00:06:46.038 --> 00:06:51.330 know the reason, I assume it's partly to hide the the piracy 00:06:51.330 --> 00:06:57.243 app store that was bundled with it and maybe partly to hide the bug, the kernel 00:06:57.243 --> 00:07:07.370 bug, but I'm not sure about the reason. Now p0sixninja who found as far as I know 00:07:07.370 --> 00:07:12.120 the bug, the kernel bug did a writeup on the kernel bug, it's on the iPhone wiki, 00:07:12.120 --> 00:07:17.630 and he basically describes the bug and he stops at the point where he gets a crash 00:07:17.630 --> 00:07:25.530 log from gdb. So he doesn't say anything about how to exploit it. Okay, so after 00:07:25.530 --> 00:07:31.250 all these things happened then I decided to reverse engineer the untethered binary 00:07:31.250 --> 00:07:37.180 and understand the exploitation techniques and I was really interested to reverse 00:07:37.180 --> 00:07:41.289 engineer the obfuscation that the evad3rs were using, it seemed like an interesting 00:07:41.289 --> 00:07:46.250 challenge, and... but as I also mentioned earlier I was really interested to 00:07:46.250 --> 00:07:49.795 understand the exploitation techniques that they were using that was more 00:07:49.795 --> 00:07:58.510 important for me at that time. And, okay, so the jailbreak was released 00:07:58.510 --> 00:08:06.337 December 2013 and I started doing that around February 2014, and I did that while 00:08:06.337 --> 00:08:10.310 having an actual day job, right, so I was spending at most two days per week on 00:08:10.310 --> 00:08:20.360 that. So what was my setup? I had an iPhone 4, and if you know about iPhone 4s 00:08:20.360 --> 00:08:25.570 they have a boot ROM bug called limera1n which basically allows you to load 00:08:25.570 --> 00:08:31.520 arbitrary kernels, unsigned kernels, on the device and run them and that basically 00:08:31.520 --> 00:08:38.049 means that you can very easily set up kernel debugging. So initially I 00:08:38.049 --> 00:08:46.026 had an iPhone 4 device with iOS 7.0.6. I want to remind you that iPhone 4 is ARM32, 00:08:46.026 --> 00:08:52.990 right. I also had an iPhone 5s with the same version of iOS and I had that in 00:08:52.990 --> 00:09:00.269 order to verify all my findings and all my tests on - to redo my tests on an ARM64 00:09:00.269 --> 00:09:06.279 device and as I told you - the iPhone 5s at that time was the only ARM64 device. 00:09:06.279 --> 00:09:10.480 Actually, I think on the market, I don't think there was another consumer device 00:09:10.480 --> 00:09:19.240 with ARM64 at that time. So that's the exact version of version 7 I was analyzing 00:09:19.240 --> 00:09:26.269 and of course IDA, gdb, lldb. Now the lols in this slide they don't actually refer to 00:09:26.269 --> 00:09:30.639 something funny they actually mean something very painful and that caused a 00:09:30.639 --> 00:09:37.090 lot of like sleepless nights, but I'll get onto that. Okay, a few things about the 00:09:37.090 --> 00:09:44.310 obfuscation. So, not all the functions of the entire binary were obfuscated, but 00:09:44.310 --> 00:09:51.980 some of the important ones were, and those were the ones that were triggering the bug 00:09:51.980 --> 00:09:56.930 and they were actually doing heap manipulation and all the other important 00:09:56.930 --> 00:10:01.180 things. Now I have been told, I haven't checked that, but I have been told that 00:10:01.180 --> 00:10:05.256 later versions remove the obfuscation but I'm not sure about that, I haven't 00:10:05.256 --> 00:10:09.769 verified it and I already had my implementation done at that point so I 00:10:09.769 --> 00:10:20.170 wasn't that interested to look at that. So as I mentioned the kernel bug that the 00:10:20.170 --> 00:10:26.733 evasi0n7 untethered binary was based on was found by p0sixninja, and basically as 00:10:26.733 --> 00:10:34.040 far as he says on that iPhone wiki page he used that six line bash script fuzzer to 00:10:34.040 --> 00:10:41.840 find it. So as you can see he basically creates device nodes and, with 00:10:41.840 --> 00:10:50.439 controlled arguments here like minor and major numbers. Now in order to get to the 00:10:50.439 --> 00:10:57.100 point to create device nodes you basically need to be outside of the application 00:10:57.100 --> 00:11:04.329 sandbox that exists on iOS and you also need root privileges and that's what I 00:11:04.329 --> 00:11:08.224 refer to as the userland part of the evasi0n7 binary and I'm not going to cover 00:11:08.224 --> 00:11:14.810 that at all. So I'm gonna start my analysis from the point on that we have 00:11:14.810 --> 00:11:19.321 escaped the sandbox, we have obtained root and now we go to exploit the kernel 00:11:19.321 --> 00:11:29.268 bug. Now that's code from that version of the XNU kernel that had the bug. Now this 00:11:29.268 --> 00:11:39.533 ptsd_open function is called everytime userland code opens a /dev/ptmx device and 00:11:39.533 --> 00:11:43.936 then this ptmx_get_ioctl function is called. Now the important thing here 00:11:43.936 --> 00:11:46.779 is that dev here is completely user controlled and then 00:11:46.779 --> 00:11:49.023 it's passed to this ptmx_get_ioctl 00:11:49.023 --> 00:11:54.759 function with no checks at all, right, and then this ptmx_get_ioctl function uses 00:11:54.759 --> 00:11:59.949 this to index an array without any checks. So basically the bug's an invalid indexing 00:11:59.949 --> 00:12:05.618 bug, right, so since we can control that you can put here whatever. I have here the 00:12:05.618 --> 00:12:14.365 ptmx_ioctl struct that, okay, this array here is, so this state struct here is 00:12:14.365 --> 00:12:21.790 global to the kernel and this pis_ioctl_list array here is on the kernel 00:12:21.790 --> 00:12:30.418 heap and it is an array of ptmx_ioctl structs and that's the PTMX ioctl struct 00:12:30.418 --> 00:12:35.610 and the important thing here is, that I'm going to refer to again and again 00:12:35.610 --> 00:12:41.289 during the talk, is that it has a pointer to a tty struct as the first element of 00:12:41.289 --> 00:12:50.680 the structure. Okay, so we control the index to the array, so what can we do with 00:12:50.680 --> 00:12:57.349 that? So here as you can see it return the ptmx_get_ioctl function returns 00:12:57.349 --> 00:13:04.961 whatever it indexes, right. So, as you can see here is it assigns this pti variable 00:13:04.961 --> 00:13:10.682 and then does all kinds of interesting things, so pti is controllable, tp is 00:13:10.682 --> 00:13:14.163 controllable here as well after this dereference here to some controllable 00:13:14.163 --> 00:13:21.449 value and, I mean in other code parts of the kernel this is called again and so 00:13:21.449 --> 00:13:26.980 there are there are a lot of things to consider when you know the bug and 00:13:26.980 --> 00:13:33.788 then you try to think how to exploit it. Okay, one important thing here that I 00:13:33.788 --> 00:13:44.380 wanted to mention is that this ptmx, this function here ptmx_get_ioctl also 00:13:44.380 --> 00:13:51.850 does the allocation of this struct here, of this tty struct here and that's 00:13:51.850 --> 00:14:00.282 important because I'm going to use further on. Okay, another important thing is that 00:14:00.282 --> 00:14:05.934 you basically, this bug what allows you to do is you can control the size of this 00:14:05.934 --> 00:14:14.602 array here, so by, can you see that? Okay, so by repeatedly open the ptmx 00:14:14.602 --> 00:14:21.824 device you can grow this array and you can grow it as you see here by this grow 00:14:21.824 --> 00:14:29.830 vector that's 16, but it doesn't matter. What matters is that the size of this 00:14:29.830 --> 00:14:38.299 array in bytes is controllable by you, the person who are trying to exploit this bug. 00:14:38.299 --> 00:14:44.679 Now, for example these are notes from my exploit so if I did one allocation, if I 00:14:44.679 --> 00:14:51.239 did one open of this ptmx device then this array was going into kalloc_64. If I was 00:14:51.239 --> 00:14:59.089 doing 17 it was going to kalloc_128, if I was doing 33 opens here it was going to 00:14:59.089 --> 00:15:06.709 kalloc_192 and so on and so forth. So I could decide in which kalloc zone I could 00:15:06.709 --> 00:15:14.009 place the array. If you don't know kalloc zones, they are basically, you can think 00:15:14.009 --> 00:15:20.829 them as container, you can think kalloc zones as containers for heap objects on 00:15:20.829 --> 00:15:26.579 the kernel heap. All of them can be of different type but they're, all of them 00:15:26.579 --> 00:15:33.265 are of the same size, right, so kalloc_64 can have different structures of size 64 00:15:33.265 --> 00:15:43.258 bytes, but all of them are our size 64 bytes. Okay so I started debugging the 00:15:43.260 --> 00:15:49.936 untethered binary in userland, that's how I started. So initially I was using gdb 00:15:49.936 --> 00:15:57.889 and I found out that nothing worked with gdb. It was at that point Apple was 00:15:57.889 --> 00:16:01.641 starting to move from gdb to lldb, so I don't, maybe that was the reason gdb 00:16:01.641 --> 00:16:05.960 wasn't tested at all. So when I say nothing worked I mean that I was 00:16:05.960 --> 00:16:11.799 placing break points and they weren't hitting and I was trying like stepping and 00:16:11.799 --> 00:16:16.269 it was continuing execution and stuff like that. Sometimes I couldn't even attach the 00:16:16.269 --> 00:16:23.534 binary. So then I moved to lldb, on lldb set up with debugserver and things were 00:16:23.534 --> 00:16:29.489 much better. Now, while I was experimenting stealing from, just with 00:16:29.489 --> 00:16:35.436 userland debugging my iPhone 4 device went to into a recovery loop and I wasn't able 00:16:35.436 --> 00:16:46.339 to get out of it, so I was forced to do a clean restore of the device. The problem 00:16:46.339 --> 00:16:51.749 was that at that time only iOS 7.1 was signed by Apple, so I couldn't install a 00:16:51.749 --> 00:16:55.889 version of files that hit the kernel that hit the bug that I was interested to look 00:16:55.889 --> 00:16:59.610 at, but on the other hand I couldn't not restore my device because that was the 00:16:59.610 --> 00:17:05.240 only device I had at the point I could do kernel debugging with. So I updated my 00:17:05.240 --> 00:17:11.805 device to 7.1. As I said just told you 7.1 didn't have a vulnerable kernel 00:17:11.805 --> 00:17:22.208 to this bug, so what I wanted to do was basically to boot an iOS 7.1 device with a 00:17:22.208 --> 00:17:27.990 7.0.6 kernel, and in order to do that I could use the limera1n bug that allowed me 00:17:27.990 --> 00:17:32.854 to boot arbitrary kernels and the utility to do that was redsn0w, right. The problem 00:17:32.854 --> 00:17:40.400 was that redsn0w only supported up to iOS 6 and it wasn't, it didn't have support 00:17:40.400 --> 00:17:46.100 for iOS 7 so I left all the other things I was doing and I started reversing redsn0w 00:17:46.100 --> 00:17:51.530 to understand how it worked. Redsn0w, if you don't know it's, it was back then 00:17:51.530 --> 00:17:55.740 and still is closed source, right, so I started reversing that to understand how 00:17:55.740 --> 00:18:00.875 it worked in order to support, for me to hot patch it, to binary 00:18:00.875 --> 00:18:06.646 patch it to add support for iOS 7 and I spent like I don't know maybe a month on 00:18:06.646 --> 00:18:11.699 that and then I realized that it was, it wasn't leading me anywhere, I couldn't 00:18:11.699 --> 00:18:17.029 understand a lot of things about how redsn0w was implemented, so I I stopped 00:18:17.029 --> 00:18:25.700 doing that, and at that point I found opensn0w which was an effort by winocm to 00:18:25.700 --> 00:18:32.160 implement redsn0w as open source. So, it seemed to have support for iOS 7 and that 00:18:32.160 --> 00:18:40.120 was good, I tested that and it was working. Now my problem was that I 00:18:40.120 --> 00:18:44.460 couldn't have an arbitrary length of boot-args. Boot-args are the 00:18:44.460 --> 00:18:48.590 arguments that you pass to the kernel when it boots and they are really important in 00:18:48.590 --> 00:18:57.630 iOS because by passing certain boot-args to the kernel you can disable sign checks, 00:18:57.630 --> 00:19:02.320 you can enable kernel debugging, so it's really important to be able to pass 00:19:02.320 --> 00:19:09.470 arbitrary length boot-args. And iOS 7.1 was using absurd 9 character so that was 00:19:09.470 --> 00:19:15.726 the reason opensn0w couldn't support more So what I ended up doing was I patched 00:19:15.726 --> 00:19:22.556 iBEC, which is basically the loader of the kernel, right, that passes boot- 00:19:22.556 --> 00:19:29.935 args to the kernel when it boots and, basically I changed the pointer to the 00:19:29.935 --> 00:19:35.571 boot-args to some other place that had much more space. So at that point I was 00:19:35.571 --> 00:19:41.619 able to pass arbitrary-length boot-args to my kernel. So where we are at last? So I 00:19:41.619 --> 00:19:50.358 had an iPhone 4 device with iOS 7.1 and I was using opensn0w to boot the 7.0.6 00:19:50.358 --> 00:19:56.795 kernel that had the bug that I was interested to exploit. Now, one side note 00:19:56.795 --> 00:20:04.161 here is that as I was doing that and I was trying to add to open snow all the patches 00:20:04.161 --> 00:20:09.762 to the kernel to enable kernel debugging, I was reversing the evasi0n7 binary as 00:20:09.762 --> 00:20:15.217 well. Now, the evasi0n7 binary was trying also to, after it exploited the kernel 00:20:15.217 --> 00:20:19.799 it was patching it to enable kernel debugging, but, so I was just copying 00:20:19.799 --> 00:20:23.740 their patches, right, and adding them to opensn0w, but I realized at some point 00:20:23.740 --> 00:20:29.919 that they missed some check for the debug- enabled variable and KDP wasn't really 00:20:29.919 --> 00:20:35.919 working, so the session was established and it seemed like it was working, but if 00:20:35.919 --> 00:20:40.934 you tried to actually use the kernel, the KDP, the kernel debugging setup for 00:20:40.934 --> 00:20:45.470 to do actual, like to attach debugger to the kernel and do whatever, like place a 00:20:45.470 --> 00:20:54.241 breakpoint or step then KDP just froze. So I added another part that was required on 00:20:54.241 --> 00:21:02.730 that. Ok, so kernel debugging at last, but that's not really what happened, because 00:21:02.730 --> 00:21:07.981 you know breakpoints didn't always work so you were placing a breakpoint and it 00:21:07.981 --> 00:21:12.708 wasn't hitting when execution was reaching there and you were trying to step 00:21:12.708 --> 00:21:17.340 instructions and the execution just continues, so you were stepping one 00:21:17.340 --> 00:21:21.210 instruction it was just like you would type in continue and if you were taking 00:21:21.210 --> 00:21:26.755 too long to type an lldb command then KDP froze and then you had to restart your 00:21:26.755 --> 00:21:33.261 device, re-establish the kernel debugging session and start from zero. And if you 00:21:33.261 --> 00:21:37.951 issue commands too fast then KDB froze again, so you have to reboot again. It was 00:21:37.951 --> 00:21:47.320 amazing, it was great time. And now I did similar stuff with iOS 6 and I distinctly 00:21:47.320 --> 00:21:53.110 remember that was much easier and kernel debugging worked much better. And... I 00:21:53.110 --> 00:21:58.669 mean the issue that comes to everyone's mind that does that is: do Apple engineers 00:21:58.669 --> 00:22:05.580 really use KDP for debugging the iOS kernel or do they use something else? 00:22:06.240 --> 00:22:15.330 Okay, so now I could debug the evasi0n7 untethered binary both from the userland 00:22:15.330 --> 00:22:23.130 side and from the kernel side, and that was good because I was analyzing at run 00:22:23.130 --> 00:22:31.730 time and at the same time I was reversing it in IDA, so the obfuscation who... I 00:22:31.730 --> 00:22:38.480 could do it much faster since I was taking hints from runtime. So I... at that point 00:22:38.480 --> 00:22:42.860 things started moving fast and I quickly found that it was abusing the data by 00:22:42.860 --> 00:22:49.179 structure to obtain read/write access to physical memory. I mean that was 00:22:49.179 --> 00:22:52.940 interesting to me, but I was expecting something else. I was expecting something 00:22:52.940 --> 00:22:58.389 like what they did in iOS in the evasi0n6 jailbreak, that they did like a lot of 00:22:58.389 --> 00:23:04.387 heap manipulation and that's my interest actually, heap exploitation. So at that 00:23:04.387 --> 00:23:10.370 point I decided to stop reversing it and reimplement the exploit the way that I 00:23:10.370 --> 00:23:16.190 wanted to do it. So obviously that wasn't work from scratch, it was from everything 00:23:16.190 --> 00:23:20.330 that I understood up to that point, and what I really wanted to use was the 00:23:20.330 --> 00:23:25.410 vm_map_copy structures technique by Dowd and Mandt and I'm going to explain that in 00:23:25.410 --> 00:23:31.669 the following slides, how it works. Okay, so at that point I had the clear 00:23:31.669 --> 00:23:37.090 understanding of the bug, what it was and I had the general idea like about how to 00:23:37.090 --> 00:23:41.779 exploit it and I mean if you've done that you know then it takes a lot of pen 00:23:41.779 --> 00:23:47.980 and paper like ideas you develop on paper, then you go test them and they don't work 00:23:47.980 --> 00:23:53.409 and then you design them again and then again and you fail and you despair and 00:23:53.409 --> 00:23:58.289 then you suddenly have an idea and you spend like I don't know like two nights 00:23:58.289 --> 00:24:04.029 stay up until 5:00 in the morning testing things and they don't work and then you 00:24:04.029 --> 00:24:10.700 despair again and ad nauseam. But eventually you get somewhere so let's talk 00:24:10.700 --> 00:24:18.630 about exploitation now. Now, a few things to refresh your memory about the bug. So 00:24:18.630 --> 00:24:26.200 as I said it was an invalid indexing bug. This pis_ioctl_list array was on the heap 00:24:26.200 --> 00:24:32.760 and I could control in which kalloc zone it can go. I can grow it, but once I grow 00:24:32.760 --> 00:24:42.700 it I cannot shrink it back. Now, that's code from that ptmx_get_ioctl function, so 00:24:42.700 --> 00:24:46.760 what... basically what it does it allocates a new ptmx_ioctl structure and 00:24:46.760 --> 00:24:53.294 then it uses the index that you provide... that you control to store the address on 00:24:53.294 --> 00:25:01.090 the array. Now, this allocation here... this struct here goes into kalloc.88 and 00:25:01.090 --> 00:25:07.895 that's useful for the next parts. Okay, a few things about the technique I wanted to 00:25:07.895 --> 00:25:13.000 use... about the exploitation technique I wanted to use. So it's the vm_map_copy 00:25:13.000 --> 00:25:19.160 technique, it was proposed by Dowd and Mandt and basically they were spraying the 00:25:19.160 --> 00:25:24.779 heap with these structs here, the vm_map_copy structs, and assuming you have 00:25:24.779 --> 00:25:31.250 like some way to corrupt this struct that you've sprayed on the heap if you can 00:25:31.250 --> 00:25:39.299 overwrite this kdata element here, then basically what you have is a leak of 00:25:39.299 --> 00:25:44.669 kernel memory other adjacent like next to the kdata, whatever is below or above the 00:25:44.669 --> 00:25:49.941 kdata pointer or arbitrary if you put whatever address you want in there. By 00:25:49.941 --> 00:25:58.019 overwriting the kalloc_size element here and then freeing the struct on the heap, 00:25:58.019 --> 00:26:03.909 you put it on a wrong zone and basically when you allocate it back, since you put 00:26:03.909 --> 00:26:10.157 it on on a different size zone, you can have a heap overflow. So that's a general 00:26:10.157 --> 00:26:14.021 overview of this technique. So but you corrupt this struct and you get primitive 00:26:14.021 --> 00:26:21.840 exploitation primitives. Okay, so what was the idea I had at that point? The idea 00:26:21.840 --> 00:26:28.659 was to use the... this pis_ioctl_list index bug to corrupt this kdata pointer 00:26:28.659 --> 00:26:38.370 here and to have arbitrarily... Sorry, we have a relative leak of kernel heap 00:26:38.370 --> 00:26:44.760 memory, and that would be my first step towards exploiting the bug. Of course the 00:26:44.760 --> 00:26:52.480 end goal is to have arbitrary read/write, right, and of course it was just a fuzzy 00:26:52.480 --> 00:26:56.269 idea at that point and you know that's always the goal, but when you study the 00:26:56.269 --> 00:27:03.620 bug and you see the different code paths and how the things you affect are used, 00:27:03.620 --> 00:27:08.330 then you have some maybe not completely concrete things in your mind, but you know 00:27:08.330 --> 00:27:14.234 that interesting things can happen, so that's what I had at that point. 00:27:14.234 --> 00:27:23.871 Okay, so let's talk about the exploitation strategies now. So at stage one I sprayed 00:27:23.871 --> 00:27:31.399 the kernel heap with vm_map_copy structs and I decided to work on the kalloc.256 00:27:31.399 --> 00:27:36.279 zone, and the reason for that was completely arbitrary... was because of all 00:27:36.279 --> 00:27:40.590 the kernel debugging I have done up to this point of this entire binary I saw 00:27:40.590 --> 00:27:45.860 that this kalloc zone was not really used that much, either by the kernel or by 00:27:45.860 --> 00:27:51.970 whatever the exploit was doing. So... that's good because it means that you 00:27:51.970 --> 00:27:55.950 can... you as an exploiter can have much better control over the kernel heap if 00:27:55.950 --> 00:28:04.701 there aren't other things placing allocations on the zone you work. So I 00:28:04.701 --> 00:28:12.610 decided to use the kalloc.256 zone and I avoided of course kalloc.384 because the 00:28:12.610 --> 00:28:20.559 tty structs were going there and that would really mess up my heap arrangements. 00:28:20.559 --> 00:28:30.286 So the first... let me actually... ok. So what I wanted to do was to do this. 00:28:30.286 --> 00:28:37.249 So initially you spray the heap with vm_map_copy structs and you control both 00:28:37.249 --> 00:28:41.820 their size and their contents, the content don't matter at this point. So it... just 00:28:41.820 --> 00:28:48.419 the size matters. So I spray with 256 bytes vm_map_copy structs and then I free 00:28:48.419 --> 00:28:53.131 every other second one and I create this kind of pattern like a vm_map_copy and a 00:28:53.131 --> 00:28:59.210 free slot and a vm_map_copy and a free slot and then I grow the pis_ioctl_list 00:28:59.210 --> 00:29:08.620 array to 256 bytes and then it goes into one of these free slots here. Now, the 00:29:08.620 --> 00:29:14.990 code for doing that looks something like that, so what this basically does it 00:29:14.990 --> 00:29:24.509 sends... it creates this... so if you see here the out of line mach messages as 00:29:24.509 --> 00:29:31.570 basically these vm_map_copy structs and... Their size is 256, their buffer doesn't 00:29:31.570 --> 00:29:37.950 matter at this point and you just send them like machs and methods. And then 00:29:37.950 --> 00:29:42.990 after you've sprayed with them then you free every second one here... with this 00:29:42.990 --> 00:29:51.779 loop here. So in order to make this free slot you just receive this mach out of 00:29:51.779 --> 00:29:58.027 line messages that correspond to the vm_map_copy structs. And after you've 00:29:58.027 --> 00:30:04.519 created the holes you basically grow the array to 256 bytes. How do you do that? As 00:30:04.519 --> 00:30:12.010 I mentioned earlier you open the dev ptmx device a number of times. How many times 00:30:12.010 --> 00:30:18.429 doesn't matter, like a specific number of times that I mentioned earlier, that I 00:30:18.429 --> 00:30:26.370 have noticed grows it 256 bytes. So that's the arrangement you have at that first 00:30:26.370 --> 00:30:35.520 stage. Okay, so the second stage is done on the kalloc.88 zone. So I spray again 00:30:35.520 --> 00:30:41.640 with vm_map_copy structs and this time I make them 88 bytes to go to 00:30:41.640 --> 00:30:50.570 the kalloc.88 zone and then I create again holes. And then I trigger the bug with an 00:30:50.570 --> 00:30:56.250 invalid index value and remember that when you trigger the bug a ptmx_ioctl struct is 00:30:56.250 --> 00:31:01.610 allocated and this goes to kalloc.88. But because on kalloc.88 I have created this 00:31:01.610 --> 00:31:06.840 pattern of used free used free it goes into one of the free slots. So now I have 00:31:06.840 --> 00:31:13.620 a ptmx_ioctl struct in one of my free slots. I don't know where that is but I 00:31:13.620 --> 00:31:23.089 know that it falls into the pattern, right, so I trigger the bug and remember 00:31:23.089 --> 00:31:29.200 that basically you control this index, right, so since I control the index I 00:31:29.200 --> 00:31:35.270 point it to the vm_map... to the kdata element of the vm_map_copy struct that I 00:31:35.270 --> 00:31:39.809 know is below the free slot that the array went into. I don't know the address, 00:31:39.809 --> 00:31:46.950 right, I can't put like an address there, but I can... I know the relatives... the 00:31:46.950 --> 00:31:52.330 relative distance in bytes because I created the pattern... the heap pattern. 00:31:52.330 --> 00:31:58.289 So let's go to... okay. So it looks like that. So that's my first stage, right, 00:31:58.289 --> 00:32:02.594 free, vm_map_copy, ... and this is the same pattern on the kalloc.88 zone. 00:32:02.594 --> 00:32:08.000 When you trigger the bug, this ptmx_ioctl structure is allocated. It goes into one 00:32:08.000 --> 00:32:16.590 of the free slots, right, and then the bug itself, which is what we see here is... 00:32:16.590 --> 00:32:21.340 remember you control the index, so this is the new allocation that went here, and 00:32:21.340 --> 00:32:27.210 then it goes and stores the address where the index tells it to store it. But 00:32:27.210 --> 00:32:31.499 remember that this is controlled, we control that, so what I do I point this 00:32:31.499 --> 00:32:36.809 here relatively to the neighboring vm_map_copy struct at the kdata field, 00:32:36.809 --> 00:32:42.465 right. So in this kdata field here of the vm_map_copy struct I have now this 00:32:42.465 --> 00:32:52.740 address, right. So that's how the heap looks like. I have here the code, it's 00:32:52.740 --> 00:33:00.660 very similar to the first stage that you spray with vm_map_copy structs of size 88, 00:33:00.660 --> 00:33:05.919 machs and methods, right, and then you receive every second one, you create the 00:33:05.919 --> 00:33:15.909 holes on the 88 zone and then you trigger the bug here, right. This invalid pis 00:33:15.909 --> 00:33:29.610 index number here is basically what points relatively here, right. So I have now the 00:33:29.610 --> 00:33:37.179 address of this ptmx_ioctl struct which is an address on the kalloc.88 zone. I have 00:33:37.179 --> 00:33:42.669 it on the kdata field of this vm_map_copy struct here. So what I do... I can simply 00:33:42.669 --> 00:33:51.350 receive these methods and in its content I can see the address of that slot on the 00:33:51.350 --> 00:34:00.539 kalloc.88 zone. So that's the code to do that, I simply receive all the messages 00:34:00.539 --> 00:34:12.080 and that's my address. Okay, so at this point I only... what I only have is this 00:34:12.080 --> 00:34:21.500 address here, right? I have the address of this heap slot. So, at that point I 00:34:21.500 --> 00:34:28.699 started looking at other code paths that this invalid index... what other 00:34:28.699 --> 00:34:34.595 variables this invalid index was influencing and I found the code path that 00:34:34.595 --> 00:34:40.270 was actually giving... was giving me a write and... But in order to reach that I 00:34:40.270 --> 00:34:45.570 needed to survive several dereferences, and what I only knew was just the 00:34:45.570 --> 00:34:50.790 kalloc.88 address, right? Nothing else. So I will now walk you through everything 00:34:50.790 --> 00:35:00.710 that gave me this write. So I clean up the kalloc.256 zone and I spray it again with 00:35:00.710 --> 00:35:06.384 vm_map_copy structs and create holes exactly like the previous step... 00:35:06.384 --> 00:35:15.073 the first stage. Again, next to the pis_ioctl_list array I have a vm_map_copy 00:35:15.073 --> 00:35:23.110 struct, but at this time I... in all the the vm_map_copy structs I put a payload of 00:35:23.110 --> 00:35:29.890 the... of this fake ptmx_ioctl address I have. And remember that the first element 00:35:29.890 --> 00:35:40.250 of the ptmx_ioctl struct is a pointer to tty struct and I can use the leaked 00:35:40.250 --> 00:35:44.860 address I have for this pointer that I don't know... I didn't know where to point 00:35:44.860 --> 00:35:52.880 it to. So, the next step was to clean up the kalloc.88 zone and spray it again, and 00:35:52.880 --> 00:35:58.650 again I sprayed with vm_map_copy structs, but at this time at their payload I can 00:35:58.650 --> 00:36:07.231 put now the fake tty struct that the ptmx_ioctl struct is pointing to. The 00:36:07.231 --> 00:36:15.780 problem at that point was that the tty struct with 256 bytes and kalloc.88 has... 00:36:15.780 --> 00:36:22.480 the slots are only 88 bytes, so I couldn't just with the elements of the... just with 00:36:22.480 --> 00:36:29.311 the first 88 byte elements, I couldn't get to the path that was giving the write, so 00:36:29.311 --> 00:36:44.730 I needed to find some other way to host my fake tty struct. So remember that I 00:36:44.730 --> 00:36:50.730 couldn't work on any other kalloc zone or anywhere else because what I only knew was 00:36:50.730 --> 00:36:59.207 the address of that kalloc.88 zone, I had nothing else to build on. So at that point 00:36:59.207 --> 00:37:07.070 I started doing a much more complicated heap arrangement. So instead of spraying 00:37:07.070 --> 00:37:15.830 just one thing I was spraying... I was trying to create a pattern of two 00:37:15.830 --> 00:37:20.480 controlled things. Now, I couldn't use vm_map_copy structs for both these slots 00:37:20.480 --> 00:37:24.930 because the vm_map_copy structs has a header, right? So it would mess up my 00:37:24.930 --> 00:37:34.390 fake tty struct. So by reading i0n1c's kernel heap exploitation slides, I 00:37:34.390 --> 00:37:40.828 realized that I could spray the heap with XML properties of length 88 from that 00:37:40.828 --> 00:37:48.411 AppleJPEGDriver and I could place as a second controlled object after the 00:37:48.411 --> 00:37:53.130 vm_map_copy struct these XML properties which are completely controlled in 00:37:53.130 --> 00:37:58.190 content, and I could host the second part of the tty struct there. I mean, it's 00:37:58.190 --> 00:38:06.190 still not 256 bytes, but what it gives me is the ability to survive all dereferences 00:38:06.190 --> 00:38:14.430 to reach the write that I was interested in. Okay. So, a few things about the 00:38:14.430 --> 00:38:20.080 tty struct. So that's what I got... I wanted to create on the kalloc.88 zone, 00:38:20.080 --> 00:38:28.051 right, so that's the tty struct that the ptmx_ioctl struct is pointing to. Now, 00:38:28.051 --> 00:38:38.230 what basically I wanted to do here is I wanted to point... the final thing was 00:38:38.230 --> 00:38:45.610 to use this clist struct to control this element here, c_cs, as a start of the ring 00:38:45.610 --> 00:38:50.609 buffer for the tty, to give me an arbitrary write... Sorry, to give me a 00:38:50.609 --> 00:38:56.500 controlled write. I started playing a bit with to use it to do arbitrary write, but 00:38:56.500 --> 00:39:04.340 I found that I wasn't able to do it because at later stage some other parts of 00:39:04.340 --> 00:39:09.957 the tty struct were needed that I wasn't able to control, so I only had two 00:39:09.957 --> 00:39:17.500 88-slots to host my fake tty struct. So that wasn't stable. So I was only 00:39:17.500 --> 00:39:25.660 using that to do a relative write. So we'll see the code later on, let's go to 00:39:25.660 --> 00:39:32.430 the heap layout. So that's the third stage. Again, remember I sprayed the 00:39:32.430 --> 00:39:38.940 kalloc.256 zone with vm_map_copy structs/ frees, just place my pis_ioctl_list array 00:39:38.940 --> 00:39:43.150 next to vm_map_copy struct. Remember that I control the contents of vm_map_copy, 00:39:43.150 --> 00:39:52.270 right, so I placed in the buffer of vm_map_copy this ptmx_ioctl address that I 00:39:52.270 --> 00:39:59.650 know and I point the invalid index that I control to this ptmx_ioctl... this address 00:39:59.650 --> 00:40:03.830 that I put here. And what is this address? It's that leaked address that I got in the 00:40:03.830 --> 00:40:11.550 previous stage which points to the kalloc.88 zone. And what's the arrangement 00:40:11.550 --> 00:40:16.780 of that kalloc.88 zone? It's as I told you a vm_map_copy followed by an XML properties. 00:40:16.780 --> 00:40:21.170 vm_map_copy, XML properties... And all this hosts this fake tty struct, right? 00:40:21.170 --> 00:40:28.160 All these are the same, I just explained here how it looks like. So this points to 00:40:28.160 --> 00:40:35.090 the kdata element here and the rest of it holds the rest of the... all this is 00:40:35.090 --> 00:40:39.660 basically the fake tty struct, like the buffer of the vm_map_copy and then 00:40:39.660 --> 00:40:47.370 following the XML contents of this heap allocation. And where do I... this c_cs 00:40:47.370 --> 00:40:53.045 pointer that I told you that I wanted to control, where do I point it? I point it 00:40:53.045 --> 00:40:56.572 relatively again, I don't know any addresses but I can put it relatively 00:40:56.572 --> 00:41:02.420 since I know the... since I created this heap arrangement, I can put it relatively 00:41:02.420 --> 00:41:07.380 to the size of the kalloc size of the neighboring vm_map_copy struct. And why do 00:41:07.380 --> 00:41:13.720 I need this? Because I want to use the vm_map_copy technique by Mandt and Dowd 00:41:13.720 --> 00:41:20.060 that I mentioned earlier, so that's the end goal. So what's the code looks like? 00:41:20.060 --> 00:41:25.910 Okay, that's the spray of 256, we've seen that a lot of times, then we have the 00:41:25.910 --> 00:41:34.004 freeze... wait, no, that's not the freeze. So that's the allocations of the 256... 00:41:34.004 --> 00:41:37.864 that's... yeah, I don't have the freeze here because they don't matter, because we 00:41:37.864 --> 00:41:42.880 have seen them before. So what I have here is the spray of the kalloc.88 zone and the 00:41:42.880 --> 00:41:46.720 important thing here is that... what I wanted to show you that is that at every 00:41:46.720 --> 00:41:53.510 step I took two allocations. One is the vm_map_copy struct here with the machs and 00:41:53.510 --> 00:42:00.840 methods, and the second part is the XML properties, which are sprayed on the heap 00:42:00.840 --> 00:42:09.920 when you open the device driver, the AppleJPEGDriver. And what are the contents 00:42:09.920 --> 00:42:15.590 of that XML properties? They're basically that fake... the second part of the fake 00:42:15.590 --> 00:42:20.282 tty struct that you have the controlled c_cs pointer that will give me the 00:42:20.282 --> 00:42:27.438 relative write. So if you see here, I have this function setup_fake_tty that 00:42:27.438 --> 00:42:33.230 basically creates the structs so I don't have to type all the time, and we are at 00:42:33.230 --> 00:42:37.740 second stage here, and basically what you can see here is the creation of the 00:42:37.740 --> 00:42:41.770 fake tty struct, right? So that's the different elements of the fake tty as we 00:42:41.770 --> 00:42:47.690 saw it from the code. And that's the write offset I wanted to... that I pointed to 00:42:47.690 --> 00:42:54.050 the kdata field of the neighboring vm_map_copy struct. So, again, that's how 00:42:54.050 --> 00:43:02.360 it looks like in the heap. Okay, so after that, after we have arranged the... we 00:43:02.360 --> 00:43:08.780 have arranged it this way, we trigger again the invalid index array bug, but at 00:43:08.780 --> 00:43:13.920 this time on the slave ptmx device. I was only doing that on a master ptmx device, 00:43:13.920 --> 00:43:18.070 but in order to reach that write code path that I mentioned, you need to get on a 00:43:18.070 --> 00:43:24.080 slave ptmx device. So that's what happens here. And then you simply write to the 00:43:24.080 --> 00:43:29.830 corresponding descriptor and it just dereferences this c_cs that you controlled 00:43:29.830 --> 00:43:33.860 and your end... and it writes with whatever you want to write. And what do I 00:43:33.860 --> 00:43:39.010 want to write? I want to write a new size for the vm_map_copy struct... for the 00:43:39.010 --> 00:43:42.841 kalloc size field of the vm... of the neighboring vm_map_copy struct, so I can 00:43:42.841 --> 00:43:52.730 use the Dowd and Mandt technique. So, putting everything together. So at that 00:43:52.730 --> 00:43:57.410 point I have a controlled corruption of a vm_map_copy struct and I can use the 00:43:57.410 --> 00:44:04.000 primitives to get arbitrary... an arbitrary leak, so I can leak for example 00:44:04.000 --> 00:44:10.230 the KSLR-slide and I can do a heap overflow. Again these are how you can use 00:44:10.230 --> 00:44:18.580 the primitives that Mandt and Dowd gave us. Now I also know my location on the 00:44:18.580 --> 00:44:24.610 kernel heap, and remember that... that's basically... we found that on the stage... 00:44:24.610 --> 00:44:29.380 on the first... on the first of stages and we only... we use only that, like where 00:44:29.380 --> 00:44:36.580 that ptmx_ioctl struct was stored on the kernel heap, that's the only thing we 00:44:36.580 --> 00:44:41.770 knew, that address, in order to successively build on it, in order to 00:44:41.770 --> 00:44:47.200 reach like a much more useful primitive. And the important... the interesting thing 00:44:47.200 --> 00:44:50.690 here is that everything up to this point is data only, right? So you haven't 00:44:50.690 --> 00:44:55.090 injected any code, you haven't done anything at all that you could be caught 00:44:55.090 --> 00:45:00.850 somehow by a kernel self-protection mechanism or these kind of things, 00:45:00.850 --> 00:45:10.310 everything's data only. So once you reach that point, how do you get PC control? So 00:45:10.310 --> 00:45:18.400 since you can use Dowd's and and Mandt's technique, you can basically do a heap 00:45:18.400 --> 00:45:23.480 overflow, so you can again do a heap arrangement, you can place IOKit objects 00:45:23.480 --> 00:45:31.000 next to vm_map_copy structs where you can overflow from, and you can corrupt IOKit 00:45:31.000 --> 00:45:36.840 objects and from there you can have... also you can do an arbitrary write... 00:45:36.840 --> 00:45:43.470 read/write, so you can... by the arbitrary read you can read the vtables of the IOKit 00:45:43.470 --> 00:45:48.650 objects so you know the KSLR-slide and you can corrupt it in order to get PC 00:45:48.650 --> 00:45:55.500 control. Of course getting to a whole jailbreak from that point is out of the 00:45:55.500 --> 00:46:01.030 scope of this talk, and... but is not that hard actually from that point on. And 00:46:01.030 --> 00:46:09.551 okay, so after doing all that how close was that exploit to the evasi0n... to the 00:46:09.551 --> 00:46:15.660 real evasi0n7 kernel exploiter? I'd say it was pretty far off, but I mean it wasn't 00:46:15.660 --> 00:46:22.040 my point to recreate it like completely, but it was my point to play with the heap 00:46:22.040 --> 00:46:29.260 and to try to do complex heap arrangements and to see how much I understand the iOS 00:46:29.260 --> 00:46:36.730 kernel heap, that was the point of this whole exercise for me. Okay, so some 00:46:36.730 --> 00:46:44.290 lessons learned. So the real surprising thing for me at that point was that I 00:46:44.290 --> 00:46:52.760 couldn't believe that Apple does kernel debugging by KDB. It was very flaky, it 00:46:52.760 --> 00:46:57.630 was very unstable as I told you. If you type commands too fast it froze, if you 00:46:57.630 --> 00:47:03.430 type commands very slowly it had like a go-stop timer and froze, I think. 00:47:03.430 --> 00:47:08.280 there was a claim of something like that and it's unbeliev... I couldn't believe 00:47:08.280 --> 00:47:14.670 that the Apple engineers were using this interface to do kernel debugging. So it 00:47:14.670 --> 00:47:23.730 was really hard to do anything on the kernel side of idevices. But of course I 00:47:23.730 --> 00:47:27.280 don't really mean that you shouldn't mess with these things, right? I mean, these 00:47:27.280 --> 00:47:31.941 devices are really interesting and it's really becoming harder to hack them, but I 00:47:31.941 --> 00:47:37.070 think it's much more fun and I think the only takeaway may be that you shouldn't 00:47:37.070 --> 00:47:41.310 report bugs to Apple at all and if you need street cred you should just report 00:47:41.310 --> 00:47:48.060 white elephant bugs now. I mean that's always good. And I mean this very... this 00:47:48.060 --> 00:47:52.220 is getting very esoteric, right, there are not a lot of information and Apple keeps 00:47:52.220 --> 00:47:55.690 changing stuff and everything is closed source, I mean, all the important parts 00:47:55.690 --> 00:48:01.110 are closed source... and I mean, I really think people that work on that things 00:48:01.110 --> 00:48:08.240 should share notes as much as possible. Okay, so these are some of the people I 00:48:08.240 --> 00:48:15.190 was talking to while doing all this and I want to mention them, and basically that's 00:48:15.190 --> 00:48:21.570 all of the material I have and I'm open to any questions you might have. 00:48:21.570 --> 00:48:32.850 applause Herald: Thank you, argp, for the talk. So 00:48:32.850 --> 00:48:42.831 we have prepared microphones 1, 2, 3 and 4 in the room and we have a Signal Angel, I 00:48:42.831 --> 00:48:50.870 think. You... when you have questions, you can give me a hand sign, but I 00:48:50.870 --> 00:48:58.050 think we start with microphone 2 here in the front. And please ask questions and no 00:48:58.050 --> 00:49:01.510 comments, there's time after the talk. Okay, go ahead. 00:49:01.510 --> 00:49:03.830 Q: Thanks for the awesome talk. argp: Thanks. 00:49:03.830 --> 00:49:11.960 Q: I have a question about heap spraying. Was your heap spraying really stable? If 00:49:11.960 --> 00:49:17.080 it is not successful, did it crash the device? 00:49:17.080 --> 00:49:21.850 argp: Yeah. So I haven't mentioned it here, but it was pretty stable I think. 00:49:21.850 --> 00:49:25.130 It was something like... because I did a lot of tests for that because it was 00:49:25.130 --> 00:49:31.480 really interesting for me to know. It was maybe something like 90%, so 9 out of 10 00:49:31.480 --> 00:49:35.141 times it worked, but if it didn't work - yeah, then... yes it crashed the kernel 00:49:35.141 --> 00:49:40.250 and crashed the device, yeah. Q: And did you try to return heap into 00:49:40.250 --> 00:49:44.990 some kind of initial state to start your exploit from scratch? 00:49:44.990 --> 00:49:50.230 argp: Yeah, that's true I haven't included that, but you're right. So the initial 00:49:50.230 --> 00:49:56.860 step on every spray that I mentioned here was to spray a lot of objects of the 00:49:56.860 --> 00:50:01.740 specific size you were targeting in order to get basically a new page of the kalloc 00:50:01.740 --> 00:50:07.120 zone, right? So you... so even if as I told you the kalloc 256 zone wasn't 00:50:07.120 --> 00:50:11.220 that busy, it's still... there were still allocations going on it, right? So if you 00:50:11.220 --> 00:50:16.390 did a lot of initial spraying, you were making sure that when you're... the 00:50:16.390 --> 00:50:21.690 allocations that mattered to you we're made, were on a new page that weren't... 00:50:21.690 --> 00:50:24.110 wasn't too much noise from other allocations from the kernel. So yeah, 00:50:24.110 --> 00:50:26.930 you're right I haven't included that, but yeah, that happened. 00:50:26.930 --> 00:50:29.900 Q: Thanks, great. argp: Thanks. 00:50:29.900 --> 00:50:36.200 Herald: Then microphone 1, please. Q: Also thank you for your awesome talk 00:50:36.200 --> 00:50:37.710 again. argp: Thanks. 00:50:37.710 --> 00:50:43.609 Q: My question was nowadays it's way harder to use vm_copy I think Apple truly 00:50:43.609 --> 00:50:49.480 deprecated it, it's not possible anymore that due to security. Do you see hope in 00:50:49.480 --> 00:50:54.560 reconstructing some function that does the same or is it totally dead now? 00:50:54.560 --> 00:50:57.780 argp: Oh, you mean the vm_map_copy technique? 00:50:57.780 --> 00:51:00.740 Q: Yes. argp: No, I think it's completely dead 00:51:00.740 --> 00:51:03.940 now. Q: All right. And I recently saw on the 00:51:03.940 --> 00:51:10.310 iOS logs vulnerabilities that again a vulnerability in AppleJPEGDriver was 00:51:10.310 --> 00:51:15.060 found. Do you think... have you looked into it or... 00:51:15.060 --> 00:51:20.050 argp: Well, Apple... the AppleJPEGDriver is one of the 4, I think, IOkit drivers 00:51:20.050 --> 00:51:25.820 that you can reach from the container sandbox, right? So that means it's very 00:51:25.820 --> 00:51:31.260 fast by everyone, Apple included, and very audited. So I'm not saying that there 00:51:31.260 --> 00:51:36.170 aren't many... there aren't things there, like interesting findings, but if there 00:51:36.170 --> 00:51:38.640 are they're not going to live much longer, I think. 00:51:38.640 --> 00:51:41.680 Q: Okay, thank you. Herald: Thanks for your question and now 00:51:41.680 --> 00:51:45.000 from the Signal Angel a question from the Internet. 00:51:45.000 --> 00:51:48.650 Signal Angel: Yes, I have a question from the internet. How long did this research 00:51:48.650 --> 00:51:52.800 take you? You said two weeks in the beginning, but from begin to end, how many 00:51:52.800 --> 00:51:55.430 hours about? Because you also said it was during work? 00:51:55.430 --> 00:51:59.750 argp: No, it didn't it didn't take two weeks, no. It took like maybe close to 00:51:59.750 --> 00:52:05.030 three months or two months and something like that. So I spent... as I mentioned I 00:52:05.030 --> 00:52:09.190 spent like a complete month, I think, like - maybe three weeks, maybe not a complete 00:52:09.190 --> 00:52:16.560 month just on reversing redsn0w and trying to get redsn0w to play with iOS7. So I 00:52:16.560 --> 00:52:21.790 wouldn't count this month in the exploit part of it, right? So if you're interested 00:52:21.790 --> 00:52:29.000 just in the kernel exploit part I would say something like maybe seven weeks, 00:52:29.000 --> 00:52:36.170 something like that. But just with 2 maybe 3 days per week right, not complete weeks. 00:52:36.170 --> 00:52:40.240 Herald: Okay, then microphone 1, please. 00:52:40.240 --> 00:52:45.740 Q: Congratulations on your talk which was really interesting, I liked it a lot and 00:52:45.740 --> 00:52:51.090 my question is if the technique you used to exploit the bug was in FreeBSD or any 00:52:51.090 --> 00:52:56.320 other BSD as well? argp: Oh no, no. I mean, the vm_map_copy 00:52:56.320 --> 00:53:02.900 struct doesn't exist anywhere else except the XNU kernel. But I think the 00:53:02.900 --> 00:53:06.921 interesting takeaway is that you can do complex heap arrangements if you 00:53:06.921 --> 00:53:13.960 understand the kernel heep allocator, right? So this process I described by 00:53:13.960 --> 00:53:18.740 creating holes and maybe controlling 2 allocations in order to host fake 00:53:18.740 --> 00:53:24.630 structures that you are able then to use to get exploitation primitives then that's 00:53:24.630 --> 00:53:30.740 applicable everywhere, right? Herald: Okay, then we go to microphone 2 00:53:30.740 --> 00:53:35.810 again, please. Q: So I saw one sentence, just not report 00:53:35.810 --> 00:53:42.830 or... just don't report the bugs. I would like to understand your thinking behind, 00:53:42.830 --> 00:53:48.980 because I think this is really important for companies to know the bugs that they 00:53:48.980 --> 00:53:54.800 made and yeah, make the products better and this is really beneficial for 00:53:54.800 --> 00:54:00.950 researcher because for example Apple they pay a lot of money for the bugs. What... 00:54:00.950 --> 00:54:07.050 argp: Okay, yeah, I don't have much to say on that. I mean, apart from: if all the 00:54:07.050 --> 00:54:11.030 bugs are fixed then you won't be able to do this kind of work and it's no fun. 00:54:11.030 --> 00:54:17.760 Sorry, I don't have anything else to say on that. Sorry, I don't have anything 00:54:17.760 --> 00:54:23.140 else, no comment. Herald: Okay. Signal Angel, do we have 00:54:23.140 --> 00:54:31.310 another question from the internet? Okay, then please a big round of applause for 00:54:31.310 --> 00:54:33.539 our speaker! argp: Thanks. 00:54:33.539 --> 00:54:35.233 applause 00:54:35.233 --> 00:54:39.864 postroll music 00:54:39.864 --> 00:54:57.000 subtitles created by c3subtitles.de in the year 2020. Join, and help us!