maco 1.2.15__py3-none-any.whl → 1.2.17__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.
maco/model/model.py CHANGED
@@ -391,6 +391,18 @@ class ExtractorModel(ForbidModel):
391
391
 
392
392
  proxy: List[Proxy] = []
393
393
 
394
+ class ICMP(ForbidModel):
395
+ """Usage of ICMP."""
396
+
397
+ type: Optional[int] = None
398
+ code: Optional[int] = None
399
+ header: Optional[str] = None # Some malware uses non-standard header fields
400
+ hostname: Optional[str] = None
401
+
402
+ usage: Optional[ConnUsageEnum] = None
403
+
404
+ icmp: List[ICMP] = []
405
+
394
406
  #
395
407
  # inter process communication (IPC)
396
408
  #
maco/utils.py CHANGED
@@ -1,8 +1,6 @@
1
1
  """Common utilities shared between the MACO collector and configextractor-py."""
2
2
 
3
3
  import importlib
4
- import importlib.machinery
5
- import importlib.util
6
4
  import inspect
7
5
  import json
8
6
  import logging
@@ -13,8 +11,9 @@ import shutil
13
11
  import subprocess
14
12
  import sys
15
13
  import tempfile
14
+ from importlib.machinery import SourceFileLoader
16
15
 
17
- from multiprocess import Queue
16
+ from multiprocess import Process, Queue
18
17
 
19
18
  from maco import yara
20
19
 
@@ -27,9 +26,8 @@ from base64 import b64decode
27
26
  from copy import deepcopy
28
27
  from glob import glob
29
28
  from logging import Logger
30
- from pkgutil import walk_packages
31
29
  from types import ModuleType
32
- from typing import Callable, Dict, List, Set, Tuple, Union
30
+ from typing import Callable, Dict, List, Tuple, Union
33
31
 
34
32
  from uv import find_uv_bin
35
33
 
@@ -261,15 +259,15 @@ def _install_required_packages(create_venv: bool, directories: List[str], python
261
259
  # This prevents issues during maco development and building extractors against local libraries.
262
260
  if create_venv:
263
261
  # when running in custom virtual environment, always upgrade packages.
264
- install_command.append("-U")
262
+ install_command.extend(["--upgrade", "--no-cache"])
265
263
 
266
264
  # Update the pip install command depending on where the dependencies are coming from
267
265
  if "requirements.txt" in req_files:
268
266
  # Perform a pip install using the requirements flag
269
- install_command.extend(["-r", "requirements.txt"])
267
+ install_command.extend(["--requirements", "requirements.txt"])
270
268
  elif "pyproject.toml" in req_files:
271
269
  # Assume we're dealing with a project directory
272
- pyproject_command = ["-e", "."]
270
+ pyproject_command = ["--editable", "."]
273
271
 
274
272
  # Check to see if there are optional dependencies required
275
273
  with open(os.path.join(dir, "pyproject.toml"), "rb") as f:
@@ -343,13 +341,43 @@ def find_and_insert_venv(path: str, venvs: List[str]) -> Tuple[str, str]:
343
341
  return venv, site_package
344
342
 
345
343
 
344
+ def register_extractor_module(
345
+ extractor_source_file: str,
346
+ module_name: str,
347
+ venvs: List[str],
348
+ extractor_module_callback: Callable[[ModuleType, str], None],
349
+ logger: Logger,
350
+ ):
351
+ """Register the extractor module in isolation.
352
+
353
+ Args:
354
+ extractor_source_file (str): Path to source file of extractor
355
+ module_name (str): The name of the module relative to the package directory
356
+ venvs (List[str]): List of virtual environments
357
+ extractor_module_callback (Callable[[ModuleType, str], None]): Callback used to register extractors
358
+ logger (Logger): Logger to use
359
+
360
+ """
361
+ try:
362
+ logger.info(f"Inspecting '{extractor_source_file}' for extractors..")
363
+ venv, site_packages = find_and_insert_venv(extractor_source_file, venvs)
364
+ loader = SourceFileLoader(
365
+ module_name,
366
+ extractor_source_file,
367
+ )
368
+ extractor_module_callback(loader.load_module(), venv)
369
+ finally:
370
+ # Cleanup virtual environment that was loaded into PATH
371
+ if venv and site_packages in sys.path:
372
+ sys.path.remove(site_packages)
373
+
374
+
346
375
  def register_extractors(
347
376
  current_directory: str,
348
377
  venvs: List[str],
349
378
  extractor_files: List[str],
350
379
  extractor_module_callback: Callable[[ModuleType, str], None],
351
380
  logger: Logger,
352
- default_loaded_modules: Set[str] = set(sys.modules.keys()),
353
381
  ):
354
382
  """Register extractors with in the current directory.
355
383
 
@@ -359,7 +387,6 @@ def register_extractors(
359
387
  extractor_files (List[str]): List of extractor files found
360
388
  extractor_module_callback (Callable[[ModuleType, str], None]): Callback used to register extractors
361
389
  logger (Logger): Logger to use
362
- default_loaded_modules (Set[str]): Set of default loaded modules
363
390
  """
364
391
  package_name = os.path.basename(current_directory)
365
392
  parent_directory = os.path.dirname(current_directory)
@@ -375,74 +402,25 @@ def register_extractors(
375
402
  sys.path.insert(1, current_directory)
376
403
  sys.path.insert(1, parent_directory)
377
404
 
378
- # Insert any virtual environment necessary to load directory as package
379
- package_venv, package_site_packages = find_and_insert_venv(current_directory, venvs)
380
- package = importlib.import_module(package_name)
405
+ # Load the potential extractors directly from the source file
406
+ registration_processes = []
407
+ for extractor_source_file in extractor_files:
408
+ module_name = extractor_source_file.replace(f"{parent_directory}/", "").replace("/", ".")[:-3]
409
+ p = Process(
410
+ target=register_extractor_module,
411
+ args=(extractor_source_file, module_name, venvs, extractor_module_callback, logger),
412
+ )
413
+ p.start()
414
+ registration_processes.append(p)
381
415
 
382
- # Walk through our new package and find the extractors that YARA identified
383
- for module_path, module_name, ispkg in walk_packages(package.__path__, package.__name__ + "."):
384
- if ispkg:
385
- # Skip packages
386
- continue
416
+ for p in registration_processes:
417
+ p.join()
387
418
 
388
- module_path = os.path.realpath(os.path.join(module_path.path, module_name.rsplit(".", 1)[1]) + ".py")
389
- if module_path in extractor_files:
390
- # Cross this extractor off the list of extractors to find
391
- logger.debug(f"Inspecting '{module_name}' for extractors..")
392
- extractor_files.remove(module_path)
393
- try:
394
- # This is an extractor we've been looking for, load the module and invoke callback
395
- venv, site_packages = find_and_insert_venv(module_path, venvs)
396
- module = importlib.import_module(module_name)
397
- module.__file__ = os.path.realpath(module.__file__)
398
-
399
- # Patch the original directory information into the module
400
- original_package_name = os.path.basename(current_directory)
401
- module.__name__ = module.__name__.replace(package_name, original_package_name)
402
- module.__package__ = module.__package__.replace(package_name, original_package_name)
403
- extractor_module_callback(module, venv)
404
- finally:
405
- # Cleanup virtual environment that was loaded into PATH
406
- if venv and site_packages in sys.path:
407
- sys.path.remove(site_packages)
408
-
409
- if not extractor_files:
410
- return
411
419
  finally:
412
420
  # Cleanup changes made to PATH
413
421
  sys.path.remove(parent_directory)
414
422
  sys.path.remove(current_directory)
415
423
 
416
- if package_venv and package_site_packages in sys.path:
417
- sys.path.remove(package_site_packages)
418
-
419
- # Remove any modules that were loaded to deconflict with later modules loads
420
- [sys.modules.pop(k) for k in set(sys.modules.keys()) - default_loaded_modules]
421
-
422
- # If there still exists extractor files we haven't found yet, try searching in the available subdirectories
423
- if extractor_files:
424
- for dir in os.listdir(current_directory):
425
- path = os.path.join(current_directory, dir)
426
- if dir == "__pycache__":
427
- # Ignore the cache created
428
- continue
429
- elif dir.endswith(".egg-info"):
430
- # Ignore these directories
431
- continue
432
- elif dir.startswith("."):
433
- # Ignore hidden directories
434
- continue
435
-
436
- if os.path.isdir(path):
437
- # Check subdirectory to find the rest of the detected extractors
438
- register_extractors(
439
- path, venvs, extractor_files, extractor_module_callback, logger, default_loaded_modules
440
- )
441
-
442
- if not extractor_files:
443
- # We were able to find all the extractor files
444
- break
445
-
446
424
 
447
425
  def proxy_logging(queue: Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
448
426
  """Ensures logging is set up correctly for a child process and then executes the callback."""
maco/yara.py CHANGED
@@ -3,7 +3,7 @@
3
3
  import re
4
4
  from collections import namedtuple
5
5
  from itertools import cycle
6
- from typing import Dict, List
6
+ from typing import Dict, List, Union
7
7
 
8
8
  import yara_x
9
9
 
@@ -104,7 +104,7 @@ class Rules:
104
104
  for rule in self._rules:
105
105
  yield rule
106
106
 
107
- def match(self, filepath: str = None, data: bytes = None) -> List[Match]:
107
+ def match(self, filepath: str = None, data: Union[bytes, bytearray] = None) -> List[Match]:
108
108
  """Performs a scan to check for YARA rules matches based on the file, either given by path or buffer.
109
109
 
110
110
  Returns:
@@ -114,6 +114,9 @@ class Rules:
114
114
  with open(filepath, "rb") as fp:
115
115
  data = fp.read()
116
116
 
117
+ if isinstance(data, bytearray):
118
+ data = bytes(data)
119
+
117
120
  return [Match(m, data) for m in self.scanner.scan(data).matching_rules]
118
121
 
119
122
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maco
3
- Version: 1.2.15
3
+ Version: 1.2.17
4
4
  Author: sl-govau
5
5
  Maintainer: cccs-rs
6
6
  License: MIT License
@@ -33,7 +33,7 @@ Requires-Dist: cart
33
33
  Requires-Dist: pydantic>=2.0.0
34
34
  Requires-Dist: tomli>=1.1.0; python_version < "3.11"
35
35
  Requires-Dist: uv
36
- Requires-Dist: yara-x==0.11.0
36
+ Requires-Dist: yara-x
37
37
  Requires-Dist: multiprocess>=0.70.17
38
38
  Dynamic: license-file
39
39
 
@@ -14,21 +14,21 @@ maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
14
14
  maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
15
15
  maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
16
16
  maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
17
- maco/utils.py,sha256=rXKrrKTNi7DEC5SZUnUQcxnRRmJXRp0y4DuVaDkBYvY,24977
18
- maco/yara.py,sha256=gkHHxwZNxzZV7nHZM3HNUmhHXB7VW82voCHK5mHpt2Q,3970
17
+ maco/utils.py,sha256=7Xf-kWCDm1DdpBCGOvecEb_hqKoRgNJi0M_OYsJeSrM,23405
18
+ maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
19
19
  maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
20
- maco/model/model.py,sha256=whdeqwphReHpgQ5f6kODB7pQI3UEylTTiVqNq_FHNBg,24156
21
- maco-1.2.15.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
20
+ maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
21
+ maco-1.2.17.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
22
22
  model_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  model_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
24
24
  model_setup/maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
25
25
  model_setup/maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
26
26
  model_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
27
27
  model_setup/maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
28
- model_setup/maco/utils.py,sha256=rXKrrKTNi7DEC5SZUnUQcxnRRmJXRp0y4DuVaDkBYvY,24977
29
- model_setup/maco/yara.py,sha256=gkHHxwZNxzZV7nHZM3HNUmhHXB7VW82voCHK5mHpt2Q,3970
28
+ model_setup/maco/utils.py,sha256=7Xf-kWCDm1DdpBCGOvecEb_hqKoRgNJi0M_OYsJeSrM,23405
29
+ model_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
30
30
  model_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
31
- model_setup/maco/model/model.py,sha256=whdeqwphReHpgQ5f6kODB7pQI3UEylTTiVqNq_FHNBg,24156
31
+ model_setup/maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
32
32
  pipelines/publish.yaml,sha256=xt3WNU-5kIICJgKIiiE94M3dWjS3uEiun-n4OmIssK8,1471
33
33
  pipelines/test.yaml,sha256=btJVI-R39UBeYosGu7TOpU6V9ogFW3FT3ROtWygQGQ0,1472
34
34
  tests/data/example.txt.cart,sha256=j4ZdDnFNVq7lb-Qi4pY4evOXKQPKG-GSg-n-uEqPhV0,289
@@ -42,8 +42,8 @@ tests/extractors/bob/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
42
42
  tests/extractors/bob/bob.py,sha256=4fpqy_O6NDinJImghyW5OwYgnaB05aY4kgoIS_C3c_U,253
43
43
  tests/extractors/import_rewriting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
44
  tests/extractors/import_rewriting/importer.py,sha256=wqF1AG2zXXuj9EMt9qlDorab-UD0GYuFggtrCuz4sf0,289735
45
- maco-1.2.15.dist-info/METADATA,sha256=BBjPNqDyPQPPwFHL0G0LqOrM2zYURFENydH2K63J6aU,15232
46
- maco-1.2.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- maco-1.2.15.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
48
- maco-1.2.15.dist-info/top_level.txt,sha256=iMRwuzmrHA3zSwiSeMIl6FWhzRpn_st-I4fAv-kw5_o,49
49
- maco-1.2.15.dist-info/RECORD,,
45
+ maco-1.2.17.dist-info/METADATA,sha256=7NtcX0tJ94BxrswwvqTQO9Ou-UVURL5-j0nBOSGoWQY,15224
46
+ maco-1.2.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
+ maco-1.2.17.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
48
+ maco-1.2.17.dist-info/top_level.txt,sha256=iMRwuzmrHA3zSwiSeMIl6FWhzRpn_st-I4fAv-kw5_o,49
49
+ maco-1.2.17.dist-info/RECORD,,
@@ -391,6 +391,18 @@ class ExtractorModel(ForbidModel):
391
391
 
392
392
  proxy: List[Proxy] = []
393
393
 
394
+ class ICMP(ForbidModel):
395
+ """Usage of ICMP."""
396
+
397
+ type: Optional[int] = None
398
+ code: Optional[int] = None
399
+ header: Optional[str] = None # Some malware uses non-standard header fields
400
+ hostname: Optional[str] = None
401
+
402
+ usage: Optional[ConnUsageEnum] = None
403
+
404
+ icmp: List[ICMP] = []
405
+
394
406
  #
395
407
  # inter process communication (IPC)
396
408
  #
model_setup/maco/utils.py CHANGED
@@ -1,8 +1,6 @@
1
1
  """Common utilities shared between the MACO collector and configextractor-py."""
2
2
 
3
3
  import importlib
4
- import importlib.machinery
5
- import importlib.util
6
4
  import inspect
7
5
  import json
8
6
  import logging
@@ -13,8 +11,9 @@ import shutil
13
11
  import subprocess
14
12
  import sys
15
13
  import tempfile
14
+ from importlib.machinery import SourceFileLoader
16
15
 
17
- from multiprocess import Queue
16
+ from multiprocess import Process, Queue
18
17
 
19
18
  from maco import yara
20
19
 
@@ -27,9 +26,8 @@ from base64 import b64decode
27
26
  from copy import deepcopy
28
27
  from glob import glob
29
28
  from logging import Logger
30
- from pkgutil import walk_packages
31
29
  from types import ModuleType
32
- from typing import Callable, Dict, List, Set, Tuple, Union
30
+ from typing import Callable, Dict, List, Tuple, Union
33
31
 
34
32
  from uv import find_uv_bin
35
33
 
@@ -261,15 +259,15 @@ def _install_required_packages(create_venv: bool, directories: List[str], python
261
259
  # This prevents issues during maco development and building extractors against local libraries.
262
260
  if create_venv:
263
261
  # when running in custom virtual environment, always upgrade packages.
264
- install_command.append("-U")
262
+ install_command.extend(["--upgrade", "--no-cache"])
265
263
 
266
264
  # Update the pip install command depending on where the dependencies are coming from
267
265
  if "requirements.txt" in req_files:
268
266
  # Perform a pip install using the requirements flag
269
- install_command.extend(["-r", "requirements.txt"])
267
+ install_command.extend(["--requirements", "requirements.txt"])
270
268
  elif "pyproject.toml" in req_files:
271
269
  # Assume we're dealing with a project directory
272
- pyproject_command = ["-e", "."]
270
+ pyproject_command = ["--editable", "."]
273
271
 
274
272
  # Check to see if there are optional dependencies required
275
273
  with open(os.path.join(dir, "pyproject.toml"), "rb") as f:
@@ -343,13 +341,43 @@ def find_and_insert_venv(path: str, venvs: List[str]) -> Tuple[str, str]:
343
341
  return venv, site_package
344
342
 
345
343
 
344
+ def register_extractor_module(
345
+ extractor_source_file: str,
346
+ module_name: str,
347
+ venvs: List[str],
348
+ extractor_module_callback: Callable[[ModuleType, str], None],
349
+ logger: Logger,
350
+ ):
351
+ """Register the extractor module in isolation.
352
+
353
+ Args:
354
+ extractor_source_file (str): Path to source file of extractor
355
+ module_name (str): The name of the module relative to the package directory
356
+ venvs (List[str]): List of virtual environments
357
+ extractor_module_callback (Callable[[ModuleType, str], None]): Callback used to register extractors
358
+ logger (Logger): Logger to use
359
+
360
+ """
361
+ try:
362
+ logger.info(f"Inspecting '{extractor_source_file}' for extractors..")
363
+ venv, site_packages = find_and_insert_venv(extractor_source_file, venvs)
364
+ loader = SourceFileLoader(
365
+ module_name,
366
+ extractor_source_file,
367
+ )
368
+ extractor_module_callback(loader.load_module(), venv)
369
+ finally:
370
+ # Cleanup virtual environment that was loaded into PATH
371
+ if venv and site_packages in sys.path:
372
+ sys.path.remove(site_packages)
373
+
374
+
346
375
  def register_extractors(
347
376
  current_directory: str,
348
377
  venvs: List[str],
349
378
  extractor_files: List[str],
350
379
  extractor_module_callback: Callable[[ModuleType, str], None],
351
380
  logger: Logger,
352
- default_loaded_modules: Set[str] = set(sys.modules.keys()),
353
381
  ):
354
382
  """Register extractors with in the current directory.
355
383
 
@@ -359,7 +387,6 @@ def register_extractors(
359
387
  extractor_files (List[str]): List of extractor files found
360
388
  extractor_module_callback (Callable[[ModuleType, str], None]): Callback used to register extractors
361
389
  logger (Logger): Logger to use
362
- default_loaded_modules (Set[str]): Set of default loaded modules
363
390
  """
364
391
  package_name = os.path.basename(current_directory)
365
392
  parent_directory = os.path.dirname(current_directory)
@@ -375,74 +402,25 @@ def register_extractors(
375
402
  sys.path.insert(1, current_directory)
376
403
  sys.path.insert(1, parent_directory)
377
404
 
378
- # Insert any virtual environment necessary to load directory as package
379
- package_venv, package_site_packages = find_and_insert_venv(current_directory, venvs)
380
- package = importlib.import_module(package_name)
405
+ # Load the potential extractors directly from the source file
406
+ registration_processes = []
407
+ for extractor_source_file in extractor_files:
408
+ module_name = extractor_source_file.replace(f"{parent_directory}/", "").replace("/", ".")[:-3]
409
+ p = Process(
410
+ target=register_extractor_module,
411
+ args=(extractor_source_file, module_name, venvs, extractor_module_callback, logger),
412
+ )
413
+ p.start()
414
+ registration_processes.append(p)
381
415
 
382
- # Walk through our new package and find the extractors that YARA identified
383
- for module_path, module_name, ispkg in walk_packages(package.__path__, package.__name__ + "."):
384
- if ispkg:
385
- # Skip packages
386
- continue
416
+ for p in registration_processes:
417
+ p.join()
387
418
 
388
- module_path = os.path.realpath(os.path.join(module_path.path, module_name.rsplit(".", 1)[1]) + ".py")
389
- if module_path in extractor_files:
390
- # Cross this extractor off the list of extractors to find
391
- logger.debug(f"Inspecting '{module_name}' for extractors..")
392
- extractor_files.remove(module_path)
393
- try:
394
- # This is an extractor we've been looking for, load the module and invoke callback
395
- venv, site_packages = find_and_insert_venv(module_path, venvs)
396
- module = importlib.import_module(module_name)
397
- module.__file__ = os.path.realpath(module.__file__)
398
-
399
- # Patch the original directory information into the module
400
- original_package_name = os.path.basename(current_directory)
401
- module.__name__ = module.__name__.replace(package_name, original_package_name)
402
- module.__package__ = module.__package__.replace(package_name, original_package_name)
403
- extractor_module_callback(module, venv)
404
- finally:
405
- # Cleanup virtual environment that was loaded into PATH
406
- if venv and site_packages in sys.path:
407
- sys.path.remove(site_packages)
408
-
409
- if not extractor_files:
410
- return
411
419
  finally:
412
420
  # Cleanup changes made to PATH
413
421
  sys.path.remove(parent_directory)
414
422
  sys.path.remove(current_directory)
415
423
 
416
- if package_venv and package_site_packages in sys.path:
417
- sys.path.remove(package_site_packages)
418
-
419
- # Remove any modules that were loaded to deconflict with later modules loads
420
- [sys.modules.pop(k) for k in set(sys.modules.keys()) - default_loaded_modules]
421
-
422
- # If there still exists extractor files we haven't found yet, try searching in the available subdirectories
423
- if extractor_files:
424
- for dir in os.listdir(current_directory):
425
- path = os.path.join(current_directory, dir)
426
- if dir == "__pycache__":
427
- # Ignore the cache created
428
- continue
429
- elif dir.endswith(".egg-info"):
430
- # Ignore these directories
431
- continue
432
- elif dir.startswith("."):
433
- # Ignore hidden directories
434
- continue
435
-
436
- if os.path.isdir(path):
437
- # Check subdirectory to find the rest of the detected extractors
438
- register_extractors(
439
- path, venvs, extractor_files, extractor_module_callback, logger, default_loaded_modules
440
- )
441
-
442
- if not extractor_files:
443
- # We were able to find all the extractor files
444
- break
445
-
446
424
 
447
425
  def proxy_logging(queue: Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
448
426
  """Ensures logging is set up correctly for a child process and then executes the callback."""
model_setup/maco/yara.py CHANGED
@@ -3,7 +3,7 @@
3
3
  import re
4
4
  from collections import namedtuple
5
5
  from itertools import cycle
6
- from typing import Dict, List
6
+ from typing import Dict, List, Union
7
7
 
8
8
  import yara_x
9
9
 
@@ -104,7 +104,7 @@ class Rules:
104
104
  for rule in self._rules:
105
105
  yield rule
106
106
 
107
- def match(self, filepath: str = None, data: bytes = None) -> List[Match]:
107
+ def match(self, filepath: str = None, data: Union[bytes, bytearray] = None) -> List[Match]:
108
108
  """Performs a scan to check for YARA rules matches based on the file, either given by path or buffer.
109
109
 
110
110
  Returns:
@@ -114,6 +114,9 @@ class Rules:
114
114
  with open(filepath, "rb") as fp:
115
115
  data = fp.read()
116
116
 
117
+ if isinstance(data, bytearray):
118
+ data = bytes(data)
119
+
117
120
  return [Match(m, data) for m in self.scanner.scan(data).matching_rules]
118
121
 
119
122
 
File without changes