maco 1.2.19__py3-none-any.whl → 1.2.21__py3-none-any.whl
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.
- extractor_setup/maco/cli.py +34 -0
- extractor_setup/maco/model/model.py +2 -0
- maco/cli.py +34 -0
- maco/model/model.py +2 -0
- {maco-1.2.19.dist-info → maco-1.2.21.dist-info}/METADATA +2 -3
- {maco-1.2.19.dist-info → maco-1.2.21.dist-info}/RECORD +13 -13
- {maco-1.2.19.dist-info → maco-1.2.21.dist-info}/WHEEL +1 -1
- model_setup/maco/cli.py +34 -0
- model_setup/maco/model/model.py +2 -0
- pipelines/test.yaml +0 -4
- {maco-1.2.19.dist-info → maco-1.2.21.dist-info}/entry_points.txt +0 -0
- {maco-1.2.19.dist-info → maco-1.2.21.dist-info}/licenses/LICENSE.md +0 -0
- {maco-1.2.19.dist-info → maco-1.2.21.dist-info}/top_level.txt +0 -0
extractor_setup/maco/cli.py
CHANGED
|
@@ -27,6 +27,7 @@ def process_file(
|
|
|
27
27
|
pretty: bool,
|
|
28
28
|
force: bool,
|
|
29
29
|
include_base64: bool,
|
|
30
|
+
extracted_dir: str = "",
|
|
30
31
|
):
|
|
31
32
|
"""Process a filestream with the extractors and rules.
|
|
32
33
|
|
|
@@ -37,6 +38,7 @@ def process_file(
|
|
|
37
38
|
pretty (bool): Pretty print the JSON output
|
|
38
39
|
force (bool): Run all extractors regardless of YARA rule match
|
|
39
40
|
include_base64 (bool): include base64'd data in output
|
|
41
|
+
extracted_dir (str): directory to write CaRTed binary data to
|
|
40
42
|
|
|
41
43
|
Returns:
|
|
42
44
|
(dict): The output from the extractors analyzing the sample
|
|
@@ -87,6 +89,34 @@ def process_file(
|
|
|
87
89
|
if include_base64:
|
|
88
90
|
# this can be large
|
|
89
91
|
row["base64"] = base64.b64encode(row["data"]).decode("utf8")
|
|
92
|
+
|
|
93
|
+
# write binary data to disk if enabled
|
|
94
|
+
if extracted_dir:
|
|
95
|
+
# only allow writes to already existing directories with permissions
|
|
96
|
+
if os.path.isdir(extracted_dir) and os.access(extracted_dir, os.W_OK):
|
|
97
|
+
filepath = os.path.abspath(os.path.join(extracted_dir, f"{row['sha256']}.cart"))
|
|
98
|
+
# don't overwrite existing files
|
|
99
|
+
if os.path.exists(filepath):
|
|
100
|
+
logger.debug(f"{filepath} already exists.")
|
|
101
|
+
else:
|
|
102
|
+
# CaRT data before writing to disk
|
|
103
|
+
in_stream = io.BytesIO(row["data"])
|
|
104
|
+
output_stream = io.BytesIO()
|
|
105
|
+
try:
|
|
106
|
+
cart.pack_stream(in_stream, output_stream)
|
|
107
|
+
except Exception:
|
|
108
|
+
logger.error(f"Error trying to CaRT binary output ({row['sha256']}) from {path_file}.")
|
|
109
|
+
else:
|
|
110
|
+
output_stream.seek(0)
|
|
111
|
+
try:
|
|
112
|
+
with open(filepath, "wb") as f:
|
|
113
|
+
f.write(output_stream.getbuffer())
|
|
114
|
+
logger.debug(f"Wrote binary output to {filepath}.")
|
|
115
|
+
except (FileNotFoundError, PermissionError, OSError):
|
|
116
|
+
logger.error(f"Error trying to write binary output to {filepath}")
|
|
117
|
+
else:
|
|
118
|
+
logger.error(f"Cannot write files to {extracted_dir}")
|
|
119
|
+
|
|
90
120
|
# do not print raw bytes to console
|
|
91
121
|
row.pop("data")
|
|
92
122
|
ret[extractor_name] = resp
|
|
@@ -107,6 +137,7 @@ def process_filesystem(
|
|
|
107
137
|
include_base64: bool,
|
|
108
138
|
create_venv: bool = False,
|
|
109
139
|
skip_install: bool = False,
|
|
140
|
+
extracted_dir: str = "",
|
|
110
141
|
) -> Tuple[int, int, int]:
|
|
111
142
|
"""Process filesystem with extractors and print results of extraction.
|
|
112
143
|
|
|
@@ -159,6 +190,7 @@ def process_filesystem(
|
|
|
159
190
|
pretty=pretty,
|
|
160
191
|
force=force,
|
|
161
192
|
include_base64=include_base64,
|
|
193
|
+
extracted_dir=extracted_dir,
|
|
162
194
|
)
|
|
163
195
|
if resp:
|
|
164
196
|
num_hits += 1
|
|
@@ -194,6 +226,7 @@ def main():
|
|
|
194
226
|
help="Include base64 encoded binary data in output "
|
|
195
227
|
"(can be large, consider printing to file rather than console)",
|
|
196
228
|
)
|
|
229
|
+
parser.add_argument("--binarydir", type=str, help="directory to write extracted binary data to")
|
|
197
230
|
parser.add_argument("--logfile", type=str, help="file to log output")
|
|
198
231
|
parser.add_argument("--include", type=str, help="comma separated extractors to run")
|
|
199
232
|
parser.add_argument("--exclude", type=str, help="comma separated extractors to not run")
|
|
@@ -268,6 +301,7 @@ def main():
|
|
|
268
301
|
include_base64=args.base64,
|
|
269
302
|
create_venv=args.create_venv,
|
|
270
303
|
skip_install=not args.force_install,
|
|
304
|
+
extracted_dir=args.binarydir,
|
|
271
305
|
)
|
|
272
306
|
|
|
273
307
|
|
|
@@ -48,6 +48,8 @@ class Encryption(ForbidModel):
|
|
|
48
48
|
iv: Optional[str] = None # initialisation vector
|
|
49
49
|
seed: Optional[str] = None
|
|
50
50
|
nonce: Optional[str] = None
|
|
51
|
+
password: Optional[str] = None
|
|
52
|
+
salt: Optional[str] = None
|
|
51
53
|
constants: List[str] = []
|
|
52
54
|
|
|
53
55
|
usage: Optional[UsageEnum] = None
|
maco/cli.py
CHANGED
|
@@ -27,6 +27,7 @@ def process_file(
|
|
|
27
27
|
pretty: bool,
|
|
28
28
|
force: bool,
|
|
29
29
|
include_base64: bool,
|
|
30
|
+
extracted_dir: str = "",
|
|
30
31
|
):
|
|
31
32
|
"""Process a filestream with the extractors and rules.
|
|
32
33
|
|
|
@@ -37,6 +38,7 @@ def process_file(
|
|
|
37
38
|
pretty (bool): Pretty print the JSON output
|
|
38
39
|
force (bool): Run all extractors regardless of YARA rule match
|
|
39
40
|
include_base64 (bool): include base64'd data in output
|
|
41
|
+
extracted_dir (str): directory to write CaRTed binary data to
|
|
40
42
|
|
|
41
43
|
Returns:
|
|
42
44
|
(dict): The output from the extractors analyzing the sample
|
|
@@ -87,6 +89,34 @@ def process_file(
|
|
|
87
89
|
if include_base64:
|
|
88
90
|
# this can be large
|
|
89
91
|
row["base64"] = base64.b64encode(row["data"]).decode("utf8")
|
|
92
|
+
|
|
93
|
+
# write binary data to disk if enabled
|
|
94
|
+
if extracted_dir:
|
|
95
|
+
# only allow writes to already existing directories with permissions
|
|
96
|
+
if os.path.isdir(extracted_dir) and os.access(extracted_dir, os.W_OK):
|
|
97
|
+
filepath = os.path.abspath(os.path.join(extracted_dir, f"{row['sha256']}.cart"))
|
|
98
|
+
# don't overwrite existing files
|
|
99
|
+
if os.path.exists(filepath):
|
|
100
|
+
logger.debug(f"{filepath} already exists.")
|
|
101
|
+
else:
|
|
102
|
+
# CaRT data before writing to disk
|
|
103
|
+
in_stream = io.BytesIO(row["data"])
|
|
104
|
+
output_stream = io.BytesIO()
|
|
105
|
+
try:
|
|
106
|
+
cart.pack_stream(in_stream, output_stream)
|
|
107
|
+
except Exception:
|
|
108
|
+
logger.error(f"Error trying to CaRT binary output ({row['sha256']}) from {path_file}.")
|
|
109
|
+
else:
|
|
110
|
+
output_stream.seek(0)
|
|
111
|
+
try:
|
|
112
|
+
with open(filepath, "wb") as f:
|
|
113
|
+
f.write(output_stream.getbuffer())
|
|
114
|
+
logger.debug(f"Wrote binary output to {filepath}.")
|
|
115
|
+
except (FileNotFoundError, PermissionError, OSError):
|
|
116
|
+
logger.error(f"Error trying to write binary output to {filepath}")
|
|
117
|
+
else:
|
|
118
|
+
logger.error(f"Cannot write files to {extracted_dir}")
|
|
119
|
+
|
|
90
120
|
# do not print raw bytes to console
|
|
91
121
|
row.pop("data")
|
|
92
122
|
ret[extractor_name] = resp
|
|
@@ -107,6 +137,7 @@ def process_filesystem(
|
|
|
107
137
|
include_base64: bool,
|
|
108
138
|
create_venv: bool = False,
|
|
109
139
|
skip_install: bool = False,
|
|
140
|
+
extracted_dir: str = "",
|
|
110
141
|
) -> Tuple[int, int, int]:
|
|
111
142
|
"""Process filesystem with extractors and print results of extraction.
|
|
112
143
|
|
|
@@ -159,6 +190,7 @@ def process_filesystem(
|
|
|
159
190
|
pretty=pretty,
|
|
160
191
|
force=force,
|
|
161
192
|
include_base64=include_base64,
|
|
193
|
+
extracted_dir=extracted_dir,
|
|
162
194
|
)
|
|
163
195
|
if resp:
|
|
164
196
|
num_hits += 1
|
|
@@ -194,6 +226,7 @@ def main():
|
|
|
194
226
|
help="Include base64 encoded binary data in output "
|
|
195
227
|
"(can be large, consider printing to file rather than console)",
|
|
196
228
|
)
|
|
229
|
+
parser.add_argument("--binarydir", type=str, help="directory to write extracted binary data to")
|
|
197
230
|
parser.add_argument("--logfile", type=str, help="file to log output")
|
|
198
231
|
parser.add_argument("--include", type=str, help="comma separated extractors to run")
|
|
199
232
|
parser.add_argument("--exclude", type=str, help="comma separated extractors to not run")
|
|
@@ -268,6 +301,7 @@ def main():
|
|
|
268
301
|
include_base64=args.base64,
|
|
269
302
|
create_venv=args.create_venv,
|
|
270
303
|
skip_install=not args.force_install,
|
|
304
|
+
extracted_dir=args.binarydir,
|
|
271
305
|
)
|
|
272
306
|
|
|
273
307
|
|
maco/model/model.py
CHANGED
|
@@ -48,6 +48,8 @@ class Encryption(ForbidModel):
|
|
|
48
48
|
iv: Optional[str] = None # initialisation vector
|
|
49
49
|
seed: Optional[str] = None
|
|
50
50
|
nonce: Optional[str] = None
|
|
51
|
+
password: Optional[str] = None
|
|
52
|
+
salt: Optional[str] = None
|
|
51
53
|
constants: List[str] = []
|
|
52
54
|
|
|
53
55
|
usage: Optional[UsageEnum] = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maco
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.21
|
|
4
4
|
Summary: Maco is a framework for creating and using malware configuration extractors.
|
|
5
5
|
Author: sl-govau
|
|
6
6
|
Maintainer: cccs-rs
|
|
@@ -22,8 +22,6 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
22
22
|
Classifier: Intended Audience :: Developers
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
24
|
Classifier: License :: OSI Approved :: MIT License
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
26
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
27
25
|
Classifier: Programming Language :: Python :: 3.10
|
|
28
26
|
Classifier: Programming Language :: Python :: 3.11
|
|
29
27
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -72,6 +70,7 @@ This framework is actively being used by:
|
|
|
72
70
|
| [configextractor-py](https://github.com/CybercentreCanada/configextractor-py) | A tool designed to run extractors from multiple frameworks and uses the MACO model for output harmonization | [](https://github.com/CybercentreCanada/configextractor-py/blob/main/LICENSE.md) |
|
|
73
71
|
| <a href="https://github.com/jeFF0Falltrades/rat_king_parser"><img src="https://images.weserv.nl/?url=raw.githubusercontent.com/jeFF0Falltrades/rat_king_parser/master/.github/logo.png?v=4&h=100&w=100&fit=cover&maxage=7d"/> </a> | A robust, multiprocessing-capable, multi-family RAT config parser/extractor that is compatible with MACO | [](https://github.com/jeFF0Falltrades/rat_king_parser/blob/master/LICENSE) |
|
|
74
72
|
| <a href="https://github.com/CAPESandbox/community"><img src="https://images.weserv.nl/?url=github.com/CAPESandbox.png?v=4&h=100&w=100&fit=cover&maxage=7d0&mask=circle"/> </a> | A parser/extractor repository containing MACO extractors that's authored by the CAPE community but is integrated in [CAPE](https://github.com/kevoreilly/CAPEv2) deployments.<br>**Note: These MACO extractors wrap and parse the original CAPE extractors.** | [](https://github.com/kevoreilly/CAPEv2/blob/master/LICENSE) |
|
|
73
|
+
| <a href="https://github.com/SEKOIA-IO/Community"><img src="https://images.weserv.nl/?url=github.com/SEKOIA-IO.png?v=4&h=100&w=100&fit=cover&maxage=7d0&mask=circle"/> </a> | A parser/extractor repository containing MACO extractors that's authored by the SEKOIA community. | [](https://github.com/SEKOIA-IO/Community/blob/main/LICENSE.md) |
|
|
75
74
|
|
|
76
75
|
## Model Example
|
|
77
76
|
|
|
@@ -10,37 +10,37 @@ demo_extractors/complex/complex.py,sha256=GYKmPOD8-fyVHxwjZb-3t1IghKVMuLtdUvCs5C
|
|
|
10
10
|
demo_extractors/complex/complex_utils.py,sha256=5kdMl-niSH9d-d3ChuItpmlPT4U-S9g-iyBZlR4tfmQ,296
|
|
11
11
|
extractor_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
extractor_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
|
|
13
|
-
extractor_setup/maco/cli.py,sha256=
|
|
13
|
+
extractor_setup/maco/cli.py,sha256=jFtYWuKNlqcnSl0W4vgITctpgfd3J9kgN37IwoW3pDY,11477
|
|
14
14
|
extractor_setup/maco/collector.py,sha256=I0Nidf4-xcvoe6X0bbCsAXjr66iPf00JDO6ocKkaZLc,8309
|
|
15
15
|
extractor_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
|
|
16
16
|
extractor_setup/maco/extractor.py,sha256=nqIfUcrc_l57FicKZc6HLtN223-_zkYWL1AYMy1WAmA,3007
|
|
17
17
|
extractor_setup/maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
|
|
18
18
|
extractor_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
|
|
19
19
|
extractor_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
|
|
20
|
-
extractor_setup/maco/model/model.py,sha256=
|
|
20
|
+
extractor_setup/maco/model/model.py,sha256=a98XB7C6P_9JHNsodzbaRomr17rLYH6J4g5clH2IERY,24550
|
|
21
21
|
maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
|
|
23
|
-
maco/cli.py,sha256=
|
|
23
|
+
maco/cli.py,sha256=jFtYWuKNlqcnSl0W4vgITctpgfd3J9kgN37IwoW3pDY,11477
|
|
24
24
|
maco/collector.py,sha256=I0Nidf4-xcvoe6X0bbCsAXjr66iPf00JDO6ocKkaZLc,8309
|
|
25
25
|
maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
|
|
26
26
|
maco/extractor.py,sha256=nqIfUcrc_l57FicKZc6HLtN223-_zkYWL1AYMy1WAmA,3007
|
|
27
27
|
maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
|
|
28
28
|
maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
|
|
29
29
|
maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
|
|
30
|
-
maco/model/model.py,sha256=
|
|
31
|
-
maco-1.2.
|
|
30
|
+
maco/model/model.py,sha256=a98XB7C6P_9JHNsodzbaRomr17rLYH6J4g5clH2IERY,24550
|
|
31
|
+
maco-1.2.21.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
|
|
32
32
|
model_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
model_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
|
|
34
|
-
model_setup/maco/cli.py,sha256=
|
|
34
|
+
model_setup/maco/cli.py,sha256=jFtYWuKNlqcnSl0W4vgITctpgfd3J9kgN37IwoW3pDY,11477
|
|
35
35
|
model_setup/maco/collector.py,sha256=I0Nidf4-xcvoe6X0bbCsAXjr66iPf00JDO6ocKkaZLc,8309
|
|
36
36
|
model_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
|
|
37
37
|
model_setup/maco/extractor.py,sha256=nqIfUcrc_l57FicKZc6HLtN223-_zkYWL1AYMy1WAmA,3007
|
|
38
38
|
model_setup/maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
|
|
39
39
|
model_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
|
|
40
40
|
model_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
|
|
41
|
-
model_setup/maco/model/model.py,sha256=
|
|
41
|
+
model_setup/maco/model/model.py,sha256=a98XB7C6P_9JHNsodzbaRomr17rLYH6J4g5clH2IERY,24550
|
|
42
42
|
pipelines/publish.yaml,sha256=BfsbDsg2ijtXF8lhRUjzkenw3zi2mL7ESNv3KuC1cVE,1626
|
|
43
|
-
pipelines/test.yaml,sha256=
|
|
43
|
+
pipelines/test.yaml,sha256=csfrKjSUXZ2PlRTYTuietFBwtO5oFNetf8Onv9AHugE,1370
|
|
44
44
|
tests/data/example.txt.cart,sha256=j4ZdDnFNVq7lb-Qi4pY4evOXKQPKG-GSg-n-uEqPhV0,289
|
|
45
45
|
tests/data/trigger_complex.txt,sha256=uqnLSrnyDGCmXwuPmZ2s8vdhH0hJs8DxvyaW_tuYY24,64
|
|
46
46
|
tests/data/trigger_complex.txt.cart,sha256=Z7qF1Zi640O45Znkl9ooP2RhSLAEqY0NRf51d-q7utU,345
|
|
@@ -52,8 +52,8 @@ tests/extractors/bob/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
52
52
|
tests/extractors/bob/bob.py,sha256=4fpqy_O6NDinJImghyW5OwYgnaB05aY4kgoIS_C3c_U,253
|
|
53
53
|
tests/extractors/import_rewriting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
tests/extractors/import_rewriting/importer.py,sha256=wqF1AG2zXXuj9EMt9qlDorab-UD0GYuFggtrCuz4sf0,289735
|
|
55
|
-
maco-1.2.
|
|
56
|
-
maco-1.2.
|
|
57
|
-
maco-1.2.
|
|
58
|
-
maco-1.2.
|
|
59
|
-
maco-1.2.
|
|
55
|
+
maco-1.2.21.dist-info/METADATA,sha256=zotTpqbih_Px3KgNFxZLKBScIIav--wjxCoOMZ97NbE,15709
|
|
56
|
+
maco-1.2.21.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
57
|
+
maco-1.2.21.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
|
|
58
|
+
maco-1.2.21.dist-info/top_level.txt,sha256=xiVS11ZoyN8ChHJQGpOzTH4ZyQ3YJe1qT3Yt4gcKGUk,65
|
|
59
|
+
maco-1.2.21.dist-info/RECORD,,
|
model_setup/maco/cli.py
CHANGED
|
@@ -27,6 +27,7 @@ def process_file(
|
|
|
27
27
|
pretty: bool,
|
|
28
28
|
force: bool,
|
|
29
29
|
include_base64: bool,
|
|
30
|
+
extracted_dir: str = "",
|
|
30
31
|
):
|
|
31
32
|
"""Process a filestream with the extractors and rules.
|
|
32
33
|
|
|
@@ -37,6 +38,7 @@ def process_file(
|
|
|
37
38
|
pretty (bool): Pretty print the JSON output
|
|
38
39
|
force (bool): Run all extractors regardless of YARA rule match
|
|
39
40
|
include_base64 (bool): include base64'd data in output
|
|
41
|
+
extracted_dir (str): directory to write CaRTed binary data to
|
|
40
42
|
|
|
41
43
|
Returns:
|
|
42
44
|
(dict): The output from the extractors analyzing the sample
|
|
@@ -87,6 +89,34 @@ def process_file(
|
|
|
87
89
|
if include_base64:
|
|
88
90
|
# this can be large
|
|
89
91
|
row["base64"] = base64.b64encode(row["data"]).decode("utf8")
|
|
92
|
+
|
|
93
|
+
# write binary data to disk if enabled
|
|
94
|
+
if extracted_dir:
|
|
95
|
+
# only allow writes to already existing directories with permissions
|
|
96
|
+
if os.path.isdir(extracted_dir) and os.access(extracted_dir, os.W_OK):
|
|
97
|
+
filepath = os.path.abspath(os.path.join(extracted_dir, f"{row['sha256']}.cart"))
|
|
98
|
+
# don't overwrite existing files
|
|
99
|
+
if os.path.exists(filepath):
|
|
100
|
+
logger.debug(f"{filepath} already exists.")
|
|
101
|
+
else:
|
|
102
|
+
# CaRT data before writing to disk
|
|
103
|
+
in_stream = io.BytesIO(row["data"])
|
|
104
|
+
output_stream = io.BytesIO()
|
|
105
|
+
try:
|
|
106
|
+
cart.pack_stream(in_stream, output_stream)
|
|
107
|
+
except Exception:
|
|
108
|
+
logger.error(f"Error trying to CaRT binary output ({row['sha256']}) from {path_file}.")
|
|
109
|
+
else:
|
|
110
|
+
output_stream.seek(0)
|
|
111
|
+
try:
|
|
112
|
+
with open(filepath, "wb") as f:
|
|
113
|
+
f.write(output_stream.getbuffer())
|
|
114
|
+
logger.debug(f"Wrote binary output to {filepath}.")
|
|
115
|
+
except (FileNotFoundError, PermissionError, OSError):
|
|
116
|
+
logger.error(f"Error trying to write binary output to {filepath}")
|
|
117
|
+
else:
|
|
118
|
+
logger.error(f"Cannot write files to {extracted_dir}")
|
|
119
|
+
|
|
90
120
|
# do not print raw bytes to console
|
|
91
121
|
row.pop("data")
|
|
92
122
|
ret[extractor_name] = resp
|
|
@@ -107,6 +137,7 @@ def process_filesystem(
|
|
|
107
137
|
include_base64: bool,
|
|
108
138
|
create_venv: bool = False,
|
|
109
139
|
skip_install: bool = False,
|
|
140
|
+
extracted_dir: str = "",
|
|
110
141
|
) -> Tuple[int, int, int]:
|
|
111
142
|
"""Process filesystem with extractors and print results of extraction.
|
|
112
143
|
|
|
@@ -159,6 +190,7 @@ def process_filesystem(
|
|
|
159
190
|
pretty=pretty,
|
|
160
191
|
force=force,
|
|
161
192
|
include_base64=include_base64,
|
|
193
|
+
extracted_dir=extracted_dir,
|
|
162
194
|
)
|
|
163
195
|
if resp:
|
|
164
196
|
num_hits += 1
|
|
@@ -194,6 +226,7 @@ def main():
|
|
|
194
226
|
help="Include base64 encoded binary data in output "
|
|
195
227
|
"(can be large, consider printing to file rather than console)",
|
|
196
228
|
)
|
|
229
|
+
parser.add_argument("--binarydir", type=str, help="directory to write extracted binary data to")
|
|
197
230
|
parser.add_argument("--logfile", type=str, help="file to log output")
|
|
198
231
|
parser.add_argument("--include", type=str, help="comma separated extractors to run")
|
|
199
232
|
parser.add_argument("--exclude", type=str, help="comma separated extractors to not run")
|
|
@@ -268,6 +301,7 @@ def main():
|
|
|
268
301
|
include_base64=args.base64,
|
|
269
302
|
create_venv=args.create_venv,
|
|
270
303
|
skip_install=not args.force_install,
|
|
304
|
+
extracted_dir=args.binarydir,
|
|
271
305
|
)
|
|
272
306
|
|
|
273
307
|
|
model_setup/maco/model/model.py
CHANGED
|
@@ -48,6 +48,8 @@ class Encryption(ForbidModel):
|
|
|
48
48
|
iv: Optional[str] = None # initialisation vector
|
|
49
49
|
seed: Optional[str] = None
|
|
50
50
|
nonce: Optional[str] = None
|
|
51
|
+
password: Optional[str] = None
|
|
52
|
+
salt: Optional[str] = None
|
|
51
53
|
constants: List[str] = []
|
|
52
54
|
|
|
53
55
|
usage: Optional[UsageEnum] = None
|
pipelines/test.yaml
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|