Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F10360240
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/http_server/code/index.html b/http_server/code/index.html
index e8053f7..0a73df8 100644
--- a/http_server/code/index.html
+++ b/http_server/code/index.html
@@ -1,186 +1,189 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Rentgen android</title>
<style>
main {
display: flex;
}
.log-section {
height: 600px;
width: 480px;
overflow-y: auto;
display: flex;
flex-direction: column;
margin-left: 20px;
}
.screen {
display: inline-block;
cursor: pointer;
}
.screen-buttons {
display: flex;
justify-content: space-around;
margin-top: 5px;
gap: 10px;
}
.screen-buttons button {
font-size: 1.1rem;
padding: 10px 20px;
width: 100%;
cursor: pointer;
background-color: transparent;
}
.screen-buttons button:hover {
background-color: aqua;
}
#clicks-log {
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console,
monospace;
}
</style>
</head>
<body>
<main>
<section class="screen-section">
<img
id="screen"
alt="android screen"
src=""
draggable="false"
class="screen"
/>
<div class="screen-buttons">
<button class="screen-buttons-home">home</button>
<button class="screen-buttons-back">back</button>
</div>
</section>
<p id="clicks-log" class="log-section"></p>
<p id="traffic-log" class="log-section"></p>
</main>
<script>
var screen = document.getElementById("screen");
var clicksLog = document.getElementById("clicks-log");
const homeButton = document.querySelector(".screen-buttons-home");
const backButton = document.querySelector(".screen-buttons-back");
let lastTouch = new Date().getTime();
const calculateElapsedTime = (last) => {
const currentTouch = new Date().getTime();
const elapsedTime = currentTouch - lastTouch;
const elapsedSec = Math.round(elapsedTime / 1000);
lastTouch = currentTouch;
return elapsedSec;
};
const waitToLog = (clickInfoText) => {
const clickInfo = document.createElement("span");
const waitInfo = document.createElement("span");
waitInfo.textContent = `await wait(${calculateElapsedTime(
lastTouch
)});`;
clicksLog.appendChild(waitInfo);
clickInfo.textContent = clickInfoText;
clicksLog.appendChild(clickInfo);
};
const registerClick = ({ path, logText, body }) => {
const clicksLog = document.getElementById("clicks-log");
const span = document.createElement("span");
waitToLog(logText);
fetch(path, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
...(body ? { body } : {}),
});
};
homeButton.addEventListener("click", () =>
registerClick({ path: "home", logText: "await homeButton();" })
);
backButton.addEventListener("click", () =>
registerClick({ path: "back", logText: "await backButton();" })
);
async function displayImage() {
try {
const response = await fetch("screen");
const blob = await response.blob();
screen.src = URL.createObjectURL(blob);
} catch (error) {
console.error("Error fetching image: ", error);
}
}
let isDragging = false;
let startDraggingPosX = 0;
let endDraggingPosX = 0;
let startDraggingPosY = 0;
let endDraggingPosY = 0;
+ const screenSize = [320, 640]
+
const handleDraggStart = (e) => {
e.preventDefault();
isDragging = true;
startDraggingPosX = e.offsetX;
startDraggingPosY = e.offsetY;
};
screen.addEventListener("mousedown", handleDraggStart);
document.addEventListener("mouseup", (e) => {
endDraggingPosX = e.offsetX;
endDraggingPosY = e.offsetY;
if (
- (isDragging && Math.abs(endDraggingPosY - startDraggingPosY) > 10) ||
- Math.abs(endDraggingPosX - startDraggingPosX) > 10
+ isDragging && (Math.abs(endDraggingPosY - startDraggingPosY) > 10 ||
+ Math.abs(endDraggingPosX - startDraggingPosX) > 10)
) {
registerClick({
path: "drag",
logText: `await drag({x:${startDraggingPosX},y:${startDraggingPosY}},{x:${e.offsetX},y:${e.offsetY}});`,
body: `startX=${startDraggingPosX}&startY=${startDraggingPosY}&endX=${e.offsetX}&endY=${e.offsetY}`,
});
- isDragging = false;
} else {
const phoneX = event.offsetX;
const phoneY = event.offsetY;
- registerClick({
- path: "touch",
- logText: `await click(${phoneX}, ${phoneY});`,
- body: `x=${phoneX}&y=${phoneY}`,
- });
+ if (phoneX <= screenSize[0] && phoneY <= screenSize[1])
+ registerClick({
+ path: "touch",
+ logText: `await click(${phoneX}, ${phoneY});`,
+ body: `x=${phoneX}&y=${phoneY}`,
+ });
}
+ isDragging = false;
});
async function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async function screenshot_loop() {
var before;
while (true) {
before = performance.now();
await displayImage();
while (performance.now() - before < ___screenshotDelayMs___)
await sleep(50);
}
}
screenshot_loop();
</script>
<script src="/trafficLog.js"></script>
</body>
</html>
diff --git a/http_server/code/index.mjs b/http_server/code/index.mjs
index 639917f..b519ae3 100644
--- a/http_server/code/index.mjs
+++ b/http_server/code/index.mjs
@@ -1,143 +1,82 @@
import express from "express";
-import net from "net";
-import fs from "fs";
import { readFile } from "node:fs/promises";
+import { guardedScreenshot, socket_client, waitFullBoot } from "./screenshot.mjs";
const device_size_x = 320;
const device_size_y = 640;
const app = express();
app.use(express.urlencoded({ extended: false }));
-const socket_client = net.createConnection({ port: 3000, host: "android" });
-
-async function sleep(time) {
- return new Promise((resolve) => setTimeout(resolve, time));
-}
-
-let doneWrite = 0;
-let screenshotPromise = null;
-
-async function screenshot() {
- const time_start = Date.now();
- socket_client.write("screenshot");
- while (!doneWrite) {
- await sleep(15);
- if (Date.now() - time_start > 2000) {
- console.error("Screenshot timed out after 2s");
- break; // timeout
- }
- }
- doneWrite = 0;
- screenshotPromise = null;
-}
-
-async function guardedScreenshot() {
- console.log("Requesting a screenshot");
- if (!screenshotPromise) {
- console.log("no ongoing promise, starting a new one");
- screenshotPromise = screenshot();
- }
- return screenshotPromise;
-}
-
-async function waitFullBoot() {
- var start = performance.now();
- var counter = 0;
-
- //will timeout after 10 min
- while (performance.now() - start < 600 * 1000) {
- var before = performance.now();
- await screenshot();
- var after = performance.now();
- if (after - before < process.env.screenshotDelayMs) counter++;
- else counter = 0;
-
- if (counter === 10) return;
- }
-
- throw new Error("wait for screenshot time to be less than 0.5s timed out");
-}
-
-let fd;
-socket_client.on("data", (dataBuf) => {
- if (dataBuf.toString() === "start")
- fd = fs.openSync("/code/screenshot.png", "w");
- else {
- if (dataBuf.toString().includes("ENDOFMSG")) {
- fs.writeSync(fd, dataBuf);
- fs.close(fd);
- doneWrite = 1;
- } else fs.writeSync(fd, dataBuf);
- }
-});
console.log("Waiting for full boot...");
await waitFullBoot();
console.log("Boot detected! activating endpoints");
-app.get("/screen", async function (req, res) {
- await guardedScreenshot();
- res.sendFile("/code/screenshot.png");
-});
-
+//GET
app.get("/favicon.ico", function (req, res) {
res.sendFile("/code/favicon.ico");
});
app.get("/trafficLog.js", function (req, res) {
res.sendFile("/code/dist/trafficLog.js");
});
app.get("/trafficLog", async function (req, res) {
res.sendFile("/log/trafficLog");
});
-app.post("/touch", function (req, res) {
- const x = parseInt(req.body.x);
- const y = parseInt(req.body.y);
-
- if (isNaN(x) || isNaN(y) || x > device_size_x || y > device_size_y) {
- res.send(
- `the query params must be x <= ${device_size_x}, y <= ${device_size_y}\n`
- );
- } else {
- socket_client.write(`touch ${x} ${y}`);
- res.sendStatus(200);
- }
+app.get("/screen", async function (req, res) {
+ await guardedScreenshot();
+ res.sendFile("/code/screenshot.png");
});
app.get("/", async function (req, res) {
let fileData = (await readFile("/code/index.html")).toString();
fileData = fileData.replace(
"___screenshotDelayMs___",
process.env.screenshotDelayMs
);
-
+
res.setHeader("Content-Type", "text/html");
res.setHeader("Content-Disposition", "inline");
-
+
res.send(fileData);
});
+//POST
app.post("/back", function (req, res) {
socket_client.write(`back`);
res.sendStatus(200);
});
app.post("/home", function (req, res) {
socket_client.write(`home`);
res.sendStatus(200);
});
+app.post("/touch", function (req, res) {
+ const x = parseInt(req.body.x);
+ const y = parseInt(req.body.y);
+
+ if (isNaN(x) || isNaN(y) || x > device_size_x || y > device_size_y) {
+ res.send(
+ `the query params must be x <= ${device_size_x}, y <= ${device_size_y}\n`
+ );
+ } else {
+ socket_client.write(`touch ${x} ${y}`);
+ res.sendStatus(200);
+ }
+});
+
app.post("/drag", function (req, res) {
const body = req.body;
const startX = Number(body.startX);
const startY = Number(body.startY);
const endX = Number(body.endX);
const endY = Number(body.endY);
socket_client.write(`drag ${startX} ${startY} ${endX} ${endY}`);
res.sendStatus(200);
});
app.listen(8080, () => console.log("Listening in port 8080"));
diff --git a/http_server/code/screenshot.mjs b/http_server/code/screenshot.mjs
new file mode 100644
index 0000000..9c93e15
--- /dev/null
+++ b/http_server/code/screenshot.mjs
@@ -0,0 +1,62 @@
+import net from "net";
+import fs from "fs";
+import { sleep } from "./utils.mjs";
+
+export const socket_client = net.createConnection({ port: 3000, host: "android" });
+
+let doneWrite = 0;
+let screenshotPromise = null;
+
+async function screenshot() {
+ const time_start = Date.now();
+ socket_client.write("screenshot");
+ while (!doneWrite) {
+ await sleep(15);
+ if (Date.now() - time_start > 2000) {
+ console.error("Screenshot timed out after 2s");
+ break; // timeout
+ }
+ }
+ doneWrite = 0;
+ screenshotPromise = null;
+}
+
+export async function guardedScreenshot() {
+ console.log("Requesting a screenshot");
+ if (!screenshotPromise) {
+ console.log("no ongoing promise, starting a new one");
+ screenshotPromise = screenshot();
+ }
+ return screenshotPromise;
+}
+
+export async function waitFullBoot() {
+ var start = performance.now();
+ var counter = 0;
+
+ //will timeout after 10 min
+ while (performance.now() - start < 600 * 1000) {
+ var before = performance.now();
+ await screenshot();
+ var after = performance.now();
+ if (after - before < process.env.screenshotDelayMs) counter++;
+ else counter = 0;
+
+ if (counter === 10) return;
+ }
+
+ throw new Error("wait for screenshot time to be less than 0.5s timed out");
+}
+
+let fd;
+socket_client.on("data", (dataBuf) => {
+ if (dataBuf.toString() === "start")
+ fd = fs.openSync("/code/screenshot.png", "w");
+ else {
+ if (dataBuf.toString().includes("ENDOFMSG")) {
+ fs.writeSync(fd, dataBuf);
+ fs.close(fd);
+ doneWrite = 1;
+ } else fs.writeSync(fd, dataBuf);
+ }
+});
\ No newline at end of file
diff --git a/http_server/code/utils.mjs b/http_server/code/utils.mjs
new file mode 100644
index 0000000..31e4abf
--- /dev/null
+++ b/http_server/code/utils.mjs
@@ -0,0 +1,3 @@
+export async function sleep(time) {
+ return new Promise((resolve) => setTimeout(resolve, time));
+}
\ No newline at end of file
diff --git a/intraContainerCom.txt b/intraContainerCom.txt
new file mode 100644
index 0000000..67d9d2d
--- /dev/null
+++ b/intraContainerCom.txt
@@ -0,0 +1,11 @@
+INTRA CONTAINER COMMUNICATION
+
+FROM HTTPSERVER TO ANDROID
+- screenshot
+- home
+- back
+- touch $x $y
+- drag $startx $starty $endx $endy
+
+FROM ANDROID TO HTTPSERVER
+- start $screenshotdata ENDOFMSG (to send screenshot data)
\ No newline at end of file
diff --git a/start.mjs b/start.mjs
index 12bc017..08d92b4 100644
--- a/start.mjs
+++ b/start.mjs
@@ -1,94 +1,94 @@
import { promises as fs } from "fs";
async function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async function checkCertExistance() {
return await Promise.all([
fs.access("./certificates/mitmproxy-ca-cert.cer", fs.constants.R_OK),
fs.access("./certificates/mitmproxy-ca-cert.p12", fs.constants.R_OK),
fs.access("./certificates/mitmproxy-ca-cert.pem", fs.constants.R_OK),
fs.access("./certificates/mitmproxy-ca.p12"),
fs.access("./certificates/mitmproxy-ca.pem"),
fs.access("./certificates/mitmproxy-dhparam.pem", fs.constants.R_OK),
]);
}
async function generateCert() {
//remove certs if they exist
try {
await $`rm -rf certificates`;
} catch {
throw new Error(
"To remove certificates, and create new ones, this command must be run with sudo"
);
}
//iniciate docker which will create certs
$`docker run --rm -v $PWD/certificates:/home/mitmproxy/.mitmproxy --name certGenerator mitmproxy/mitmproxy:9.0.1 mitmdump &`;
//wait for certs to generate
let generated = false;
while (!generated) {
try {
await checkCertExistance();
generated = true;
} catch {}
}
//kill docker container
$`docker stop certGenerator`;
}
async function generatePreAndroid() {
await $`docker build -t pre_android pre_android`;
- $`docker run --rm -v $PWD/certificates/mitmproxy-ca-cert.cer:/ca-cert.cer -v $PWD/pre_android/preconf:/preconf --device=/dev/kvm --name pre_android_cont pre_android &`;
+ $`docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --rm -v $PWD/certificates/mitmproxy-ca-cert.cer:/ca-cert.cer -v $PWD/pre_android/preconf:/preconf --device=/dev/kvm --name pre_android_cont pre_android &`;
console.log(
"Installing tls certificate and culebra into the android pre-image..."
);
//the way of knowing when the culebra install is creating a file in the shared volume
let finished = false;
while (!finished) {
try {
await fs.access(
"./pre_android/preconf/finished",
fs.constants.R_OK
),
$`rm -f ./pre_android/preconf/finished`;
finished = true;
} catch {
await sleep(100);
}
}
await $`docker commit pre_android_cont pre_android/ready`;
$`docker stop pre_android_cont`;
}
if (process.argv.length !== 4) throw new Error("expected an argument");
else if (process.argv[3] === "up") {
try {
await checkCertExistance();
} catch {
await generateCert();
}
try {
await $`docker image inspect pre_android/ready > /dev/null 2> /dev/null`;
} catch {
await generatePreAndroid();
}
await $`docker compose build`;
await $`docker compose up`;
} else if (process.argv[3] === "down") await $`docker compose down`;
else if (process.argv[3] === "generateCert") {
generateCert();
} else if (process.argv[3] === "generatePreAndroid") {
generatePreAndroid();
} else
throw new Error(
- "expected [up | down | generateCert | generatePreAndroid ] as argument"
+ "expected [ up | down | generateCert | generatePreAndroid ] as argument"
);
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 8, 05:47 (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1034069
Default Alt Text
(16 KB)
Attached To
Mode
R134 rentgen-android
Attached
Detach File
Event Timeline
Log In to Comment