00:00:00.000-->00:00:05.000 >>Hi Everyone, Uhm my name is Max Bazaliy and today we'll talk about jailbreaking Apple Watch. 00:00:10.167-->00:00:15.042 [inaudible yelling from audience] Okay, let me fix it. Oh. Yeah. That's a bit better. 00:00:15.042-->00:00:21.792 So. Once again, yeah I'm Max Bazaliy and uh I'll talk about jailbreaking Apple Watch. I work 00:00:21.792-->00:00:26.208 as a security researcher at Lookout when I focused on Malware detection. Last year I 00:00:26.208-->00:00:30.667 was the leader researcher on eh Pegasuses exploit chain. And currently focused advanced 00:00:30.667-->00:00:36.458 exploitation techniques for software hardware Uhm I I co-founded the fried Apple Team 00:00:36.458-->00:00:41.458 and I'm author various of jailbreaks for IOS, tvOS and now for ewatches. So what is apple 00:00:43.500-->00:00:50.292 watch? Uhm It's a smart watch device that was released in 2015 and it uses Apple S1 or S2 00:00:50.292-->00:00:55.292 processor. uh it's basically 32 bit architecture processor uh called the RM7K uh which is 00:00:57.542-->00:01:02.542 derived from RM7A uhm It uses taptic engine for user identifications it has eh 512mb 00:01:04.917-->00:01:09.917 of RAM and it's running the watches which is derived from IOS. So I hear a question a few 00:01:13.375-->00:01:20.042 times, why we even need to jailbreak a watch? Well, I have a few watches at home, and it 00:01:20.042-->00:01:24.375 should be pretty interesting from a security researcher's point of view. Why not give it a 00:01:24.375-->00:01:30.625 try? Why not try to jailbreak it? Cause it's hmm if I can jailbreak it I have access to 00:01:30.625-->00:01:36.875 filesystem so I can like check the watches internals. And it should be just fun to run ehm 00:01:36.875-->00:01:41.875 debuggers like radare or Frida on this teeny Apple Watch screen. Uhm or use it as iPhone 00:01:44.625-->00:01:49.625 attack vector to send some form of data to the iPhone. So before jumping to uh jailbreak 00:01:53.417-->00:01:58.042 internals let's make a quick overview of the Apple Watch security which starts from 00:01:58.042-->00:02:03.000 secure boot chain where each element in the boot chain is checked ot be properly signed by 00:02:03.000-->00:02:08.375 Apple and it basically stops boot if it's not. The next thing is Mandatory Code Signing, so 00:02:08.375-->00:02:14.250 all code that is running on the watches should be signing by trusted party. The Sandbox which 00:02:14.250-->00:02:18.708 is limited application access to other applications' data and to limit the application access to 00:02:18.708-->00:02:25.000 critical system APIs. Exploit mitigations like address space layout randomization on user 00:02:25.000-->00:02:30.000 mode and the kernel mode keep and stack cookies and of course the data execution prevention. 00:02:32.042-->00:02:36.125 Starting from second generation Apple Watch there is a hardware breakage Secure Enclave 00:02:36.125-->00:02:42.417 Processor and it's used for safe group operations and the data protection, so all user data is 00:02:42.417-->00:02:48.708 encrypted when device is locked. So, after thinking about the possible attack vectors on the 00:02:48.708-->00:02:54.417 watch and the first idea was hmm why not try to send some malformed payload or even like 00:02:54.417-->00:02:59.417 false USB descriptors because there is a teeny port, the debug port on a watch if we 00:03:02.500-->00:03:08.833 [inaudible] some of the things, we see like this small port. the problem here hu the cables from 00:03:08.833-->00:03:15.208 this debug port to USB are not public, so I don't want to mess with all the nonpublic hardware 00:03:15.208-->00:03:21.292 so I decided to switch for other way. the other way will be sent malformed emails or messages or 00:03:21.292-->00:03:26.292 photos from a phone to a watch and try to basically uhm attack the parser. Well, this will be 00:03:30.083-->00:03:35.083 still limited by a sandbox, the parsers, so I need additional out of sandbox bug to continue 00:03:37.250-->00:03:43.333 the jailbreak. Well, starting from watch to Apple added the support for uhm user defined 00:03:43.333-->00:03:48.125 application extensions which is basically the native code, which is running on watch OS, so I 00:03:48.125-->00:03:53.125 decided to stay on this one its looks pretty good and I have freedom on the bug choice. So to 00:03:56.083-->00:04:01.250 choose one of the uh uhm unfixed bugs and and use it for jailbreak. So this how the 00:04:01.250-->00:04:06.042 jailbreak may look like. So first of all we need to locate the kernel memory all the 00:04:06.042-->00:04:12.167 security measurements are in uh kernel so we need to patch the kernel to disable them. For this 00:04:12.167-->00:04:18.500 one we need to break the KSLR and find the kernel base then read the whole kernel to user 00:04:18.500-->00:04:23.500 mode, start analyzing it look for a gadgets setup primitives like read write, then finally 00:04:25.542-->00:04:31.583 patch the kernel to disable security restrictions and to run SSH client on the watch. Well 00:04:31.583-->00:04:36.583 looks do-able. So as I say uh I have a few version of uh watches at home like watch0S2 and 00:04:39.000-->00:04:45.875 watch0S3, and I started looking for a good bug. Uhm for watch0S2 there is a pretty good bug the 00:04:45.875-->00:04:51.167 CVE-4656 which is used to free in the kernel and this bug is famous because it's a part of 00:04:51.167-->00:04:57.750 the Pegasus Exploit Chain. So this may be pretty good candidate as alternative ways to 00:04:57.750-->00:05:02.750 be 4669 which is a mach port register uh it can be exported to 32-bit as a free neuron zone 00:05:04.958-->00:05:10.667 but I decided to stay with Osunserialize because it's more stable. As for watch0S2 there 00:05:10.667-->00:05:15.667 are two bugs, CVE-7644 set dp control, which was eh discovered and exploited by iron beer in uh 00:05:19.583-->00:05:26.250 mock portal jailbreak, and CVE-2370 which is heap overflow in voucher extractor side. It 00:05:26.250-->00:05:31.250 was used later by [inaudible] in yellow 10.2. So I decide to stay with CVE-2370 in watch0S3. Okay, 00:05:36.083-->00:05:41.250 eh, we now know the bugs how to get the kernel level code execution, let's start from 00:05:41.250-->00:05:46.250 leaking the kernel base. There are a few good CVEs eh CVE-4655 and CVE-4680. They both share 00:05:49.958-->00:05:56.292 the same problem. So because during the parsing in the kernel, one of the objects which 00:05:56.292-->00:06:02.333 is like OSNumber object eh it's basically object constructor missing the bound check in, 00:06:02.333-->00:06:08.417 which leads it attacker can create OS number with a high number of bits. And later on 00:06:08.417-->00:06:15.250 this high number of bits will be used as object length and the object length will be used to 00:06:15.250-->00:06:19.583 copy eh how many bytes we need to copy from a kernel stack to a kernel heap and return to the 00:06:19.583-->00:06:25.458 user of length. So this means the kernel stack memory will be leaked and we can a kernel base. 00:06:25.458-->00:06:30.458 And this bug can be triggered from the sandbox. I will check more detailed. So the bug is in 00:06:33.250-->00:06:39.500 a centralized binary which is a method to handle eh binary related data. It converts the 00:06:39.500-->00:06:45.000 binary from format to basic kernel data objects like arrays, strings, boolean, numbers, and 00:06:45.000-->00:06:50.000 so on. And the problem is when ehm the parser goes to OSNumber. The OSNumber represents the eh 00:06:52.208-->00:06:58.000 number object in the kernel. And it basically blindly draws the input argument here the value 00:06:58.000-->00:07:03.000 len and just calls it designated constructor, which is OSNumber in it. And here's a problem, 00:07:05.792-->00:07:11.708 because ehm one of the arguments which is newNumberOfBits is set to one of the class variable 00:07:11.708-->00:07:16.708 size and this size will be used later on on other [inaudible] number of byte. This leaves it a 00:07:20.667-->00:07:25.667 return value number of bytes is fully controlled by attacker and why is that? Well later on in 00:07:28.042-->00:07:34.458 ioregistry property bytes this eh number of bytes method will be used to calculate the 00:07:34.458-->00:07:39.458 OSNumber lens. And which is bad because OSNumber value is stored on the kernel stack eh here it 00:07:43.417-->00:07:48.417 is offset bytes ehm buffer and basically the object lens will be used to copy that many from 00:07:51.750-->00:07:56.250 the kernel stack that it needed from, from this buffer and returned to user mode. As it 00:07:56.250-->00:08:02.792 controls the how many bytes will be copied we can control, well like, 255 bytes and basically 00:08:02.792-->00:08:08.250 leak some of the kernel memory. If the kernel memory will ehm will have any of the kernel 00:08:08.250-->00:08:13.875 pointers it will be enough to determinate the kernel base. So we know the kernel base, now 00:08:13.875-->00:08:18.875 it's time to get some code execution in the kernel end. So, CVE-4656 is eh pretty good, it's 00:08:22.500-->00:08:27.458 used to free in in the same OSUnserialized binary, but in the different branch. Uh the 00:08:27.458-->00:08:33.833 problem here that during the unserialization the OSString object will be delegated but the 00:08:33.833-->00:08:40.000 pointer to the object still start in one of the arrays and later the routine method will be 00:08:40.000-->00:08:46.500 called on this delegated eh data which leads to user to free. So if you can relegate this object 00:08:46.500-->00:08:52.458 with attacker control object like fake OS string which point to attacker control vtable we 00:08:52.458-->00:08:57.458 can get to kernel mode code execution. This is how it's looked like. So, the same 00:08:59.583-->00:09:05.833 OSUnseriializedbinary, which parse the binary encoded [inaudible] OS uhm it's the 00:09:05.833-->00:09:10.833 problem in when the uh object will be eh deserialized and saved to object array so now we 00:09:13.667-->00:09:19.167 see the set of index macro that basically store the pointer of an object but not doing any 00:09:19.167-->00:09:25.750 memory measurement on it like not retaining the object. This is bad because later on when 00:09:25.750-->00:09:31.542 OSstring will be casted to OSsymbol the Osstring object will be delegated but the 00:09:31.542-->00:09:38.250 pointer to it will still exist in one of the arrays. And in a case of KOSSerializedObject 00:09:38.250-->00:09:43.250 which is a reference to an object uh it will be retained which caused the user to free. 00:09:45.917-->00:09:50.917 So, we get the kernel well mode execution and it uh the problem that we need to know what 00:09:53.083-->00:09:57.875 executing the kernel. So basically there are no Watch OS dump available in public in that 00:09:57.875-->00:10:04.625 time as well there is no keys for watchOS kernels. So and to basically to continue jailbreak 00:10:04.625-->00:10:10.625 I need to know some part of a kernel. And I have an idea, why not create a fake OSString, 00:10:10.625-->00:10:16.500 point it to the beginning of the kernel, and basically read the kernel as OSString chunk. Looks 00:10:16.500-->00:10:22.458 doable, eh the problem here that even the object is fake we still need the real vtable offset. And 00:10:22.458-->00:10:27.458 with vtable offset stored in data const which mean basically I need some part of the kernel 00:10:31.000-->00:10:35.583 to dump the kernel. It's like a chicken and egg problem. And I start looking for a way, is 00:10:35.583-->00:10:40.583 there any possibility to dump this vtable just in a runtime? Well, it is. Ehm, as we know the 00:10:45.000-->00:10:49.792 vtable is stored in the data const in the kernel and the data const is referenced in the 00:10:49.792-->00:10:55.500 kernel Mach-0 header. Which means it some how we can leak the kernel here, how we can leak 00:10:55.500-->00:11:00.500 the data const address in a runtime. Uhm and the offset to the data const hmm reference in 00:11:04.292-->00:11:11.042 eh in a header is always constant there are like 0X224 I determined from similar external 00:11:11.042-->00:11:17.500 build. So if in run time we can branch to start of the kernel plus this offset we can leak the 00:11:17.500-->00:11:24.208 data const. And how we can do it just use it as a fake vtable pointer. So the device will 00:11:24.208-->00:11:30.292 crash, the kernel will crash, but we will get uh the data const address. Now if we know 00:11:30.292-->00:11:36.333 the data const I was trying to calculate the offset for vtable by checking uhm, the similar 00:11:36.333-->00:11:42.792 external build from the start of the data const to the vtable. Uh, unfortunately it's not just 00:11:42.792-->00:11:46.542 work out of the box because there are, the kernels are different so I was trying to 00:11:46.542-->00:11:52.583 tune it with plus minus four bytes delta. But in reality it never works. So later on I found 00:11:52.583-->00:11:58.458 it the difference are really significant in the watchOS and the IOS, it's like more than 00:11:58.458-->00:12:04.750 hour kilobytes of difference in a data segment. So, this method is not working. Uhm Okay, just 00:12:04.750-->00:12:11.708 looking there should be some other way to do it. Uhh and I look at OSString layout in the 00:12:11.708-->00:12:18.250 memory. So for 32-bit the size of the object is like 20 bytes, for 64-bits like 32 bytes and 00:12:18.250-->00:12:24.000 the very first pointer of an object is a pointer to object vtable. And which is more 00:12:24.000-->00:12:30.500 interesting the layout of the vtable, so uh our bug triggers a user to free by calling a 00:12:30.500-->00:12:35.500 retain. Retain is like fifth element in array. So I start looking well it should be some 00:12:39.917-->00:12:44.917 way to reuse information. Uhm, here is what what I mean, eh we have the OSString object layout 00:12:47.792-->00:12:53.333 in the memory and the very first pointer of OSString object is point to object vtable. eh and 00:12:53.333-->00:12:59.917 the vtable is pointing somewhere in the kernel called section and our trigger which is OSObject 00:12:59.917-->00:13:04.917 retain is like fifth element in the array. Uh, okay, so how we can use it? What if the object 00:13:08.375-->00:13:14.208 that will be triggered in the bug will be delegated but not relocated? So this memory chunk 00:13:14.208-->00:13:20.792 will be marked as free and which is more interesting ehm, this free memory chunk will be 00:13:20.792-->00:13:26.958 pointing to next free memory chunk in the freelist. This is interesting, ehm this is how 00:13:26.958-->00:13:32.792 it's looked like so we have a node in eh and if released we have like freelist head and know 00:13:32.792-->00:13:38.750 each node is pointing to the next node in the freelist. And again is like the first pointer 00:13:38.750-->00:13:43.750 in ehm this free memory chunk is a pointer to the next free memory. So what if uhm we not 00:13:47.375-->00:13:53.333 relegate OSString object, this memory will be marked as free and uh basically now it's 00:13:53.333-->00:13:58.333 pointing to the next free node in the freelist and this pointer will be interpreted as OSString 00:14:00.583-->00:14:07.125 vtable pointer. So if we call to retain it, it will basically branch out of bounds on the next 00:14:07.125-->00:14:12.125 node. This is what I mean, so again we have the nodes, each node is pointing to other node 00:14:14.583-->00:14:19.625 and uh if it called the user to free without relegating an object eh one of the nodes will 00:14:19.625-->00:14:25.375 be interpreted as OSString. And the beginning of the node is the pointer to the next node and 00:14:25.375-->00:14:31.542 this pointer will be interpreted as a pointer to OSString vtable. Then we call a retain and uh run 00:14:31.542-->00:14:37.917 out of bounds basic- branch out of bounds to the next node. But what if we can control the next 00:14:37.917-->00:14:42.917 node? So if you spray OSString objects ehm make a holes on a heap then basic trigger to use 00:14:45.250-->00:14:50.250 of to free the pointer of to the next node will be interpreted as a vtable which is now branching 00:14:52.625-->00:14:56.958 to the next node but if this next node is OSString it will be branched just in the beginning 00:14:56.958-->00:15:02.125 of the OSString object, which is in the beginning of the vtable. This is what I mean, this is the 00:15:02.125-->00:15:07.125 initial state of the heap. With some memories allocated and a basically heaps sprayed a lot of 00:15:09.167-->00:15:16.042 OSString objects. so we fill memory and trigger some of those OSString delegations so 00:15:16.042-->00:15:22.417 basically now we have holes on the heap and triggered the user to free. One of these holes will 00:15:22.417-->00:15:28.833 be interpreted as OSString objects and pointing ot the next hole on the heap and when we 00:15:28.833-->00:15:34.958 call the retain it will be out of bounds for the next node, which in our case, is OSString. 00:15:34.958-->00:15:41.708 So we will dump vtable in the panic log. Uhm, well despite of this working, uh I get it 00:15:41.708-->00:15:48.125 working 64-bits, I can dump vtables on 64-bit kernels but for certain to be pretty painful 00:15:48.125-->00:15:53.125 to make it work because of the size miss match on the zone size and object size. So I said aw, 00:15:55.875-->00:16:00.875 it should be some other way to do it. Well, I started looking for a similar kernels and I 00:16:03.125-->00:16:08.958 found that the reference to OSString is the OSString vtable is in the IOSunserialized 00:16:08.958-->00:16:13.833 binary. This is interesting because our bug is in IOSunserialized binary and 00:16:13.833-->00:16:18.833 IOSunserialized binary is referenced in IOSunserialized XML. Say okay uhm, if somehow we 00:16:20.875-->00:16:27.333 can leak uh one of the OPcodes from IOSunserialized binary we should like calculated this 00:16:27.333-->00:16:32.333 vtable offset. [mumbles] [drinks water] So, yeah. Should be doable. Uhm, so I crash uhm in 00:16:42.792-->00:16:47.792 IOSunserialized binary during the object desterilization kernel will crash, device will 00:16:50.375-->00:16:55.375 crash, I get the panic log I just copied from a watch uh read the LO registry and now I know 00:16:57.875-->00:17:02.875 where the IOSunserialized binary is uh cleared out over the start of the kernel. Which is 00:17:05.125-->00:17:12.000 interesting because now we can start to dampen the OPcodes by the panic logs. so, we can use 00:17:12.000-->00:17:17.000 the address we want to dump as an address of our fake vtable minus 0X10. This vtable is this 00:17:20.375-->00:17:25.250 uh pointer will be interpreted as a vtable uh and branch to this address, obviously the 00:17:25.250-->00:17:32.167 device will crash but eh the- we will get the kernel panic log and the register state. And the 00:17:32.167-->00:17:37.583 register state will contain basically the PC register, which is pointing to the content of 00:17:37.583-->00:17:43.833 the address. So, I start dampening the kernel by 4-bytes by crashing the device, uhm, 00:17:43.833-->00:17:50.000 using the address as the fake vtable, uh the watch crashed wait until it's restore and now 00:17:50.000-->00:17:55.917 I need to copy panic somehow. that's a problem because it not just work out of the box, so I 00:17:55.917-->00:18:02.042 need to jailbreak my phone access the phone, uh trigger special service which basically 00:18:02.042-->00:18:07.042 copy panic from my watch to phone, then copy to a mac, parse the panic, get the uhm address 00:18:09.417-->00:18:14.417 content, put it in disassembler, get the OPcodes, and update this address with like plus four 00:18:16.875-->00:18:23.875 bytes delta, upload it to watch and repeat. So, it's like you can say it's pretty painful way 00:18:23.875-->00:18:29.125 to dump a kernel. I can say it's pretty fun, yes so. I have a lot of panics and a lot of crashes. 00:18:29.125-->00:18:34.125 Uh once again how this looks like. So, we we need to start damping OPcodes in 00:18:37.208-->00:18:42.792 IOSunserialized XML until we've found the branch to IOSunserialized binary. It's as 00:18:42.792-->00:18:49.417 soon as we leaked this address uh we can start dumping OPcodes in IOSunserialized binary until 00:18:49.417-->00:18:54.417 we've found the reference to OSString vtable. It could take like another ten panics. Again, 00:18:57.292-->00:19:03.167 the full attack plan crash an IOSunserialized XML, dump the 4 bytes, but it in disassembler, 00:19:03.167-->00:19:07.917 read the OPcodes until we find the OP code which is branched into IOSunserialized binary. 00:19:07.917-->00:19:14.667 Leak the int- leak the address and start leaking the IOSunserialized OPcodes until 00:19:14.667-->00:19:19.667 we've found the reference to OSString vtable. uhm, yeah so it takes me like a long time to, to 00:19:22.750-->00:19:29.375 dump a kernel like this way, but it's it's doable. This is how long it take uhm usually takes 00:19:29.375-->00:19:36.333 like five minutes to recover a watch after a panic and it takes another five minutes to fetch a 00:19:36.333-->00:19:41.625 panic from a watch because as I say I need to jailbreak a phone and SSH the phone and like keep 00:19:41.625-->00:19:47.458 trying and triggering the special service that is fetching all the panics. Then we copy to 00:19:47.458-->00:19:53.542 my mac, parse it, and I already don't find any way to optimise the process because I need to 00:19:53.542-->00:19:59.833 recompile the binary all the time and reupload it over to bluetooth to my apple watch. So, 00:19:59.833-->00:20:04.833 it takes me just two weeks to dump the vtable. uh, yeah but now I have the vtable, now I can 00:20:07.042-->00:20:12.333 construct my exploit. I use the fake OSString with the real vtable, pour it to the beginning 00:20:12.333-->00:20:18.167 of the kernel and start reading kernel as OSString chunks. We can even read them in eh user 00:20:18.167-->00:20:22.292 mode using IORegistryEntryGetProperty. So, I leak the kernel header, 00:20:22.292-->00:20:27.292 calculate the kernel size form header, and dump the whole kernel into user mode. Okay, we 00:20:29.417-->00:20:35.250 have a kernel but there is no symbols. So uh the first thing that I've done is start looking 00:20:35.250-->00:20:41.083 for kernel extensions, basically drivers in the kernel which are pulling to this kernel. There 00:20:41.083-->00:20:45.833 are a few ways of doing it. We can look for the XML which is usually at the end of the kernel 00:20:45.833-->00:20:52.042 which describes all the kernel extension Prolink into this kernel. Or in a bad case which 00:20:52.042-->00:20:57.708 can just look for a mark or header magic and if we find the magic we know this is the 00:20:57.708-->00:21:03.583 beginning of the sum of the kernel drivers. So I find the kernel drivers and the next step 00:21:03.583-->00:21:09.125 is to find the system call table. The trick here that system call table not truly 00:21:09.125-->00:21:13.833 changes over the watch OS versions. Which means that Apple at the new syscall at the end of 00:21:13.833-->00:21:18.667 the table but did not truly change the syscalls in the middle of the table. So if we 00:21:18.667-->00:21:24.333 found the beginning of the table we can automatically resolve more than 400 functions and get 00:21:24.333-->00:21:30.167 some bas- and basically get some symbols. The same for mach traps. And finally we can 00:21:30.167-->00:21:36.708 resolve IOkit objects vtables and get like even more symbols. So I have the same [inaudible] 00:21:36.708-->00:21:42.500 kernel and uh starting to analyze it and set up the primitives. We already have the 00:21:42.500-->00:21:48.042 exec primitive we used to free. so all I need to find some interesting gadgets for read and 00:21:48.042-->00:21:54.833 write. yeah, so they are on a slide. Uh we set up the primitives, we get the same 00:21:54.833-->00:21:59.833 disabled kernel and one thing I need is to uh get internal kernel structures layout. In 00:22:03.958-->00:22:08.708 this case there's a proc structure which represents the process structure in the kernel 00:22:08.708-->00:22:13.708 space. Uh and the kernel that's different between the IOS and the watch uh IOS and like I-I 00:22:15.917-->00:22:20.417 cannot even use the new source code. Again, because because of the differences. So I start 00:22:20.417-->00:22:25.417 reconstructing this proc uhm structure just in runtime by um looking for proc underscore 00:22:27.750-->00:22:33.625 functions they are reference to some of the fields in the proc structures so I can reconstruct 00:22:33.625-->00:22:38.625 the layout I need. In some real bad cases I just dump the piece of memory and uh look for 00:22:41.000-->00:22:46.250 constant values. for example the CPU type or the CPU subtype all of this is constant on the watch 00:22:46.250-->00:22:52.875 IOS and I know okay if it's the CPU type it should be like field 0X10 or so. so I see me 00:22:52.875-->00:22:59.167 reconstruct a few of the structure that I need and uh well now it's time to find the 00:22:59.167-->00:23:04.625 patches what to disable in the kernel. I use pretty classic approach called dispatch finder. 00:23:04.625-->00:23:11.292 So when we are looking for a string or byte references find uh uh yeah f-find the pattern 00:23:11.292-->00:23:15.792 find the reference to it and if some additional instruction analysis we can find the 00:23:15.792-->00:23:21.792 beginning of the function or the variable we need or so. Again we're solving the syscalls table 00:23:21.792-->00:23:28.375 will be pretty useful here as we can automatical resolve more than 400 functions. In some bad 00:23:28.375-->00:23:33.792 cases uh our [inaudible] two instruction and emulation was needed to determined it was the 00:23:33.792-->00:23:39.583 sum of the variables allocated. so it was a pretty big win for me, I get the same disabled 00:23:39.583-->00:23:45.958 kernel I get uh internal structures layout I know what to patch. now it's time to patch. 00:23:45.958-->00:23:50.958 Uhm. So, I begin my jailbreak where by getting escalating to root privileges and get out of 00:23:54.125-->00:23:59.125 the sandbox. So, the most easy to do it is to patch the central dysfunction. so there is no 00:24:07.500-->00:24:13.000 patch protection on 32-bit kernels eh including the apple watch so nobody really prevents 00:24:13.000-->00:24:18.458 us to patch basically the kernel and patch the kernel page tables. So I patch out the 00:24:18.458-->00:24:24.500 checks in central ID and just call central ID 00 to to get the root. Or and there is another 00:24:24.500-->00:24:31.125 way if you don't want to patch uh the kernel code. Eh, it tried to heap find the point or two in 00:24:31.125-->00:24:36.125 the old uh proc pointer in this old proc find pointer in the proc structure uhm of our 00:24:39.000-->00:24:43.625 process and this proc structure find the pointer to ucred structure. And in this ucred 00:24:43.625-->00:24:50.250 basically updates your ID area your ID fields and basically becomes root. The same thing is 00:24:50.250-->00:24:55.583 how to get out of the sandbox the same ucred structure just move out the sandbox label no 00:24:55.583-->00:25:00.583 label, no sandbox restrictions So we are out of the sandbox the next thing is uh how to obtain 00:25:02.917-->00:25:09.208 the kernel task the kernel task is eh pretty useful way to write anywhere in the kernel memory, 00:25:09.208-->00:25:15.333 read anywhere, and even allocate the kernel memory. so most obvious way to do it is uh to 00:25:15.333-->00:25:20.333 patch task for pid, is a special api that return uhm the process task to user mode based on the 00:25:23.000-->00:25:29.125 process ID Of course there is a hard coded check if the process ID is zero, which is kernel, 00:25:29.125-->00:25:34.125 return now. So we can patch out this check and just read the kernel task. other way to do it 00:25:37.583-->00:25:42.583 is uhm again enter the heap look for eh alt proc pointer and this alt proc pointer finds the proc 00:25:45.250-->00:25:51.250 structure for the kernel uhm find eh pointer to a task structure in a kernel memory and 00:25:51.250-->00:25:56.250 s-save the send right, which is itself. Just write to our task uhm bootstrap port. Then in user 00:25:59.875-->00:26:04.917 mode we can read it by task get special port it will convert this point or two useful task 00:26:04.917-->00:26:09.917 structure well yeah we get the kernel task port. With the kernel task it's pretty easy now 00:26:12.667-->00:26:18.625 to write anywhere in the kernel memory including the kernel text so I start disable the code sign 00:26:18.625-->00:26:24.375 checks There is a global variable which is called debug which is referenced by functions 00:26:24.375-->00:26:29.375 which like said the debugger capabilities for kernel or one of the drivers so we can set it 00:26:32.500-->00:26:38.375 globally to one or we can patch eh [inaudible] debugger only for eh kernel extensions we need by 00:26:38.375-->00:26:43.375 updating NL symbol pointers. hmm the next thing is update the amfi variables like cs 00:26:46.125-->00:26:51.750 enforcement disable and all invalid signature. This will allow us to run any unsigned 00:26:51.750-->00:26:57.833 code on the apple watch. And the last thing we need is to remount the root filesystem the problem 00:26:57.833-->00:27:04.208 here is that the root filesystem is mounted as read only which means if we want to override the 00:27:04.208-->00:27:09.542 some of the other binaries or just add the new binaries we needed to remount it first to be 00:27:09.542-->00:27:15.958 right, there are a few ways of doing it uh there is a mock mount function in the kernel and 00:27:15.958-->00:27:21.667 this function is checking if the filesystem is a root file system prevent it from remounting so we 00:27:21.667-->00:27:28.500 can patch out this check, call it remount or again it's ready heap find the pointer to rootfs 00:27:28.500-->00:27:33.500 vnode and this uh vnode find the pointer to the mac uh the mount flex and basically remove the 00:27:35.667-->00:27:41.875 check and then remove the flag which represents this filesystem as root filesystem which means 00:27:41.875-->00:27:47.583 this filesystem is not the filesystem we can easily remount uh with a mac mount additionally 00:27:47.583-->00:27:52.583 we need to patch uh lightweight volume manager it's a special kernel uhm extension which is 00:27:54.958-->00:28:01.750 prevent us to write any data to protect it partitions. in our case the root defensive 00:28:01.750-->00:28:06.750 partition so we need to find map for IO uh function and patch our its write protected check in 00:28:09.958-->00:28:15.333 addition said PE i an has debugger capabilities in this light right below manager. So 00:28:15.333-->00:28:20.333 yeah basically we patch the kernel we disable most of the restrictions so now I start to 00:28:22.583-->00:28:29.292 basic compile my payload i recompile the dropbear which is lightweight ssh client for this 00:28:29.292-->00:28:35.750 ARMv7k architecture and recompile the basic tools package like PS, mode, LS and so 00:28:35.750-->00:28:40.750 on put everything in my watch S extension and basically as soon as I get out of sandbox copy to 00:28:43.625-->00:28:50.333 a root filesystem there is a problem here when I spawned the dropbear it got killed it got 00:28:50.333-->00:28:56.250 killed by sandbox which means the watchOS is more restrictions than the IOS so some of the 00:28:56.250-->00:29:01.792 thing that just work on IOS get killed by sandbox in the watch OS so I just found poitners to 00:29:01.792-->00:29:08.542 specific sandbox operations in the kernel and just know the mount okay now it should work uh 00:29:08.542-->00:29:13.542 but I have a surprise here is a list of watchOS interfaces the AWDL0 looks promising which is 00:29:16.500-->00:29:21.500 apple wifi direct but LC now it works only eh bluetooth which may be a problem because I plan 00:29:26.208-->00:29:31.208 to basic connect from my mac to a watch over the SSH and I need to somehow to figure out how to 00:29:34.542-->00:29:39.542 uh run this SSH over the bluetooth. And there is a way uh thanks to for Luca to point me 00:29:41.958-->00:29:48.000 to eh this possibility We can eh use mobile framework uh mobile device framework on my on the 00:29:48.000-->00:29:53.542 mac and send the special message to phone And the fun part that phones should not be jailbroken 00:29:53.542-->00:29:57.583 it's it can be any release phone. so we send a message which say hey please start 00:29:57.583-->00:30:02.583 forwarding service port with port 22 and uh we get a response with eh companion proxy server 00:30:06.167-->00:30:11.667 ports. so basically what what we've done we bind the port on the watch to some random port on 00:30:11.667-->00:30:16.667 the phone And later on we can use this port on the phone to bind it to some port on the mac 00:30:19.667-->00:30:24.667 oops what happened? uhm I guess it it HDMI yep okay uhm so as I said we bind some port on the 00:30:35.917-->00:30:40.917 watch to some random port on the phone and bind this port on the phone to some port on ehm mac 00:30:44.417-->00:30:50.375 and basically over this USB and bluetooth uh we can run this SSH connection and basically it 00:30:50.375-->00:30:55.375 works uh now I can show how uhhh okay yes so yeah the very first thing I need to do is like bind 00:31:09.083-->00:31:14.083 this port and call it like bluetooth proxy which bind port 22 on the watch to eh phone and 00:31:16.333-->00:31:22.625 uh bind the same port from the phone to my mac now it can use just a local host with this port 00:31:22.625-->00:31:27.625 to connect over the bluetooth to the watch yeah we got the shells up it so let's prove that we are 00:31:34.917-->00:31:39.917 running on the apple watch by tuning the uname which is apple watch on uh watch 1 2 okay let's 00:31:45.208-->00:31:52.083 try one of the command line too like psm dump delete all the processes so we see that the 00:31:52.083-->00:31:57.667 watch OS is pretty similar for the IOS for the point of security and the point how the 00:31:57.667-->00:32:02.667 eh operating system work or example we can yeah we can least our dropbear client which is 00:32:05.750-->00:32:10.750 yeah doing SSH connection so as I said I recompile the basic tools like tar, like http to 00:32:15.958-->00:32:22.542 easily archive or unarchive stuff to copy files from the watch but as for me it's pretty 00:32:22.542-->00:32:27.667 painful to copy file from the watch to the phone then copy it from eh phone to a mac. uhm so I 00:32:27.667-->00:32:32.667 found more easier way ehm just http directly from mac to watch and just upload the files so in 00:32:37.208-->00:32:42.208 this case eh I just take procs explorer binary it's a tool written by Jonathan Lewin and 00:32:44.292-->00:32:49.292 yeah copy it to the watch we get a pretty good speed over the bluetooth uh still open yeah so 00:32:54.583-->00:32:59.583 it's copied now lets prove that it's basic on the watch by running our procs explorer. as I 00:33:02.292-->00:33:08.875 say it is a toolit's like similar to PS or TOP but shows the memory pressure and some 00:33:08.875-->00:33:15.792 other useful things so the process called the watchpwnz is our jailbreak. so yeah basically 00:33:15.792-->00:33:20.792 the copying to watch for Now we need to find a way how to easy copy files from the watch to a 00:33:23.542-->00:33:28.542 mac for this purpose I use like SSHT watch tar, basic archives some of the files I need uh and 00:33:32.167-->00:33:37.167 use the pipe to easily just dump everything to my mac laptop like check how it work so yeah it 00:33:42.042-->00:33:48.625 start archiving the product frameworks on the apple watch and I will switch to my mac 00:33:48.625-->00:33:53.625 basically to prove that we got some files copied especially like 3 megabytes of applewatch 00:34:02.333-->00:34:07.875 data was just copied to my mac which is like one single comment. okay this is basically 00:34:07.875-->00:34:12.875 the ssh on the watch uh so I've start looking. okay. We've got the jailbreak on the watch and 00:34:15.000-->00:34:20.000 the watch have a access to SMS calls, even the Photos and emails can be synched to the 00:34:23.208-->00:34:28.208 watch it can fetch GPS location from a phone it in some cases if you use a watch to answer a call 00:34:30.417-->00:34:35.958 it has a microphone usage and even its enrolled in apple pay so it may be pretty interesting 00:34:35.958-->00:34:40.958 to to look what is on a file system so as I said we have a jailbreak so it has full access 00:34:43.458-->00:34:50.167 to file systems and we can look for sql3 databases not limited to the , messages, call history, 00:34:50.167-->00:34:55.167 contacts, emails, and so on so what's going to be next? I've basically recompiled the hooking 00:34:58.375-->00:35:03.542 and engine that can do interposing on trampolining to hook some of the system 00:35:03.542-->00:35:10.000 functions. Which means that I can catch data when the data will be syncing between iphone 00:35:10.000-->00:35:15.000 and the watch. So maybe in the future we will see tweaks for the watch or as I said we can 00:35:17.667-->00:35:22.667 run the frida or the radare on this pretty small watch screen. Okay uhm so as we see the 00:35:27.667-->00:35:32.667 watchOS is pretty secure operating system it's securities equal to IOS but still address 00:35:35.000-->00:35:40.292 some differences and uh some of the techniques that we used on IOS should be adapted for the 00:35:40.292-->00:35:45.292 watchOS And as for me eh the data forensic may be a little bit easier on the watch as on 00:35:47.583-->00:35:51.208 the phone because the phone has all the kernel patch protectors and like hardware restriction 00:35:51.208-->00:35:56.208 which watch doesn't have. Okay uhm basically we still have time for questions, yeah it was an 00:36:06.708-->00:36:10.500 apple watch jailbreak [applause]