Page MenuHomeSealhub

No OneTemporary

diff --git a/android/conf/docker-entrypoint.sh b/android/conf/docker-entrypoint.sh
index 3446143..645d2c2 100644
--- a/android/conf/docker-entrypoint.sh
+++ b/android/conf/docker-entrypoint.sh
@@ -1,10 +1,24 @@
bash /conf/start_culebra.sh &
npm i -C /code
bash /conf/wait_for_sd.sh
adb shell su root /tmp/frida-server &
+apt-get install iptables -y
-cd /frida-scripts && perl -i -0777p -e 's|CERT_PEM = .*?;|CERT_PEM = `'"$(cat /certificates/ca.pem | sed -z 's/\n/\\n/g')"'`;|gsm' config.js
+# configuring the pinning / unpinning scripts
+perl -i -0777p -e 's|CERT_PEM = .*?;|CERT_PEM = `'"$(cat /certificates/mitmproxy-ca-cert.pem | sed -z 's/\n/\\n/g')"'`;|gsm' /frida-scripts/config.js
+perl -i -0777p -e 's|const PROXY_SUPPORTS_SOCKS5 = false|const PROXY_SUPPORTS_SOCKS5 = true|gsm' /frida-scripts/config.js
+perl -i -0777p -e 's|const BLOCK_HTTP3 = true|const BLOCK_HTTP3 = true|gsm' /frida-scripts/config.js
+perl -i -0777p -e 's|const PROXY_PORT = 8000|const PROXY_PORT = 8000|gsm' /frida-scripts/config.js
+
+# configuring forwarding the proxy info to mitmproxy
adb reverse tcp:8000 tcp:8000
+# iptables -t nat -A OUTPUT -p tcp --dport 8000 -j DNAT --to-destination $(getent hosts mitmproxy | awk '{ print $1 }'):8000
+
+iptables -t nat -A OUTPUT -m addrtype --src-type LOCAL --dst-type LOCAL -p tcp --dport 8000 -j DNAT --to-destination $(getent hosts mitmproxy | awk '{ print $1 }'):1080
+iptables -t nat -A POSTROUTING -m addrtype --src-type LOCAL --dst-type UNICAST -j MASQUERADE
+
+# iptables -t nat -A POSTROUTING -p tcp -d mitmproxy --dport 8000 -j SNAT --to-source 127.0.0.1:8000
+
node /code/index.mjs
diff --git a/android/entrypoint.sh b/android/entrypoint.sh
index 8c4dd8e..ecb5f2e 100755
--- a/android/entrypoint.sh
+++ b/android/entrypoint.sh
@@ -1,31 +1,31 @@
#!/bin/bash
set -e
-node /proxy_cache_thing/dist/index.js &
-CACHE_PID=$!
+# node /proxy_cache_thing/dist/index.js &
+# CACHE_PID=$!
-/httptoolkit-server/bin/run start -c /certificates &
-HTTPTOOLKIT_SERVER_PID=$!
+# /httptoolkit-server/bin/run start -c /certificates &
+# HTTPTOOLKIT_SERVER_PID=$!
bash /conf/docker-entrypoint.sh &
ANDROID_PID=$!
function check_dead() {
- if ! ps -p $CACHE_PID > /dev/null; then
- echo "[ERROR] The proxy cache died, exiting...";
- exit 1;
- fi
- if ! ps -p $HTTPTOOLKIT_SERVER_PID > /dev/null; then
- echo "[ERROR] The httptoolkit_server died, exiting...";
- exit 1;
- fi
+ # if ! ps -p $CACHE_PID > /dev/null; then
+ # echo "[ERROR] The proxy cache died, exiting...";
+ # exit 1;
+ # fi
+ # if ! ps -p $HTTPTOOLKIT_SERVER_PID > /dev/null; then
+ # echo "[ERROR] The httptoolkit_server died, exiting...";
+ # exit 1;
+ # fi
if ! ps -p $ANDROID_PID > /dev/null; then
echo "[ERROR] The android emulator died, exiting...";
exit 1;
fi
}
# Exit on error
while true; do
check_dead;
sleep 1;
done
diff --git a/docker-compose.yaml b/docker-compose.yaml
index 0b693af..f374de8 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -1,59 +1,67 @@
services:
android:
build:
context: ./android/
args:
PROXY_PORT: "45459"
SERVER_PORT: "45456"
LOOPBACK_PORT: "10000"
MONITORING_API_PORT: "10001"
container_name: httptoolkit_server
container_name: android
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
+ - net.ipv4.conf.all.route_localnet=1
cap_add:
- NET_ADMIN
devices:
- /dev/kvm
networks:
- rent_gen_android
ports:
- 45456:45459 # This cannot change
- 45457:45459 # This cannot change
- 10001:10001 # api port
- 3000:3000 # android server port
- 3001:3001 # Notifications server
- 5556:5556 # emulator grpc port
volumes:
- $PWD/shared_buffer:/shared_buffer
- $PWD/android/conf:/conf
- $PWD/certificates:/certificates
- $PWD/android/code:/code
+ mitmproxy:
+ build: ./mitmproxy
+ networks:
+ - rent_gen_android
+ volumes:
+ - $PWD/certificates:/root/.mitmproxy
+ container_name: mitmproxy
httptoolkit_ui:
build:
context: ./httptoolkit_ui/
args:
# The ip / hostname using which,
# the browser can reach this docker session
DOCKER_HOST: "127.0.0.1"
container_name: httptoolkit_ui
networks:
- rent_gen_android
ports:
- 9080:9080
http_server:
build: ./http_server/
container_name: http_server
networks:
- rent_gen_android
volumes:
- $PWD/http_server/code:/code
- $PWD/shared_buffer:/shared_buffer
- $PWD/log:/log
ports:
- 8080:8080
networks:
rent_gen_android:
driver: bridge
diff --git a/http_server/code/index.html b/http_server/code/index.html
index 3ac14b2..2dd1c6c 100644
--- a/http_server/code/index.html
+++ b/http_server/code/index.html
@@ -1,146 +1,146 @@
<!doctype html>
<html lang="en">
<head style="height: 100vh">
<meta charset="UTF-8" />
<title>Rentgen android</title>
<script src="/htmx.js"></script>
<link rel="stylesheet" href="styles.css" />
<script src="/main.js" type="module"></script>
</head>
<body>
<div id="notifications"></div>
<div id="resp" style="display: none"></div>
<main>
<section class="screen-section">
<img
id="screen"
alt="android screen"
src=""
draggable="false"
class="screen"
style="flex-grow: 0"
tabindex="0"
/>
<div class="screen-buttons" style="flex-grow: 0">
<button class="screen-buttons-recent-apps">recent-apps</button>
<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
multiple
/>
</label>
<button type="submit">Install the app</button>
</form>
</section>
<div class="tab-section">
<div class="tab">
<button
class="tablinks active"
onclick="main.open_tab(event, 'httptoolkit-tab')"
>
HttpToolkit UI
</button>
<button class="tablinks" onclick="main.open_tab(event, 'logs-tab')">
Logs
</button>
<button
class="tablinks"
onclick="main.open_tab(event, 'controls-tab')"
>
Device Controls
</button>
</div>
<div class="tabcontent" id="logs-tab">
<div id="logs">
<p id="clicks-log" class="log-section"></p>
<div id="traffic-log" class="log-section">
<div>
<button onClick="main.download_har()">Download HAR</button>
<button onClick="main.inspect_har()">Inspect HAR</button>
<div>
<h2>stats:</h2>
<p id="traffic-log-req-res-pairs">
Request + responce pairs: 0
</p>
<p id="traffic-log-waiting">
Waiting for the responce: 0
</p>
</div>
<div id="traffic-log-lines">
</div>
</div>
</div>
</div>
</div>
<div class="tabcontent active" id="httptoolkit-tab">
- <iframe
- id="httptoolkit-frame"
- style="flex-grow: 1"
- src="http://localhost:9080/"
- title="httptoolkit"
- ></iframe>
+ <!-- <iframe -->
+ <!-- id="httptoolkit-frame" -->
+ <!-- style="flex-grow: 1" -->
+ <!-- src="http://localhost:9080/" -->
+ <!-- title="httptoolkit" -->
+ <!-- ></iframe> -->
</div>
<div class="tabcontent" id="controls-tab">
<form id="set_coords" onsubmit="main.coords_handler(event)">
<label>
Latitude:
<input type="text" name="lat" />
</label>
<label>
Longitude:
<input type="text" name="lon" />
</label>
<button type="submit">Submit coords</button>
</form>
<button id="reset_adid_btn" onclick="main.reset_adid_handler(event)">
Reset ADID
</button>
<table>
<thead></thead>
<tbody>
<tr>
<td>ADID:</td>
<td id="adid_priv_info_table">UNKNOWN</td>
</tr>
<tr>
<td>Longitude:</td>
<td id="lon_priv_info_table">UNKNOWN</td>
</tr>
<tr>
<td>Latitude:</td>
<td id="lat_priv_info_table">UNKNOWN</td>
</tr>
</tbody>
</table>
<h2>Lanuch app</h2>
<form id="launch_app_form">
<select name="appid" id="app_id_select">
</select>
<button type="submit">Launch app</button>
</form>
<h2>Open ports</h2>
<p id="open-ports"></p>
</div>
</div>
</main>
</body>
</html>
diff --git a/http_server/code/src/main.ts b/http_server/code/src/main.ts
index c20b4c5..07e8a15 100644
--- a/http_server/code/src/main.ts
+++ b/http_server/code/src/main.ts
@@ -1,297 +1,297 @@
// make the export accessible from inline js
import * as main from "./main";
// for some reason doing the same with the window object doesn't work
(globalThis as any).main = main;
import {
backButton,
clicksLog,
homeButton,
socket,
screen,
adid_priv_info_table,
lat_priv_info_table,
lon_priv_info_table,
recentButton,
open_ports,
app_id_select,
launch_app_form,
} from "./shared";
import { start_notifications } from "./notifications";
import { start_traffic_log } from "./traffic_log";
export { download_har, inspect_har } from "./traffic_log";
export function reset_adid_handler(_: Event) {
socket.emit("reset_adid");
}
export function coords_handler(e: FormDataEvent) {
e.preventDefault();
const form_data = new FormData(e.target as HTMLFormElement);
socket.emit("setcoord", {
lon: Number.parseFloat(form_data.get("lon") as string),
lat: Number.parseFloat(form_data.get("lat") as string),
});
}
export function open_tab(evt: Event, tab_name: string) {
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 as HTMLElement).classList.add("active");
}
let lastTouch = new Date().getTime();
export const calculateElapsedTime = () => {
const currentTouch = new Date().getTime();
const elapsedTime = currentTouch - lastTouch;
const elapsedSec = Math.round(elapsedTime / 1000);
lastTouch = currentTouch;
return elapsedSec;
};
export const waitToLog = (clickInfoText: string) => {
const clickInfo = document.createElement("span");
const waitInfo = document.createElement("span");
waitInfo.textContent = `await wait(${calculateElapsedTime()});`;
clicksLog.appendChild(waitInfo);
clickInfo.textContent = clickInfoText;
clicksLog.appendChild(clickInfo);
};
export const registerClick = ({
path,
logText,
body,
}: {
path: string;
logText: string;
body?: any;
}) => {
waitToLog(logText);
socket.emit(path, body ? body : {});
};
homeButton.addEventListener("click", () =>
registerClick({ path: "home", logText: "await homeButton();" })
);
backButton.addEventListener("click", () =>
registerClick({ path: "back", logText: "await backButton();" })
);
recentButton.addEventListener("click", () =>
registerClick({ path: "recent", logText: "await recentButton();" })
);
socket.on("screenshot_data", (data) => {
try {
const blob = new Blob([data]);
screen.src = URL.createObjectURL(blob);
} catch (error) {
console.error("Error fetching image: ", error);
}
});
socket.on("private_info", (data) => {
console.log("private_info");
adid_priv_info_table.textContent = data.adid;
lat_priv_info_table.textContent = data.latitude;
lon_priv_info_table.textContent = data.longitude;
});
socket.on("open_ports", (data: string[]) => {
console.log("open_ports");
open_ports.textContent = data.toString();
});
async function installed_apps_loop() {
var before;
while (true) {
before = performance.now();
socket.emit("installed_apps_req");
while (performance.now() - before < 2000) await sleep(100);
}
}
socket.on("installed_apps", (data) => {
let all_ids = new Set();
let all_inserted_ids = new Set();
for (let app of data) {
all_ids.add(app.identifier);
}
// remove all the elements that are no longer in the set
for (const el of app_id_select.children) {
const opt = el as HTMLOptionElement;
if (!all_ids.has(opt.value)) opt.remove();
else all_inserted_ids.add(opt.value);
}
for (let app of data) {
if (all_inserted_ids.has(app.identifier))
continue;
let app_opt = document.createElement("option");
app_opt.value = app.identifier;
app_opt.innerText = app.name;
app_id_select.appendChild(app_opt);
}
});
(launch_app_form as HTMLFormElement).addEventListener("submit", (event) => {
event.preventDefault();
event.stopImmediatePropagation();
const form_data = new FormData(event.target as HTMLFormElement);
socket.emit("start_frida_app", form_data.get("appid"));
})
socket.emit("private_info_req");
socket.onAny((ev, ...args) => {
console.log("ev: ", ev, args);
});
async function displayImage() {
socket.emit("screenshot");
}
let isDragging = false;
const screenSize = [320, 640];
export function calcMousePos(event: MouseEvent) {
let rect = screen.getBoundingClientRect();
let x = ((event.clientX - rect.left) / rect.width) * screenSize[0];
let y = ((event.clientY - rect.top) / rect.height) * screenSize[1];
x = Math.min(Math.max(x, 0), screenSize[0]);
y = Math.min(Math.max(y, 0), screenSize[1]);
return { x, y };
}
screen.addEventListener(
"mousemove",
(event) => {
if (!isDragging) return;
let pos = calcMousePos(event);
if (isDragging) {
registerClick({
path: "motionevent",
logText: `await motionevent({motionType: "MOVE", x:${pos.x},y:${pos.y}}});`,
body: {
motionType: "MOVE",
x: pos.x,
y: pos.y,
},
});
}
},
false
);
export const handleDraggStart = (event: MouseEvent) => {
isDragging = true;
let pos = calcMousePos(event);
registerClick({
path: "motionevent",
logText: `await motionevent({motionType: "DOWN", x:${pos.x},y:${pos.y}}});`,
body: {
motionType: "DOWN",
x: pos.x,
y: pos.y,
},
});
};
screen.addEventListener("mousedown", handleDraggStart);
document.addEventListener("mouseup", (e) => {
if (!isDragging) return;
isDragging = false;
let pos = calcMousePos(e);
registerClick({
path: "motionevent",
logText: `await motionevent({motionType: "MOVE", x:${pos.x},y:${pos.y}}});`,
body: {
motionType: "MOVE",
x: pos.x,
y: pos.y,
},
});
registerClick({
path: "motionevent",
logText: `await motionevent({motionType: "UP", x:${pos.x},y:${pos.y}}});`,
body: {
motionType: "UP",
x: pos.x,
y: pos.y,
},
});
});
window.addEventListener("keydown", (event) => {
let key = event.key;
if (key === "Space") key = " ";
else if (key !== "Enter" && key !== "Backspace" && key.length !== 1) return;
console.log(event.key, key);
if (screen.matches(":hover")) {
registerClick({
path: "key",
logText: `await key(${event.key});`,
body: { key },
});
}
});
export async function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async function screenshot_loop() {
var before;
while (true) {
before = performance.now();
await displayImage();
// TODO: Make this dynamic again
while (performance.now() - before < 100) await sleep(50);
}
}
async function open_ports_loop() {
var before;
while (true) {
before = performance.now();
socket.emit("open_ports_req");
while (performance.now() - before < 2000) await sleep(100);
}
}
installed_apps_loop();
open_ports_loop();
screenshot_loop();
start_notifications();
-start_traffic_log();
+// start_traffic_log();
diff --git a/mitmproxy/Dockerfile b/mitmproxy/Dockerfile
new file mode 100644
index 0000000..0fe6425
--- /dev/null
+++ b/mitmproxy/Dockerfile
@@ -0,0 +1,8 @@
+FROM mitmproxy/mitmproxy
+
+USER root
+WORKDIR /root
+
+# CMD bash -c 'echo hello from mitmproxy && mitmdump -w /root/.mitmproxy/dump --set mode="socks5@0.0.0.0:1080"'
+cmd sleep 1000000000
+#--set mode="regular@0.0.0.0:8000"
diff --git a/pre_android/Dockerfile b/pre_android/Dockerfile
index b3c5238..9363c80 100644
--- a/pre_android/Dockerfile
+++ b/pre_android/Dockerfile
@@ -1,10 +1,10 @@
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 --channel=2 "system-images;android-35;google_apis;x86_64" \
&& echo no | avdmanager create avd -n virtual_dev -b google_apis/x86_64 -k "system-images;android-35;google_apis;x86_64" \
- && apt-get update && apt-get install -y iproute2 iputils-ping npm git libxml2-utils telnet bc aapt python3 python3-pip \
+ && apt-get update && apt-get install -y iptables iproute2 iputils-ping npm git libxml2-utils telnet bc aapt python3 python3-pip \
&& pip install frida-tools && git clone https://github.com/httptoolkit/frida-interception-and-unpinning /frida-scripts
CMD bash /preconf/docker-entrypoint.sh

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 8, 12:12 (13 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1034565
Default Alt Text
(18 KB)

Event Timeline