Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F7112638
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/android/conf/install.sh b/android/conf/install.sh
index 42d63c1..8fc425f 100644
--- a/android/conf/install.sh
+++ b/android/conf/install.sh
@@ -1,4 +1,4 @@
#!/bin/bash
set -e
# -r to replace an existing application if any
-/opt/android-sdk-linux/platform-tools/adb install -r /shared_buffer/app.apk
+/opt/android-sdk-linux/platform-tools/adb install-multiple -r /shared_buffer/*.apk
diff --git a/http_server/code/index.html b/http_server/code/index.html
index 09edaf1..0780381 100644
--- a/http_server/code/index.html
+++ b/http_server/code/index.html
@@ -1,320 +1,320 @@
<!DOCTYPE html>
<html lang="en">
<head style="height: 100vh">
<meta charset="UTF-8" />
<title>Rentgen android</title>
<script src="/htmx.js"></script>
<style>
main {
display: flex;
}
.log-section {
height: auto;
width: 400px;
overflow: 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;
}
.tab {
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
.tabcontent.active {
display: flex;
flex-grow: 1;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
html,
body, main{
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
}
main {
display:flex;
flex-direction: row;
align-items: stretch;
}
#logs-tab {
overflow: auto;
text-wrap: wrap;
}
.screen-section {
display: flex;
flex-direction: column;
}
.screen-section #screen, .screen-section.screen_buttons {
flex-grow: 0;
}
.tab-section {
display: flex; flex-direction: column; flex-grow: 1;
}
<!-- TODO: A notification system -->
#resp {
display: none;
}
#upload_form {
display:flex;
flex-direction: column;
}
#upload_form button, #upload_form label {
border: 2px solid #ccc;
background-color: #f1f1f1;
cursor: pointer;
padding: 3px 10px;
transition: 0.3s;
}
#upload_form button:hover, #upload_form label:hover {
background-color: #ddd;
}
</style>
</head>
<body>
<div id="resp"></div>
<main>
<section class="screen-section" >
<img
id="screen"
alt="android screen"
src=""
draggable="false"
class="screen"
style="flex-grow: 0"
/>
<div class="screen-buttons" style="flex-grow: 0">
<button class="screen-buttons-home">home</button>
<button class="screen-buttons-back">back</button>
</div>
<form id="upload_form" hx-post="/upload_apk" enctype="multipart/form-data" hx-target="#resp">
<label id="upload_input" for="app">Select file
- <input type="file" id="app" name="app" accept=".apk" required/>
+ <input type="file" id="app" name="app" accept=".apk" required multiple/>
</label>
<button type="submit">Install the app</button>
</form>
</section>
<div class="tab-section" >
<div class="tab">
<button class="tablinks active" onclick="open_tab(event, 'httptoolkit-tab')">HttpToolkit UI</button>
<button class="tablinks" onclick="open_tab(event, 'logs-tab')">Logs</button>
</div>
<div class="tabcontent" id="logs-tab">
<p id="clicks-log" class="log-section" ></p>
<p id="traffic-log" class="log-section"></p>
</div>
<div class="tabcontent active" id="httptoolkit-tab">
<iframe id="httptoolkit-frame" style="flex-grow: 1;" src="http://localhost:9080/" title="httptoolkit"></iframe>
</div>
</div>
</main>
<script>
function open_tab(evt, tab_name) {
let i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
if (tabcontent[i].id != tab_name) {
tabcontent[i].classList.remove("active");
} else {
tabcontent[i].classList.add("active");
}
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].classList.remove("active")
}
// Show the current tab, and add an "active" class to the button that opened the tab
evt.currentTarget.classList.add("active");
}
</script>
<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)
) {
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}`,
});
} else if (e.target === screen) {
const phoneX = event.offsetX;
const phoneY = event.offsetY;
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 5066b91..32d82bf 100644
--- a/http_server/code/index.mjs
+++ b/http_server/code/index.mjs
@@ -1,110 +1,111 @@
import express from "express";
import { readFile } from "node:fs/promises";
import {
guardedScreenshot,
android_websocket,
waitFullBoot,
} from "./screenshot.mjs";
+import { execSync } from 'node:child_process';
+
import fileUpload from 'express-fileupload';
const device_size_x = 320;
const device_size_y = 640;
const app = express();
app.use(express.urlencoded({ extended: false }));
console.log("Waiting for full boot...");
await waitFullBoot();
console.log("Boot detected! activating endpoints");
//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("/htmx.js", function (req, res) {
res.sendFile("/code/node_modules/htmx.org/dist/htmx.min.js");
});
app.get("/trafficLog", async function (req, res) {
res.sendFile("/log/trafficLog");
});
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) {
android_websocket.send(`back`);
res.sendStatus(200);
});
// default options
app.use(fileUpload());
-app.post('/upload_apk',function (req, res) {
+app.post('/upload_apk', async function (req, res) {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
- let file = req.files.app;
- let uploadPath = '/shared_buffer/app.apk';
-
- file.mv(uploadPath, function(err) {
- if (err)
- return res.status(500).send(err);
- android_websocket.send(`install`);
- res.send('File uploaded!');
- });
+ execSync("rm -rf /shared_buffer/*");
+ console.log(req.files);
+ for (const [idx, file] of req.files.app.entries()) {
+ let uploadPath = '/shared_buffer/app' + idx + '.apk';
+ await file.mv(uploadPath);
+ }
+ android_websocket.send(`install`);
+ res.send('Files uploaded!');
})
app.post("/home", function (req, res) {
android_websocket.send(`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 {
android_websocket.send(`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);
android_websocket.send(`drag ${startX} ${startY} ${endX} ${endY}`);
res.sendStatus(200);
});
app.listen(8080, () => console.log("Listening in port 8080"));
diff --git a/pre_android/Dockerfile b/pre_android/Dockerfile
index 4789670..95efdde 100644
--- a/pre_android/Dockerfile
+++ b/pre_android/Dockerfile
@@ -1,10 +1,9 @@
FROM runmymind/docker-android-sdk:ubuntu-standalone-20230511
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/android-sdk-linux/cmdline-tools/latest/bin:/opt/android-sdk-linux/cmdline-tools/tools/bin:/opt/android-sdk-linux/tools/bin:/opt/android-sdk-linux/build-tools/32.0.0:/opt/android-sdk-linux/platform-tools:/opt/android-sdk-linux/emulator:/opt/android-sdk-linux/bin
-RUN sdkmanager "system-images;android-33;google_apis;x86_64"
-RUN echo no | avdmanager create avd -n virtual_dev -b google_apis/x86_64 -k "system-images;android-33;google_apis;x86_64"
-
-RUN apt-get update && apt-get install -y iproute2 iputils-ping iptables redsocks npm git
+RUN sdkmanager --channel=2 "system-images;android-30;google_apis;x86_64" \
+ && echo no | avdmanager create avd -n virtual_dev -b google_apis/x86_64 -k "system-images;android-30;google_apis;x86_64" \
+ && apt-get update && apt-get install -y iproute2 iputils-ping npm git
CMD bash /preconf/docker-entrypoint.sh
diff --git a/pre_android/preconf/docker-entrypoint.sh b/pre_android/preconf/docker-entrypoint.sh
index 770c6ea..149ae85 100644
--- a/pre_android/preconf/docker-entrypoint.sh
+++ b/pre_android/preconf/docker-entrypoint.sh
@@ -1,15 +1,11 @@
-hashed_name=`openssl x509 -inform PEM -subject_hash_old -in /ca-cert.pem | head -1`
-
adb start-server
emulator -avd virtual_dev -writable-system -no-window -no-audio &
-cp /ca-cert.pem /$hashed_name.0
-bash /preconf/install_cert.sh $hashed_name.0
bash /preconf/install_culebra.sh
adb emu avd snapshot save configured
adb emu kill
#to let the host know it finished installing
install -m 777 /dev/null /preconf/finished
tail -f /dev/null
diff --git a/pre_android/preconf/install_cert.sh b/pre_android/preconf/install_cert.sh
deleted file mode 100644
index 0c0b5a6..0000000
--- a/pre_android/preconf/install_cert.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-wait-for-offline() {
- while [ $(adb devices | grep offline | wc -l) -eq 0 ]; do
- sleep 0.1
- done
-}
-
-adb wait-for-device
-adb root
-
-wait-for-offline
-adb wait-for-device
-adb shell avbctl disable-verification
-
-#here may be the issue with the bypass (start)
-adb wait-for-device
-adb reboot
-
-adb wait-for-device
-adb root
-#(end)
-
-wait-for-offline
-adb wait-for-device
-adb remount
-
-adb wait-for-device
-adb reboot
-
-adb wait-for-device
-adb root
-
-wait-for-offline
-adb wait-for-device
-adb remount
-
-adb wait-for-device
-adb push /$1 /system/etc/security/cacerts
-adb shell chmod 664 /system/etc/security/cacerts/$1
-adb reboot
-
-#wait for complete boot
-adb wait-for-device
-while [ "$(adb shell getprop sys.boot_completed | tr -d '\r')" != "1" ]; do
- sleep 1
-done
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 23:52 (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
799741
Default Alt Text
(15 KB)
Attached To
Mode
R134 rentgen-android
Attached
Detach File
Event Timeline
Log In to Comment