maco 1.2.8__tar.gz → 1.2.10__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.
Files changed (67) hide show
  1. {maco-1.2.8/maco.egg-info → maco-1.2.10}/PKG-INFO +3 -2
  2. {maco-1.2.8 → maco-1.2.10}/maco/collector.py +23 -3
  3. {maco-1.2.8 → maco-1.2.10}/maco/utils.py +9 -8
  4. {maco-1.2.8 → maco-1.2.10/maco.egg-info}/PKG-INFO +3 -2
  5. {maco-1.2.8 → maco-1.2.10}/maco.egg-info/requires.txt +1 -0
  6. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/collector.py +23 -3
  7. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/utils.py +9 -8
  8. {maco-1.2.8 → maco-1.2.10}/requirements.txt +1 -0
  9. {maco-1.2.8 → maco-1.2.10}/.gitignore +0 -0
  10. {maco-1.2.8 → maco-1.2.10}/.vscode/settings.json +0 -0
  11. {maco-1.2.8 → maco-1.2.10}/LICENSE.md +0 -0
  12. {maco-1.2.8 → maco-1.2.10}/README.md +0 -0
  13. {maco-1.2.8 → maco-1.2.10}/demo_extractors/__init__.py +0 -0
  14. {maco-1.2.8 → maco-1.2.10}/demo_extractors/complex/__init__.py +0 -0
  15. {maco-1.2.8 → maco-1.2.10}/demo_extractors/complex/complex.py +0 -0
  16. {maco-1.2.8 → maco-1.2.10}/demo_extractors/complex/complex_utils.py +0 -0
  17. {maco-1.2.8 → maco-1.2.10}/demo_extractors/elfy.py +0 -0
  18. {maco-1.2.8 → maco-1.2.10}/demo_extractors/limit_other.py +0 -0
  19. {maco-1.2.8 → maco-1.2.10}/demo_extractors/nothing.py +0 -0
  20. {maco-1.2.8 → maco-1.2.10}/demo_extractors/requirements.txt +0 -0
  21. {maco-1.2.8 → maco-1.2.10}/demo_extractors/shared.py +0 -0
  22. {maco-1.2.8 → maco-1.2.10}/maco/__init__.py +0 -0
  23. {maco-1.2.8 → maco-1.2.10}/maco/base_test.py +0 -0
  24. {maco-1.2.8 → maco-1.2.10}/maco/cli.py +0 -0
  25. {maco-1.2.8 → maco-1.2.10}/maco/extractor.py +0 -0
  26. {maco-1.2.8 → maco-1.2.10}/maco/model/__init__.py +0 -0
  27. {maco-1.2.8 → maco-1.2.10}/maco/model/model.py +0 -0
  28. {maco-1.2.8 → maco-1.2.10}/maco/yara.py +0 -0
  29. {maco-1.2.8 → maco-1.2.10}/maco.egg-info/SOURCES.txt +0 -0
  30. {maco-1.2.8 → maco-1.2.10}/maco.egg-info/dependency_links.txt +0 -0
  31. {maco-1.2.8 → maco-1.2.10}/maco.egg-info/entry_points.txt +0 -0
  32. {maco-1.2.8 → maco-1.2.10}/maco.egg-info/top_level.txt +0 -0
  33. {maco-1.2.8 → maco-1.2.10}/model_setup/LICENSE.md +0 -0
  34. {maco-1.2.8 → maco-1.2.10}/model_setup/README.md +0 -0
  35. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/__init__.py +0 -0
  36. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/base_test.py +0 -0
  37. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/cli.py +0 -0
  38. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/extractor.py +0 -0
  39. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/model/__init__.py +0 -0
  40. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/model/model.py +0 -0
  41. {maco-1.2.8 → maco-1.2.10}/model_setup/maco/yara.py +0 -0
  42. {maco-1.2.8 → maco-1.2.10}/model_setup/pyproject.toml +0 -0
  43. {maco-1.2.8 → maco-1.2.10}/model_setup/setup.py +0 -0
  44. {maco-1.2.8 → maco-1.2.10}/pipelines/publish.yaml +0 -0
  45. {maco-1.2.8 → maco-1.2.10}/pipelines/test.yaml +0 -0
  46. {maco-1.2.8 → maco-1.2.10}/pyproject.toml +0 -0
  47. {maco-1.2.8 → maco-1.2.10}/setup.cfg +0 -0
  48. {maco-1.2.8 → maco-1.2.10}/tests/benchmark.py +0 -0
  49. {maco-1.2.8 → maco-1.2.10}/tests/data/example.txt.cart +0 -0
  50. {maco-1.2.8 → maco-1.2.10}/tests/data/trigger_complex.txt +0 -0
  51. {maco-1.2.8 → maco-1.2.10}/tests/data/trigger_complex.txt.cart +0 -0
  52. {maco-1.2.8 → maco-1.2.10}/tests/extractors/__init__.py +0 -0
  53. {maco-1.2.8 → maco-1.2.10}/tests/extractors/basic.py +0 -0
  54. {maco-1.2.8 → maco-1.2.10}/tests/extractors/basic_longer.py +0 -0
  55. {maco-1.2.8 → maco-1.2.10}/tests/extractors/bob/__init__.py +0 -0
  56. {maco-1.2.8 → maco-1.2.10}/tests/extractors/bob/bob.py +0 -0
  57. {maco-1.2.8 → maco-1.2.10}/tests/extractors/test_basic.py +0 -0
  58. {maco-1.2.8 → maco-1.2.10}/tests/pytest.ini +0 -0
  59. {maco-1.2.8 → maco-1.2.10}/tests/requirements.txt +0 -0
  60. {maco-1.2.8 → maco-1.2.10}/tests/test_base_test.py +0 -0
  61. {maco-1.2.8 → maco-1.2.10}/tests/test_cli.py +0 -0
  62. {maco-1.2.8 → maco-1.2.10}/tests/test_demo_extractors.py +0 -0
  63. {maco-1.2.8 → maco-1.2.10}/tests/test_detection.py +0 -0
  64. {maco-1.2.8 → maco-1.2.10}/tests/test_extractor.py +0 -0
  65. {maco-1.2.8 → maco-1.2.10}/tests/test_helpers.py +0 -0
  66. {maco-1.2.8 → maco-1.2.10}/tests/test_model.py +0 -0
  67. {maco-1.2.8 → maco-1.2.10}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: maco
3
- Version: 1.2.8
3
+ Version: 1.2.10
4
4
  Author: sl-govau
5
5
  Maintainer: cccs-rs
6
6
  License: MIT License
@@ -35,6 +35,7 @@ Requires-Dist: tomli>=1.1.0; python_version < "3.11"
35
35
  Requires-Dist: uv
36
36
  Requires-Dist: yara-python
37
37
  Requires-Dist: yara-x==0.11.0
38
+ Requires-Dist: multiprocess>=0.70.17
38
39
 
39
40
  # Maco - Malware config extractor framework
40
41
 
@@ -5,11 +5,11 @@ import logging
5
5
  import logging.handlers
6
6
  import os
7
7
  import sys
8
- from multiprocessing import Manager, Process, Queue
9
8
  from tempfile import NamedTemporaryFile
10
9
  from types import ModuleType
11
- from typing import Any, BinaryIO, Dict, List, Union
10
+ from typing import Any, BinaryIO, Dict, List, TypedDict, Union
12
11
 
12
+ from multiprocess import Manager, Process, Queue
13
13
  from pydantic import BaseModel
14
14
 
15
15
  from maco import extractor, model, utils, yara
@@ -40,6 +40,26 @@ def _verify_response(resp: Union[BaseModel, dict]) -> Dict:
40
40
  return resp.model_dump(exclude_defaults=True)
41
41
 
42
42
 
43
+ class ExtractorMetadata(TypedDict):
44
+ """Extractor-supplied metadata."""
45
+
46
+ author: str
47
+ family: str
48
+ last_modified: str
49
+ sharing: str
50
+ description: str
51
+
52
+
53
+ class ExtractorRegistration(TypedDict):
54
+ """Registration collected by the collector for a single extractor."""
55
+
56
+ venv: str
57
+ module_path: str
58
+ module_name: str
59
+ extractor_class: str
60
+ metadata: ExtractorMetadata
61
+
62
+
43
63
  class Collector:
44
64
  def __init__(
45
65
  self,
@@ -60,7 +80,7 @@ class Collector:
60
80
 
61
81
  path_extractors = os.path.realpath(path_extractors)
62
82
  self.path: str = path_extractors
63
- self.extractors: Dict[str, Dict[str, str]] = {}
83
+ self.extractors: Dict[str, ExtractorRegistration] = {}
64
84
 
65
85
  with Manager() as manager:
66
86
  extractors = manager.dict()
@@ -6,7 +6,6 @@ import inspect
6
6
  import json
7
7
  import logging
8
8
  import logging.handlers
9
- import multiprocessing
10
9
  import os
11
10
  import re
12
11
  import shutil
@@ -14,6 +13,8 @@ import subprocess
14
13
  import sys
15
14
  import tempfile
16
15
 
16
+ from multiprocess import Queue
17
+
17
18
  from maco import yara
18
19
 
19
20
  if sys.version_info >= (3, 11):
@@ -38,8 +39,8 @@ logger = logging.getLogger("maco.lib.utils")
38
39
 
39
40
  VENV_DIRECTORY_NAME = ".venv"
40
41
 
41
- RELATIVE_FROM_RE = re.compile(r"from (\.+)")
42
- RELATIVE_FROM_IMPORT_RE = re.compile(r"from (\.+) import")
42
+ RELATIVE_FROM_RE = re.compile(rb"from (\.+)")
43
+ RELATIVE_FROM_IMPORT_RE = re.compile(rb"from (\.+) import")
43
44
 
44
45
  UV_BIN = find_uv_bin()
45
46
 
@@ -170,19 +171,19 @@ def scan_for_extractors(root_directory: str, scanner: yara.Rules, logger: Logger
170
171
  # Scan Python file for potential extractors
171
172
  if package:
172
173
  # Inspect the contents and look for any relative import issues
173
- with open(path, "r") as f:
174
+ with open(path, "rb") as f:
174
175
  data = f.read()
175
176
 
176
- with open(path, "w") as f:
177
+ with open(path, "wb") as f:
177
178
  # Replace any relative importing with absolute
178
179
  curr_dir = os.path.dirname(path)
179
180
  split = curr_dir.split("/")[::-1]
180
181
  for pattern in [RELATIVE_FROM_IMPORT_RE, RELATIVE_FROM_RE]:
181
182
  for match in pattern.findall(data):
182
- depth = match.count(".")
183
+ depth = match.count(b".")
183
184
  abspath = ".".join(split[depth - 1 : split.index(package) + 1][::-1])
184
185
  abspath += "." if pattern == RELATIVE_FROM_RE else ""
185
- data = data.replace(f"from {match}", f"from {abspath}", 1)
186
+ data = data.replace(f"from {match.decode()}".encode(), f"from {abspath}".encode(), 1)
186
187
  f.write(data)
187
188
 
188
189
  if scanner.match(path):
@@ -390,7 +391,7 @@ def register_extractors(
390
391
  break
391
392
 
392
393
 
393
- def proxy_logging(queue: multiprocessing.Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
394
+ def proxy_logging(queue: Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
394
395
  """Ensures logging is set up correctly for a child process and then executes the callback."""
395
396
  logger = logging.getLogger()
396
397
  qh = logging.handlers.QueueHandler(queue)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: maco
3
- Version: 1.2.8
3
+ Version: 1.2.10
4
4
  Author: sl-govau
5
5
  Maintainer: cccs-rs
6
6
  License: MIT License
@@ -35,6 +35,7 @@ Requires-Dist: tomli>=1.1.0; python_version < "3.11"
35
35
  Requires-Dist: uv
36
36
  Requires-Dist: yara-python
37
37
  Requires-Dist: yara-x==0.11.0
38
+ Requires-Dist: multiprocess>=0.70.17
38
39
 
39
40
  # Maco - Malware config extractor framework
40
41
 
@@ -3,6 +3,7 @@ pydantic>=2.0.0
3
3
  uv
4
4
  yara-python
5
5
  yara-x==0.11.0
6
+ multiprocess>=0.70.17
6
7
 
7
8
  [:python_version < "3.11"]
8
9
  tomli>=1.1.0
@@ -5,11 +5,11 @@ import logging
5
5
  import logging.handlers
6
6
  import os
7
7
  import sys
8
- from multiprocessing import Manager, Process, Queue
9
8
  from tempfile import NamedTemporaryFile
10
9
  from types import ModuleType
11
- from typing import Any, BinaryIO, Dict, List, Union
10
+ from typing import Any, BinaryIO, Dict, List, TypedDict, Union
12
11
 
12
+ from multiprocess import Manager, Process, Queue
13
13
  from pydantic import BaseModel
14
14
 
15
15
  from maco import extractor, model, utils, yara
@@ -40,6 +40,26 @@ def _verify_response(resp: Union[BaseModel, dict]) -> Dict:
40
40
  return resp.model_dump(exclude_defaults=True)
41
41
 
42
42
 
43
+ class ExtractorMetadata(TypedDict):
44
+ """Extractor-supplied metadata."""
45
+
46
+ author: str
47
+ family: str
48
+ last_modified: str
49
+ sharing: str
50
+ description: str
51
+
52
+
53
+ class ExtractorRegistration(TypedDict):
54
+ """Registration collected by the collector for a single extractor."""
55
+
56
+ venv: str
57
+ module_path: str
58
+ module_name: str
59
+ extractor_class: str
60
+ metadata: ExtractorMetadata
61
+
62
+
43
63
  class Collector:
44
64
  def __init__(
45
65
  self,
@@ -60,7 +80,7 @@ class Collector:
60
80
 
61
81
  path_extractors = os.path.realpath(path_extractors)
62
82
  self.path: str = path_extractors
63
- self.extractors: Dict[str, Dict[str, str]] = {}
83
+ self.extractors: Dict[str, ExtractorRegistration] = {}
64
84
 
65
85
  with Manager() as manager:
66
86
  extractors = manager.dict()
@@ -6,7 +6,6 @@ import inspect
6
6
  import json
7
7
  import logging
8
8
  import logging.handlers
9
- import multiprocessing
10
9
  import os
11
10
  import re
12
11
  import shutil
@@ -14,6 +13,8 @@ import subprocess
14
13
  import sys
15
14
  import tempfile
16
15
 
16
+ from multiprocess import Queue
17
+
17
18
  from maco import yara
18
19
 
19
20
  if sys.version_info >= (3, 11):
@@ -38,8 +39,8 @@ logger = logging.getLogger("maco.lib.utils")
38
39
 
39
40
  VENV_DIRECTORY_NAME = ".venv"
40
41
 
41
- RELATIVE_FROM_RE = re.compile(r"from (\.+)")
42
- RELATIVE_FROM_IMPORT_RE = re.compile(r"from (\.+) import")
42
+ RELATIVE_FROM_RE = re.compile(rb"from (\.+)")
43
+ RELATIVE_FROM_IMPORT_RE = re.compile(rb"from (\.+) import")
43
44
 
44
45
  UV_BIN = find_uv_bin()
45
46
 
@@ -170,19 +171,19 @@ def scan_for_extractors(root_directory: str, scanner: yara.Rules, logger: Logger
170
171
  # Scan Python file for potential extractors
171
172
  if package:
172
173
  # Inspect the contents and look for any relative import issues
173
- with open(path, "r") as f:
174
+ with open(path, "rb") as f:
174
175
  data = f.read()
175
176
 
176
- with open(path, "w") as f:
177
+ with open(path, "wb") as f:
177
178
  # Replace any relative importing with absolute
178
179
  curr_dir = os.path.dirname(path)
179
180
  split = curr_dir.split("/")[::-1]
180
181
  for pattern in [RELATIVE_FROM_IMPORT_RE, RELATIVE_FROM_RE]:
181
182
  for match in pattern.findall(data):
182
- depth = match.count(".")
183
+ depth = match.count(b".")
183
184
  abspath = ".".join(split[depth - 1 : split.index(package) + 1][::-1])
184
185
  abspath += "." if pattern == RELATIVE_FROM_RE else ""
185
- data = data.replace(f"from {match}", f"from {abspath}", 1)
186
+ data = data.replace(f"from {match.decode()}".encode(), f"from {abspath}".encode(), 1)
186
187
  f.write(data)
187
188
 
188
189
  if scanner.match(path):
@@ -390,7 +391,7 @@ def register_extractors(
390
391
  break
391
392
 
392
393
 
393
- def proxy_logging(queue: multiprocessing.Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
394
+ def proxy_logging(queue: Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
394
395
  """Ensures logging is set up correctly for a child process and then executes the callback."""
395
396
  logger = logging.getLogger()
396
397
  qh = logging.handlers.QueueHandler(queue)
@@ -4,3 +4,4 @@ tomli >= 1.1.0 ; python_version < "3.11"
4
4
  uv
5
5
  yara-python
6
6
  yara-x==0.11.0
7
+ multiprocess>=0.70.17
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
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