maco 1.2.17__py3-none-any.whl → 1.2.18__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.
@@ -0,0 +1,129 @@
1
+ """yara-python facade that uses yara-x."""
2
+
3
+ import re
4
+ from collections import namedtuple
5
+ from itertools import cycle
6
+ from typing import Dict, List, Union
7
+
8
+ import yara_x
9
+
10
+ from maco.exceptions import SyntaxError
11
+
12
+ RULE_ID_RE = re.compile("(\w+)? ?rule (\w+)")
13
+
14
+
15
+ # Create interfaces that resembles yara-python (but is running yara-x under the hood)
16
+ class StringMatchInstance:
17
+ """Instance of a string match."""
18
+
19
+ def __init__(self, match: yara_x.Match, file_content: bytes):
20
+ """Initializes StringMatchInstance."""
21
+ self.matched_data = file_content[match.offset : match.offset + match.length]
22
+ self.matched_length = match.length
23
+ self.offset = match.offset
24
+ self.xor_key = match.xor_key
25
+
26
+ def plaintext(self) -> bytes:
27
+ """Plaintext of the matched data.
28
+
29
+ Returns:
30
+ (bytes): Plaintext of the matched cipher text
31
+ """
32
+ if not self.xor_key:
33
+ # No need to XOR the matched data
34
+ return self.matched_data
35
+ else:
36
+ return bytes(c ^ k for c, k in zip(self.matched_data, cycle(self.xor_key)))
37
+
38
+
39
+ class StringMatch:
40
+ """String match."""
41
+
42
+ def __init__(self, pattern: yara_x.Pattern, file_content: bytes):
43
+ """Initializes StringMatch."""
44
+ self.identifier = pattern.identifier
45
+ self.instances = [StringMatchInstance(match, file_content) for match in pattern.matches]
46
+ self._is_xor = any([match.xor_key for match in pattern.matches])
47
+
48
+ def is_xor(self):
49
+ """Checks if string match is xor'd.
50
+
51
+ Returns:
52
+ (bool): True if match is xor'd
53
+ """
54
+ return self._is_xor
55
+
56
+
57
+ class Match:
58
+ """Match."""
59
+
60
+ def __init__(self, rule: yara_x.Rule, file_content: bytes):
61
+ """Initializes Match."""
62
+ self.rule = rule.identifier
63
+ self.namespace = rule.namespace
64
+ self.tags = list(rule.tags) or []
65
+ self.meta = dict()
66
+ # Ensure metadata doesn't get overwritten
67
+ for k, v in rule.metadata:
68
+ self.meta.setdefault(k, []).append(v)
69
+ self.strings = [StringMatch(pattern, file_content) for pattern in rule.patterns]
70
+
71
+
72
+ class Rules:
73
+ """Rules."""
74
+
75
+ def __init__(self, source: str = None, sources: Dict[str, str] = None):
76
+ """Initializes Rules.
77
+
78
+ Raises:
79
+ SyntaxError: Raised when there's a syntax error in the YARA rule.
80
+ """
81
+ Rule = namedtuple("Rule", "identifier namespace is_global")
82
+ if source:
83
+ sources = {"default": source}
84
+
85
+ try:
86
+ self._rules = []
87
+ compiler = yara_x.Compiler(relaxed_re_syntax=True)
88
+ for namespace, source in sources.items():
89
+ compiler.new_namespace(namespace)
90
+ for rule_type, id in RULE_ID_RE.findall(source):
91
+ is_global = True if rule_type == "global" else False
92
+ self._rules.append(Rule(namespace=namespace, identifier=id, is_global=is_global))
93
+ compiler.add_source(source)
94
+ self.scanner = yara_x.Scanner(compiler.build())
95
+ except yara_x.CompileError as e:
96
+ raise SyntaxError(e)
97
+
98
+ def __iter__(self):
99
+ """Iterate over rules.
100
+
101
+ Yields:
102
+ YARA rules
103
+ """
104
+ for rule in self._rules:
105
+ yield rule
106
+
107
+ def match(self, filepath: str = None, data: Union[bytes, bytearray] = None) -> List[Match]:
108
+ """Performs a scan to check for YARA rules matches based on the file, either given by path or buffer.
109
+
110
+ Returns:
111
+ (List[Match]): A list of YARA matches.
112
+ """
113
+ if filepath:
114
+ with open(filepath, "rb") as fp:
115
+ data = fp.read()
116
+
117
+ if isinstance(data, bytearray):
118
+ data = bytes(data)
119
+
120
+ return [Match(m, data) for m in self.scanner.scan(data).matching_rules]
121
+
122
+
123
+ def compile(source: str = None, sources: Dict[str, str] = None) -> Rules:
124
+ """Compiles YARA rules from source or from sources.
125
+
126
+ Returns:
127
+ (Rules): a Rules object
128
+ """
129
+ return Rules(source, sources)
maco/utils.py CHANGED
@@ -280,8 +280,8 @@ def _install_required_packages(create_venv: bool, directories: List[str], python
280
280
 
281
281
  install_command.extend(pyproject_command)
282
282
 
283
- # always require maco to be installed
284
- install_command.append("maco")
283
+ # Always require maco-extractor to be installed
284
+ install_command.append("maco-extractor")
285
285
  logger.debug(f"Install command: {' '.join(install_command)} [{dir}]")
286
286
  # this uses VIRTUAL_ENV to control usage of a virtual environment
287
287
  p = subprocess.run(
@@ -1,6 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maco
3
- Version: 1.2.17
3
+ Version: 1.2.18
4
+ Summary: Maco is a framework for creating and using malware configuration extractors.
4
5
  Author: sl-govau
5
6
  Maintainer: cccs-rs
6
7
  License: MIT License
@@ -8,28 +8,38 @@ demo_extractors/terminator.py,sha256=nxoZYRteYDQS7wp-aAsCaxCSJ9FSE54jPrW3fJpRVho
8
8
  demo_extractors/complex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  demo_extractors/complex/complex.py,sha256=GYKmPOD8-fyVHxwjZb-3t1IghKVMuLtdUvCs5C5yPe0,2625
10
10
  demo_extractors/complex/complex_utils.py,sha256=5kdMl-niSH9d-d3ChuItpmlPT4U-S9g-iyBZlR4tfmQ,296
11
+ extractor_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ extractor_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
13
+ extractor_setup/maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
14
+ extractor_setup/maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
15
+ extractor_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
16
+ extractor_setup/maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
17
+ extractor_setup/maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
18
+ extractor_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
19
+ extractor_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
20
+ extractor_setup/maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
11
21
  maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
22
  maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
13
23
  maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
14
24
  maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
15
25
  maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
16
26
  maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
17
- maco/utils.py,sha256=7Xf-kWCDm1DdpBCGOvecEb_hqKoRgNJi0M_OYsJeSrM,23405
27
+ maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
18
28
  maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
19
29
  maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
20
30
  maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
21
- maco-1.2.17.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
31
+ maco-1.2.18.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
22
32
  model_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
33
  model_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
24
34
  model_setup/maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
25
35
  model_setup/maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
26
36
  model_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
27
37
  model_setup/maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
28
- model_setup/maco/utils.py,sha256=7Xf-kWCDm1DdpBCGOvecEb_hqKoRgNJi0M_OYsJeSrM,23405
38
+ model_setup/maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
29
39
  model_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
30
40
  model_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
31
41
  model_setup/maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
32
- pipelines/publish.yaml,sha256=xt3WNU-5kIICJgKIiiE94M3dWjS3uEiun-n4OmIssK8,1471
42
+ pipelines/publish.yaml,sha256=yjc3eqrI-LHLSfZ0DPtxwdfPDT0NI6LUA_zy61UxN_8,1654
33
43
  pipelines/test.yaml,sha256=btJVI-R39UBeYosGu7TOpU6V9ogFW3FT3ROtWygQGQ0,1472
34
44
  tests/data/example.txt.cart,sha256=j4ZdDnFNVq7lb-Qi4pY4evOXKQPKG-GSg-n-uEqPhV0,289
35
45
  tests/data/trigger_complex.txt,sha256=uqnLSrnyDGCmXwuPmZ2s8vdhH0hJs8DxvyaW_tuYY24,64
@@ -42,8 +52,8 @@ tests/extractors/bob/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
42
52
  tests/extractors/bob/bob.py,sha256=4fpqy_O6NDinJImghyW5OwYgnaB05aY4kgoIS_C3c_U,253
43
53
  tests/extractors/import_rewriting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
54
  tests/extractors/import_rewriting/importer.py,sha256=wqF1AG2zXXuj9EMt9qlDorab-UD0GYuFggtrCuz4sf0,289735
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,,
55
+ maco-1.2.18.dist-info/METADATA,sha256=citbYasnfKhc-PAxK7tLQt_Dc2LZRbhKn26ChD0PC3g,15310
56
+ maco-1.2.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ maco-1.2.18.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
58
+ maco-1.2.18.dist-info/top_level.txt,sha256=xiVS11ZoyN8ChHJQGpOzTH4ZyQ3YJe1qT3Yt4gcKGUk,65
59
+ maco-1.2.18.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  demo_extractors
2
+ extractor_setup
2
3
  maco
3
4
  model_setup
4
5
  pipelines
model_setup/maco/utils.py CHANGED
@@ -280,8 +280,8 @@ def _install_required_packages(create_venv: bool, directories: List[str], python
280
280
 
281
281
  install_command.extend(pyproject_command)
282
282
 
283
- # always require maco to be installed
284
- install_command.append("maco")
283
+ # Always require maco-extractor to be installed
284
+ install_command.append("maco-extractor")
285
285
  logger.debug(f"Install command: {' '.join(install_command)} [{dir}]")
286
286
  # this uses VIRTUAL_ENV to control usage of a virtual environment
287
287
  p = subprocess.run(
pipelines/publish.yaml CHANGED
@@ -12,34 +12,33 @@ pool:
12
12
  vmImage: "ubuntu-22.04"
13
13
 
14
14
  jobs:
15
- - job: test
16
- displayName: Test
17
- strategy:
18
- matrix:
19
- Python38:
20
- python.version: '3.8'
21
- Python39:
22
- python.version: '3.9'
23
- Python310:
24
- python.version: '3.10'
25
- Python311:
26
- python.version: '3.11'
27
- Python312:
28
- python.version: '3.12'
29
- steps:
30
- - task: UsePythonVersion@0
31
- displayName: 'Use Python $(python.version)'
32
- inputs:
33
- versionSpec: '$(python.version)'
15
+ # - job: test
16
+ # displayName: Test
17
+ # strategy:
18
+ # matrix:
19
+ # Python38:
20
+ # python.version: '3.8'
21
+ # Python39:
22
+ # python.version: '3.9'
23
+ # Python310:
24
+ # python.version: '3.10'
25
+ # Python311:
26
+ # python.version: '3.11'
27
+ # Python312:
28
+ # python.version: '3.12'
29
+ # steps:
30
+ # - task: UsePythonVersion@0
31
+ # displayName: 'Use Python $(python.version)'
32
+ # inputs:
33
+ # versionSpec: '$(python.version)'
34
34
 
35
- - script: |
36
- set -x
35
+ # - script: |
36
+ # set -x
37
37
 
38
- python -m pip install -U tox
39
- python -m tox -e py
38
+ # python -m pip install -U tox
39
+ # python -m tox -e py
40
40
 
41
41
  - job: build_and_deploy
42
- dependsOn: test
43
42
  displayName: Build and Deploy
44
43
  variables:
45
44
  - group: deployment-information
@@ -64,6 +63,13 @@ jobs:
64
63
  ls ../dist
65
64
  displayName: Build (Model Only)
66
65
 
66
+ - script: |
67
+ set -x
68
+ cd extractor_setup
69
+ python -m build --outdir ../dist
70
+ ls ../dist
71
+ displayName: Build (Extractor Essentials)
72
+
67
73
  - script: |
68
74
  set -xv # Echo commands before they are run
69
75
  sudo env "PATH=$PATH" python -m pip install --no-cache-dir twine
File without changes