Page MenuHomeSealhub

No OneTemporary

diff --git a/android/conf/start_culebra.sh b/android/conf/start_culebra.sh
index 98931e2..ec941ad 100644
--- a/android/conf/start_culebra.sh
+++ b/android/conf/start_culebra.sh
@@ -1,18 +1,18 @@
set -x
function culebra_loop() {
export PATH=$PATH:/root/culebraDependencies
cd /root/culebra
while true; do
./culebratester2 start-server
done
}
rm -f /opt/android-sdk-linux/.android/avd/virtual_dev.avd/*.lock
adb start-server
-emulator -avd virtual_dev -writable-system -no-window -no-audio &
+emulator -avd virtual_dev -writable-system -no-window -no-audio -memory 4096 &
adb wait-for-device
adb emu avd snapshot load configured
culebra_loop
diff --git a/http_server/code/index.mjs b/http_server/code/index.mjs
index a60e24e..222f219 100644
--- a/http_server/code/index.mjs
+++ b/http_server/code/index.mjs
@@ -1,111 +1,110 @@
import express from "express";
import { readFile } from "node:fs/promises";
import { execSync } from "node:child_process";
import { Server } from "socket.io";
import { io } from "socket.io-client";
import { build_html } from "./har-analyzer/build_html.js"
import fileUpload from "express-fileupload";
const app = express();
async function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
console.log("Waiting for full boot...");
// bidirectional forwarding
// Wait untill the connection
const back = io("ws://android:3000", {
reconnectionAttempts: 1000000,
reconnectionDelay: 100,
});
while (!back.connected) {
await sleep(100);
}
console.log("Boot detected! activating endpoints");
app.use(express.urlencoded({ extended: false }));
app.use(express.static("/code/dist"));
//GET
app.get("/favicon.ico", function (_req, res) {
res.sendFile("/code/favicon.ico");
});
app.get("/htmx.js", function (_req, res) {
res.sendFile("/code/node_modules/htmx.org/dist/htmx.min.js");
});
app.get("/socket.io.js", function (_req, res) {
res.sendFile("/code/node_modules/socket.io/client-dist/socket.io.js");
});
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.use(express.text({limit: "100mb"}));
app.post("/inspect_har", function (req, res) {
let body = JSON.parse(req.body);
let har = JSON.stringify(body.har);
- console.log(har);
let private_data;
if (body.private_data)
- private_data = JSON.stringify(body.private_data);
+ private_data = body.private_data;
res.setHeader("Content-Type", "text/html");
res.send(build_html(har, private_data, "/code/har-analyzer/"));
});
app.use(fileUpload());
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.");
}
execSync("rm -rf /shared_buffer/*");
if (Array.isArray(req.files.app)) {
for (const [idx, file] of req.files.app.entries()) {
let uploadPath = "/shared_buffer/app" + idx + ".apk";
await file.mv(uploadPath);
}
} else {
let uploadPath = "/shared_buffer/app" + 0 + ".apk";
await req.files.app.mv(uploadPath);
}
back.emit("install");
res.send("Files uploaded!");
});
let server = app.listen(8080, () => console.log("Listening in port 8080"));
const front = new Server(server);
// forwarding the messages
front.on("connection", (socket) => {
socket.onAny((event, ...args) => {
if (back.connected) {
back.emit(event, ...args);
} else {
console.log("Front tried to send: ", event, ...args);
}
});
});
back.onAny((event, ...args) => {
front.emit(event, ...args);
});
diff --git a/http_server/code/src/notifications.jsx b/http_server/code/src/notifications.jsx
index 5105dc3..edfe1b8 100644
--- a/http_server/code/src/notifications.jsx
+++ b/http_server/code/src/notifications.jsx
@@ -1,68 +1,67 @@
import { render, Component } from "preact";
import { io } from "socket.io-client";
function rand_num() {
return Math.floor(Math.random() * Number.MAX_VALUE);
}
class Notifications extends Component {
constructor() {
super();
this.state = { notifications: [] };
}
remove_notification(id) {
const newNotifications = this.state.notifications.filter(
(notification) => notification.id !== id
);
this.setState({ notifications: newNotifications });
}
componentDidMount() {
// This should also be dynamic
io().on("notification", (data) => {
let new_id = rand_num();
this.setState({
notifications: [
{ id: new_id, notification: data },
...this.state.notifications,
],
});
// a 10 sec timeout
setTimeout(() => {
this.remove_notification(new_id);
}, 10000);
});
}
render() {
- console.log("Render", this.state.notifications);
return this.state.notifications.map(({ id, notification }) => (
<div
onClick={() => this.remove_notification(id)}
style={`
background-color: ${notification.is_ok ? "#66ff99" : "#ff5c33"};
border-radius: 5px;
border-width: 2px;
border-style: solid;
border-color: ${notification.is_ok ? "#369648" : "#a23915"};
padding: 5px;
margin-top: 2px;
margin-bottom: 2px;
`}
>
<div>
<b>{notification.context}</b>
</div>
<div>
{notification.message.split("\n").map((line) => (
<p>{line}</p>
))}
</div>
</div>
));
}
}
render(<Notifications />, document.getElementById("notifications"));
diff --git a/http_server/code/src/trafficLog.tsx b/http_server/code/src/trafficLog.tsx
index c90b3ba..461648e 100644
--- a/http_server/code/src/trafficLog.tsx
+++ b/http_server/code/src/trafficLog.tsx
@@ -1,237 +1,253 @@
import { Entry, Har, PostData, Request, Response } from "har-format";
import { render, Component } from "preact";
type MyState = {
finished_entries: Entry[];
unfinished_entries: Map<string, Entry>;
};
class TrafficLog extends Component {
connection: WebSocket | undefined;
state: MyState = { finished_entries: [], unfinished_entries: new Map() };
constructor() {
super();
}
componentDidMount() {
// This should also be dynamic
this.connection = new WebSocket("ws://localhost:10001");
this.connection.onmessage = (msg) => {
this.process_msg(msg.data);
this.setState({
finished_entries: this.state.finished_entries,
unfinished_entries: this.state.unfinished_entries,
});
};
this.connection.onclose = this.connection.onerror = () => {
window.location.reload();
};
}
render() {
const download_har = () => {
var tempLink = document.createElement("a");
var taBlob = new Blob([JSON.stringify(this.export_har())], {
type: "text/plain",
});
tempLink.setAttribute("href", URL.createObjectURL(taBlob));
tempLink.setAttribute("download", `rentgendroid-capture.har`);
tempLink.click();
URL.revokeObjectURL(tempLink.href);
};
const inspect_har = async () => {
const req_body = {
har: this.export_har(),
- private_data: undefined,
+ private_data: [
+ [
+ "adid",
+ document.getElementById("adid_priv_info_table")!
+ .textContent,
+ ],
+ [
+ "latitude",
+ document.getElementById("lat_priv_info_table")!
+ .textContent,
+ ],
+ [
+ "longitude",
+ document.getElementById("lon_priv_info_table")!
+ .textContent,
+ ],
+ ],
};
+
const resp = await fetch("/inspect_har", {
- method: "POST",
- body: JSON.stringify(req_body),
- })
+ method: "POST",
+ body: JSON.stringify(req_body),
+ });
const resp_text = await resp.text();
const newWindow = window.open();
newWindow?.document.write(resp_text);
newWindow?.document.close();
-
- }
+ };
const contentWithLineBreaks = this.state.finished_entries.map((req) => {
return (
<span>
{req.request.url}
<br />
</span>
);
});
return (
<div>
<button onClick={download_har}>Download HAR</button>
<button onClick={inspect_har}>Inspect HAR</button>
<div>
<h2>stats: </h2>
<p>
Request + responce pairs:{" "}
{this.state.finished_entries.length}
</p>
<p>
Waiting for the responce:{" "}
{this.state.unfinished_entries.size}
</p>
</div>
<div>{contentWithLineBreaks}</div>
</div>
);
}
process_msg(s: string) {
let obj = JSON.parse(s);
console.log(obj);
if (obj.type !== "data") return;
if (obj.payload && obj.payload.data && obj.payload.data.requestReceived)
this.process_req(obj.payload.data.requestReceived);
if (
obj.payload &&
obj.payload.data &&
obj.payload.data.responseCompleted
)
this.process_res(obj.payload.data.responseCompleted);
}
process_res(res: any) {
let entry = this.state.unfinished_entries.get(res.id)!;
let content_type = "application/text";
let headers = JSON.parse(res.rawHeaders).map(
(header: [string, string]) => {
if (header[0].toLowerCase() === "content-type")
content_type = header[1];
return { name: header[0], value: header[1], comment: "" };
}
);
//'{"startTime":1751745139334,
// "startTimestamp":347666.762487,
// "bodyReceivedTimestamp":347667.529477,
// "headersSentTimestamp":347906.038202,
// "responseSentTimestamp":347906.616067}'
let timing_events = JSON.parse(res.timingEvents);
let start_ts = timing_events.startTimestamp;
let got_headers_ts = timing_events.headersSentTimestamp;
let end_ts = timing_events.responseSentTimestamp;
let wait_time = got_headers_ts - start_ts;
let recieve_time = end_ts - got_headers_ts;
let response: Response = {
status: res.statusCode,
statusText: res.statusMessage,
httpVersion: entry.request.httpVersion,
cookies: [],
headers,
content: {
size: 0,
mimeType: content_type,
text: res.body,
encoding: "base64",
},
redirectURL: "",
headersSize: -1,
bodySize: -1,
};
entry.response = response;
entry.timings.wait = wait_time;
entry.timings.receive = recieve_time;
this.state.unfinished_entries.delete(res.id);
this.state.finished_entries.push(entry);
}
process_req(req: any) {
let content_type = "application/text";
let headers = JSON.parse(req.rawHeaders).map(
(header: [string, string]) => {
if (header[0].toLowerCase() === "Content-Type")
content_type = header[1];
return { name: header[0], value: header[1], comment: "" };
}
);
let timing_events = JSON.parse(req.timingEvents);
let start_time: number = timing_events.startTime!;
let start_datetime = new Date(start_time).toISOString();
let request: Request = {
method: req.method,
url: req.url,
httpVersion: req.httpVersion,
cookies: [],
headers,
queryString: [],
postData: req.body
? ({ text: req.body, mimeType: content_type } as PostData)
: undefined,
headersSize: -1,
bodySize: -1,
comment: "",
};
//'{"startTime":1751745139334,"startTimestamp":347666.762487,"bodyReceivedTimestamp":347667.529477,"headersSentTimestamp":347906.038202,"responseSentTimestamp":347906.616067}'
let entry: Entry = {
startedDateTime: start_datetime,
time: 0,
request: request,
response: {
status: 0,
statusText: "",
httpVersion: "",
cookies: [],
headers: [],
content: {
size: 0,
mimeType: "",
},
redirectURL: "",
headersSize: 0,
bodySize: 0,
},
cache: {},
timings: {
wait: 0,
receive: 0,
},
};
this.state.unfinished_entries.set(req.id, entry);
}
export_har(): Har {
let ret: Har = {
log: {
version: "1.2",
creator: {
name: "Rentgendroid",
version: "0.0.1",
},
entries: [
...this.state.finished_entries,
...this.state.unfinished_entries.values(),
],
},
};
return ret;
}
}
render(<TrafficLog />, document.getElementById("traffic-log")!);
diff --git a/pre_android/preconf/docker-entrypoint.sh b/pre_android/preconf/docker-entrypoint.sh
index 8b20b68..e288388 100644
--- a/pre_android/preconf/docker-entrypoint.sh
+++ b/pre_android/preconf/docker-entrypoint.sh
@@ -1,23 +1,25 @@
adb start-server
-emulator -avd virtual_dev -writable-system -no-window -no-audio &
+
+emulator -avd virtual_dev -writable-system -no-window -no-audio -memory 4096 &
+
bash /preconf/install_adidreader.sh
bash /preconf/install_culebra.sh
# Open google maps once, skip all the screens, and give it gps permissions
adb shell am start-activity com.google.android.apps.maps
sleep 8
adb shell input tap 268 49
sleep 4
adb shell input tap 290 323
sleep 6
adb shell input tap 147 413
sleep 10
adb shell am stop-app com.google.android.apps.maps
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

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 8, 05:30 (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1034053
Default Alt Text
(12 KB)

Event Timeline