Skip to content

Commit e0b124b

Browse files
author
doomedraven
committed
demux
1 parent 9dfa8f1 commit e0b124b

File tree

5 files changed

+80
-32
lines changed

5 files changed

+80
-32
lines changed

lib/cuckoo/common/demux.py

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
cuckoo_conf = Config()
3333
web_cfg = Config("web")
3434
tmp_path = cuckoo_conf.cuckoo.get("tmppath", "/tmp")
35-
linux_enabled = web_cfg.linux.get("enabled", False)
35+
# ToDo allow_static
36+
linux_enabled = web_cfg.linux.get("enabled", False) or web_cfg.linux.get("static_only", False)
3637

3738
demux_extensions_list = {
3839
b".accdr",
@@ -162,7 +163,8 @@ def is_valid_package(package: str) -> bool:
162163
return any(ptype in package for ptype in VALID_PACKAGES)
163164

164165

165-
def _sf_children(child: sfFile) -> bytes:
166+
# ToDo fix return type
167+
def _sf_children(child: sfFile): # -> bytes:
166168
path_to_extract = ""
167169
_, ext = os.path.splitext(child.filename)
168170
ext = ext.lower()
@@ -184,15 +186,17 @@ def _sf_children(child: sfFile) -> bytes:
184186
_ = path_write_file(path_to_extract, child.contents)
185187
except Exception as e:
186188
log.error(e, exc_info=True)
187-
return path_to_extract.encode()
189+
return (path_to_extract.encode(), child.platform, child.get_type(), child.get_size())
188190

189191

190-
def demux_sflock(filename: bytes, options: str, check_shellcode: bool = True) -> List[bytes]:
192+
# ToDo fix typing need to add str as error msg
193+
def demux_sflock(filename: bytes, options: str, check_shellcode: bool = True): # -> List[bytes]:
191194
retlist = []
192195
# do not extract from .bin (downloaded from us)
193196
if os.path.splitext(filename)[1] == b".bin":
194-
return retlist
197+
return retlist, ""
195198

199+
# ToDo need to introduce error msgs here
196200
try:
197201
password = options2passwd(options) or "infected"
198202
try:
@@ -201,9 +205,13 @@ def demux_sflock(filename: bytes, options: str, check_shellcode: bool = True) ->
201205
unpacked = unpack(filename, check_shellcode=check_shellcode)
202206

203207
if unpacked.package in whitelist_extensions:
204-
return [filename]
208+
file = File(filename)
209+
magic_type = file.get_type()
210+
platform = file.get_platform()
211+
file_size = file.get_size()
212+
return [filename, platform, magic_type, file_size], ""
205213
if unpacked.package in blacklist_extensions:
206-
return [filename]
214+
return [], "blacklisted package"
207215
for sf_child in unpacked.children:
208216
if sf_child.to_dict().get("children"):
209217
retlist.extend(_sf_children(ch) for ch in sf_child.children)
@@ -214,7 +222,7 @@ def demux_sflock(filename: bytes, options: str, check_shellcode: bool = True) ->
214222
retlist.append(_sf_children(sf_child))
215223
except Exception as e:
216224
log.error(e, exc_info=True)
217-
return list(filter(None, retlist))
225+
return list(filter(None, retlist)), ""
218226

219227

220228
def demux_sample(filename: bytes, package: str, options: str, use_sflock: bool = True, platform: str = ""): # -> tuple[bytes, str]:
@@ -227,21 +235,29 @@ def demux_sample(filename: bytes, package: str, options: str, use_sflock: bool =
227235
if isinstance(filename, str) and use_sflock:
228236
filename = filename.encode()
229237

238+
error_list = []
230239
retlist = []
231240
# if a package was specified, trim if allowed and required
232241
if package:
233-
234242
if package in ("msix",):
235243
retlist.append((filename, "windows"))
236244
else:
237245
if File(filename).get_size() <= web_cfg.general.max_sample_size or (
238246
web_cfg.general.allow_ignore_size and "ignore_size_check" in options
239247
):
240-
retlist.append((filename, platform))
248+
retlist.append((filename, platform, ""))
241249
else:
242250
if web_cfg.general.enable_trim and trim_file(filename):
243251
retlist.append((trimmed_path(filename), platform))
244-
return retlist
252+
else:
253+
error_list.append(
254+
{
255+
os.path.basename(
256+
filename
257+
): "File too bit, enable 'allow_ignore_size' in web.conf or use 'ignore_size_check' option"
258+
}
259+
)
260+
return retlist, error_list
245261

246262
# handle quarantine files
247263
tmp_path = unquarantine(filename)
@@ -259,9 +275,16 @@ def demux_sample(filename: bytes, package: str, options: str, use_sflock: bool =
259275
if use_sflock:
260276
if HAS_SFLOCK:
261277
retlist = demux_office(filename, password, platform)
262-
return retlist
278+
return retlist, error_list
263279
else:
264280
log.error("Detected password protected office file, but no sflock is installed: poetry install")
281+
error_list.append(
282+
{
283+
os.path.basename(
284+
filename
285+
): "Detected password protected office file, but no sflock is installed or correct password provided"
286+
}
287+
)
265288

266289
# don't try to extract from Java archives or executables
267290
if (
@@ -279,6 +302,13 @@ def demux_sample(filename: bytes, package: str, options: str, use_sflock: bool =
279302
else:
280303
if web_cfg.general.enable_trim and trim_file(filename):
281304
retlist.append((trimmed_path(filename), platform))
305+
else:
306+
error_list.append(
307+
{
308+
os.path.basename(filename),
309+
"File too bit, enable 'allow_ignore_size' in web.conf or use 'ignore_size_check' option",
310+
}
311+
)
282312
return retlist
283313

284314
new_retlist = []
@@ -288,26 +318,34 @@ def demux_sample(filename: bytes, package: str, options: str, use_sflock: bool =
288318
check_shellcode = False
289319

290320
# all in one unarchiver
291-
retlist = demux_sflock(filename, options, check_shellcode) if HAS_SFLOCK and use_sflock else []
321+
retlist, error_msg = demux_sflock(filename, options, check_shellcode) if HAS_SFLOCK and use_sflock else []
292322
# if it isn't a ZIP or an email, or we aren't able to obtain anything interesting from either, then just submit the
293323
# original file
294324
if not retlist:
325+
if error_msg:
326+
error_list.append({os.path.basename(filename), error_msg})
295327
new_retlist.append((filename, platform))
296328
else:
297-
for filename in retlist:
329+
for filename, platform, magic_type, file_size in retlist:
298330
# verify not Windows binaries here:
299-
file = File(filename)
300-
magic_type = file.get_type()
301-
platform = file.get_platform()
302331
if platform == "linux" and not linux_enabled and "Python" not in magic_type:
332+
error_list.append({os.path.basename(filename): "Linux processing is disabled"})
303333
continue
304334

305-
if file.get_size() > web_cfg.general.max_sample_size and not (
335+
if file_size > web_cfg.general.max_sample_size and not (
306336
web_cfg.general.allow_ignore_size and "ignore_size_check" in options
307337
):
308338
if web_cfg.general.enable_trim:
309339
# maybe identify here
310340
if trim_file(filename):
311341
filename = trimmed_path(filename)
342+
else:
343+
error_list.append(
344+
{
345+
os.path.basename(filename),
346+
"File too bit, enable 'allow_ignore_size' in web.conf or use 'ignore_size_check' option",
347+
}
348+
)
312349
new_retlist.append((filename, platform))
313-
return new_retlist[:10]
350+
351+
return new_retlist[:10], error_list

lib/cuckoo/common/web_utils.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,6 @@ def download_file(**kwargs):
591591
onesuccess = False
592592

593593
username = False
594-
demux_error_msgs = []
595594
"""
596595
put here your custom username assignation from your custom auth, Ex:
597596
request_url = kwargs["request"].build_absolute_uri()
@@ -719,14 +718,12 @@ def download_file(**kwargs):
719718
if not static and "dist_extract" in kwargs["options"]:
720719
static = True
721720

722-
demux_error_msgs = []
723-
724721
for machine in kwargs.get("task_machines", []):
725722
if machine == "first":
726723
machine = None
727724

728725
# Keep this as demux_sample_and_add_to_db in DB
729-
task_ids_new, extra_details, demux_error_msgs = db.demux_sample_and_add_to_db(
726+
task_ids_new, extra_details = db.demux_sample_and_add_to_db(
730727
file_path=kwargs["path"],
731728
package=package,
732729
timeout=timeout,
@@ -769,7 +766,7 @@ def download_file(**kwargs):
769766
if not onesuccess:
770767
return "error", {"error": f"Provided hash not found on {kwargs['service']}"}
771768

772-
return "ok", kwargs["task_ids"], demux_error_msgs
769+
return "ok", kwargs["task_ids"], extra_details.get("erros", [])
773770

774771

775772
def save_script_to_storage(task_ids, kwargs):

lib/cuckoo/core/database.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
distconf = Config("distributed")
120120
web_conf = Config("web")
121121
LINUX_ENABLED = web_conf.linux.enabled
122+
LINUX_STATIC = web_conf.linux.static_only
122123
DYNAMIC_ARCH_DETERMINATION = web_conf.general.dynamic_arch_determination
123124

124125
if repconf.mongodb.enabled:
@@ -1538,7 +1539,7 @@ def demux_sample_and_add_to_db(
15381539
package, _ = self._identify_aux_func(file_path, package, check_shellcode=check_shellcode)
15391540

15401541
# extract files from the (potential) archive
1541-
extracted_files = demux_sample(file_path, package, options, platform=platform)
1542+
extracted_files, demux_error_msgs = demux_sample(file_path, package, options, platform=platform)
15421543
# check if len is 1 and the same file, if diff register file, and set parent
15431544
if extracted_files and (file_path, platform) not in extracted_files:
15441545
sample_parent_id = self.register_sample(File(file_path), source_url=source_url)
@@ -1547,6 +1548,18 @@ def demux_sample_and_add_to_db(
15471548

15481549
# create tasks for each file in the archive
15491550
for file, platform in extracted_files:
1551+
# ToDo we lose package here and send APKs to windows
1552+
if platform in ("linux", "darwin") and LINUX_STATIC:
1553+
task_ids += self.add_static(
1554+
file_path=file_path,
1555+
priority=priority,
1556+
tlp=tlp,
1557+
user_id=user_id,
1558+
username=username,
1559+
options=options,
1560+
package=package,
1561+
)
1562+
continue
15501563
if static:
15511564
# On huge loads this just become a bottleneck
15521565
config = False
@@ -1621,6 +1634,8 @@ def demux_sample_and_add_to_db(
16211634

16221635
if config and isinstance(config, dict):
16231636
details = {"config": config.get("cape_config", {})}
1637+
if demux_error_msgs:
1638+
details["errors"] = demux_error_msgs
16241639
# this is aim to return custom data, think of this as kwargs
16251640
return task_ids, details
16261641

utils/submit.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ def main():
345345
try:
346346
tmp_path = store_temp_file(open(file_path, "rb").read(), sanitize_filename(os.path.basename(file_path)))
347347
with db.session.begin():
348+
# ToDo expose extra_details["errors"]
348349
task_ids, extra_details = db.demux_sample_and_add_to_db(
349350
file_path=tmp_path,
350351
package=args.package,

web/apiv2/views.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,14 @@ def tasks_create_static(request):
187187
options = request.data.get("options", "")
188188
priority = force_int(request.data.get("priority"))
189189

190-
resp["error"] = False
190+
resp["error"] = []
191191
files = request.FILES.getlist("file")
192192
extra_details = {}
193193
task_ids = []
194-
demux_error_msgs = []
195194
for sample in files:
196195
tmp_path = store_temp_file(sample.read(), sanitize_filename(sample.name))
197196
try:
198-
task_id, extra_details, demux_error_msg = db.demux_sample_and_add_to_db(
197+
task_id, extra_details = db.demux_sample_and_add_to_db(
199198
tmp_path,
200199
options=options,
201200
priority=priority,
@@ -204,8 +203,8 @@ def tasks_create_static(request):
204203
user_id=request.user.id or 0,
205204
)
206205
task_ids.extend(task_id)
207-
if demux_error_msg:
208-
demux_error_msgs.extend(demux_error_msg)
206+
if extra_details.get("erros"):
207+
resp["errors"].extend(extra_details["errors"])
209208
except CuckooDemuxError as e:
210209
resp = {"error": True, "error_value": e}
211210
return Response(resp)
@@ -229,8 +228,6 @@ def tasks_create_static(request):
229228
resp["url"].append("{0}/submit/status/{1}".format(apiconf.api.get("url"), tid))
230229
else:
231230
resp = {"error": True, "error_value": "Error adding task to database"}
232-
if demux_error_msgs:
233-
resp["errors"].extend(demux_error_msgs)
234231
return Response(resp)
235232

236233

0 commit comments

Comments
 (0)