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)]