import child_process from "child_process"; import fs from "fs"; import { Server } from "socket.io"; async function spawnPromise(program, args) { return new Promise((resolve, _reject) => { let output = ""; const process = child_process.spawn(program, args); process.stdout.on("data", (data) => { output += data; }); process.stderr.on("data", (data) => { output += data; }); process.on("close", (code) => { resolve({ output, code }); }); }); } let io = new Server(); import { get_screenshot } from "./screenshot.mjs"; async function send_private_data() { let adid = await spawnPromise("bash", ["/conf/get_adid.sh"]); adid = adid.output; let gps_coords = await spawnPromise("bash", ["/conf/get_location.sh"]); gps_coords = gps_coords.output; gps_coords = gps_coords.trim().split(","); io.emit("private_info", { adid, latitude: gps_coords[0], longitude: gps_coords[1], }); } async function send_open_ports() { let ports = new Set( (await spawnPromise("bash", ["/conf/get_ports.sh"])).output .trim() .split(" ") ); let start_ports = fs.readFileSync("/ports").toString().trim().split(" "); for (let port of start_ports) { ports.delete(port); } io.emit("open_ports", [...ports]); } async function send_installed_apps() { let out = await spawnPromise("bash", ["/conf/get_installed_apps.sh"]); if (out.code != 0) { send_notification( io, false, "Listing installed apps with frida", out.output ); } io.emit("installed_apps", JSON.parse(out.output)); } function send_notification(socket, is_ok, context, message) { socket.emit("notification", { is_ok, context, message, }); } let gps_setting_in_progress = false; //maybe check output of child processes and send errors in some way io.on("connection", (socket) => { socket.onAny((ev, ...args) => { console.log("server got: ", ev, ...args); }); let screenshots_in_flight = 0; socket.on("screenshot", async () => { if (screenshots_in_flight > 1) return; screenshots_in_flight++; let screen; try { screen = await fetch( "http://localhost:9987/v2/uiDevice/screenshot" ); let body = await screen.bytes(); screen = (await get_screenshot()).buffer; socket.emit("screenshot_data", body); } catch (err) { console.error( "Failed to get the screenshot from culebra, the emulator probably died", err ); return; } screenshots_in_flight--; }); let priv_data_requests_in_flight = 0; socket.on("private_info_req", async () => { if (priv_data_requests_in_flight > 3) return; priv_data_requests_in_flight++; await send_private_data(); priv_data_requests_in_flight--; }); let port_requests_in_flight = 0; socket.on("open_ports_req", async () => { if (port_requests_in_flight > 3) return; port_requests_in_flight++; await send_open_ports(); port_requests_in_flight--; }); let installed_apps_requests_in_flight = 0; socket.on("installed_apps_req", async () => { if (installed_apps_requests_in_flight > 3) return; installed_apps_requests_in_flight++; await send_installed_apps(); installed_apps_requests_in_flight--; }); socket.on("start_frida_app", async (app_id) => { await spawnPromise("bash", ["/conf/start_frida_app.sh", app_id]); send_notification( socket, true, "Frida intercepting stopped", "the traffic of " + app_id + " is no longer being intercepted" ); }); socket.on("reset_adid", async () => { await spawnPromise("bash", ["/conf/reset_adid.sh"]); await send_private_data(); }); socket.on("back", async () => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } await spawnPromise("bash", ["/conf/back.sh"]); }); socket.on("recent", async () => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } await spawnPromise("bash", ["/conf/recent.sh"]); }); socket.on("home", async () => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } await spawnPromise("bash", ["/conf/home.sh"]); }); socket.on("install", async () => { const res = await spawnPromise("bash", ["/conf/install.sh"]); send_notification( socket, res.code === 0, "Installing the application", res.output ); }); // drag handles both drag and click socket.on("motionevent", async (data) => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } await spawnPromise("bash", [ "/conf/motionevent.sh", data.motionType, data.x + "", data.y + "", ]); }); // drag handles both drag and click socket.on("drag", async (data) => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } await spawnPromise("bash", [ "/conf/drag.sh", data.startX + "", data.startY + "", data.endX + "", data.endY + "", data.dragTime + "", ]); }); socket.on("key", async (data) => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } await spawnPromise("bash", ["/conf/press_key.sh", data.key]); }); socket.on("setcoord", async (data) => { if (gps_setting_in_progress) { send_notification( socket, false, "Interactions not allowed when setting gps coordinates", "" ); return; } gps_setting_in_progress = true; const res = await spawnPromise("bash", [ "/conf/set_geo_full.sh", data.lon + "", data.lat + "", ]); send_notification( socket, res.code === 0, "Setting the moch location", res.output ); gps_setting_in_progress = false; await send_private_data(); }); }); io.listen(3000); console.log("listening on port 3000");