WEBVTT 00:00:00.000 --> 00:00:00.958 [Translated by {Iikka}{Yli-Kuivila} (ITKST56 course assignment at JYU.FI)] 00:00:00.958 --> 00:00:13.699 33C3 preroll music 00:00:13.699 --> 00:00:17.760 Herald: The Max is a security researcher at Lookout has been doing this about 10 00:00:17.760 --> 00:00:22.780 years, he spent a lot of time in obfuscation, exploit development, security 00:00:22.780 --> 00:00:28.160 research, previous Black Hat speaker, currently focused on mobile security 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 00:00:33.579 --> 00:00:38.210 Pegasus malware today. With that, I will turn over to Max to take it away. 00:00:38.210 --> 00:00:39.529 Max: Thank you. 00:00:39.529 --> 00:00:47.090 applause 00:00:47.090 --> 00:00:51.660 M: Hi, everyone, say my name is Max Bazaliy, and today we'll talk about 00:00:51.660 --> 00:00:57.609 the Pegasus Internals. I'm from Kiev, Ukraine, currently work as a security 00:00:57.609 --> 00:01:02.370 researcher at Lookout and last few years focused on a jailbreak techniques. So 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 00:01:06.540 --> 00:01:12.979 iOS jailbreak, including eight and nine. So Pegasus. Pegasus is a high quality 00:01:12.979 --> 00:01:19.704 espionage software that can be used for complete surveillance of a device. Just 00:01:19.704 --> 00:01:23.710 everything from stealing your personal data up to remotely activating a 00:01:23.710 --> 00:01:30.870 microphone or camera on a device without any indication it's really happening. So 00:01:30.870 --> 00:01:35.820 in order Pegasus to work, it need to jailbreak a device first because the iOS 00:01:35.820 --> 00:01:40.570 sandbox prevents application from spying on each other. So that's why Pegasus rely 00:01:40.570 --> 00:01:49.320 on a trident exploit chain to completely own a device and install persistence that 00:01:49.320 --> 00:01:55.250 can be used on each device. Here's a really terrifying list of targeted apps, 00:01:55.250 --> 00:02:03.102 including even the known as most secure ones, like Telegram, WhatsApp, Viber. And 00:02:03.102 --> 00:02:08.259 I'm pretty sure you can find your favorite messenger in this list. Before going into 00:02:08.259 --> 00:02:12.150 a deep technical analysis of the vulnerabilities used, I want to tell a 00:02:12.150 --> 00:02:18.300 story how we get it - a Pegasus sample. So police met Ahmed Mansoor, who's mostly 00:02:18.300 --> 00:02:23.239 known for his job as a human right defender. He's even a recipient of Martin 00:02:23.239 --> 00:02:29.459 Ennals award, sometimes called the Nobel Prize for Human Rights. So I understand 00:02:29.459 --> 00:02:39.530 this year Ahmed received a message with a text that someone in a state prison got - 00:02:39.530 --> 00:02:45.640 someone is imprisoned in a state prison. So and he received another text with a 00:02:45.640 --> 00:02:52.300 similar thing the next day. But previously he was targeted by hacking team in 2012 00:02:52.300 --> 00:02:58.910 and got FinFisher in 2011. So now, instead of clicking on the link, he contacted the 00:02:58.910 --> 00:03:03.040 Citizen Lab because he was working with those guys before. So he sent a link for 00:03:03.040 --> 00:03:09.469 Citizen Lab to analysis and we are in Lookout research team. We get initial 00:03:09.469 --> 00:03:13.989 sample and a link from a Citizen Lab. So in this story, I mostly will focusing 00:03:13.989 --> 00:03:23.840 about technical, part. So in order to work - Pegasus rely on the Trident exploit 00:03:23.840 --> 00:03:29.819 chain and it uses three stages. So on the first stage, it uses a memory corruption 00:03:29.819 --> 00:03:34.659 to achieve a remote code execution in a Safari context. After that, it jumps - 00:03:34.659 --> 00:03:38.549 after this on a device - it jumps to a second stage and uses two vulnerabilities 00:03:38.549 --> 00:03:42.299 to exploit the kernel. One is used for by - by the Kernel Address Space layout 00:03:42.299 --> 00:03:47.590 randomisation and another to achieve kernel - a remote - a kernel code 00:03:47.590 --> 00:03:51.510 execution kernel level code execution. And finally, on the third stage it 00:03:51.510 --> 00:03:57.950 installs espionage software and uses a special trick to achieve on device 00:03:57.950 --> 00:04:03.040 persistence. So I will focus on each stage more detailed. The first stage, as they 00:04:03.040 --> 00:04:08.920 say, is a single use spear-phish url that will be invalidated after the first click. 00:04:08.920 --> 00:04:13.629 It contains obfuscated JavaScript that first thing it do it checking for a device 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 00:04:20.340 --> 00:04:25.730 device processor type the different versions of shellcode will be downloaded. 00:04:25.730 --> 00:04:30.380 Which is in stage two. And finally exploits remote code execution 00:04:30.380 --> 00:04:34.525 vulnerability in a webkit in order to execute the shellcode. So what 00:04:34.525 --> 00:04:42.600 vulnerability will it use it? CVE 4657 remote code execution in WebKit. Basically 00:04:42.600 --> 00:04:46.910 the vulnerability is use after free that achieved by using two bugs and in a sample 00:04:46.910 --> 00:04:52.940 that we got it's not stable because it relies on WebKit garbage collector. The 00:04:52.940 --> 00:04:57.760 problem itself lives in a - MarkedArgumentBuffer that can be exploited 00:04:57.760 --> 00:05:02.030 by usage of the defined properties. So defined properties is a method that 00:05:02.030 --> 00:05:07.870 defines new or modified properties directly on object. It takes a few 00:05:07.870 --> 00:05:13.540 arguments and the object itself and the properties objects which can have 00:05:13.540 --> 00:05:20.910 descriptors that constitute the property to be defined or modified. It have a 00:05:20.910 --> 00:05:26.070 pretty simple algorithm, it contain few loops on the very first iteration of each 00:05:26.070 --> 00:05:30.090 property descriptor checking for a formatting and after that get appended to 00:05:30.090 --> 00:05:35.790 a descriptor's vector and to make sure that the reference to property descriptors 00:05:35.790 --> 00:05:40.020 do not become stale, they need to be protected from being garbage collected. 00:05:40.020 --> 00:05:44.740 For this purpose MarkedArgumentBuffer is used. We see it at the very very end, 00:05:44.740 --> 00:05:49.530 MarkedArgumentBuffer append. So MarkedArgumentBuffer prevents objects from 00:05:49.530 --> 00:05:59.250 being deallocated. And after each property -get has been validated and it's okay, the 00:05:59.250 --> 00:06:03.240 defineOwnProperty associate each user supplied property with a target object. 00:06:03.240 --> 00:06:08.150 And here is a problem, because it's possi- ble when the defineProperty will be called 00:06:08.150 --> 00:06:13.610 it's possible to call any user defined JavaScript methods. If in these JavaScript 00:06:13.610 --> 00:06:19.810 methods garbage collection can be triggered, it will deallocate any unmarked 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 00:06:26.410 --> 00:06:30.390 words about MarkedArgumentBuffer and JavaScript garbage collector. So 00:06:30.390 --> 00:06:33.640 JavaScript garbage collector is respon- sible for deallocating an object from 00:06:33.640 --> 00:06:37.900 a memory when they are no longer referenced. It runs at a - random 00:06:37.900 --> 00:06:42.670 intervals and based on the current memory pressure, the current device types and so 00:06:42.670 --> 00:06:48.550 on. And when garbage collector checking if objects should be deallocated, it walks 00:06:48.550 --> 00:06:53.190 through the stack and check for reference to an object. A reference to an object 00:06:53.190 --> 00:06:57.500 also may exist in the application heap, but in this case an alternative is used 00:06:57.500 --> 00:07:04.140 called the slowAppend. So MarkedArgumentBuffer is initial inline 00:07:04.140 --> 00:07:10.510 stack contains eight values. Well, that's mean when the ninth value will be added to 00:07:10.510 --> 00:07:15.570 the MarkedArgumentBuffer the capacity will be expanded. It will be moved from a stack 00:07:15.570 --> 00:07:25.840 memory to a heap memory. This is what the slowAppend is doing. SlowAppend move stack 00:07:25.840 --> 00:07:31.810 from a - move buffer from a stack to a heap, and now object not automatically 00:07:31.810 --> 00:07:37.060 protected from a garbage collection. And to make sure they were not deallocated, 00:07:37.060 --> 00:07:45.650 they need to be added to heap's markListSet. This is what we see here. So 00:07:45.650 --> 00:07:50.170 slowAppend trying to acquire heap context and it can be acquired adding an object 00:07:50.170 --> 00:07:59.639 like, marking an object into markListSet. And here is a problem, because when the 00:07:59.639 --> 00:08:02.940 heap context can be acquired, it can be acquired for a complex object, only for a 00:08:02.940 --> 00:08:08.110 complex object. So this mean for primitive types like integer, booleans and so on, 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 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 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 00:08:27.720 --> 00:08:31.750 properties will be a simple type, like an integer, so they're not automatically 00:08:31.750 --> 00:08:35.959 protected by garbage collection and all the next corresponding values will be not 00:08:35.959 --> 00:08:41.610 protected as well because of the bug in the slowAppend. Here is a picture that's 00:08:41.610 --> 00:08:46.820 illustrating it and in reality the reference to JavaScript objects still 00:08:46.820 --> 00:08:53.330 exist. But if, uh, in a in a call to definedOwnProperty method, any of the user 00:08:53.330 --> 00:08:57.360 supplied methods will be called, they can remove this reference and object will 00:08:57.360 --> 00:09:03.460 be deallocated. So to summarize, all the information here is how it can be 00:09:03.460 --> 00:09:09.620 exploited. So we specify an props object which contain 12 descriptors and first 00:09:09.620 --> 00:09:16.401 nine of them values are simple typed, like zeroes, eight. Which mean that p8, which 00:09:16.401 --> 00:09:22.510 is the ninth value bit will be added to markListSet. It will trigger the 00:09:22.510 --> 00:09:28.690 slowAppend and the buffer will be moved from a stack to a heap. And the next 00:09:28.690 --> 00:09:34.090 corresponding value is just - length and which not_number and array will be not 00:09:34.090 --> 00:09:37.390 marked by markListSet and not automatically protected by garbage 00:09:37.390 --> 00:09:44.010 collection. What happened next, when different properties will be called on the 00:09:44.010 --> 00:09:49.370 length property and you'll try to convert not_number to a number which for that 00:09:49.370 --> 00:09:54.371 user's defined it toString method will be called. The toString method remove the 00:09:54.371 --> 00:09:58.400 last reference for an array and forces the garbage collection cycle by allocating a 00:09:58.400 --> 00:10:04.070 large amount of memory. Which leads that object will be deallocated by garbage 00:10:04.070 --> 00:10:08.450 collector. The very next thing it is doing is reallocate the new object over a stale 00:10:08.450 --> 00:10:14.180 one. So this is how specially crafted use after free was used in Safari to achieve 00:10:14.180 --> 00:10:19.650 remote code execution and to execute a shellcode. The shellcode exist in a second 00:10:19.650 --> 00:10:25.100 stage, which is a payload which contained the shellcode and compressed data. The 00:10:25.100 --> 00:10:28.460 most interesting for us is the shellcode because it's used for a kernel 00:10:28.460 --> 00:10:33.770 exploitation in Safari context and the compressed data basically is a loader 00:10:33.770 --> 00:10:38.980 that downloads and decrypts the next stage. One of the vulnerabilities used is 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 00:10:45.820 --> 00:10:51.050 randomization. It exploits the information that constructor and OSUnseralizeBinary 00:10:51.050 --> 00:10:58.140 method they miss bound checking. So that mean that attacker can create OSNumber 00:10:58.140 --> 00:11:02.070 object with a really high number of bits and call it within the application sandbox 00:11:02.070 --> 00:11:05.670 where io_registry_entry_get_property_bytes. 00:11:05.670 --> 00:11:10.790 Here's how it looked like. So OSUnseralizeBinary method to handle binary 00:11:10.790 --> 00:11:16.250 serializations in a kernel. It converts a binary format to basic kernel data object. 00:11:16.250 --> 00:11:21.960 It supports different container types, sets, dictionaries, array, object types, 00:11:21.960 --> 00:11:26.720 strings, numbers and the point of interest in this is the OSNumber. So as we see 00:11:26.720 --> 00:11:34.200 here, it passed two arguments: value and length and there is no real check that for 00:11:34.200 --> 00:11:39.950 - for length property. So this mean we can control the length that is passed to an 00:11:39.950 --> 00:11:45.440 object. And why it is a problem, because here is a constructor for OSNumber:init 00:11:45.440 --> 00:11:51.770 and as we see the length property passed here is newnNumberOfBits and it 00:11:51.770 --> 00:11:56.060 overrides the size variable. And the problem that size is used in other 00:11:56.060 --> 00:12:02.040 methods, in a case that OSNumber numberOfBytes, which leads it return value 00:12:02.040 --> 00:12:08.370 of numberOfBytes is now fully controlled by attacker. Which is real bad because 00:12:08.370 --> 00:12:12.400 it's used next in io_registry_entry_get_property_bytes which 00:12:12.400 --> 00:12:17.920 handle OSNumbers and its use numberOfBytes to calculate the object's length, the 00:12:17.920 --> 00:12:24.330 OSNumber length. But unfortunately it use a stack based buffer to parse and save 00:12:24.330 --> 00:12:31.600 OSNumber value. And what happened next, it is copying memory from kernel stack to 00:12:31.600 --> 00:12:37.420 heap used the attacker controlled length. Which mean we can specify how many bytes 00:12:37.420 --> 00:12:43.960 will be copied from a kernel stack and returned to user land. This is what 00:12:43.960 --> 00:12:52.800 happens: the first thing we are doing, we are create a properties array that have a 00:12:52.800 --> 00:12:59.950 dictionary which have a OSNumber with a high length in our case, is 256. Next, we 00:12:59.950 --> 00:13:04.560 need to spawn the user client by calling IOService open extended, which will 00:13:04.560 --> 00:13:11.000 deserialize this OSNumber object and crea- te this object in the - in the kernel. And 00:13:11.000 --> 00:13:16.089 now we need to read it by calling the IORegistryEntryGetProperty, which leads it 00:13:16.089 --> 00:13:22.590 - we copied the 256 bytes of the kernel stack memory and the kernel stack memory 00:13:22.590 --> 00:13:26.960 will contain kernel pointers. And from a kernel pointer, we can determine the 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, 00:13:32.850 --> 00:13:40.110 which is CVE 4656 it is use-after-free to achieve kernel level code execution. It 00:13:40.110 --> 00:13:44.180 exploits information because the setAtIndex macro does not really retain an 00:13:44.180 --> 00:13:48.420 object and we can trigger it within the application sandbox from 00:13:48.420 --> 00:13:56.940 OSUnserializeBinary. Again the OSUnserializeBinary it's a function that 00:13:56.940 --> 00:14:01.940 parse and deserialize objects in the kernel - it support different data types - 00:14:01.940 --> 00:14:06.550 different container types. And the interesting thing it supports kOSSerialize 00:14:06.550 --> 00:14:12.490 object. It means that we can create a reference to another object. Really 00:14:12.490 --> 00:14:18.270 useful in the future, because in a way of deserializing and parsing objects 00:14:18.270 --> 00:14:24.490 OSUnserializeBinary saved object pointer to a special objects array. And using 00:14:24.490 --> 00:14:29.170 setAtIndex for it. And as we see setAtIndex just save object pointer to 00:14:29.170 --> 00:14:37.410 array with some index not retaining it. It's bad, because the next code, which 00:14:37.410 --> 00:14:44.200 casting OSString to a OSSymbol it is releasing the object pointer. What does it 00:14:44.200 --> 00:14:48.790 mean? We still have an array that holds all the object pointers, which is objects 00:14:48.790 --> 00:14:55.770 array, and we just released one of the objects but still hold the pointer. If we 00:14:55.770 --> 00:15:00.200 can create a reference to an object we can exploit use-after-free. This is what 00:15:00.200 --> 00:15:03.560 happens because kOSSerializeObject allows us to create a reference and we will just 00:15:03.560 --> 00:15:09.410 call retain on already deserialized, already deallocated object. This is how 00:15:09.410 --> 00:15:14.490 exploit look like. So first of all, we create OSdictionary and it will contain a 00:15:14.490 --> 00:15:19.530 string that due the bug will be deallocated. So now we need to reallocate 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 00:15:27.510 --> 00:15:34.580 case, OSString class in a memory will be 32 bytes. We need to allocate the same 00:15:34.580 --> 00:15:39.930 size. For this purpose OSData is a perfect candidate because we can control OSData 00:15:39.930 --> 00:15:46.460 buffer, buffer size and buffer content. So what we can do, we can create a fake 00:15:46.460 --> 00:15:50.860 OSString with a fake vtable and this fake vtable will point to some digits in the 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 00:15:55.630 --> 00:16:01.630 kOSSerializeObject. So once again, OSString got deserialized, deallocated, 00:16:01.630 --> 00:16:05.290 reallocated to a new object, which is OSData buffer, which will point to the 00:16:05.290 --> 00:16:12.649 same memory spot: we've got a use-after- free. So after getting use-after-free, 00:16:12.649 --> 00:16:20.290 Pegasus uses some kernel patches to disable security checks like setuid to 00:16:20.290 --> 00:16:26.190 easily escalate the privileges, bypass amfi checks by patching out 00:16:26.190 --> 00:16:31.570 amfi_get_out_of_my_way, disable code signment enforcement by patching 00:16:31.570 --> 00:16:36.060 cs_enforcement_disable variable and finally, a remount the system partition to 00:16:36.060 --> 00:16:41.720 be readable, & writable so it can execute a loader for the next stage to download 00:16:41.720 --> 00:16:50.990 and decrypt the next stage. The next stage contain the real espionage stuff that will 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 00:16:58.910 --> 00:17:09.350 a three groups. One is a process group which have a main process: sniffing 00:17:09.350 --> 00:17:14.850 services model that use a SIP protocol to communicate with command control like a 00:17:14.850 --> 00:17:20.370 process manager and so on. The next interesting thing is a group of the 00:17:20.370 --> 00:17:24.919 dylibs, because Pegasus rely on the Cydia substrate - the jailbreak framework called 00:17:24.919 --> 00:17:29.410 - they renamed it as libdata. It uses Cydia substrate to inject dynamic 00:17:29.410 --> 00:17:34.429 libraries into application process. So in our case, we have a dynamic libraries for 00:17:34.429 --> 00:17:38.202 Viber, for Whatsapp which can be injected into the application space to install 00:17:38.202 --> 00:17:44.990 application hooks. And the last thing is com.apple.itunesstored file. Which is a 00:17:44.990 --> 00:17:53.870 JavaScript that contain code and the shellcode that will execute - that can 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. 00:18:00.480 --> 00:18:06.870 JSC binary is like a helper for JavaScript core, JavaScript and in Apple. And 00:18:06.870 --> 00:18:12.330 it can lead to unsigned code execution. In combination with rtbyddyd trick it can be 00:18:12.330 --> 00:18:18.780 used to completely gain persistence on the device. It exploits that it is a bad cast 00:18:18.780 --> 00:18:24.929 in setEarlyValue method and fortunately it can be triggered only from Jesty 00:18:24.929 --> 00:18:32.030 application context. So what is a problem? It exploits the problem in JavaScript 00:18:32.030 --> 00:18:37.190 binding SetImpureGetterDelegate which have in C++ for function 00:18:37.190 --> 00:18:40.880 SetImpureGetterDelegate. This function takes a few arguments - one is the 00:18:40.880 --> 00:18:47.890 impureGetter and the second one is a generic isObject that will be set as this 00:18:47.890 --> 00:18:54.790 impureGetter delegate. The problem will be next slide - so we just parse two 00:18:54.790 --> 00:18:59.370 arguments and call a setDelegate. The setDelegate called set which finally 00:18:59.370 --> 00:19:05.080 called setEarlyValue. Here is a problem, because there is no real check that the 00:19:05.080 --> 00:19:10.670 object type passed to setImpureGetterDelegate is really 00:19:10.670 --> 00:19:15.950 ImpureGetter. So this means that if any other object type will be passed, it will 00:19:15.950 --> 00:19:21.050 be improperly downcasted as ImpureGetter pointer. That's what happened here. So 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 00:19:28.180 --> 00:19:33.200 overwrite on those object fields. Here are the same function, but now decompiled in IDA 00:19:33.200 --> 00:19:39.620 Pro. So in our case ImpureGetter is a base variable here and the delegate is this 00:19:39.620 --> 00:19:46.020 generic JS object. We see that the pointer, which is base plus 16, can be 00:19:46.020 --> 00:19:50.910 overridden with a pointer to a delegate. Which lead - you see on the right 00:19:50.910 --> 00:19:55.760 JSArrayBufferView class - if I pass JSArrayBufferView class as a first 00:19:55.760 --> 00:20:01.620 argument, the m_vector field will be overwritten with a pointer to a delegate. 00:20:01.620 --> 00:20:09.720 Which is really bad, because it can lead to readable, writeable primitives. To 00:20:09.720 --> 00:20:14.429 exploit that Pegasus uses two dataviews. I will call them dataview one and dataview 00:20:14.429 --> 00:20:20.860 two. And to call and setImpureGetterDelegate on both, which 00:20:20.860 --> 00:20:24.910 leads it m_vector field in the first dataview will be overwritten with the 00:20:24.910 --> 00:20:31.080 pointer for the second dataview. And now by setting and reading the values on the 00:20:31.080 --> 00:20:36.400 first dataview we can override object fields in the second. While we need it, we 00:20:36.400 --> 00:20:42.500 can map the second dataview as entire process memory by overwriting the second 00:20:42.500 --> 00:20:46.580 dataview arraybuffer offset to be zero by overwriting the second dataview length to 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. 00:20:52.460 --> 00:20:56.630 So basically the second dataview now is mapped to the entire process space and we 00:20:56.630 --> 00:21:05.390 can getint, setint to get arbitrary read and write anywhere in the process memory. 00:21:05.390 --> 00:21:09.950 The same thing can be used even to get execution primitive. But in this case, we 00:21:09.950 --> 00:21:16.400 can call setImpureGetterDelegate twice and instead of exposing the entire process 00:21:16.400 --> 00:21:21.380 memory, we can leak just an object address. If you can leak an object 00:21:21.380 --> 00:21:26.530 address, we can produce a function that have like hundreds of try - empty try- 00:21:26.530 --> 00:21:33.230 catch constructions and force JIT to compile it. And in a - in this process, a 00:21:33.230 --> 00:21:38.580 special, readable, writeable, executable memory segment will be allocated. We can 00:21:38.580 --> 00:21:45.270 leak address of this JIT segment, overwrite it with a shellcode and execute. 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 00:21:51.790 --> 00:21:58.040 boot. It is used with a persistence mechanism which is rtbuddyd. So the 00:21:58.040 --> 00:22:03.730 problem is that System spawning rtbuddyd service with a special early-boot 00:22:03.730 --> 00:22:10.500 argument. This mean if you take any other binary signed by Apple and name it as 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 00:22:14.820 --> 00:22:20.700 take JSC binary which is signed by Apple, name it as rtbuddyd, then take a 00:22:20.700 --> 00:22:26.900 JavaScript that contain exploit. Make it a sym link, call it early-boot which leads 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 00:22:31.500 --> 00:22:37.130 js-exploit instead. So with this trick and the bad cast it re-exploits kernel on 00:22:37.130 --> 00:22:46.480 each device boot. There is some tricks the Pegasus use to make it harder to 00:22:46.480 --> 00:22:51.540 reverse engineer, like use one time links. So after you click on any of the link 00:22:51.540 --> 00:22:57.490 they'll be invalidated and now redirect to Google or other sites. It re-encrypts all 00:22:57.490 --> 00:23:02.920 the payloads each time they are downloaded just on the fly. And of course, they are 00:23:02.920 --> 00:23:09.900 trying to hide itself to make it look like a system component. Um, of course, it 00:23:09.900 --> 00:23:15.100 blocks iOS system updates to make sure you can't - you cannot batch your device just 00:23:15.100 --> 00:23:22.510 on the fly, to clear all the evidence: clear Safari history and caches and we 00:23:22.510 --> 00:23:30.290 found a self-destruct mechanism that can be triggered remotely or on a time out. So 00:23:30.290 --> 00:23:35.510 in addition to this terrifying list of supported applications, it records any 00:23:35.510 --> 00:23:40.710 microphone usage, any camera usage, GPS, location, keychain passwords, even 00:23:40.710 --> 00:23:47.250 including the Wi-Fi and the router one. Why they need router - I don't know. 00:23:47.250 --> 00:23:51.280 Application hooking. So how how it operates. As I mentioned earlier, it use 00:23:51.280 --> 00:23:57.299 Cydia substrate and with the help of Cydia substrate it preloads dynamic libraries 00:23:57.299 --> 00:24:04.809 into application process and intercept some critical functions. It uses Cynject 00:24:04.809 --> 00:24:10.870 to run into already - into already running processes. So this is like a high level 00:24:10.870 --> 00:24:18.130 picture of how it looks like. So all the application level critical functions and 00:24:18.130 --> 00:24:21.940 the framework level critical functions are intercepted by Pegasus. So now Pegasus can 00:24:21.940 --> 00:24:27.570 control them, can collect them, can back them, can send Command & Control and so 00:24:27.570 --> 00:24:36.150 on. To summarize, Pegasus is a remote jailbreak spotted in the wild. It's pretty 00:24:36.150 --> 00:24:42.059 scary because it doesn't require any user interaction. And the last similar thing 00:24:42.059 --> 00:24:47.753 was like five years ago when the comex released his jailbreakme 3. This year Luca 00:24:47.753 --> 00:24:52.920 Todesco used one of the Trident vulnerabilities for his jailbreaking. 00:24:54.290 --> 00:24:59.870 I want to say a special thanks to Citizen Lab for helping out with achieving a 00:24:59.870 --> 00:25:05.289 Pegasus sample. All the Lookout research & response team, the Divergent security guys 00:25:05.289 --> 00:25:11.310 and all the individual researchers who was involved in the research. So last some 00:25:11.310 --> 00:25:17.470 useful links which contain a 44 page PDF report with a really, really deep details 00:25:17.470 --> 00:25:23.710 on the vulnerabilities that is used even with the difference between 32 and 64 bit 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 00:25:31.059 --> 00:25:33.280 guys have any questions? 00:25:33.290 --> 00:25:41.562 applause 00:25:44.682 --> 00:25:48.432 M: Mm hmm. H: OK, please keep it brief. We only have 00:25:48.432 --> 00:25:50.470 some minutes left for the questions, and if there are any questions, please go to 00:25:50.470 --> 00:25:56.830 the microphones in the hall. And we start with the Signal Angel from the Internet. 00:25:56.830 --> 00:26:03.530 SA: Thank you. Is there any way to build your app, protect it from this exploit? 00:26:03.530 --> 00:26:13.160 M: Yes, it is, because the Pegasus use some of the known jailbreak techniques it 00:26:13.160 --> 00:26:18.480 is possible to detect for example that system partition is remounted as readable 00:26:18.480 --> 00:26:23.650 & writable. It could be one of the indicators that some generic jailbreak is 00:26:23.650 --> 00:26:29.900 running on a device. Or like check for especially file that Pegasus use but like 00:26:29.900 --> 00:26:33.870 better check it in general for jailbreak pages, the kernel pages. 00:26:33.870 --> 00:26:37.540 audience shuffling noise H: Please try to stay a bit quiet. We are 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 00:26:40.170 --> 00:26:47.100 seated until afterwards and if you have to leave now, please do not talk. Microphone 00:26:47.100 --> 00:26:50.200 three, please. M3: What's the user experience during 00:26:50.200 --> 00:26:53.480 this? M: User experience, I mean - you mean - 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 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, 00:27:07.110 --> 00:27:13.080 the mobile web browser opens and just closes and crashes. There is no new 00:27:13.080 --> 00:27:19.340 applications spotted on your on visible applications and so on. But in a real it's 00:27:19.340 --> 00:27:26.390 running like three new system services, but they are not visible to a user. 00:27:26.390 --> 00:27:29.370 H: Thank you. And please, another question from the Internet. 00:27:29.370 --> 00:27:33.300 SA: Thank you. Have you any idea how active this exploit is in the world? 00:27:33.300 --> 00:27:39.590 M: Say it again please? SA: Have you any idea how active this 00:27:39.590 --> 00:27:46.580 exploit is in the wild? M: I'm sure it was a very targeted attack 00:27:46.580 --> 00:27:51.860 because, uh, these exploits are pretty expensive. For example, uh, Zerodium now 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 00:27:59.770 --> 00:28:06.860 this like spyware, want to like - want to deal malware accessible for everyone. So I 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 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, 00:28:19.690 --> 00:28:22.480 very targeted thing because it's very expensive. 00:28:22.480 --> 00:28:26.590 H: Thank you for this answer. Microphone number five, please. 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 00:28:33.300 --> 00:28:38.720 they using any other software? And how spread is this in the wild again? 00:28:38.720 --> 00:28:42.919 M: Yeah. So in this case, we focused mostly on the technicalities of the 00:28:42.919 --> 00:28:49.809 Pegasus itself, but Citizen Lab made their investigation on NSO and the like the 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 00:28:56.600 --> 00:29:00.140 on that. So they have much more information. 00:29:02.280 --> 00:29:07.750 H: Do we have a question from the Internet? Am I overlooking anyone? No, 00:29:07.750 --> 00:29:10.150 then this is it, thank you for your talk. 00:29:10.150 --> 00:29:14.480 applause 00:29:15.091 --> 00:29:24.670 postroll music 00:29:24.670 --> 00:29:37.610 Subtitles created by c3subtitles.de in the year 2022. Join, and help us! 00:29:37.610 --> 00:29:39.000 [Translated by {Iikka}{Yli-Kuivila} (ITKST56 course assignment at JYU.FI)]