cli-anything-godzilla 1.0.0__tar.gz

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.
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: cli-anything-godzilla
3
+ Version: 1.0.0
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: click>=8.0.0
6
+ Requires-Dist: prompt-toolkit>=3.0.0
7
+ Requires-Dist: pyyaml>=6.0.0
8
+ Dynamic: requires-dist
9
+ Dynamic: requires-python
@@ -0,0 +1,401 @@
1
+ # cli-anything-godzilla
2
+
3
+ [English](#english) | [简体中文](#简体中文)
4
+
5
+ ---
6
+
7
+ ## English
8
+
9
+ CLI harness for Godzilla Security Testing Tool.
10
+
11
+ > **Note**: This is a standalone CLI tool that works with the original Godzilla GUI tool.
12
+
13
+ ### Features
14
+
15
+ - ✅ Complete project management (create, open, save, info)
16
+ - ✅ Shell management (add, list, update, remove, test connection)
17
+ - ✅ Short ID support (all shell commands support short IDs)
18
+ - ✅ C2 Profile management (load and validate)
19
+ - ✅ Interactive REPL mode with friendly UI
20
+ - ✅ JSON output mode for AI agent integration
21
+ - ✅ Compatible with original Godzilla project database
22
+
23
+ ### Installation
24
+
25
+ #### Prerequisites
26
+
27
+ - Python 3.12+ (tested with Python 3.12.8)
28
+ - Java Runtime Environment (JRE) 11+
29
+ - Godzilla JAR file (Godzilla15.jar)
30
+
31
+ #### Install the CLI
32
+
33
+ ```bash
34
+ # From PyPI (when published)
35
+ pip install cli-anything-godzilla
36
+
37
+ # Or install locally for development
38
+ git clone https://github.com/fengchenzxc/cli-anything-godzilla.git
39
+ cd cli-anything-godzilla
40
+ pip install -e .
41
+ ```
42
+
43
+ #### Verify Installation
44
+
45
+ ```bash
46
+ which cli-anything-godzilla
47
+ cli-anything-godzilla --help
48
+ ```
49
+
50
+ ### Usage
51
+
52
+ #### Start Interactive REPL Mode
53
+
54
+ ```bash
55
+ # Start with no arguments (enter REPL mode)
56
+ cli-anything-godzilla
57
+
58
+ # Or specify a project
59
+ cli-anything-godzilla -p /path/to/project
60
+ ```
61
+
62
+ #### Project Management
63
+
64
+ ```bash
65
+ # Create a new project
66
+ cli-anything-godzilla project new my-project -n "My Project" -d "Project description"
67
+
68
+ # Open an existing project
69
+ cli-anything-godzilla project open /path/to/project
70
+
71
+ # Show project information
72
+ cli-anything-godzilla project info
73
+
74
+ # List all projects
75
+ cli-anything-godzilla project list
76
+
77
+ # Close current project
78
+ cli-anything-godzilla project close
79
+ ```
80
+
81
+ #### Shell Management
82
+
83
+ ```bash
84
+ # Add a shell
85
+ cli-anything-godzilla shell add -u http://target.com/shell.jsp -p password
86
+
87
+ # List all shells
88
+ cli-anything-godzilla shell list
89
+
90
+ # Get shell details (supports short ID)
91
+ cli-anything-godzilla shell get 31f09e27
92
+
93
+ # Test shell connectivity (supports short ID)
94
+ cli-anything-godzilla shell test 31f09e27
95
+
96
+ # Update shell configuration
97
+ cli-anything-godzilla shell update 31f09e27 --remark "Updated remark"
98
+
99
+ # Remove a shell (supports short ID)
100
+ cli-anything-godzilla shell remove 31f09e27
101
+
102
+ # Export shells
103
+ cli-anything-godzilla shell export shells.json
104
+
105
+ # Import shells
106
+ cli-anything-godzilla shell import shells.json
107
+ ```
108
+
109
+ #### C2 Profile Management
110
+
111
+ ```bash
112
+ # List available profiles
113
+ cli-anything-godzilla profile list
114
+
115
+ # Load a profile
116
+ cli-anything-godzilla profile load /path/to/profile.yml
117
+
118
+ # Validate a profile
119
+ cli-anything-godzilla profile validate /path/to/profile.yml
120
+ ```
121
+
122
+ #### JSON Output Mode
123
+
124
+ All commands support `--json` flag for machine-readable output:
125
+
126
+ ```bash
127
+ cli-anything-godzilla --json shell list
128
+ cli-anything-godzilla --json shell get 31f09e27
129
+ cli-anything-godzilla --json project info
130
+ ```
131
+
132
+ ### REPL Commands
133
+
134
+ When in interactive mode, use these commands:
135
+
136
+ | Command | Description |
137
+ |--------|-------------|
138
+ | `help` | Show available commands |
139
+ | `exit` | Exit REPL mode |
140
+ | `project info` | Show project information |
141
+ | `project list` | List all projects |
142
+ | `shell list` | List all shells |
143
+ | `shell get <id>` | Get shell details |
144
+ | `shell add <url> <password>` | Add new shell |
145
+ | `shell test <id>` | Test shell connectivity |
146
+ | `shell update <id> --remark "xxx"` | Update shell remark |
147
+ | `shell remove <id>` | Remove shell |
148
+ | `profile list` | List C2 profiles |
149
+
150
+ ### Configuration
151
+
152
+ #### Supported Payload Types
153
+
154
+ - `JavaDynamicPayload` - Java dynamic payload
155
+ - `CSharpDynamicPayload` - C# dynamic payload
156
+ - `PhpDynamicPayload` - PHP dynamic payload
157
+
158
+ #### Supported Encryption Types
159
+
160
+ - `xor` - XOR encryption
161
+ - `aes128` - AES-128 encryption
162
+ - `aes256` - AES-256 encryption
163
+ - `base64` - Base64 encoding
164
+ - `hex` - Hexadecimal encoding
165
+ - `raw` - Raw data
166
+ - `rsa` - RSA encryption
167
+
168
+ ### Running Tests
169
+
170
+ ```bash
171
+ # Run unit tests
172
+ cd /path/to/agent-harness
173
+ python3.12 -m pytest cli_anything/godzilla/tests/test_core.py -v
174
+
175
+ # Run E2E tests
176
+ python3.12 -m pytest cli_anything/godzilla/tests/test_full_e2e.py -v -s
177
+
178
+ # Run with force-installed mode
179
+ CLI_ANYTHING_FORCE_INSTALLED=1 python3.12 -m pytest cli_anything/godzilla/tests/ -v -s
180
+ ```
181
+
182
+ ---
183
+
184
+ ## 简体中文
185
+
186
+ CLI 命令行工具包,用于哥斯拉(Godzilla)WebShell 管理器的安全测试。
187
+
188
+ > **注意**: 本项目是一个独立的 CLI 工具,与原版哥斯拉 GUI 工具配合使用。
189
+
190
+ ### 功能特性
191
+
192
+ - ✅ 完整的项目管理(创建、打开、保存、信息)
193
+ - ✅ Shell 管理(添加、查看、更新、删除、测试连接)
194
+ - ✅ 短 ID 支持(所有 shell 命令支持使用短 ID)
195
+ - ✅ C2 Profile 管理(加载和验证)
196
+ - ✅ 交互式 REPL 模式,界面友好
197
+ - ✅ JSON 输出模式(便于 AI 代理集成)
198
+ - ✅ 兼容原版哥斯拉项目数据库
199
+
200
+ ### 安装
201
+
202
+ #### 前置要求
203
+
204
+ - Python 3.12+ (已测试 Python 3.12.8)
205
+ - Java Runtime Environment (JRE) 11+
206
+ - 哥斯拉 JAR 文件 (Godzilla15.jar)
207
+
208
+ #### 安装 CLI
209
+
210
+ ```bash
211
+ # 从 PyPI 安装 (发布后)
212
+ pip install cli-anything-godzilla
213
+
214
+ # 或本地开发安装
215
+ git clone https://github.com/fengchenzxc/cli-anything-godzilla.git
216
+ cd cli-anything-godzilla
217
+ pip install -e .
218
+ ```
219
+
220
+ #### 验证安装
221
+
222
+ ```bash
223
+ which cli-anything-godzilla
224
+ cli-anything-godzilla --help
225
+ ```
226
+
227
+ ### 使用方法
228
+
229
+ #### 启动交互式 REPL 模式
230
+
231
+ ```bash
232
+ # 无参数启动(进入 REPL 模式)
233
+ cli-anything-godzilla
234
+
235
+ # 指定项目启动
236
+ cli-anything-godzilla -p /path/to/project
237
+ ```
238
+
239
+ #### 项目管理
240
+
241
+ ```bash
242
+ # 创建新项目
243
+ cli-anything-godzilla project new my-project -n "我的项目" -d "项目描述"
244
+
245
+ # 打开已有项目
246
+ cli-anything-godzilla project open /path/to/project
247
+
248
+ # 查看项目信息
249
+ cli-anything-godzilla project info
250
+
251
+ # 列出所有项目
252
+ cli-anything-godzilla project list
253
+
254
+ # 关闭当前项目
255
+ cli-anything-godzilla project close
256
+ ```
257
+
258
+ #### Shell 管理
259
+
260
+ ```bash
261
+ # 添加 shell
262
+ cli-anything-godzilla shell add -u http://target.com/shell.jsp -p password
263
+
264
+ # 列出所有 shell
265
+ cli-anything-godzilla shell list
266
+
267
+ # 获取 shell 详情(支持短 ID)
268
+ cli-anything-godzilla shell get 31f09e27
269
+
270
+ # 测试 shell 连接(支持短 ID)
271
+ cli-anything-godzilla shell test 31f09e27
272
+
273
+ # 更新 shell 配置
274
+ cli-anything-godzilla shell update 31f09e27 --remark "更新备注"
275
+
276
+ # 删除 shell(支持短 ID)
277
+ cli-anything-godzilla shell remove 31f09e27
278
+
279
+ # 导出 shell
280
+ cli-anything-godzilla shell export shells.json
281
+
282
+ # 导入 shell
283
+ cli-anything-godzilla shell import shells.json
284
+ ```
285
+
286
+ #### C2 Profile 管理
287
+
288
+ ```bash
289
+ # 列出可用的 profiles
290
+ cli-anything-godzilla profile list
291
+
292
+ # 加载 profile
293
+ cli-anything-godzilla profile load /path/to/profile.yml
294
+
295
+ # 验证 profile
296
+ cli-anything-godzilla profile validate /path/to/profile.yml
297
+ ```
298
+
299
+ #### JSON 输出模式
300
+
301
+ 所有命令支持 `--json` 标志,输出机器可读格式:
302
+
303
+ ```bash
304
+ cli-anything-godzilla --json shell list
305
+ cli-anything-godzilla --json shell get 31f09e27
306
+ cli-anything-godzilla --json project info
307
+ ```
308
+
309
+ ### REPL 交互命令
310
+
311
+ 在交互模式下,可使用以下命令:
312
+
313
+ | 命令 | 描述 |
314
+ |------|------|
315
+ | `help` | 显示可用命令 |
316
+ | `exit` | 退出 REPL 模式 |
317
+ | `project info` | 显示项目信息 |
318
+ | `project list` | 列出所有项目 |
319
+ | `shell list` | 列出所有 shell |
320
+ | `shell get <id>` | 获取 shell 详情 |
321
+ | `shell add <url> <password>` | 添加新 shell |
322
+ | `shell test <id>` | 测试 shell 连接 |
323
+ | `shell update <id> --remark "xxx"` | 更新 shell 备注 |
324
+ | `shell remove <id>` | 删除 shell |
325
+ | `profile list` | 列出 C2 profiles |
326
+
327
+ ### 配置
328
+
329
+ #### 支持的载荷类型
330
+
331
+ - `JavaDynamicPayload` - Java 动态载荷
332
+ - `CSharpDynamicPayload` - C# 动态载荷
333
+ - `PhpDynamicPayload` - PHP 动态载荷
334
+
335
+ #### 支持的加密方式
336
+
337
+ - `xor` - XOR 加密
338
+ - `aes128` - AES-128 加密
339
+ - `aes256` - AES-256 加密
340
+ - `base64` - Base64 编码
341
+ - `hex` - 十六进制编码
342
+ - `raw` - 原始数据
343
+ - `rsa` - RSA 加密
344
+
345
+ ### 运行测试
346
+
347
+ ```bash
348
+ # 运行单元测试
349
+ cd /path/to/agent-harness
350
+ python3.12 -m pytest cli_anything/godzilla/tests/test_core.py -v
351
+
352
+ # 运行 E2E 测试
353
+ python3.12 -m pytest cli_anything/godzilla/tests/test_full_e2e.py -v -s
354
+
355
+ # 使用强制安装模式运行测试
356
+ CLI_ANYTHING_FORCE_INSTALLED=1 python3.12 -m pytest cli_anything/godzilla/tests/ -v -s
357
+ ```
358
+
359
+ ### 兼容性
360
+
361
+ - 可直接打开原版哥斯拉创建的项目(自动生成配置文件)
362
+ - 数据库列名使用 camelCase(与原版哥斯拉保持一致)
363
+ - 支持 HTTP 请求头的 JSON 和纯文本两种格式
364
+
365
+ ---
366
+
367
+ ## Project Structure / 项目结构
368
+
369
+ ```
370
+ cli_anything/godzilla/
371
+ ├── __init__.py
372
+ ├── godzilla_cli.py # Main CLI entry point / CLI 主入口
373
+ ├── core/
374
+ │ ├── __init__.py
375
+ │ ├── project.py # Project management / 项目管理
376
+ │ ├── shell.py # Shell management / Shell 管理
377
+ │ ├── profile.py # C2 Profile management / C2 Profile 管理
378
+ │ └── database.py # Database operations / 数据库操作
379
+ ├── utils/
380
+ │ ├── __init__.py
381
+ │ ├── godzilla_backend.py # Godzilla JAR integration / 哥斯拉 JAR 集成
382
+ │ └── repl_skin.py # REPL interface / REPL 界面
383
+ └── tests/
384
+ ├── TEST.md # Test plan and results / 测试计划和结果
385
+ ├── test_core.py # Unit tests / 单元测试
386
+ └── test_full_e2e.py # E2E tests / E2E 测试
387
+ ```
388
+
389
+ ---
390
+
391
+ ## License / 许可证
392
+
393
+ MIT License
394
+
395
+ ---
396
+
397
+ ## Disclaimer / 免责声明
398
+
399
+ **English**: This tool is for authorized security testing and research purposes only. Unauthorized use is illegal.
400
+
401
+ **中文**: 本工具仅供安全研究和授权测试使用。使用本工具进行未经授权的测试是非法的。
@@ -0,0 +1,57 @@
1
+ """
2
+ cli-anything-godzilla: CLI harness for Godzilla WebShell Manager.
3
+
4
+ This package provides a stateful CLI interface to the Godzilla security testing tool.
5
+ """
6
+
7
+ __version__ = "1.0.0"
8
+ __author__ = "cli-anything"
9
+
10
+ from cli_anything.godzilla.core.project import (
11
+ create_project,
12
+ open_project,
13
+ save_project,
14
+ close_project,
15
+ get_project_info,
16
+ list_projects,
17
+ )
18
+ from cli_anything.godzilla.core.shell import (
19
+ ShellEntity,
20
+ add_shell,
21
+ update_shell,
22
+ remove_shell,
23
+ list_shells,
24
+ get_shell,
25
+ test_shell,
26
+ )
27
+ from cli_anything.godzilla.core.profile import (
28
+ C2Profile,
29
+ load_profile,
30
+ save_profile,
31
+ list_profiles,
32
+ validate_profile,
33
+ )
34
+
35
+ __all__ = [
36
+ # Project management
37
+ "create_project",
38
+ "open_project",
39
+ "save_project",
40
+ "close_project",
41
+ "get_project_info",
42
+ "list_projects",
43
+ # Shell management
44
+ "ShellEntity",
45
+ "add_shell",
46
+ "update_shell",
47
+ "remove_shell",
48
+ "list_shells",
49
+ "get_shell",
50
+ "test_shell",
51
+ # Profile management
52
+ "C2Profile",
53
+ "load_profile",
54
+ "save_profile",
55
+ "list_profiles",
56
+ "validate_profile",
57
+ ]
@@ -0,0 +1,583 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ cli-anything-godzilla: CLI harness for Godzilla WebShell Manager.
4
+
5
+ A stateful CLI interface that allows AI agents to operate Godzilla
6
+ without needing a GUI.
7
+ """
8
+
9
+ import click
10
+ import json
11
+ import sys
12
+ import os
13
+ from pathlib import Path
14
+ from typing import Optional, Dict, List, Any
15
+
16
+ try:
17
+ import yaml
18
+ except ImportError:
19
+ yaml = None
20
+
21
+ from cli_anything.godzilla.core.project import (
22
+ create_project,
23
+ open_project,
24
+ save_project,
25
+ close_project,
26
+ get_project_info,
27
+ list_projects,
28
+ get_current_project,
29
+ )
30
+ from cli_anything.godzilla.core.shell import (
31
+ add_shell,
32
+ update_shell,
33
+ remove_shell,
34
+ list_shells,
35
+ get_shell,
36
+ test_shell,
37
+ export_shells,
38
+ import_shells,
39
+ ShellEntity,
40
+ )
41
+ from cli_anything.godzilla.core.profile import (
42
+ load_profile,
43
+ list_profiles,
44
+ validate_profile,
45
+ C2Profile,
46
+ )
47
+ from cli_anything.godzilla.utils.repl_skin import ReplSkin
48
+
49
+
50
+ # Global context
51
+ @click.group(invoke_without_command=True)
52
+ @click.option("-p", "--project", "project_path", help="Path to project file")
53
+ @click.option("--jar", "--jar-path", "jar_path", help="Path to Godzilla JAR file")
54
+ @click.option("--json", "json_output", is_flag=True, help="Output in JSON format")
55
+ @click.pass_context
56
+ def cli(ctx, project_path: str, jar_path: str, json_output: bool):
57
+ """Main CLI entry point."""
58
+ ctx.ensure_object(dict)
59
+ ctx.obj["project"] = project_path
60
+ ctx.obj["jar_path"] = jar_path
61
+ ctx.obj["json_flag"] = json_output
62
+
63
+ # Open project if path specified
64
+ if project_path:
65
+ try:
66
+ open_project(project_path)
67
+ except Exception as e:
68
+ click.echo(f"Error opening project: {e}", err=True)
69
+
70
+ # If no subcommand, enter REPL mode
71
+ if ctx.invoked_subcommand is None:
72
+ ctx.invoke(repl)
73
+
74
+
75
+ @cli.command()
76
+ def version():
77
+ """Show version information."""
78
+ click.echo("cli-anything-godzilla v1.0.0")
79
+ click.echo("\033[36mA CLI harness for Godzilla Security Testing Tool\033[0m")
80
+
81
+
82
+ @cli.command()
83
+ def help_cmd():
84
+ """Show comprehensive help."""
85
+ help_text = """
86
+ \033[36mcli-anything-godzilla\033[0m - CLI harness for Godzilla Security Testing Tool
87
+
88
+ \033[33mCommands:\033[0m
89
+ \033[32mproject\033[0m Project management (create, open, save, info)
90
+ \033[32mshell\033[0m Shell management (add, list, test, export, import)
91
+ \033[32mprofile\033[0m C2 Profile management (load, save, validate)
92
+ \033[32mrepl\033[0m Interactive REPL mode
93
+ \033[32mversion\033[0m Show version information
94
+
95
+ \033[33mExamples:\033[0m
96
+ # Create a new project
97
+ cli-anything-godzilla project new my-project
98
+
99
+ # Open existing project
100
+ cli-anything-godzilla project open ./project.json
101
+
102
+ # Add a shell interactively
103
+ cli-anything-godzilla
104
+
105
+ # List shells
106
+ cli-anything-godzilla shell list
107
+
108
+ \033[33mGlobal Options:\033[0m
109
+ -p, --project Path to project file
110
+ --jar Path to Godzilla JAR file
111
+ --json Output in JSON format
112
+ """
113
+ click.echo(help_text)
114
+
115
+
116
+ # Project commands group
117
+ @cli.group("project")
118
+ def project_cli():
119
+ """Project management commands."""
120
+ pass
121
+
122
+
123
+ @project_cli.command("new")
124
+ @click.option("-n", "--name", required=True, help="Project name")
125
+ @click.option("-d", "--description", default="", help="Project description")
126
+ @click.option("-o", "--output", "output_path", help="Output directory path")
127
+ def project_new(name: str, description: str, output_path: Optional[str]):
128
+ """Create a new project."""
129
+ try:
130
+ project = create_project(name=name, path=output_path, description=description)
131
+ skin = ReplSkin("godzilla", "1.0.0")
132
+ skin.success(f"Created project: {name}")
133
+ skin.status("Path", str(project.project_path))
134
+ except Exception as e:
135
+ click.echo(f"Error: {e}", err=True)
136
+ sys.exit(1)
137
+
138
+
139
+ @project_cli.command("open")
140
+ @click.argument("path", required=True)
141
+ def project_open(path: str):
142
+ """Open an existing project."""
143
+ try:
144
+ project = open_project(path)
145
+ skin = ReplSkin("godzilla", "1.0.0")
146
+ skin.success(f"Opened project: {project.name}")
147
+ skin.status("Path", path)
148
+ except FileNotFoundError:
149
+ click.echo(f"Project not found: {path}", err=True)
150
+ sys.exit(1)
151
+ except Exception as e:
152
+ click.echo(f"Error: {e}", err=True)
153
+ sys.exit(1)
154
+
155
+
156
+ @project_cli.command("info")
157
+ @click.pass_context
158
+ def project_info(ctx):
159
+ """Show current project information."""
160
+ project = get_current_project()
161
+ if not project:
162
+ click.echo("No project open. Use 'project open' first.")
163
+ return
164
+
165
+ info = get_project_info(project)
166
+ if ctx.obj.get("json_flag"):
167
+ click.echo(json.dumps(info, indent=2))
168
+ else:
169
+ skin = ReplSkin("godzilla", "1.0.0")
170
+ skin.status("Name", info.get("name", "N/A"))
171
+ skin.status("Path", info.get("path", "N/A"))
172
+ skin.status("Shells", str(info.get("shell_count", 0)))
173
+
174
+
175
+ @project_cli.command("list")
176
+ @click.pass_context
177
+ def project_list(ctx):
178
+ """List all projects."""
179
+ projects = list_projects()
180
+ if ctx.obj.get("json_flag"):
181
+ click.echo(json.dumps(projects, indent=2))
182
+ else:
183
+ skin = ReplSkin("godzilla", "1.0.0")
184
+ if not projects:
185
+ skin.info("No projects found")
186
+ return
187
+ for p in projects:
188
+ click.echo(f" {p['name']}: {p['path']}")
189
+
190
+
191
+ @project_cli.command("close")
192
+ def project_close_cmd():
193
+ """Close current project."""
194
+ project = get_current_project()
195
+ if not project:
196
+ click.echo("No project open.")
197
+ return
198
+ close_project(project)
199
+ skin = ReplSkin("godzilla", "1.0.0")
200
+ skin.success("Project closed")
201
+
202
+
203
+ # Shell commands group
204
+ @cli.group("shell")
205
+ def shell_cli():
206
+ """Shell management commands."""
207
+ pass
208
+
209
+
210
+ @shell_cli.command("add")
211
+ @click.option("-u", "--url", required=True, help="Shell URL")
212
+ @click.option("-p", "--password", required=True, help="Shell password")
213
+ @click.option("-k", "--secret-key", default="", help="Secret key")
214
+ @click.option("--payload", default="JavaDynamicPayload", help="Payload type")
215
+ @click.option("--cryption", default="xor", help="Encryption method")
216
+ @click.option("--encoding", default="UTF-8", help="Character encoding")
217
+ @click.option("--remark", default="", help="Shell remark")
218
+ @click.pass_context
219
+ def shell_add(ctx, url: str, password: str, secret_key: str, payload: str, cryption: str, encoding: str, remark: str):
220
+ """Add a new shell."""
221
+ project = get_current_project()
222
+ if not project:
223
+ click.echo("No project open. Use 'project open' first.", err=True)
224
+ sys.exit(1)
225
+
226
+ try:
227
+ shell = add_shell(
228
+ url=url,
229
+ password=password,
230
+ secret_key=secret_key,
231
+ payload=payload,
232
+ cryption=cryption,
233
+ encoding=encoding,
234
+ remark=remark,
235
+ )
236
+ skin = ReplSkin("godzilla", "1.0.0")
237
+ skin.success(f"Added shell: {shell.id}")
238
+ skin.status("URL", shell.url)
239
+ skin.status("Payload", shell.payload)
240
+ except Exception as e:
241
+ click.echo(f"Error: {e}", err=True)
242
+ sys.exit(1)
243
+
244
+
245
+ @shell_cli.command("list")
246
+ @click.pass_context
247
+ def shell_list(ctx):
248
+ """List all shells."""
249
+ project = get_current_project()
250
+ if not project:
251
+ click.echo("No project open. Use 'project open' first.", err=True)
252
+ return
253
+
254
+ shells = list_shells()
255
+ if ctx.obj.get("json_flag"):
256
+ output = [s.to_dict() for s in shells]
257
+ click.echo(json.dumps(output, indent=2))
258
+ else:
259
+ skin = ReplSkin("godzilla", "1.0.0")
260
+ if not shells:
261
+ skin.info("No shells configured")
262
+ return
263
+ for s in shells:
264
+ click.echo(f" {s.id[:8]}: {s.url} ({s.payload})")
265
+
266
+
267
+ @shell_cli.command("get")
268
+ @click.argument("shell_id", required=True)
269
+ @click.pass_context
270
+ def shell_get(ctx, shell_id: str):
271
+ """Get shell details."""
272
+ project = get_current_project()
273
+ if not project:
274
+ click.echo("No project open. Use 'project open' first.", err=True)
275
+ return
276
+
277
+ shell = get_shell(shell_id)
278
+ if not shell:
279
+ click.echo(f"Shell not found: {shell_id}", err=True)
280
+ return
281
+
282
+ if ctx.obj.get("json_flag"):
283
+ click.echo(json.dumps(shell.to_dict(), indent=2))
284
+ else:
285
+ skin = ReplSkin("godzilla", "1.0.0")
286
+ skin.status("ID", shell.id)
287
+ skin.status("URL", shell.url)
288
+ skin.status("Payload", shell.payload)
289
+ skin.status("Cryption", shell.cryption)
290
+
291
+
292
+ @shell_cli.command("update")
293
+ @click.argument("shell_id", required=True)
294
+ @click.option("--url", help="Update URL")
295
+ @click.option("--password", help="Update password")
296
+ @click.option("--remark", help="Update remark")
297
+ @click.pass_context
298
+ def shell_update(ctx, shell_id: str, url: Optional[str], password: Optional[str], remark: Optional[str]):
299
+ """Update shell configuration."""
300
+ project = get_current_project()
301
+ if not project:
302
+ click.echo("No project open. Use 'project open' first.", err=True)
303
+ return
304
+
305
+ kwargs = {}
306
+ if url:
307
+ kwargs["url"] = url
308
+ if password:
309
+ kwargs["password"] = password
310
+ if remark:
311
+ kwargs["remark"] = remark
312
+
313
+ if not kwargs:
314
+ click.echo("No updates specified.")
315
+ return
316
+
317
+ success = update_shell(shell_id, **kwargs)
318
+ if success:
319
+ skin = ReplSkin("godzilla", "1.0.0")
320
+ skin.success(f"Updated shell: {shell_id}")
321
+ else:
322
+ click.echo(f"Shell not found: {shell_id}", err=True)
323
+
324
+
325
+ @shell_cli.command("remove")
326
+ @click.argument("shell_id", required=True)
327
+ @click.pass_context
328
+ def shell_remove(ctx, shell_id: str):
329
+ """Remove a shell."""
330
+ project = get_current_project()
331
+ if not project:
332
+ click.echo("No project open. Use 'project open' first.", err=True)
333
+ return
334
+
335
+ success = remove_shell(shell_id)
336
+ if success:
337
+ skin = ReplSkin("godzilla", "1.0.0")
338
+ skin.success(f"Removed shell: {shell_id}")
339
+ else:
340
+ click.echo(f"Shell not found: {shell_id}", err=True)
341
+
342
+
343
+ @shell_cli.command("test")
344
+ @click.argument("shell_id", required=True)
345
+ @click.pass_context
346
+ def shell_test_cmd(ctx, shell_id: str):
347
+ """Test shell connectivity."""
348
+ project = get_current_project()
349
+ if not project:
350
+ click.echo("No project open. Use 'project open' first.", err=True)
351
+ return
352
+
353
+ result = test_shell(shell_id)
354
+ if ctx.obj.get("json_flag"):
355
+ click.echo(json.dumps(result, indent=2))
356
+ else:
357
+ skin = ReplSkin("godzilla", "1.0.0")
358
+ if result.get("success"):
359
+ skin.success("Shell connection successful")
360
+ else:
361
+ skin.error(f"Shell connection failed: {result.get('error')}")
362
+
363
+
364
+ @shell_cli.command("export")
365
+ @click.argument("output", required=True)
366
+ @click.option("-i", "--ids", help="Comma-separated shell IDs")
367
+ @click.pass_context
368
+ def shell_export(ctx, output: str, ids: Optional[str]):
369
+ """Export shells to JSON file."""
370
+ project = get_current_project()
371
+ if not project:
372
+ click.echo("No project open. Use 'project open' first.", err=True)
373
+ return
374
+
375
+ shell_ids = ids.split(",") if ids else None
376
+ export_shells(output, shell_ids)
377
+ skin = ReplSkin("godzilla", "1.0.0")
378
+ skin.success(f"Exported shells to {output}")
379
+
380
+
381
+ @shell_cli.command("import")
382
+ @click.argument("input_file", required=True)
383
+ @click.option("--overwrite", is_flag=True, help="Overwrite existing shells")
384
+ @click.pass_context
385
+ def shell_import(ctx, input_file: str, overwrite: bool):
386
+ """Import shells from JSON file."""
387
+ project = get_current_project()
388
+ if not project:
389
+ click.echo("No project open. Use 'project open' first.", err=True)
390
+ return
391
+
392
+ count = import_shells(input_file, overwrite)
393
+ skin = ReplSkin("godzilla", "1.0.0")
394
+ skin.success(f"Imported {count} shells")
395
+
396
+
397
+ # Profile commands group
398
+ @cli.group("profile")
399
+ def profile_cli():
400
+ """C2 Profile management commands."""
401
+ pass
402
+
403
+
404
+ @profile_cli.command("list")
405
+ @click.pass_context
406
+ def profile_list(ctx):
407
+ """List available C2 profiles."""
408
+ project = get_current_project()
409
+ profiles = []
410
+
411
+ if project and project.is_open:
412
+ profile_dir = Path(project.project_path) / "profile"
413
+ if profile_dir.exists():
414
+ for f in profile_dir.glob("*.profile"):
415
+ profiles.append({
416
+ "name": f.stem,
417
+ "path": str(f),
418
+ })
419
+
420
+ if ctx.obj.get("json_flag"):
421
+ click.echo(json.dumps(profiles, indent=2))
422
+ else:
423
+ skin = ReplSkin("godzilla", "1.0.0")
424
+ if not profiles:
425
+ skin.info("No profiles found")
426
+ else:
427
+ for p in profiles:
428
+ click.echo(f" {p['name']}: {p['path']}")
429
+
430
+
431
+ @profile_cli.command("load")
432
+ @click.argument("path", required=True)
433
+ @click.pass_context
434
+ def profile_load(ctx, path: str):
435
+ """Load a C2 profile from file."""
436
+ try:
437
+ profile = load_profile(path)
438
+ skin = ReplSkin("godzilla", "1.0.0")
439
+ skin.success(f"Loaded profile: {profile.name}")
440
+ if ctx.obj.get("json_flag"):
441
+ click.echo(json.dumps(profile.to_dict(), indent=2))
442
+ except Exception as e:
443
+ click.echo(f"Error loading profile: {e}", err=True)
444
+ sys.exit(1)
445
+
446
+
447
+ @profile_cli.command("validate")
448
+ @click.argument("path", required=True)
449
+ @click.pass_context
450
+ def profile_validate(ctx, path: str):
451
+ """Validate a C2 profile file."""
452
+ try:
453
+ with open(path, 'r') as f:
454
+ data = yaml.safe_load(f) if yaml else {}
455
+ errors = validate_profile(data)
456
+ if ctx.obj.get("json_flag"):
457
+ click.echo(json.dumps({"valid": len(errors) == 0, "errors": errors}, indent=2))
458
+ else:
459
+ skin = ReplSkin("godzilla", "1.0.0")
460
+ if errors:
461
+ skin.error("Profile validation failed:")
462
+ for err in errors:
463
+ click.echo(f" - {err}")
464
+ else:
465
+ skin.success("Profile is valid")
466
+ except Exception as e:
467
+ click.echo(f"Error: {e}", err=True)
468
+ sys.exit(1)
469
+
470
+
471
+ # REPL command
472
+ @cli.command("repl")
473
+ @click.option("-p", "--project", "project_path", help="Path to project file")
474
+ @click.pass_context
475
+ def repl(ctx, project_path: Optional[str]):
476
+ """Start interactive REPL mode."""
477
+ # Load project if specified
478
+ if project_path:
479
+ try:
480
+ open_project(project_path)
481
+ except Exception as e:
482
+ click.echo(f"Error opening project: {e}", err=True)
483
+
484
+ current_project = get_current_project()
485
+ skin = ReplSkin("godzilla", "1.0.0")
486
+ skin.print_banner()
487
+
488
+ if current_project:
489
+ skin.info(f"Project: {current_project.name}")
490
+
491
+ # Command registry for help
492
+ commands = {
493
+ "help": "Show this help",
494
+ "exit": "Exit REPL",
495
+ "project info": "Show project information",
496
+ "project list": "List all projects",
497
+ "shell list": "List all shells",
498
+ "shell get <id>": "Get shell details",
499
+ "shell add <url> <password>": "Add new shell",
500
+ "shell test <id>": "Test shell connectivity",
501
+ "profile list": "List C2 profiles",
502
+ }
503
+
504
+ skin.info("Type 'help' for available commands")
505
+
506
+ # Simple REPL loop
507
+ while True:
508
+ try:
509
+ line = input("godzilla> ")
510
+ if not line:
511
+ continue
512
+
513
+ line = line.strip()
514
+ if not line:
515
+ continue
516
+
517
+ # Handle commands
518
+ if line in ["exit", "quit", "q"]:
519
+ skin.print_goodbye()
520
+ break
521
+ elif line in ["help", "h", "?"]:
522
+ skin.help(commands)
523
+ elif line == "project info":
524
+ ctx.invoke(project_info)
525
+ elif line == "project list":
526
+ ctx.invoke(project_list)
527
+ elif line == "shell list":
528
+ ctx.invoke(shell_list)
529
+ elif line.startswith("shell get "):
530
+ # 支持 shell_id (支持短ID)
531
+ parts = line.split(maxsplit=2)
532
+ if len(parts) >= 3:
533
+ shell_id = parts[2].strip()
534
+ ctx.invoke(shell_get, shell_id=shell_id)
535
+ elif line.startswith("shell add "):
536
+ # Support url and password
537
+ parts = line.split(maxsplit=2)
538
+ if len(parts) >= 3:
539
+ url = parts[1].strip()
540
+ password = parts[2].strip()
541
+ ctx.invoke(shell_add, url=url, password=password)
542
+ elif line.startswith("shell test "):
543
+ # support shell_id (支持短ID)
544
+ parts = line.split(maxsplit=2)
545
+ if len(parts) >= 3:
546
+ shell_id = parts[2].strip()
547
+ ctx.invoke(shell_test_cmd, shell_id=shell_id)
548
+ elif line.startswith("shell update "):
549
+ # support shell update with short ID
550
+ parts = line.split(maxsplit=2)
551
+ if len(parts) >= 3:
552
+ shell_id = parts[2].strip()
553
+ # 简单的更新,只支持 shell update <id> --remark "xxx" 格式
554
+ if " --remark " in line:
555
+ remark_parts = line.split(" --remark ", 1)
556
+ remark = remark_parts[1].strip().strip('"')
557
+ ctx.invoke(shell_update, shell_id=shell_id, remark=remark)
558
+ elif line.startswith("shell remove "):
559
+ # support shell remove with short ID
560
+ parts = line.split(maxsplit=2)
561
+ if len(parts) >= 3:
562
+ shell_id = parts[2].strip()
563
+ ctx.invoke(shell_remove, shell_id=shell_id)
564
+ elif line == "profile list":
565
+ ctx.invoke(profile_list)
566
+ else:
567
+ skin.error(f"Unknown command: {line}")
568
+ skin.info("Type 'help' for available commands")
569
+
570
+ except KeyboardInterrupt:
571
+ skin.print_goodbye()
572
+ break
573
+ except Exception as e:
574
+ skin.error(f"Error: {e}")
575
+
576
+
577
+ def main():
578
+ """Entry point for CLI."""
579
+ cli()
580
+
581
+
582
+ if __name__ == "__main__":
583
+ main()
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: cli-anything-godzilla
3
+ Version: 1.0.0
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: click>=8.0.0
6
+ Requires-Dist: prompt-toolkit>=3.0.0
7
+ Requires-Dist: pyyaml>=6.0.0
8
+ Dynamic: requires-dist
9
+ Dynamic: requires-python
@@ -0,0 +1,10 @@
1
+ README.md
2
+ setup.py
3
+ cli_anything/godzilla/__init__.py
4
+ cli_anything/godzilla/godzilla_cli.py
5
+ cli_anything_godzilla.egg-info/PKG-INFO
6
+ cli_anything_godzilla.egg-info/SOURCES.txt
7
+ cli_anything_godzilla.egg-info/dependency_links.txt
8
+ cli_anything_godzilla.egg-info/entry_points.txt
9
+ cli_anything_godzilla.egg-info/requires.txt
10
+ cli_anything_godzilla.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cli-anything-godzilla = cli_anything.godzilla.godzilla_cli:main
@@ -0,0 +1,3 @@
1
+ click>=8.0.0
2
+ prompt-toolkit>=3.0.0
3
+ pyyaml>=6.0.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,24 @@
1
+ """
2
+ PyPI package configuration for cli-anything-godzilla.
3
+
4
+ This package provides a CLI harness for the Godzilla Security Testing Tool.
5
+ """
6
+
7
+ from setuptools import setup, find_namespace_packages
8
+
9
+ setup(
10
+ name="cli-anything-godzilla",
11
+ version="1.0.0",
12
+ packages=find_namespace_packages(include=["cli_anything.godzilla"]),
13
+ install_requires=[
14
+ "click>=8.0.0",
15
+ "prompt-toolkit>=3.0.0",
16
+ "pyyaml>=6.0.0",
17
+ ],
18
+ entry_points={
19
+ "console_scripts": [
20
+ "cli-anything-godzilla=cli_anything.godzilla.godzilla_cli:main",
21
+ ],
22
+ },
23
+ python_requires=">=3.10",
24
+ )