1 00:00:00,000 --> 00:00:00,958 [Translated by {Iikka}{Yli-Kuivila} (ITKST56 course assignment at JYU.FI)] 2 00:00:00,958 --> 00:00:13,699 *33C3 preroll music* 3 00:00:13,699 --> 00:00:17,760 Herald: The Max is a security researcher at Lookout has been doing this about 10 4 00:00:17,760 --> 00:00:22,780 years, he spent a lot of time in obfuscation, exploit development, security 5 00:00:22,780 --> 00:00:28,160 research, previous Black Hat speaker, currently focused on mobile security 6 00:00:28,160 --> 00:00:33,579 research and working on his PhD. He'll be telling you about some of the internals of 7 00:00:33,579 --> 00:00:38,210 Pegasus malware today. With that, I will turn over to Max to take it away. 8 00:00:38,210 --> 00:00:39,529 Max: Thank you. 9 00:00:39,529 --> 00:00:47,090 *applause* 10 00:00:47,090 --> 00:00:51,660 M: Hi, everyone, say my name is Max Bazaliy, and today we'll talk about 11 00:00:51,660 --> 00:00:57,609 the Pegasus Internals. I'm from Kiev, Ukraine, currently work as a security 12 00:00:57,609 --> 00:01:02,370 researcher at Lookout and last few years focused on a jailbreak techniques. So 13 00:01:02,370 --> 00:01:06,540 that's why I co-founded the Fried Apple team and we're working on a various 14 00:01:06,540 --> 00:01:12,979 iOS jailbreak, including eight and nine. So Pegasus. Pegasus is a high quality 15 00:01:12,979 --> 00:01:19,704 espionage software that can be used for complete surveillance of a device. Just 16 00:01:19,704 --> 00:01:23,710 everything from stealing your personal data up to remotely activating a 17 00:01:23,710 --> 00:01:30,870 microphone or camera on a device without any indication it's really happening. So 18 00:01:30,870 --> 00:01:35,820 in order Pegasus to work, it need to jailbreak a device first because the iOS 19 00:01:35,820 --> 00:01:40,570 sandbox prevents application from spying on each other. So that's why Pegasus rely 20 00:01:40,570 --> 00:01:49,320 on a trident exploit chain to completely own a device and install persistence that 21 00:01:49,320 --> 00:01:55,250 can be used on each device. Here's a really terrifying list of targeted apps, 22 00:01:55,250 --> 00:02:03,102 including even the known as most secure ones, like Telegram, WhatsApp, Viber. And 23 00:02:03,102 --> 00:02:08,259 I'm pretty sure you can find your favorite messenger in this list. Before going into 24 00:02:08,259 --> 00:02:12,150 a deep technical analysis of the vulnerabilities used, I want to tell a 25 00:02:12,150 --> 00:02:18,300 story how we get it - a Pegasus sample. So police met Ahmed Mansoor, who's mostly 26 00:02:18,300 --> 00:02:23,239 known for his job as a human right defender. He's even a recipient of Martin 27 00:02:23,239 --> 00:02:29,459 Ennals award, sometimes called the Nobel Prize for Human Rights. So I understand 28 00:02:29,459 --> 00:02:39,530 this year Ahmed received a message with a text that someone in a state prison got - 29 00:02:39,530 --> 00:02:45,640 someone is imprisoned in a state prison. So and he received another text with a 30 00:02:45,640 --> 00:02:52,300 similar thing the next day. But previously he was targeted by hacking team in 2012 31 00:02:52,300 --> 00:02:58,910 and got FinFisher in 2011. So now, instead of clicking on the link, he contacted the 32 00:02:58,910 --> 00:03:03,040 Citizen Lab because he was working with those guys before. So he sent a link for 33 00:03:03,040 --> 00:03:09,469 Citizen Lab to analysis and we are in Lookout research team. We get initial 34 00:03:09,469 --> 00:03:13,989 sample and a link from a Citizen Lab. So in this story, I mostly will focusing 35 00:03:13,989 --> 00:03:23,840 about technical, part. So in order to work - Pegasus rely on the Trident exploit 36 00:03:23,840 --> 00:03:29,819 chain and it uses three stages. So on the first stage, it uses a memory corruption 37 00:03:29,819 --> 00:03:34,659 to achieve a remote code execution in a Safari context. After that, it jumps - 38 00:03:34,659 --> 00:03:38,549 after this on a device - it jumps to a second stage and uses two vulnerabilities 39 00:03:38,549 --> 00:03:42,299 to exploit the kernel. One is used for by - by the Kernel Address Space layout 40 00:03:42,299 --> 00:03:47,590 randomisation and another to achieve kernel - a remote - a kernel code 41 00:03:47,590 --> 00:03:51,510 execution kernel level code execution. And finally, on the third stage it 42 00:03:51,510 --> 00:03:57,950 installs espionage software and uses a special trick to achieve on device 43 00:03:57,950 --> 00:04:03,040 persistence. So I will focus on each stage more detailed. The first stage, as they 44 00:04:03,040 --> 00:04:08,920 say, is a single use spear-phish url that will be invalidated after the first click. 45 00:04:08,920 --> 00:04:13,629 It contains obfuscated JavaScript that first thing it do it checking for a device 46 00:04:13,629 --> 00:04:20,340 type: Is it iPhone, is it iPad, is it 32 or 64 bit. And based on information about 47 00:04:20,340 --> 00:04:25,730 device processor type the different versions of shellcode will be downloaded. 48 00:04:25,730 --> 00:04:30,380 Which is in stage two. And finally exploits remote code execution 49 00:04:30,380 --> 00:04:34,525 vulnerability in a webkit in order to execute the shellcode. So what 50 00:04:34,525 --> 00:04:42,600 vulnerability will it use it? CVE 4657 remote code execution in WebKit. Basically 51 00:04:42,600 --> 00:04:46,910 the vulnerability is use after free that achieved by using two bugs and in a sample 52 00:04:46,910 --> 00:04:52,940 that we got it's not stable because it relies on WebKit garbage collector. The 53 00:04:52,940 --> 00:04:57,760 problem itself lives in a - MarkedArgumentBuffer that can be exploited 54 00:04:57,760 --> 00:05:02,030 by usage of the defined properties. So defined properties is a method that 55 00:05:02,030 --> 00:05:07,870 defines new or modified properties directly on object. It takes a few 56 00:05:07,870 --> 00:05:13,540 arguments and the object itself and the properties objects which can have 57 00:05:13,540 --> 00:05:20,910 descriptors that constitute the property to be defined or modified. It have a 58 00:05:20,910 --> 00:05:26,070 pretty simple algorithm, it contain few loops on the very first iteration of each 59 00:05:26,070 --> 00:05:30,090 property descriptor checking for a formatting and after that get appended to 60 00:05:30,090 --> 00:05:35,790 a descriptor's vector and to make sure that the reference to property descriptors 61 00:05:35,790 --> 00:05:40,020 do not become stale, they need to be protected from being garbage collected. 62 00:05:40,020 --> 00:05:44,740 For this purpose MarkedArgumentBuffer is used. We see it at the very very end, 63 00:05:44,740 --> 00:05:49,530 MarkedArgumentBuffer append. So MarkedArgumentBuffer prevents objects from 64 00:05:49,530 --> 00:05:59,250 being deallocated. And after each property -get has been validated and it's okay, the 65 00:05:59,250 --> 00:06:03,240 defineOwnProperty associate each user supplied property with a target object. 66 00:06:03,240 --> 00:06:08,150 And here is a problem, because it's possi- ble when the defineProperty will be called 67 00:06:08,150 --> 00:06:13,610 it's possible to call any user defined JavaScript methods. If in these JavaScript 68 00:06:13,610 --> 00:06:19,810 methods garbage collection can be triggered, it will deallocate any unmarked 69 00:06:19,810 --> 00:06:26,410 heap-backed object. I will go a little bit deeply in the details. First of all, a few 70 00:06:26,410 --> 00:06:30,390 words about MarkedArgumentBuffer and JavaScript garbage collector. So 71 00:06:30,390 --> 00:06:33,640 JavaScript garbage collector is respon- sible for deallocating an object from 72 00:06:33,640 --> 00:06:37,900 a memory when they are no longer referenced. It runs at a - random 73 00:06:37,900 --> 00:06:42,670 intervals and based on the current memory pressure, the current device types and so 74 00:06:42,670 --> 00:06:48,550 on. And when garbage collector checking if objects should be deallocated, it walks 75 00:06:48,550 --> 00:06:53,190 through the stack and check for reference to an object. A reference to an object 76 00:06:53,190 --> 00:06:57,500 also may exist in the application heap, but in this case an alternative is used 77 00:06:57,500 --> 00:07:04,140 called the slowAppend. So MarkedArgumentBuffer is initial inline 78 00:07:04,140 --> 00:07:10,510 stack contains eight values. Well, that's mean when the ninth value will be added to 79 00:07:10,510 --> 00:07:15,570 the MarkedArgumentBuffer the capacity will be expanded. It will be moved from a stack 80 00:07:15,570 --> 00:07:25,840 memory to a heap memory. This is what the slowAppend is doing. SlowAppend move stack 81 00:07:25,840 --> 00:07:31,810 from a - move buffer from a stack to a heap, and now object not automatically 82 00:07:31,810 --> 00:07:37,060 protected from a garbage collection. And to make sure they were not deallocated, 83 00:07:37,060 --> 00:07:45,650 they need to be added to heap's markListSet. This is what we see here. So 84 00:07:45,650 --> 00:07:50,170 slowAppend trying to acquire heap context and it can be acquired adding an object 85 00:07:50,170 --> 00:07:59,639 like, marking an object into markListSet. And here is a problem, because when the 86 00:07:59,639 --> 00:08:02,940 heap context can be acquired, it can be acquired for a complex object, only for a 87 00:08:02,940 --> 00:08:08,110 complex object. So this mean for primitive types like integer, booleans and so on, 88 00:08:08,110 --> 00:08:14,450 they're not heap backed object and they'll be not marked as a markListSet. And there 89 00:08:14,450 --> 00:08:20,480 is a bug in the slowAppend. We should be able to call it just once. So this mean 90 00:08:20,480 --> 00:08:27,720 when the buffer will be moved from a stack memory to a heap memory and one of the 91 00:08:27,720 --> 00:08:31,750 properties will be a simple type, like an integer, so they're not automatically 92 00:08:31,750 --> 00:08:35,959 protected by garbage collection and all the next corresponding values will be not 93 00:08:35,959 --> 00:08:41,610 protected as well because of the bug in the slowAppend. Here is a picture that's 94 00:08:41,610 --> 00:08:46,820 illustrating it and in reality the reference to JavaScript objects still 95 00:08:46,820 --> 00:08:53,330 exist. But if, uh, in a in a call to definedOwnProperty method, any of the user 96 00:08:53,330 --> 00:08:57,360 supplied methods will be called, they can remove this reference and object will 97 00:08:57,360 --> 00:09:03,460 be deallocated. So to summarize, all the information here is how it can be 98 00:09:03,460 --> 00:09:09,620 exploited. So we specify an props object which contain 12 descriptors and first 99 00:09:09,620 --> 00:09:16,401 nine of them values are simple typed, like zeroes, eight. Which mean that p8, which 100 00:09:16,401 --> 00:09:22,510 is the ninth value bit will be added to markListSet. It will trigger the 101 00:09:22,510 --> 00:09:28,690 slowAppend and the buffer will be moved from a stack to a heap. And the next 102 00:09:28,690 --> 00:09:34,090 corresponding value is just - length and which not_number and array will be not 103 00:09:34,090 --> 00:09:37,390 marked by markListSet and not automatically protected by garbage 104 00:09:37,390 --> 00:09:44,010 collection. What happened next, when different properties will be called on the 105 00:09:44,010 --> 00:09:49,370 length property and you'll try to convert not_number to a number which for that 106 00:09:49,370 --> 00:09:54,371 user's defined it toString method will be called. The toString method remove the 107 00:09:54,371 --> 00:09:58,400 last reference for an array and forces the garbage collection cycle by allocating a 108 00:09:58,400 --> 00:10:04,070 large amount of memory. Which leads that object will be deallocated by garbage 109 00:10:04,070 --> 00:10:08,450 collector. The very next thing it is doing is reallocate the new object over a stale 110 00:10:08,450 --> 00:10:14,180 one. So this is how specially crafted use after free was used in Safari to achieve 111 00:10:14,180 --> 00:10:19,650 remote code execution and to execute a shellcode. The shellcode exist in a second 112 00:10:19,650 --> 00:10:25,100 stage, which is a payload which contained the shellcode and compressed data. The 113 00:10:25,100 --> 00:10:28,460 most interesting for us is the shellcode because it's used for a kernel 114 00:10:28,460 --> 00:10:33,770 exploitation in Safari context and the compressed data basically is a loader 115 00:10:33,770 --> 00:10:38,980 that downloads and decrypts the next stage. One of the vulnerabilities used is 116 00:10:38,980 --> 00:10:45,820 a CVE 4655, which is a info leak that's used to bypass a kernel address layout 117 00:10:45,820 --> 00:10:51,050 randomization. It exploits the information that constructor and OSUnseralizeBinary 118 00:10:51,050 --> 00:10:58,140 method they miss bound checking. So that mean that attacker can create OSNumber 119 00:10:58,140 --> 00:11:02,070 object with a really high number of bits and call it within the application sandbox 120 00:11:02,070 --> 00:11:05,670 where io_registry_entry_get_property_bytes. 121 00:11:05,670 --> 00:11:10,790 Here's how it looked like. So OSUnseralizeBinary method to handle binary 122 00:11:10,790 --> 00:11:16,250 serializations in a kernel. It converts a binary format to basic kernel data object. 123 00:11:16,250 --> 00:11:21,960 It supports different container types, sets, dictionaries, array, object types, 124 00:11:21,960 --> 00:11:26,720 strings, numbers and the point of interest in this is the OSNumber. So as we see 125 00:11:26,720 --> 00:11:34,200 here, it passed two arguments: value and length and there is no real check that for 126 00:11:34,200 --> 00:11:39,950 - for length property. So this mean we can control the length that is passed to an 127 00:11:39,950 --> 00:11:45,440 object. And why it is a problem, because here is a constructor for OSNumber:init 128 00:11:45,440 --> 00:11:51,770 and as we see the length property passed here is newnNumberOfBits and it 129 00:11:51,770 --> 00:11:56,060 overrides the size variable. And the problem that size is used in other 130 00:11:56,060 --> 00:12:02,040 methods, in a case that OSNumber numberOfBytes, which leads it return value 131 00:12:02,040 --> 00:12:08,370 of numberOfBytes is now fully controlled by attacker. Which is real bad because 132 00:12:08,370 --> 00:12:12,400 it's used next in io_registry_entry_get_property_bytes which 133 00:12:12,400 --> 00:12:17,920 handle OSNumbers and its use numberOfBytes to calculate the object's length, the 134 00:12:17,920 --> 00:12:24,330 OSNumber length. But unfortunately it use a stack based buffer to parse and save 135 00:12:24,330 --> 00:12:31,600 OSNumber value. And what happened next, it is copying memory from kernel stack to 136 00:12:31,600 --> 00:12:37,420 heap used the attacker controlled length. Which mean we can specify how many bytes 137 00:12:37,420 --> 00:12:43,960 will be copied from a kernel stack and returned to user land. This is what 138 00:12:43,960 --> 00:12:52,800 happens: the first thing we are doing, we are create a properties array that have a 139 00:12:52,800 --> 00:12:59,950 dictionary which have a OSNumber with a high length in our case, is 256. Next, we 140 00:12:59,950 --> 00:13:04,560 need to spawn the user client by calling IOService open extended, which will 141 00:13:04,560 --> 00:13:11,000 deserialize this OSNumber object and crea- te this object in the - in the kernel. And 142 00:13:11,000 --> 00:13:16,089 now we need to read it by calling the IORegistryEntryGetProperty, which leads it 143 00:13:16,089 --> 00:13:22,590 - we copied the 256 bytes of the kernel stack memory and the kernel stack memory 144 00:13:22,590 --> 00:13:26,960 will contain kernel pointers. And from a kernel pointer, we can determine the 145 00:13:26,960 --> 00:13:32,850 kernel base. So now we get a kernel base and we can jump to the next vulnerability, 146 00:13:32,850 --> 00:13:40,110 which is CVE 4656 it is use-after-free to achieve kernel level code execution. It 147 00:13:40,110 --> 00:13:44,180 exploits information because the setAtIndex macro does not really retain an 148 00:13:44,180 --> 00:13:48,420 object and we can trigger it within the application sandbox from 149 00:13:48,420 --> 00:13:56,940 OSUnserializeBinary. Again the OSUnserializeBinary it's a function that 150 00:13:56,940 --> 00:14:01,940 parse and deserialize objects in the kernel - it support different data types - 151 00:14:01,940 --> 00:14:06,550 different container types. And the interesting thing it supports kOSSerialize 152 00:14:06,550 --> 00:14:12,490 object. It means that we can create a reference to another object. Really 153 00:14:12,490 --> 00:14:18,270 useful in the future, because in a way of deserializing and parsing objects 154 00:14:18,270 --> 00:14:24,490 OSUnserializeBinary saved object pointer to a special objects array. And using 155 00:14:24,490 --> 00:14:29,170 setAtIndex for it. And as we see setAtIndex just save object pointer to 156 00:14:29,170 --> 00:14:37,410 array with some index not retaining it. It's bad, because the next code, which 157 00:14:37,410 --> 00:14:44,200 casting OSString to a OSSymbol it is releasing the object pointer. What does it 158 00:14:44,200 --> 00:14:48,790 mean? We still have an array that holds all the object pointers, which is objects 159 00:14:48,790 --> 00:14:55,770 array, and we just released one of the objects but still hold the pointer. If we 160 00:14:55,770 --> 00:15:00,200 can create a reference to an object we can exploit use-after-free. This is what 161 00:15:00,200 --> 00:15:03,560 happens because kOSSerializeObject allows us to create a reference and we will just 162 00:15:03,560 --> 00:15:09,410 call retain on already deserialized, already deallocated object. This is how 163 00:15:09,410 --> 00:15:14,490 exploit look like. So first of all, we create OSdictionary and it will contain a 164 00:15:14,490 --> 00:15:19,530 string that due the bug will be deallocated. So now we need to reallocate 165 00:15:19,530 --> 00:15:27,510 it with our controlled object to fit in the same memory spot. It's OSString in our 166 00:15:27,510 --> 00:15:34,580 case, OSString class in a memory will be 32 bytes. We need to allocate the same 167 00:15:34,580 --> 00:15:39,930 size. For this purpose OSData is a perfect candidate because we can control OSData 168 00:15:39,930 --> 00:15:46,460 buffer, buffer size and buffer content. So what we can do, we can create a fake 169 00:15:46,460 --> 00:15:50,860 OSString with a fake vtable and this fake vtable will point to some digits in the 170 00:15:50,860 --> 00:15:55,630 kernel. The very last thing we need to do is trigger a user-after-free by adding a 171 00:15:55,630 --> 00:16:01,630 kOSSerializeObject. So once again, OSString got deserialized, deallocated, 172 00:16:01,630 --> 00:16:05,290 reallocated to a new object, which is OSData buffer, which will point to the 173 00:16:05,290 --> 00:16:12,649 same memory spot: we've got a use-after- free. So after getting use-after-free, 174 00:16:12,649 --> 00:16:20,290 Pegasus uses some kernel patches to disable security checks like setuid to 175 00:16:20,290 --> 00:16:26,190 easily escalate the privileges, bypass amfi checks by patching out 176 00:16:26,190 --> 00:16:31,570 amfi_get_out_of_my_way, disable code signment enforcement by patching 177 00:16:31,570 --> 00:16:36,060 cs_enforcement_disable variable and finally, a remount the system partition to 178 00:16:36,060 --> 00:16:41,720 be readable, & writable so it can execute a loader for the next stage to download 179 00:16:41,720 --> 00:16:50,990 and decrypt the next stage. The next stage contain the real espionage stuff that will 180 00:16:50,990 --> 00:16:58,910 be used to sniff all the like SMS, all the calls, all the like personal data. It have 181 00:16:58,910 --> 00:17:09,350 a three groups. One is a process group which have a main process: sniffing 182 00:17:09,350 --> 00:17:14,850 services model that use a SIP protocol to communicate with command control like a 183 00:17:14,850 --> 00:17:20,370 process manager and so on. The next interesting thing is a group of the 184 00:17:20,370 --> 00:17:24,919 dylibs, because Pegasus rely on the Cydia substrate - the jailbreak framework called 185 00:17:24,919 --> 00:17:29,410 - they renamed it as libdata. It uses Cydia substrate to inject dynamic 186 00:17:29,410 --> 00:17:34,429 libraries into application process. So in our case, we have a dynamic libraries for 187 00:17:34,429 --> 00:17:38,202 Viber, for Whatsapp which can be injected into the application space to install 188 00:17:38,202 --> 00:17:44,990 application hooks. And the last thing is com.apple.itunesstored file. Which is a 189 00:17:44,990 --> 00:17:53,870 JavaScript that contain code and the shellcode that will execute - that can 190 00:17:53,870 --> 00:18:00,480 execute unsigned code. I will focus on it next. So the bug exists in a JSC binary. 191 00:18:00,480 --> 00:18:06,870 JSC binary is like a helper for JavaScript core, JavaScript and in Apple. And 192 00:18:06,870 --> 00:18:12,330 it can lead to unsigned code execution. In combination with rtbyddyd trick it can be 193 00:18:12,330 --> 00:18:18,780 used to completely gain persistence on the device. It exploits that it is a bad cast 194 00:18:18,780 --> 00:18:24,929 in setEarlyValue method and fortunately it can be triggered only from Jesty 195 00:18:24,929 --> 00:18:32,030 application context. So what is a problem? It exploits the problem in JavaScript 196 00:18:32,030 --> 00:18:37,190 binding SetImpureGetterDelegate which have in C++ for function 197 00:18:37,190 --> 00:18:40,880 SetImpureGetterDelegate. This function takes a few arguments - one is the 198 00:18:40,880 --> 00:18:47,890 impureGetter and the second one is a generic isObject that will be set as this 199 00:18:47,890 --> 00:18:54,790 impureGetter delegate. The problem will be next slide - so we just parse two 200 00:18:54,790 --> 00:18:59,370 arguments and call a setDelegate. The setDelegate called set which finally 201 00:18:59,370 --> 00:19:05,080 called setEarlyValue. Here is a problem, because there is no real check that the 202 00:19:05,080 --> 00:19:10,670 object type passed to setImpureGetterDelegate is really 203 00:19:10,670 --> 00:19:15,950 ImpureGetter. So this means that if any other object type will be passed, it will 204 00:19:15,950 --> 00:19:21,050 be improperly downcasted as ImpureGetter pointer. That's what happened here. So 205 00:19:21,050 --> 00:19:28,180 it's a bad cast that have no real check for object type and which lead that we can 206 00:19:28,180 --> 00:19:33,200 overwrite on those object fields. Here are the same function, but now decompiled in IDA 207 00:19:33,200 --> 00:19:39,620 Pro. So in our case ImpureGetter is a base variable here and the delegate is this 208 00:19:39,620 --> 00:19:46,020 generic JS object. We see that the pointer, which is base plus 16, can be 209 00:19:46,020 --> 00:19:50,910 overridden with a pointer to a delegate. Which lead - you see on the right 210 00:19:50,910 --> 00:19:55,760 JSArrayBufferView class - if I pass JSArrayBufferView class as a first 211 00:19:55,760 --> 00:20:01,620 argument, the m_vector field will be overwritten with a pointer to a delegate. 212 00:20:01,620 --> 00:20:09,720 Which is really bad, because it can lead to readable, writeable primitives. To 213 00:20:09,720 --> 00:20:14,429 exploit that Pegasus uses two dataviews. I will call them dataview one and dataview 214 00:20:14,429 --> 00:20:20,860 two. And to call and setImpureGetterDelegate on both, which 215 00:20:20,860 --> 00:20:24,910 leads it m_vector field in the first dataview will be overwritten with the 216 00:20:24,910 --> 00:20:31,080 pointer for the second dataview. And now by setting and reading the values on the 217 00:20:31,080 --> 00:20:36,400 first dataview we can override object fields in the second. While we need it, we 218 00:20:36,400 --> 00:20:42,500 can map the second dataview as entire process memory by overwriting the second 219 00:20:42,500 --> 00:20:46,580 dataview arraybuffer offset to be zero by overwriting the second dataview length to 220 00:20:46,580 --> 00:20:52,460 be four gigabytes in a case of 32 bit process and set type as fast array type. 221 00:20:52,460 --> 00:20:56,630 So basically the second dataview now is mapped to the entire process space and we 222 00:20:56,630 --> 00:21:05,390 can getint, setint to get arbitrary read and write anywhere in the process memory. 223 00:21:05,390 --> 00:21:09,950 The same thing can be used even to get execution primitive. But in this case, we 224 00:21:09,950 --> 00:21:16,400 can call setImpureGetterDelegate twice and instead of exposing the entire process 225 00:21:16,400 --> 00:21:21,380 memory, we can leak just an object address. If you can leak an object 226 00:21:21,380 --> 00:21:26,530 address, we can produce a function that have like hundreds of try - empty try- 227 00:21:26,530 --> 00:21:33,230 catch constructions and force JIT to compile it. And in a - in this process, a 228 00:21:33,230 --> 00:21:38,580 special, readable, writeable, executable memory segment will be allocated. We can 229 00:21:38,580 --> 00:21:45,270 leak address of this JIT segment, overwrite it with a shellcode and execute. 230 00:21:45,270 --> 00:21:51,790 So this is how the bad cast can be used to like re-exploit even a kernel on each 231 00:21:51,790 --> 00:21:58,040 boot. It is used with a persistence mechanism which is rtbuddyd. So the 232 00:21:58,040 --> 00:22:03,730 problem is that System spawning rtbuddyd service with a special early-boot 233 00:22:03,730 --> 00:22:10,500 argument. This mean if you take any other binary signed by Apple and name it as 234 00:22:10,500 --> 00:22:14,820 rbuddyd, it will be spawned on a boot. That is what the Pegasus is doing. So they 235 00:22:14,820 --> 00:22:20,700 take JSC binary which is signed by Apple, name it as rtbuddyd, then take a 236 00:22:20,700 --> 00:22:26,900 JavaScript that contain exploit. Make it a sym link, call it early-boot which leads 237 00:22:26,900 --> 00:22:31,500 to when the rtbuddyd will be spawned it with early-boot it will call JSC with the 238 00:22:31,500 --> 00:22:37,130 js-exploit instead. So with this trick and the bad cast it re-exploits kernel on 239 00:22:37,130 --> 00:22:46,480 each device boot. There is some tricks the Pegasus use to make it harder to 240 00:22:46,480 --> 00:22:51,540 reverse engineer, like use one time links. So after you click on any of the link 241 00:22:51,540 --> 00:22:57,490 they'll be invalidated and now redirect to Google or other sites. It re-encrypts all 242 00:22:57,490 --> 00:23:02,920 the payloads each time they are downloaded just on the fly. And of course, they are 243 00:23:02,920 --> 00:23:09,900 trying to hide itself to make it look like a system component. Um, of course, it 244 00:23:09,900 --> 00:23:15,100 blocks iOS system updates to make sure you can't - you cannot batch your device just 245 00:23:15,100 --> 00:23:22,510 on the fly, to clear all the evidence: clear Safari history and caches and we 246 00:23:22,510 --> 00:23:30,290 found a self-destruct mechanism that can be triggered remotely or on a time out. So 247 00:23:30,290 --> 00:23:35,510 in addition to this terrifying list of supported applications, it records any 248 00:23:35,510 --> 00:23:40,710 microphone usage, any camera usage, GPS, location, keychain passwords, even 249 00:23:40,710 --> 00:23:47,250 including the Wi-Fi and the router one. Why they need router - I don't know. 250 00:23:47,250 --> 00:23:51,280 Application hooking. So how how it operates. As I mentioned earlier, it use 251 00:23:51,280 --> 00:23:57,299 Cydia substrate and with the help of Cydia substrate it preloads dynamic libraries 252 00:23:57,299 --> 00:24:04,809 into application process and intercept some critical functions. It uses Cynject 253 00:24:04,809 --> 00:24:10,870 to run into already - into already running processes. So this is like a high level 254 00:24:10,870 --> 00:24:18,130 picture of how it looks like. So all the application level critical functions and 255 00:24:18,130 --> 00:24:21,940 the framework level critical functions are intercepted by Pegasus. So now Pegasus can 256 00:24:21,940 --> 00:24:27,570 control them, can collect them, can back them, can send Command & Control and so 257 00:24:27,570 --> 00:24:36,150 on. To summarize, Pegasus is a remote jailbreak spotted in the wild. It's pretty 258 00:24:36,150 --> 00:24:42,059 scary because it doesn't require any user interaction. And the last similar thing 259 00:24:42,059 --> 00:24:47,753 was like five years ago when the comex released his jailbreakme 3. This year Luca 260 00:24:47,753 --> 00:24:52,920 Todesco used one of the Trident vulnerabilities for his jailbreaking. 261 00:24:54,290 --> 00:24:59,870 I want to say a special thanks to Citizen Lab for helping out with achieving a 262 00:24:59,870 --> 00:25:05,289 Pegasus sample. All the Lookout research & response team, the Divergent security guys 263 00:25:05,289 --> 00:25:11,310 and all the individual researchers who was involved in the research. So last some 264 00:25:11,310 --> 00:25:17,470 useful links which contain a 44 page PDF report with a really, really deep details 265 00:25:17,470 --> 00:25:23,710 on the vulnerabilities that is used even with the difference between 32 and 64 bit 266 00:25:23,710 --> 00:25:31,059 ones. So if you're interested in. Please take a look. I think this is it do you 267 00:25:31,059 --> 00:25:33,280 guys have any questions? 268 00:25:33,290 --> 00:25:41,562 *applause* 269 00:25:44,682 --> 00:25:48,432 M: Mm hmm. H: OK, please keep it brief. We only have 270 00:25:48,432 --> 00:25:50,470 some minutes left for the questions, and if there are any questions, please go to 271 00:25:50,470 --> 00:25:56,830 the microphones in the hall. And we start with the Signal Angel from the Internet. 272 00:25:56,830 --> 00:26:03,530 SA: Thank you. Is there any way to build your app, protect it from this exploit? 273 00:26:03,530 --> 00:26:13,160 M: Yes, it is, because the Pegasus use some of the known jailbreak techniques it 274 00:26:13,160 --> 00:26:18,480 is possible to detect for example that system partition is remounted as readable 275 00:26:18,480 --> 00:26:23,650 & writable. It could be one of the indicators that some generic jailbreak is 276 00:26:23,650 --> 00:26:29,900 running on a device. Or like check for especially file that Pegasus use but like 277 00:26:29,900 --> 00:26:33,870 better check it in general for jailbreak pages, the kernel pages. 278 00:26:33,870 --> 00:26:37,540 *audience shuffling noise* H: Please try to stay a bit quiet. We are 279 00:26:37,540 --> 00:26:40,170 still in the middle of the Q & A. If you don't have to leave now, please stay 280 00:26:40,170 --> 00:26:47,100 seated until afterwards and if you have to leave now, please do not talk. Microphone 281 00:26:47,100 --> 00:26:50,200 three, please. M3: What's the user experience during 282 00:26:50,200 --> 00:26:53,480 this? M: User experience, I mean - you mean - 283 00:26:53,480 --> 00:26:59,071 you mean when you get a device infected by Pegasus? Well, there is it's scary there 284 00:26:59,071 --> 00:27:07,110 is no real indicators on a device that you get something. That you click on the link, 285 00:27:07,110 --> 00:27:13,080 the mobile web browser opens and just closes and crashes. There is no new 286 00:27:13,080 --> 00:27:19,340 applications spotted on your on visible applications and so on. But in a real it's 287 00:27:19,340 --> 00:27:26,390 running like three new system services, but they are not visible to a user. 288 00:27:26,390 --> 00:27:29,370 H: Thank you. And please, another question from the Internet. 289 00:27:29,370 --> 00:27:33,300 SA: Thank you. Have you any idea how active this exploit is in the world? 290 00:27:33,300 --> 00:27:39,590 M: Say it again please? SA: Have you any idea how active this 291 00:27:39,590 --> 00:27:46,580 exploit is in the wild? M: I'm sure it was a very targeted attack 292 00:27:46,580 --> 00:27:51,860 because, uh, these exploits are pretty expensive. For example, uh, Zerodium now 293 00:27:51,860 --> 00:27:59,770 pays 1,5 million for remote jailbreaks like these so I don't think that actors of 294 00:27:59,770 --> 00:28:06,860 this like spyware, want to like - want to deal malware accessible for everyone. So I 295 00:28:06,860 --> 00:28:11,960 think it's a very very targeted attacks. It is hard to predict how many devices was 296 00:28:11,960 --> 00:28:19,690 infected by Pegasus. Now we know about the Mansoor one. So, again, I think it's very, 297 00:28:19,690 --> 00:28:22,480 very targeted thing because it's very expensive. 298 00:28:22,480 --> 00:28:26,590 H: Thank you for this answer. Microphone number five, please. 299 00:28:26,590 --> 00:28:33,300 M5: Do you have any more information on the NSO or the group that's behind it? Are 300 00:28:33,300 --> 00:28:38,720 they using any other software? And how spread is this in the wild again? 301 00:28:38,720 --> 00:28:42,919 M: Yeah. So in this case, we focused mostly on the technicalities of the 302 00:28:42,919 --> 00:28:49,809 Pegasus itself, but Citizen Lab made their investigation on NSO and the like the 303 00:28:49,809 --> 00:28:56,600 NSO is like cyber arms dealer. So please take a look about in a Citizen Lab report 304 00:28:56,600 --> 00:29:00,140 on that. So they have much more information. 305 00:29:02,280 --> 00:29:07,750 H: Do we have a question from the Internet? Am I overlooking anyone? No, 306 00:29:07,750 --> 00:29:10,150 then this is it, thank you for your talk. 307 00:29:10,150 --> 00:29:14,480 *applause* 308 00:29:15,091 --> 00:29:24,670 *postroll music* 309 00:29:24,670 --> 00:29:37,610 Subtitles created by c3subtitles.de in the year 2022. Join, and help us! 310 00:29:37,610 --> 00:29:39,000 [Translated by {Iikka}{Yli-Kuivila} (ITKST56 course assignment at JYU.FI)]