1 00:00:00,000 --> 00:00:19,520 36c3 preroll 2 00:00:19,520 --> 00:00:25,990 Herald: To everybody here, please be welcome to this fantastic kid here. I 3 00:00:25,990 --> 00:00:31,249 learned a lot from him, even though he's only since two years playing around with 4 00:00:31,249 --> 00:00:37,380 iOS. I mentioned as well the first untethering case that I had with my phone 5 00:00:37,380 --> 00:00:44,010 was something about iOS 5.1 and with every update, you had to do the whole shebang 6 00:00:44,010 --> 00:00:50,910 again. Of course, that's what I remember. So please give a warm welcome here too 7 00:00:50,910 --> 00:00:54,470 littlelailo. Do I spell this correctly? Offscreen: Yeah. 8 00:00:54,470 --> 00:01:03,250 Herald: Yes, littlelailo is really a very fascinating geek. He actually hacks any 9 00:01:03,250 --> 00:01:08,610 kind of OS device, to my opinion. Any kind of. Yeah. So throw it to him and it comes 10 00:01:08,610 --> 00:01:14,390 back in pieces. He's as sharp as a knife. Please give him a warm, well, welcoming 11 00:01:14,390 --> 00:01:17,850 applause. We're gonna untether iOS. Yay! 12 00:01:17,850 --> 00:01:23,760 applause 13 00:01:23,760 --> 00:01:28,470 littlelailo: Okay, so yeah, I'm littlelailo, as already introduced. I'm 14 00:01:28,470 --> 00:01:34,120 interested in I.T. security in general. And I started to look into iOS about two 15 00:01:34,120 --> 00:01:40,670 years ago and then I met three awesome guys: @s1guza, @stek29 and @iBSparkes. And 16 00:01:40,670 --> 00:01:46,790 we basically started to chat a lot and in the end also released the "jailbreak me" 17 00:01:46,790 --> 00:01:50,950 for iOS 10 on https://totally- not.spyware.lol/. For everybody who isn't 18 00:01:50,950 --> 00:01:55,430 familiar with the jailbreak scene, it's like rooting on Android. So it basically 19 00:01:55,430 --> 00:02:02,420 is a tool that gives the user the capability to tweak the device, and that's 20 00:02:02,420 --> 00:02:06,170 mostly done by basically installing a jailbreak in this case. You just go to a 21 00:02:06,170 --> 00:02:07,920 website on the slide there [https://totally-not.spyware.lol/] and it 22 00:02:07,920 --> 00:02:12,490 will install a package manager on your phone and then the end user can install 23 00:02:12,490 --> 00:02:17,980 tweaks. So just a little dynamic libraries and they get injected into all the other 24 00:02:17,980 --> 00:02:21,500 system processes and then they can obviously modify their memory. And that, 25 00:02:21,500 --> 00:02:25,620 for example, allows customization of the home screen or something like that. And 26 00:02:25,620 --> 00:02:31,770 basically with the release, we also formed the team @Jakeblair420 was created with a 27 00:02:31,770 --> 00:02:35,070 Twitter account. There are also a few demos there if you want to check it out 28 00:02:35,070 --> 00:02:39,699 after the talk. And I basically had this pipe dream that in my life. I really want 29 00:02:39,699 --> 00:02:44,740 to achieve an untethered jailbreak using only some sort of plist or other save file 30 00:02:44,740 --> 00:02:49,890 corruption. So basically there are different kinds of jailbreaks. In modern 31 00:02:49,890 --> 00:02:54,480 jailbreak the most common kind are semi- untethered, which means that the users has 32 00:02:54,480 --> 00:02:59,580 to connect their device to a PC when they first install a jailbreak and then they 33 00:02:59,580 --> 00:03:04,250 sideload an app onto the device or it just installs itself there. And then on each 34 00:03:04,250 --> 00:03:09,160 reboot, the user has to go into the app and press a button to jailbreak the phone. 35 00:03:09,160 --> 00:03:14,370 And basically, after they reboot, they lose the jailbreak and have to go through 36 00:03:14,370 --> 00:03:19,510 this process again. And with an untethered jailbreak, the jailbreak gains persistent 37 00:03:19,510 --> 00:03:24,250 installation and then they will automatically jailbreak the device on each 38 00:03:24,250 --> 00:03:31,900 boot. So the device automatically boots jailbroke. The untether can be divided 39 00:03:31,900 --> 00:03:37,390 into four stages. The first stage is when the config file or database stage. I would go 40 00:03:37,390 --> 00:03:42,150 over how we gain execution of the boot. Then the config parser bug that gives us 41 00:03:42,150 --> 00:03:47,970 the right opey primitive. And then I will talk about the main bug, the ASLR bypass, 42 00:03:47,970 --> 00:03:53,090 which allows us to get into ROP. Then stage two is basically a kernel exploit 43 00:03:53,090 --> 00:03:58,360 and completely written in ROP and there I will go over the two main kernel bugs: the 44 00:03:58,360 --> 00:04:03,570 kASLR leak and then the racy double free we used to get the kernel read/write, and 45 00:04:03,570 --> 00:04:09,690 I will also talk about the kASLR weakness and RootDomain user client memory leak 46 00:04:09,690 --> 00:04:14,440 which aided us in exploitation. And after we get kernel read/write, we can remove a 47 00:04:14,440 --> 00:04:19,810 few restrictions from Apple. Mainly we can bypass code signing and that gives us the 48 00:04:19,810 --> 00:04:24,380 ability to load an unsigned dynamic library into our process. So now in stage 49 00:04:24,380 --> 00:04:30,210 3, we are basically C, we are dynamic library and there we are stashing the 50 00:04:30,210 --> 00:04:36,830 kernel task port to host special port 4. So iOS has this concept of ports and task 51 00:04:36,830 --> 00:04:41,770 ports. And basically, if you have a send right to a task port of a process, you can 52 00:04:41,770 --> 00:04:48,219 read and write its memory. They're most used for inter process communication. And 53 00:04:48,219 --> 00:04:53,409 where modern jailbreaks used to stash the kernel task port into a special port 4 so 54 00:04:53,409 --> 00:04:57,830 that other user mode applications can then retrieve it and with that retrieved and 55 00:04:57,830 --> 00:05:01,810 with send right they can just read and write process memory. And after that I 56 00:05:01,810 --> 00:05:07,740 just fix up everything and then spawn stage four and that's basically running in 57 00:05:07,740 --> 00:05:12,599 a separate process. That has a few advantages I will go into later. It's 58 00:05:12,599 --> 00:05:15,699 basically performing the whole post exploitation process, including launching 59 00:05:15,699 --> 00:05:19,689 substrate - the framework that's used for tweek injection and then performing 60 00:05:19,689 --> 00:05:24,099 ldrestart to restart or launch demons on the system and inject the tweaks into 61 00:05:24,099 --> 00:05:30,931 them. In stage 1, we first need to get execution after boot, and when iOS boots 62 00:05:30,931 --> 00:05:35,830 launchd is the first process that's running on the system and it then loads a 63 00:05:35,830 --> 00:05:41,871 dynamic library with a list of executables - that are LaunchDaemons - and there are a 64 00:05:41,871 --> 00:05:47,219 few flags associated with them. If the "run and load" flag is set, launchd will 65 00:05:47,219 --> 00:05:52,759 then spawn all of those LaunchDaemons afterwards. And we basically just take one 66 00:05:52,759 --> 00:05:58,591 of those launch demons, namely Racoon. So what is Racoon? Basically Racoon is part 67 00:05:58,591 --> 00:06:07,030 of the ipsec package. And it's a VPN client used to interact with an IPSec VPN 68 00:06:07,030 --> 00:06:13,919 server. And the problem is though, that IPsec-Tools project has been abandoned 69 00:06:13,919 --> 00:06:18,649 since 2014. So they officially here state on their website that the development of 70 00:06:18,649 --> 00:06:22,789 the project has been abandoned and that IPsec-Tools has security issues. You 71 00:06:22,789 --> 00:06:29,059 should not use it. Apple still decided it was a good idea to ship it after 2014 and 72 00:06:29,059 --> 00:06:34,680 they now maintain their own fork on https://opensource.apple.com . And yeah, 73 00:06:34,680 --> 00:06:39,099 basically the only thing that's important for the talk is that raccoon has a 74 00:06:39,099 --> 00:06:43,560 configuration parser. So on startup it will just look for a file on disk and 75 00:06:43,560 --> 00:06:49,080 start to parse that. And that's written in yacc so completely written in C. So memory 76 00:06:49,080 --> 00:06:53,789 corruption might become a problem. And it actually is a problem as we can see if the 77 00:06:53,789 --> 00:07:00,409 config parser bug and for that when we have to go back a bit. Basically in 2011 78 00:07:00,409 --> 00:07:08,619 Pod2g released Corona for iOS 5, which was also an untethered. He used a bug in 79 00:07:08,619 --> 00:07:15,699 Racoon in the configuration parser and Pod2g found this one on an old bug tracker 80 00:07:15,699 --> 00:07:20,789 and basically the IPsec website had this bug tracker there. There users could just 81 00:07:20,789 --> 00:07:27,460 report problems with their programs and one user in 2009 I think reported a bug 82 00:07:27,460 --> 00:07:31,509 that if he would use the specific config Racoon would just segfault, but nobody 83 00:07:31,509 --> 00:07:36,930 looked at this for two years. So in 2011 Pod2g realized that this was actually 84 00:07:36,930 --> 00:07:40,539 exploitable and then used in a jailbreak. And after that, obviously Apple got aware 85 00:07:40,539 --> 00:07:45,610 of it. And then they also said that they fixed it. And it's got a CV, assigned 86 00:07:45,610 --> 00:07:53,910 CVS-2012-2737. And yeah, they say that this was improved through improved bounds 87 00:07:53,910 --> 00:07:58,869 checking. So let's look at the patch. That's the function before the patch and 88 00:07:58,869 --> 00:08:03,249 that's the function after the patch. And if this was too fast for you, here's the 89 00:08:03,249 --> 00:08:07,559 diff. So basically there is no difference. The bug is still there and Apple didn't 90 00:08:07,559 --> 00:08:13,029 patch it. What really happened here was that basically this is obviously a 91 00:08:13,029 --> 00:08:17,529 configuration parser. So there are different statements that nearly do the 92 00:08:17,529 --> 00:08:22,610 same thing. There are these nbns4 statements to parse an IP address and 93 00:08:22,610 --> 00:08:27,180 there are wins4 statement followed by an IP address and both of them have to parse 94 00:08:27,180 --> 00:08:33,940 the IP address. So the function for parsing that was just copy pasted from 95 00:08:33,940 --> 00:08:41,130 another one. And yeah, basically Apple fixed the bug in the other function. Which 96 00:08:41,130 --> 00:08:47,520 I don't get because basically the engineer there had to look at PoC Pod2g provided 97 00:08:47,520 --> 00:08:51,250 then they had to realize okay, the bug is in there, fix it, then they had to 98 00:08:51,250 --> 00:08:55,050 recompile and never tested against the original PoC because otherwise Racoon 99 00:08:55,050 --> 00:08:59,620 would have crashed again. Yeah, it's basically an off by one which allows you 100 00:08:59,620 --> 00:09:05,640 to overwrite the index of an array and Pod2g gave a talk about this and we can 101 00:09:05,640 --> 00:09:11,390 basically reuse his strategy from back in 2011 to get a write primitive. 102 00:09:11,390 --> 00:09:16,730 Again, the one function here at the top. You can see the yacc syntax so an addrwins 103 00:09:16,730 --> 00:09:21,240 list has to consist of either an addrwins statement or addrwins statement followed 104 00:09:21,240 --> 00:09:25,600 by a comma, followed by an addrwins list. So that's a recursion. There can be 105 00:09:25,600 --> 00:09:31,020 multiple addrwins statements in a row. And then below that, an addrwins statement is 106 00:09:31,020 --> 00:09:35,390 defined as containing an address string. And that's just a regex to match an IP 107 00:09:35,390 --> 00:09:38,950 version 4 address. And if the parcel finds that it would run the code between those 108 00:09:38,950 --> 00:09:44,480 two brackets. So they get the pointer to a global struct and then they check if this 109 00:09:44,480 --> 00:09:50,500 nbns4_index is bigger than MAXWINS and if so, they return an error. The problem here 110 00:09:50,500 --> 00:09:54,620 is that this is off by 1. It shouldn't be checking if it's greater than so, but it 111 00:09:54,620 --> 00:09:58,440 should be a check for greater or equal than MAXWINS. And after that, they use 112 00:09:58,440 --> 00:10:03,090 thisinet_pton function to basically parse the address, which is in this variable 113 00:10:03,090 --> 00:10:10,130 into the nbns4 array at the nbns4 index and then post-increment the index. And 114 00:10:10,130 --> 00:10:13,990 that will also be coming in handy when exploiting this bug. So yeah. How is 115 00:10:13,990 --> 00:10:18,740 exploitation done? Basically there are here the globals, there is this Lcconfig 116 00:10:18,740 --> 00:10:23,610 pointer in the globals pointing to a heap structure and that the parser also uses. 117 00:10:23,610 --> 00:10:29,670 And then there is this dns4 array followed by the dns_area_index and then the nbns4 118 00:10:29,670 --> 00:10:35,341 array followed by the nbns_4_array_index so we can just use mode_cfg statement 119 00:10:35,341 --> 00:10:39,270 followed by this wins4 statement with the IP address to parse the IP address in the 120 00:10:39,270 --> 00:10:44,630 first array element and we can repeat this process four times to then move the index 121 00:10:44,630 --> 00:10:49,680 out of bounds. So now it's pointing to itself and the cool thing is about that is 122 00:10:49,680 --> 00:10:53,910 that therefore there would be a good idea to use integers for those area indexes 123 00:10:53,910 --> 00:10:59,110 instead of unsigned integers so we can just point them... you just use negative 124 00:10:59,110 --> 00:11:04,260 numbers to bypass the bounds check. So we'll overwrite it with -1 to point it to 125 00:11:04,260 --> 00:11:09,110 an dns_array_index and then we use another wins statement to override the 126 00:11:09,110 --> 00:11:13,130 dns_array_index with a negative number. And the cool thing about this is that 127 00:11:13,130 --> 00:11:16,400 because of the post-incrementation, it will move it back to zero so we can repeat 128 00:11:16,400 --> 00:11:20,760 this process as often times as we want, and we will use a negative number to 129 00:11:20,760 --> 00:11:24,740 basically point it to the Lcconfig pointer. And then we can use two dns4 130 00:11:24,740 --> 00:11:28,940 statements to override the Lcconfig pointer and point it anywhere in memory. 131 00:11:28,940 --> 00:11:34,660 And after that we can use a timer statement with a counter. Then the 132 00:11:34,660 --> 00:11:39,510 parsible just tried to write it to the Lcconfig structure so it will de-reference 133 00:11:39,510 --> 00:11:44,200 our pointer and write it there and the interval statement will basically write to 134 00:11:44,200 --> 00:11:49,740 an uint32, which is followed by the uint where the counter statement is written so 135 00:11:49,740 --> 00:11:53,500 we can turn this into a 64 bit write anywhere primitive and write anywhere in 136 00:11:53,500 --> 00:11:59,560 process memory and that gives us an ability to basically exploit the ASLR 137 00:11:59,560 --> 00:12:05,030 bypass. So this is the main bug of the whole untethered and allows us to 138 00:12:05,030 --> 00:12:10,350 basically have this primitive. And it's also the reason why I decided to give this 139 00:12:10,350 --> 00:12:14,530 talk this year and not last year, because there the bug was pretty fresh and only 140 00:12:14,530 --> 00:12:20,550 patched in iOS 12 and it gives to an attacker the ability to exploit zero click 141 00:12:20,550 --> 00:12:23,680 more easily because they just need the write anywhere primitive. And that's why I 142 00:12:23,680 --> 00:12:29,740 held back on it. Siguza found it after looking into Apple's patches of the Corona 143 00:12:29,740 --> 00:12:35,410 ASLR bypass and basically from Pod2g's presentation, we as a team learned that 144 00:12:35,410 --> 00:12:40,160 ASLR is always bypassed when a writable region is larger than the maximum slide, 145 00:12:40,160 --> 00:12:45,100 because then there's always a writable address in process memory and you can use 146 00:12:45,100 --> 00:12:51,230 this to brute force the slide and Siguza found out that there was what was also the 147 00:12:51,230 --> 00:12:56,680 same problem with the cache in iOS 11 and a few versions of iOS 10 actually. So 148 00:12:56,680 --> 00:13:02,200 what's the cache? Basically, the cache is a pre compiled blob containing the dynamic 149 00:13:02,200 --> 00:13:07,550 link libraries from Apple. So on each released, you just move all of those into 150 00:13:07,550 --> 00:13:13,430 one big file to optimize load times of apps and keep memory pressure low. So it's 151 00:13:13,430 --> 00:13:19,230 a pretty big file. And for that on boot the kernel needs to calculate a slide and 152 00:13:19,230 --> 00:13:23,940 slide it in memory. But they only slide it once on boot because it's used in every 153 00:13:23,940 --> 00:13:30,070 process. And so Apple defines an area of memory for the cache with a base address 154 00:13:30,070 --> 00:13:35,890 and the size and that's hardcoded on iOS 11. The cache got so big that a maximum 155 00:13:35,890 --> 00:13:42,630 slide is now smaller than its data segment. So the conditioning is satisfied 156 00:13:42,630 --> 00:13:47,910 and ASLR can be bypassed, basically. And the weird thing about this is that 157 00:13:47,910 --> 00:13:54,040 actually the same thing also happened in iOS 7. Back then, the size was defined as 158 00:13:54,040 --> 00:13:58,220 500 megabytes and the cache got bigger than 500 megabytes. But before that, it 159 00:13:58,220 --> 00:14:02,650 was also in a few versions possible to have the same condition that the data 160 00:14:02,650 --> 00:14:06,910 segment again was bigger than the maximum slide. And Apple was actually also aware 161 00:14:06,910 --> 00:14:11,150 of this because Acer talked about it in one of his talks, but they just 162 00:14:11,150 --> 00:14:15,950 increased the maximum slide to 1 gigabyte and didn't edit any asserts. And now in 163 00:14:15,950 --> 00:14:22,240 iOS 11, it again got so big that the same thing happened. And we believe that they 164 00:14:22,240 --> 00:14:27,380 didn't even really notice that up until iOS 12 where the cache was now bigger than 165 00:14:27,380 --> 00:14:31,150 1 gigabyte so the kernel just couldn't fit it in the memory region and paniced. And 166 00:14:31,150 --> 00:14:35,250 because of that they just thought well, then we will increase it to 4 gigabyte 167 00:14:35,250 --> 00:14:41,140 while developing so we might see this reoccurring in I don't know, iOS 15 or 168 00:14:41,140 --> 00:14:47,300 something like that. Exploitation is also pretty simple. We can just brute force the 169 00:14:47,300 --> 00:14:52,210 slide now and there are a lot of function pointers in the data segment. So we 170 00:14:52,210 --> 00:14:58,550 decided to go with __platform_mem_move because we can reach it via strlcpy from 171 00:14:58,550 --> 00:15:02,730 the conflict parser. And the basic strategy behind this is we write a slid 172 00:15:02,730 --> 00:15:08,640 rop chain into an address we can always write to for a specific slide abc and then 173 00:15:08,640 --> 00:15:13,220 we overwrite the __platform_mem_move pointer at its unslid address plus the 174 00:15:13,220 --> 00:15:19,590 slide we just chose with a gadget that would pivot to our slid rop chain and then 175 00:15:19,590 --> 00:15:25,550 we call strlcpy. And now there are basically two possibilities. Either we 176 00:15:25,550 --> 00:15:30,220 guessed the right slide and then we jump to our gadget and pivot the stack or we 177 00:15:30,220 --> 00:15:33,500 guessed the wrong slide. But obviously nothing happened because we can just write 178 00:15:33,500 --> 00:15:38,540 there so we can go back to step one and try again. And then with that we can just 179 00:15:38,540 --> 00:15:41,650 brute force the slide till we get the right one. The catch with this, however, 180 00:15:41,650 --> 00:15:45,590 is that the write what were is pretty slow and it also needs a lot of storage. So for 181 00:15:45,590 --> 00:15:53,461 a 64 bit write I need about 120 bytes in the config file. And because there are so 182 00:15:53,461 --> 00:16:01,720 many possible slide values, the chain I have currently is around... it's only to 183 00:16:01,720 --> 00:16:07,010 rop gadgets, but the config file is already 12 megabytes, I think. And because 184 00:16:07,010 --> 00:16:11,490 of that, it takes around 10 seconds to run if it's a really bad slide. So the rop 185 00:16:11,490 --> 00:16:16,050 chain has to be as short as possible. And the other problem is that if we have a bad 186 00:16:16,050 --> 00:16:19,570 slide, we will basically smash the whole data segment and we can't really recover 187 00:16:19,570 --> 00:16:23,520 from that. So we had crashes in malloc and stuff like that while developing, 188 00:16:23,520 --> 00:16:27,650 basically. There are some solutions to that, we can have a really short rop chain 189 00:16:27,650 --> 00:16:34,100 in stage one and we can achieve this by basically just opening the big cache file 190 00:16:34,100 --> 00:16:39,440 to get a file descriptor to it and then we can map it at a static address and then 191 00:16:39,440 --> 00:16:43,300 get many gadgets there because the file is obviously code signed by Apple so we can 192 00:16:43,300 --> 00:16:47,900 just jump there after mapping it. But the problem with that is that nothing is set 193 00:16:47,900 --> 00:16:53,110 up. So malloc and other functions aren't working. But as I said earlier, the 194 00:16:53,110 --> 00:16:57,830 current cache has a smashed data segment so we don't really lose anything. And 195 00:16:57,830 --> 00:17:01,530 after having the cache at a static address we can use the open and mmap functions 196 00:17:01,530 --> 00:17:05,569 from that cache to basically map stage two into the process memory and stage two is 197 00:17:05,569 --> 00:17:16,480 just a really big rop stack. So, yeah. And then we are basically in ROP, but we can 198 00:17:16,480 --> 00:17:21,200 only use raw syscalls and not much more because everything else will either use a 199 00:17:21,200 --> 00:17:26,449 function that uses malloc or will use malloc on it's own. And the other problem 200 00:17:26,449 --> 00:17:30,360 is that basically errno is also broken. So every syscall which fails will crush the 201 00:17:30,360 --> 00:17:35,110 binary. So the first thing I do is basically map a few pages so that errno 202 00:17:35,110 --> 00:17:40,610 works again because we have a few syscalls that might fail. And then the other big 203 00:17:40,610 --> 00:17:45,150 problem is that we now need to implement the whole kernel exploit in rop. So I 204 00:17:45,150 --> 00:17:50,480 start to write a framework around this awesome gadget which is present in all the 205 00:17:50,480 --> 00:17:54,059 cache versions I looked at. Basically at the top you can see that all the high 206 00:17:54,059 --> 00:18:00,559 registers are moved into x0 through x7. So all the registers used for the calling 207 00:18:00,559 --> 00:18:07,610 convention are and then we branch with link to register based on x27. So also 208 00:18:07,610 --> 00:18:11,950 high register. And after that we load all the register values back from the stack so 209 00:18:11,950 --> 00:18:16,749 we can just chain those gadgets together to call any functions. You basically rop 210 00:18:16,749 --> 00:18:22,309 into the lower half and then chain another one of those afterwards and then they can 211 00:18:22,309 --> 00:18:26,889 load all the values, call the function and then load all the values from the stack 212 00:18:26,889 --> 00:18:32,399 again. And that's how the whole rop chain works. So yeah, I also used another gadget 213 00:18:32,399 --> 00:18:37,480 to basically add two registers together and another one which stores x0 so that I 214 00:18:37,480 --> 00:18:42,799 can store the return value on the stack and later reuse it. And for loops I use a 215 00:18:42,799 --> 00:18:46,950 gadget which just returns if x0 is zero. So it's basically just a read instruction 216 00:18:46,950 --> 00:18:51,300 then and otherwise it will tail call a function using function pointer from the 217 00:18:51,300 --> 00:18:54,890 data segment. And because I can control the whole data segment, I can just put a 218 00:18:54,890 --> 00:19:00,230 function pointer there that that will then jump to an epilog and misasligning the stack 219 00:19:00,230 --> 00:19:05,119 with that. And then I can call longjmp with two different register values and 220 00:19:05,119 --> 00:19:10,399 because of that pivot the stack to another location. And when we basically didn't 221 00:19:10,399 --> 00:19:16,399 jump outside of the loop, I just mmap the part of stage 2 which has the loop in it 222 00:19:16,399 --> 00:19:23,050 back over old stack again. And then I can just reuse to stack every time. And then 223 00:19:23,050 --> 00:19:27,529 pivot up using longjup. The problem wih this, however, is obviously that it's 224 00:19:27,529 --> 00:19:33,590 pretty slow because I use mmap as a syscall. But this can be solved by just 225 00:19:33,590 --> 00:19:38,980 unrolling your loops like for 10 iterations and then mmapping the file so 226 00:19:38,980 --> 00:19:43,390 that I get more loop iterations basically per second, which is important for the 227 00:19:43,390 --> 00:19:52,310 race. So now we will go over the kernel bug so the kASLR leak is CVS-2018-4413 by 228 00:19:52,310 --> 00:19:58,130 panicall. It was fixed in iOS 12.1 and it's luckily reachable from the Racoon 229 00:19:58,130 --> 00:20:03,289 sandbox because Apple is sandboxing most userland processes and the Racoon sandbox 230 00:20:03,289 --> 00:20:08,390 is really tight. We didn't have that much, many bugs that would work in Racoon, but 231 00:20:08,390 --> 00:20:14,510 luckily this one does because Racoon has access to the sysctl functions and this 232 00:20:14,510 --> 00:20:20,240 one is in the sysctl_progargsx function. The progargsx function basically allocates 233 00:20:20,240 --> 00:20:25,500 a page using kmem_alloc. But it doesn't zero it so it might contain old heap data 234 00:20:25,500 --> 00:20:30,889 and then they copy the process arguments to the front of the page. And now if you 235 00:20:30,889 --> 00:20:35,139 supply a wrong size from user space and there are a few other conditions that have 236 00:20:35,139 --> 00:20:40,059 to be met for some weird reason it copies from the end of the page into user space 237 00:20:40,059 --> 00:20:44,559 which I don't get why does this even get by code review. But here's a graphical 238 00:20:44,559 --> 00:20:49,909 illustration: there is basically this page is full of uninitialized data and then 239 00:20:49,909 --> 00:20:53,240 they put the process arguments in the front and copy out uniinitialized heap 240 00:20:53,240 --> 00:20:58,909 data from the back into user land and we can obviously just spray specific heap 241 00:20:58,909 --> 00:21:04,429 objects with kernel pointers in them and then free them again and use this 242 00:21:04,429 --> 00:21:08,191 primitive to maybe leak them. And if we find a kernel pointer in there, we can 243 00:21:08,191 --> 00:21:15,379 just calculate this kernel slide. So yeah. And then we come to the racy double free. 244 00:21:15,379 --> 00:21:19,679 As I said, the main problem of the untether is the racoon sandbox, so many of 245 00:21:19,679 --> 00:21:24,720 the kernel bugs that would work in iOS 11 from an app, didn't work from racoon. But 246 00:21:24,720 --> 00:21:30,080 luckily on Halloween Sparky told me about Lightspeed bug from Synacktiv, which is 247 00:21:30,080 --> 00:21:35,960 reachable from the sandbox. It's a double free in kalloc.16. The kernel allocator's 248 00:21:35,960 --> 00:21:42,879 based on zones and with different sizes. So there's, for example, kalloc.16 and 249 00:21:42,879 --> 00:21:47,270 then all objects in that zone have a size of 16 or less bytes and they are obviously 250 00:21:47,270 --> 00:21:55,460 also other zones for bigger objects. And basically there is a structure in there 251 00:21:55,460 --> 00:22:00,690 that then gets doubled. And there is the syscall that's handling async file events. 252 00:22:00,690 --> 00:22:04,370 So a user mode application can just call it and tell the kernel, hey, please write 253 00:22:04,370 --> 00:22:09,720 a buffer to a file and then move on with execution and it uses a kernel thread to 254 00:22:09,720 --> 00:22:13,639 perform those. And for that, that basically allocates a structure to contain 255 00:22:13,639 --> 00:22:18,330 some metadata like where the buffer is and to which file it should write, and the 256 00:22:18,330 --> 00:22:23,590 kernel thread obviously has to free the structure after it's done because it just 257 00:22:23,590 --> 00:22:27,850 gets into the query for the kernel thread, that then wakes up and 258 00:22:27,850 --> 00:22:33,000 maybe sees it has a new job, then performs the operation and then it has to free it, 259 00:22:33,000 --> 00:22:36,450 otherwise it will leak. But the problem here is that if an error occurred while 260 00:22:36,450 --> 00:22:41,419 setting the structure up, the second field in the structure will be zero. And then 261 00:22:41,419 --> 00:22:46,440 the structure also isn't included into the jobs list. So the kernel thread will never 262 00:22:46,440 --> 00:22:51,460 wake up and look at it. So the syscall has to free it because otherwise it will leak. 263 00:22:51,460 --> 00:22:55,100 And the problem here is that we can basically reallocate the structure before 264 00:22:55,100 --> 00:22:58,929 the syscall checks. So what happens here is that the syscall allocates the 265 00:22:58,929 --> 00:23:04,400 structure, fills it up, and then it gets added to the list and then the kernel 266 00:23:04,400 --> 00:23:09,999 thread is so fast that it runs while the syscall isn't finished yet and basically 267 00:23:09,999 --> 00:23:17,780 gets the gets the job done and frees it. And then we can spray heap objects pretty 268 00:23:17,780 --> 00:23:22,980 fast to overlay with that structure. And then the syscall finishes and checks the 269 00:23:22,980 --> 00:23:27,619 field and sees that it's zero because we just replaced it with an object that has 270 00:23:27,619 --> 00:23:32,749 zero at that location so it frees it again leading to a double free. And yeah, we can 271 00:23:32,749 --> 00:23:38,909 obviously exploit it. So for exploitation I just spam the syscall on one thread 272 00:23:38,909 --> 00:23:42,869 which is pretty hard to do in ROP, but I just call threadCreate. We've appointed 273 00:23:42,869 --> 00:23:46,970 two long jump and then pivot the stack to the application and then in the other 274 00:23:46,970 --> 00:23:52,930 thread I spray Mach messages with MACH_PORT_NULL in it. And the thing with 275 00:23:52,930 --> 00:23:58,590 Mach messages is they can be used to do inter-process communication and you can 276 00:23:58,590 --> 00:24:03,350 also transfer port rights from one process to another. So in this case we just send 277 00:24:03,350 --> 00:24:07,709 an empty port, but you could also place something else there and that will create 278 00:24:07,709 --> 00:24:14,289 a structure and kalloc.16 containing zero at that location. And and then if the Mach 279 00:24:14,289 --> 00:24:18,690 message gets freed, we can replace it with something and basically point it to 280 00:24:18,690 --> 00:24:22,859 somewhere in kernel where fake port structure lives. And when we receive the 281 00:24:22,859 --> 00:24:26,809 Mach message again, it will basically think that this is a real port and treat 282 00:24:26,809 --> 00:24:32,600 it as such. And with that we can create a fake kernel task port. But for that we 283 00:24:32,600 --> 00:24:38,409 obviously need to replace it and we need to heap spray. And most commonly iOS 284 00:24:38,409 --> 00:24:43,519 surface is used for that as a kernel extension, but because of our sandbox we 285 00:24:43,519 --> 00:24:48,419 are so limited that we don't have iOS surface access. So the question is how we 286 00:24:48,419 --> 00:24:54,310 actually spray and the rootDomainUserClient comes to rescue with 287 00:24:54,310 --> 00:25:01,179 a memory leak. So actually this function secureSleepSystemOptions is reachable from 288 00:25:01,179 --> 00:25:07,020 the raccoon sandbox and Apple has a way of basically passing data to the kernel via 289 00:25:07,020 --> 00:25:12,850 XML. So a userland application can just pass the XML to the kernel and then they 290 00:25:12,850 --> 00:25:18,039 will use this OSUnserializeXML function to turn the XML back into C++ objects which 291 00:25:18,039 --> 00:25:21,789 the kernel can then use. And if this sounds dangerous to you, it actually is. 292 00:25:21,789 --> 00:25:27,549 There were a few bugs in that. But in this case we basically this just makes sure 293 00:25:27,549 --> 00:25:33,309 with the OSDynamicCast that the data the user mode application supplied isn't 294 00:25:33,309 --> 00:25:38,499 always dictionaries so that it can use it afterwards. And the problem here is that 295 00:25:38,499 --> 00:25:44,130 we can basically just OSDataObject or an always OSArray. So this OSDynamicCast 296 00:25:44,130 --> 00:25:48,899 will fail and serialized options will become null. But the original point of 297 00:25:48,899 --> 00:25:55,570 return from OS under the XML will get lost and so we will leak that memory and we 298 00:25:55,570 --> 00:26:02,010 can just use this for spraying. So then about those two primitives, I will use to 299 00:26:02,010 --> 00:26:06,860 basically exploitation. The case law weakness, Darrell Justice CCL buffers and 300 00:26:06,860 --> 00:26:10,980 they are located in the kernel data region and because of that they are stacked with 301 00:26:10,980 --> 00:26:17,080 the same slide as the kernel text region. And this means that as long as we know the 302 00:26:17,080 --> 00:26:21,159 kernel slide we already do, that from the case of largely and we can control the 303 00:26:21,159 --> 00:26:27,659 contents of a CCL buffer and we can get data to a known address and we can easily 304 00:26:27,659 --> 00:26:33,010 do that with racoon because it runs US route. And so we can just switch all of 305 00:26:33,010 --> 00:26:37,320 this of CCL buffer, for example, place the same point structure there will be later. 306 00:26:37,320 --> 00:26:44,369 Also, place a fake trust constructively, but I will get into that. So yeah, now we 307 00:26:44,369 --> 00:26:49,869 can use that primitive to basically spray tan or state objects pointing to the CCL 308 00:26:49,869 --> 00:26:53,739 buffer. And then we just received the message again and check if the polls are 309 00:26:53,739 --> 00:27:00,120 now. And if that's the case, we best place the structure. And then for the non SMP 310 00:27:00,120 --> 00:27:04,830 version we can even get the case load by traversing a few pointers. But that's not 311 00:27:04,830 --> 00:27:10,710 needed for SMP Version because there we already got it with the case logic but 312 00:27:10,710 --> 00:27:15,039 young, Non CCL IP devices, we also don't need a CCL buffers because we can just 313 00:27:15,039 --> 00:27:20,110 place the fake port structure and use the land and then we get the kernel slide this 314 00:27:20,110 --> 00:27:24,090 way. And with the kernel slide and this fake port, we can create a fake user 315 00:27:24,090 --> 00:27:28,789 client and from there we can create a called primitive and then we can use this 316 00:27:28,789 --> 00:27:33,539 to override that pierce's trusses pointer and pointed to a buffer with two hashes 317 00:27:33,539 --> 00:27:38,179 and four stage 3 and stage 4. So basically Apple has two ways of doing code signing. 318 00:27:38,179 --> 00:27:42,749 Either it has a used land daemon that verifies third party applications or a 319 00:27:42,749 --> 00:27:48,110 test, so-called trust cache, which is a list of hashes from all of their system 320 00:27:48,110 --> 00:27:54,279 applications. And as soon as the process spawned or dynamic link library is loaded 321 00:27:54,279 --> 00:27:59,309 and they will basically first verify if the hash of that file is inside of the 322 00:27:59,309 --> 00:28:02,800 trust cache. And if so, they will just trust a binary blindly because it comes 323 00:28:02,800 --> 00:28:07,309 from Apple, basically. And now when we override this trust cache point and 324 00:28:07,309 --> 00:28:13,769 pointed to our buffer, we can basically place the hash of stage 3 and 4 there. And 325 00:28:13,769 --> 00:28:20,000 then the system will think those are apple binaries and we can just load them. So. 326 00:28:20,000 --> 00:28:24,470 Yeah. And for that we need to use a geter open. We can't use the real deal open 327 00:28:24,470 --> 00:28:29,779 because that uses malock. So we just open stage 3 to get a file descriptor. 328 00:28:29,779 --> 00:28:34,440 Then we attached a signature which now succeeds as the caches and trust cache and 329 00:28:34,440 --> 00:28:39,559 then we can map it as read executed and jump there. And then we are after two 330 00:28:39,559 --> 00:28:46,099 months of writing options. We are finally in C and we can write code more easily. 331 00:28:46,099 --> 00:28:51,229 And the problem there is that we still don't have a working cache. So we are 332 00:28:51,229 --> 00:28:57,220 still limited to the basic functionality and because of the ghetto dlopen link is 333 00:28:57,220 --> 00:29:02,599 obviously not working. So we just rely on raw as somebody follows syscalls. And I 334 00:29:02,599 --> 00:29:07,910 also pass some function pointers which I already use for stage 2. So for example, 335 00:29:07,910 --> 00:29:13,700 open and a map to stage 3. And from there we remove the con task and session into 336 00:29:13,700 --> 00:29:20,759 our special port 4 so that other user mode applications can use it. And then we can 337 00:29:20,759 --> 00:29:24,510 basically escape the sandbox by removing the sandbox label in the process 338 00:29:24,510 --> 00:29:30,700 structure, so that we can launch a new binary, because otherwise the raccoons and 339 00:29:30,700 --> 00:29:35,350 bugs doesn't allow it. But in the kernel, those process structures basically have 340 00:29:35,350 --> 00:29:39,009 this label, which tells the kernel of which sandbox to use. And as you're doing 341 00:29:39,009 --> 00:29:45,539 it, you can just tell it to not use any samples. And and then we can launch stage 342 00:29:45,539 --> 00:29:49,799 3, 4 and with that, get a working cashback. And that's the big advantage 343 00:29:49,799 --> 00:29:55,359 from like having a separate file. We now have the full cache functions working and 344 00:29:55,359 --> 00:30:01,480 can do work more easily. And then I it's just called two opposing spawn and then a 345 00:30:01,480 --> 00:30:06,449 raw exit. This to exit the daemon without crashing because of launch. You would see 346 00:30:06,449 --> 00:30:10,610 that one of the launch demons crashed and the specifics flag inside it would try to 347 00:30:10,610 --> 00:30:14,340 restart it. And then our option would run again. We obviously want to prevent that. 348 00:30:14,340 --> 00:30:21,449 So we use the exits as call to exit it. And then we are in stage 4. And from my 349 00:30:21,449 --> 00:30:25,780 side, that was just basically to block or signal. So we don't get killed by launchd. 350 00:30:25,780 --> 00:30:31,110 Because when launchd the launch and exits, it will send the kill to all this 351 00:30:31,110 --> 00:30:35,520 child process. And I need to catch that. Otherwise Stage 4 would get killed. And 352 00:30:35,520 --> 00:30:40,250 then I just called the Post Exploitation Framework, which was written by Sparky. 353 00:30:40,250 --> 00:30:45,200 And basically that does the following. It first elevates the process to root with 354 00:30:45,200 --> 00:30:50,220 current credentials, then it performs a remount of the root file system because on 355 00:30:50,220 --> 00:30:56,249 stock IOS, a file system was mounted as read only and we obviously need to 356 00:30:56,249 --> 00:31:01,470 mount it as read/write to modify some files on there and then set non it sets the 357 00:31:01,470 --> 00:31:06,589 nonce so that the user might be able to downgrade to an older version if they are 358 00:31:06,589 --> 00:31:12,099 flops. Verifies that the bootstrap was in place from the installation. And then 359 00:31:12,099 --> 00:31:17,450 checked substrates or the framework that's used for them to perform tweak injection 360 00:31:17,450 --> 00:31:23,599 and it's plugging into trust us and starts them so that they can start to inject into 361 00:31:23,599 --> 00:31:27,870 newly spawn processes. Then it's Ponce or the launch demons associate with the 362 00:31:27,870 --> 00:31:33,520 jailbreak and unloads or own demons so that we don't respawned by extended 363 00:31:33,520 --> 00:31:38,809 run. They kernel exploit again and then performs an LUV start to basically restart 364 00:31:38,809 --> 00:31:43,649 all of the launch teams off the system so that subset can inject 3 STEM. And with 365 00:31:43,649 --> 00:31:49,009 that the system is faulty, jail broken and we can perform a few cleanup steps. But 366 00:31:49,009 --> 00:31:52,750 yeah, basically the end user has jailebroken system. Then as a little 367 00:31:52,750 --> 00:31:58,240 side note while we are testing all the demons, we got killed by jetsam a lot. So 368 00:31:58,240 --> 00:32:02,769 basically jetsam is the kernel extension from Apple. That is therefore 369 00:32:02,769 --> 00:32:08,349 memory management. And they basically want to make sure the user mode application 370 00:32:08,349 --> 00:32:12,909 doesn't use too much memory because they don't have that much on iPhone. And on all 371 00:32:12,909 --> 00:32:19,019 the iPhones, actually. So there is this list and jetsam, it jetsam seems easier to 372 00:32:19,019 --> 00:32:24,909 use than process uses more than read and should use. It would just kill it. So we 373 00:32:24,909 --> 00:32:29,500 changed the values in the plist under LaunchDaemons to actually allow the 374 00:32:29,500 --> 00:32:33,820 LaunchDaemons to use more memory. But the weird thing about this is that this 375 00:32:33,820 --> 00:32:39,479 actually got us accepted by jetsam and we had normal crashes while Apple actually 376 00:32:39,479 --> 00:32:46,719 tried to mitigate that beforehand. So because jailbreak is always modify those 377 00:32:46,719 --> 00:32:50,359 configuration files on the LaunchDaemons, they start to move all of them into a 378 00:32:50,359 --> 00:32:54,489 dynamic library to guard them under code signing. So the jailbreak just couldn't 379 00:32:54,489 --> 00:32:59,330 change them anymore. But when you tried to figure out the Launchdemon at the Launch 380 00:32:59,330 --> 00:33:06,031 Demons, we dumped the dylib and ahm there was also plist embedded for 381 00:33:06,031 --> 00:33:12,429 Jetsam, but Apple was still using those files on disk. So I really want to look 382 00:33:12,429 --> 00:33:16,299 further into this because it seems like Apple isn't always ignoring those 383 00:33:16,299 --> 00:33:22,409 configurations files on disk. And then thanks to the whole team. Siguza, Sparkey, 384 00:33:22,409 --> 00:33:27,739 and Stek for bouncing ideas back and forth and writing the many part of the 385 00:33:27,739 --> 00:33:35,299 jailbreak. Then for Pod2g, Synacktiv for the kernel bugs. And basically also a big 386 00:33:35,299 --> 00:33:39,519 thanks to Saurik for substrate and the whole jailbreaking framework and for 387 00:33:39,519 --> 00:33:43,240 Swaggo, parrorgeek and Samg_is_a_Ninja for testing a few things and keeping 388 00:33:43,240 --> 00:33:49,359 motivated. And for Jonathan Levin for his books basically because he bought a few 389 00:33:49,359 --> 00:33:54,720 awesome books about IOS and that got me into it two years ago. And yeah. And in 390 00:33:54,720 --> 00:33:59,919 the future, I think exploiting kernel vulnerability with other cache functions 391 00:33:59,919 --> 00:34:05,400 and owning ROP really is a pain and that probably won't do it again. Because he's 392 00:34:05,400 --> 00:34:12,770 spent most of that. But yeah, the other big problem now is that with a 12 so the 393 00:34:12,770 --> 00:34:18,850 new iPhones pack. So point authentication kills most of these types of exploits 394 00:34:18,850 --> 00:34:23,419 because the problem there is that you would now need an ASLA bypass and the pack 395 00:34:23,419 --> 00:34:30,130 bypass to get into return oriented programing. And it's pretty unlikely to 396 00:34:30,130 --> 00:34:36,690 basically have both. And because Pegg bypasses are really rare and yet I only 397 00:34:36,690 --> 00:34:43,380 know about this one is a LA bypass. So you would have to get pretty lucky. Also un- 398 00:34:43,380 --> 00:34:48,460 tethering gets progressively harder. Apple just fixed another good idea ahead in iOS 399 00:34:48,460 --> 00:34:55,640 13.1. Basically the idea was to use printf with the format string format modify 400 00:34:55,640 --> 00:35:01,170 '%n' to get a Turing complete machine because printf, this modifier 401 00:35:01,170 --> 00:35:08,170 is basic Turing complete and then you start to develop a pack bypass basically 402 00:35:08,170 --> 00:35:14,130 and get them to ROP. But now we're in IS 13.1. I think Apple actually removed the 403 00:35:14,130 --> 00:35:19,830 '%n' modifier, so you can no longer do this. And yeah. So this idea is 404 00:35:19,830 --> 00:35:24,730 also gone. And yeah. In the end, I was able to complete my pipe dream, so I guess 405 00:35:24,730 --> 00:35:31,160 I will need a new one. So watch out, Apple and that spice. Are there any questions? 406 00:35:31,160 --> 00:35:41,090 Applause 407 00:35:41,090 --> 00:35:45,400 Herald: Thank you, littlelailo for is fantastic work. I suppose we're going to 408 00:35:45,400 --> 00:35:49,790 hear more from you in the future. Littlelailo: Maybe. 409 00:35:49,790 --> 00:35:54,940 Herald: Are there questions here in this audience. No one who wants to hire 410 00:35:54,940 --> 00:36:01,650 this guy now right away. No one. No one. Can you describe to me what change 411 00:36:01,650 --> 00:36:09,190 actually do times in these, you know, all the ASICs? Oh, yeah. Oh, yes. versions. 412 00:36:09,190 --> 00:36:11,500 Littlelailo: Well what they change to make. 413 00:36:11,500 --> 00:36:17,030 Herald: Yeah. What. Plus, you know, I told you like I started the tethering challenge 414 00:36:17,030 --> 00:36:20,360 actually at 5.1. Littlelailo: Well, they added a lot new 415 00:36:20,360 --> 00:36:25,930 mitigations and also obviously pitched a few bugs like for example, those ASLR 416 00:36:25,930 --> 00:36:31,620 bypasses that posterity used in Corona got patched. And this one also now got 417 00:36:31,620 --> 00:36:37,660 patched by accident. But yeah, I mean like some bugs are still there. For example, 418 00:36:37,660 --> 00:36:42,120 the Bug in racoon and the conflict pass. The bug is still an all day. But yeah, I 419 00:36:42,120 --> 00:36:47,840 don't really care about it. And the kernel bugs got patched by Apple. But for 420 00:36:47,840 --> 00:36:52,590 example, this synthetic one, they also also patched wrong by accident. And now it 421 00:36:52,590 --> 00:36:55,800 always leaked the strike. But I think they also fixed that now. 422 00:36:55,800 --> 00:36:59,740 Herald: Your team, you you're mentioning your team. You're working not on 423 00:36:59,740 --> 00:37:01,740 your own, of course. Littlelailo: No. 424 00:37:01,740 --> 00:37:05,820 Herald: And how would you restructured? How are the roles divided? How was... 425 00:37:05,820 --> 00:37:10,740 Littlelailo: Well, we are just like four people. So and we have this group chat and 426 00:37:10,740 --> 00:37:14,860 then we are just hanging out there and bouncing ideas back and forth and maybe 427 00:37:14,860 --> 00:37:17,640 working on some stuff. Herald: A close contact with the Apple 428 00:37:17,640 --> 00:37:22,280 developers. Littlelailo: No, not at all. 429 00:37:22,280 --> 00:37:25,870 Herald: More. Littlelailo: I mean, I reported one bug to 430 00:37:25,870 --> 00:37:31,890 their bounty once or like actually says to them that their bounty and that one got 431 00:37:31,890 --> 00:37:40,770 fixed and it was all fine. But yeah, for now, I don't report bugs at the moment. 432 00:37:40,770 --> 00:37:44,020 Herald: If you have time, you've time left now actually, you're looking for a new 433 00:37:44,020 --> 00:37:46,560 project doesn't it? Littlelailo: Yeah. Yeah. And I might 434 00:37:46,560 --> 00:37:50,290 report some of those bugs in the meantime but I mean with the presentation they know 435 00:37:50,290 --> 00:37:54,430 about them though so they might fix them. Herald: They will be listening now and at 436 00:37:54,430 --> 00:37:57,220 least probably I hope. Littlelailo: Yes. 437 00:37:57,220 --> 00:38:02,460 Herald: Is there anyone who has really, you where sitting on a question here. None 438 00:38:02,460 --> 00:38:10,360 of you? It's already noon. You know, noon passed, so could be that none of you. You 439 00:38:10,360 --> 00:38:15,260 can ask them something, maybe someone asked them something, maybe they can help 440 00:38:15,260 --> 00:38:18,490 you out with certain challenges that are there. 441 00:38:18,490 --> 00:38:23,660 Littlelailo: Well, I don't really have a question either. Laughter I have my own 442 00:38:23,660 --> 00:38:29,760 research project now. Well, like, I do stuff at the moment and look at other 443 00:38:29,760 --> 00:38:34,880 things. For example, to the bootrom exploit came out now. And so I started 444 00:38:34,880 --> 00:38:40,600 developing on the chick team with them. And that's what I currently do, basically. 445 00:38:40,600 --> 00:38:45,450 Herald: You're great, man. Littlelailo, thank you. Giving him a warm applause! 446 00:38:45,450 --> 00:38:48,380 Applause 447 00:38:48,380 --> 00:38:51,936 36c3 Postroll music 448 00:38:51,936 --> 00:39:15,000 Subtitles created by c3subtitles.de in the year 2020. Join, and help us!