sandbox-cli 0.2.26__tar.gz → 0.2.28__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.
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/.gitignore +1 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/PKG-INFO +4 -5
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/README.md +2 -3
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/pyproject.toml +2 -2
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/scanner/__init__.py +21 -4
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/console.py +0 -1
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/internal/config.py +7 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/downloader/__init__.py +12 -10
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/scanner/rescan.py +1 -1
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/LICENSE +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/NOTICE +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/__main__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/downloader.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/images.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/reporter.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/rules/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/cli/unpack.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/internal/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/internal/helpers.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/models/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/models/detections.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/compiler/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/compiler/abc.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/compiler/docker.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/compiler/ssh.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/extractors.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/merge_dll_hooks.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/scanner/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/scanner/advanced.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/unpack/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/unpack/plugins/__init__.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/unpack/plugins/abc.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/unpack/plugins/correlation.py +0 -0
- {sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/unpack/plugins/sort_by_plugins.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sandbox-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.28
|
|
4
4
|
Summary: Command line tool for interaction with sandboxes
|
|
5
5
|
Project-URL: Homepage, https://github.com/Security-Experts-Community/sandbox-cli
|
|
6
6
|
Project-URL: Documentation, https://security-experts-community.github.io/sandbox-cli
|
|
@@ -16,7 +16,7 @@ Requires-Dist: asyncssh>=2.19.0
|
|
|
16
16
|
Requires-Dist: cryptography>=44.0.0
|
|
17
17
|
Requires-Dist: cyclopts>=3.9.0
|
|
18
18
|
Requires-Dist: docker>=7.1.0
|
|
19
|
-
Requires-Dist: ptsandbox
|
|
19
|
+
Requires-Dist: ptsandbox>=5.0.0
|
|
20
20
|
Requires-Dist: pyzipper>=0.3.6
|
|
21
21
|
Requires-Dist: rich>=13.9.4
|
|
22
22
|
Requires-Dist: zstandard>=0.23.0
|
|
@@ -55,9 +55,8 @@ pip install sandbox-cli
|
|
|
55
55
|
|
|
56
56
|
NixOS:
|
|
57
57
|
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
TBA: ...
|
|
58
|
+
```sh
|
|
59
|
+
nix shell 'github:Security-Experts-Community/sandbox-cli'
|
|
61
60
|
```
|
|
62
61
|
|
|
63
62
|
### Config
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sandbox-cli"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.28"
|
|
4
4
|
description = "Command line tool for interaction with sandboxes"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -13,7 +13,7 @@ dependencies = [
|
|
|
13
13
|
"cryptography>=44.0.0",
|
|
14
14
|
"cyclopts>=3.9.0",
|
|
15
15
|
"docker>=7.1.0",
|
|
16
|
-
"ptsandbox",
|
|
16
|
+
"ptsandbox>=5.0.0",
|
|
17
17
|
"pyzipper>=0.3.6",
|
|
18
18
|
"rich>=13.9.4",
|
|
19
19
|
"zstandard>=0.23.0",
|
|
@@ -7,7 +7,7 @@ from cyclopts import App, Parameter, Token, validators
|
|
|
7
7
|
from ptsandbox.models import VNCMode
|
|
8
8
|
|
|
9
9
|
from sandbox_cli.console import console
|
|
10
|
-
from sandbox_cli.internal.config import VMImage, settings
|
|
10
|
+
from sandbox_cli.internal.config import Platform, VMImage, settings
|
|
11
11
|
from sandbox_cli.internal.helpers import validate_key
|
|
12
12
|
from sandbox_cli.utils.scanner import scan_internal
|
|
13
13
|
from sandbox_cli.utils.scanner.advanced import scan_internal_advanced
|
|
@@ -34,6 +34,20 @@ def image_converter(_: Any, tokens: Sequence[Token]) -> set[VMImage | str]:
|
|
|
34
34
|
return images
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
def rules_path_resolver(_: Any, tokens: Sequence[Token]) -> Path | None:
|
|
38
|
+
path: Path | None = None
|
|
39
|
+
for token in tokens:
|
|
40
|
+
if token.value in {Platform.LINUX, Platform.WINDOWS}:
|
|
41
|
+
if not settings.rules_path:
|
|
42
|
+
console.error("You can't use aliases without specifying the path in the config")
|
|
43
|
+
sys.exit(1)
|
|
44
|
+
|
|
45
|
+
path = settings.rules_path / token.value
|
|
46
|
+
break
|
|
47
|
+
|
|
48
|
+
return path
|
|
49
|
+
|
|
50
|
+
|
|
37
51
|
@scanner.command(name="re-scan")
|
|
38
52
|
async def re_scan(
|
|
39
53
|
traces: Annotated[
|
|
@@ -48,7 +62,8 @@ async def re_scan(
|
|
|
48
62
|
Path | None,
|
|
49
63
|
Parameter(
|
|
50
64
|
name=["--rules", "-r"],
|
|
51
|
-
help="The path to the folder with the rules or the default rules from the sandbox",
|
|
65
|
+
help="The path to the folder with the rules or the default rules from the sandbox or platform alias (windows, linux)",
|
|
66
|
+
converter=rules_path_resolver,
|
|
52
67
|
),
|
|
53
68
|
] = None,
|
|
54
69
|
out_dir: Annotated[
|
|
@@ -136,7 +151,8 @@ async def scan(
|
|
|
136
151
|
Path | None,
|
|
137
152
|
Parameter(
|
|
138
153
|
name=["--rules", "-r"],
|
|
139
|
-
help="The path to the folder with the rules or the default rules from the sandbox",
|
|
154
|
+
help="The path to the folder with the rules or the default rules from the sandbox or platform alias (windows, linux)",
|
|
155
|
+
converter=rules_path_resolver,
|
|
140
156
|
),
|
|
141
157
|
] = None,
|
|
142
158
|
out_dir: Annotated[
|
|
@@ -372,7 +388,8 @@ async def scan_new(
|
|
|
372
388
|
Path | None,
|
|
373
389
|
Parameter(
|
|
374
390
|
name=["--rules", "-r"],
|
|
375
|
-
help="The path to the folder with the rules or the default rules from the sandbox",
|
|
391
|
+
help="The path to the folder with the rules or the default rules from the sandbox or platform alias (windows, linux)",
|
|
392
|
+
converter=rules_path_resolver,
|
|
376
393
|
),
|
|
377
394
|
] = None,
|
|
378
395
|
out_dir: Annotated[
|
|
@@ -44,6 +44,11 @@ class VMImage(str, Enum):
|
|
|
44
44
|
return str(self.value)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
class Platform(str, Enum):
|
|
48
|
+
LINUX = "linux"
|
|
49
|
+
WINDOWS = "windows"
|
|
50
|
+
|
|
51
|
+
|
|
47
52
|
class Settings(BaseModel):
|
|
48
53
|
class Docker(BaseModel):
|
|
49
54
|
username: str = ""
|
|
@@ -113,9 +118,11 @@ class Settings(BaseModel):
|
|
|
113
118
|
passwords: list[str] = ["infected", "311138", "password", "12345678", "P@ssw0rd!"]
|
|
114
119
|
docker: Docker = Docker()
|
|
115
120
|
sandbox: list[Sandbox] = []
|
|
121
|
+
rules_path: Path | None = Field(default=None, alias="rules-path")
|
|
116
122
|
|
|
117
123
|
def model_post_init(self, __context: Any) -> None:
|
|
118
124
|
self.sandbox_keys = [x.sandbox_key for x in self.sandbox]
|
|
125
|
+
self.rules_path = Path(self.rules_path) if self.rules_path else None
|
|
119
126
|
|
|
120
127
|
|
|
121
128
|
def load_config(path: Path) -> Settings:
|
|
@@ -25,6 +25,7 @@ semaphore = asyncio.Semaphore(value=12)
|
|
|
25
25
|
async def _save_artifact(
|
|
26
26
|
scan_id: UUID,
|
|
27
27
|
sandbox: Sandbox,
|
|
28
|
+
out_dir: Path,
|
|
28
29
|
path: Path,
|
|
29
30
|
file_uri: str,
|
|
30
31
|
decompress: bool = False,
|
|
@@ -38,7 +39,7 @@ async def _save_artifact(
|
|
|
38
39
|
return
|
|
39
40
|
|
|
40
41
|
# sanitize path
|
|
41
|
-
path = Path(str(path).replace(" ", "_"))
|
|
42
|
+
path = out_dir / Path(str(path).replace(" ", "_"))
|
|
42
43
|
task_id: TaskID = None # type: ignore
|
|
43
44
|
|
|
44
45
|
async with semaphore:
|
|
@@ -100,11 +101,12 @@ async def download(
|
|
|
100
101
|
) -> None:
|
|
101
102
|
tasks: list[Coroutine[Any, Any, None]] = []
|
|
102
103
|
|
|
103
|
-
def add_task(path: Path, file_uri: str, decompress: bool = False) -> None:
|
|
104
|
+
def add_task(out_dir: Path, path: Path, file_uri: str, decompress: bool = False) -> None:
|
|
104
105
|
tasks.append(
|
|
105
106
|
_save_artifact(
|
|
106
107
|
scan_id=report.scan_id,
|
|
107
108
|
sandbox=sandbox,
|
|
109
|
+
out_dir=out_dir,
|
|
108
110
|
path=path,
|
|
109
111
|
file_uri=file_uri,
|
|
110
112
|
progress=progress,
|
|
@@ -134,16 +136,16 @@ async def download(
|
|
|
134
136
|
LogType.EVENT_RAW,
|
|
135
137
|
LogType.NETWORK,
|
|
136
138
|
}:
|
|
137
|
-
add_task(out_dir
|
|
139
|
+
add_task(out_dir, log.file_name, log.file_uri)
|
|
138
140
|
|
|
139
141
|
if (all or video) and log.type == LogType.SCREENSHOT:
|
|
140
|
-
add_task(out_dir
|
|
142
|
+
add_task(out_dir, log.file_name, log.file_uri)
|
|
141
143
|
|
|
142
144
|
if (all or crashdumps) and log.file_name in {"crashdump.bin", "crashdump.metadata"}:
|
|
143
|
-
add_task(out_dir / "crashdumps"
|
|
145
|
+
add_task(out_dir / "crashdumps", log.file_name, log.file_uri)
|
|
144
146
|
|
|
145
147
|
if (all or debug) and log.type in {LogType.DEBUG, LogType.GRAPH}:
|
|
146
|
-
add_task(out_dir / "debug"
|
|
148
|
+
add_task(out_dir / "debug", log.file_name, log.file_uri)
|
|
147
149
|
|
|
148
150
|
if artifacts or files or procdumps or all:
|
|
149
151
|
if not sandbox_result.details:
|
|
@@ -161,14 +163,14 @@ async def download(
|
|
|
161
163
|
|
|
162
164
|
if artifact.type == ArtifactType.FILE and (files or artifacts or all):
|
|
163
165
|
add_task(
|
|
164
|
-
out_dir / "artifacts"
|
|
166
|
+
out_dir / "artifacts",
|
|
167
|
+
artifact.file_info.file_path.removeprefix("/"),
|
|
165
168
|
artifact.file_info.file_uri,
|
|
166
169
|
)
|
|
167
170
|
if artifact.type == ArtifactType.PROCESS_DUMP and (procdumps or artifacts or all):
|
|
168
171
|
add_task(
|
|
169
|
-
out_dir
|
|
170
|
-
/
|
|
171
|
-
/ artifact.file_info.details.process_dump.process_name.removeprefix("/"), # type: ignore
|
|
172
|
+
out_dir / "process_dump",
|
|
173
|
+
artifact.file_info.details.process_dump.process_name.removeprefix("/"), # type: ignore
|
|
172
174
|
artifact.file_info.file_uri,
|
|
173
175
|
decompress=decompress,
|
|
174
176
|
)
|
|
@@ -202,7 +202,7 @@ async def rescan_internal(
|
|
|
202
202
|
drakvuf_trace = trace / "drakvuf-trace.log.zst"
|
|
203
203
|
if not drakvuf_trace.exists():
|
|
204
204
|
console.error(
|
|
205
|
-
f"drakvuf-trace.log.gz or drakvuf-trace.log.zst doesn't
|
|
205
|
+
f"drakvuf-trace.log.gz or drakvuf-trace.log.zst doesn't exist in {trace.expanduser().resolve()}"
|
|
206
206
|
)
|
|
207
207
|
sys.exit(1)
|
|
208
208
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sandbox_cli-0.2.26 → sandbox_cli-0.2.28}/sandbox_cli/utils/unpack/plugins/sort_by_plugins.py
RENAMED
|
File without changes
|