maco 1.2.5__py3-none-any.whl → 1.2.6__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.
- demo_extractors/elfy.py +1 -1
- demo_extractors/limit_other.py +5 -1
- demo_extractors/nothing.py +1 -1
- maco/base_test.py +1 -1
- maco/cli.py +8 -3
- maco/collector.py +11 -1
- maco/model/__init__.py +1 -1
- maco/model/model.py +53 -19
- maco/utils.py +19 -10
- maco/yara.py +0 -1
- {maco-1.2.5.dist-info → maco-1.2.6.dist-info}/METADATA +14 -2
- maco-1.2.6.dist-info/RECORD +44 -0
- model_setup/maco/base_test.py +1 -1
- model_setup/maco/cli.py +8 -3
- model_setup/maco/collector.py +11 -1
- model_setup/maco/model/__init__.py +1 -1
- model_setup/maco/model/model.py +53 -19
- model_setup/maco/utils.py +19 -10
- model_setup/maco/yara.py +0 -1
- pipelines/test.yaml +21 -0
- tests/extractors/bob/bob.py +1 -4
- maco-1.2.5.dist-info/RECORD +0 -44
- {maco-1.2.5.dist-info → maco-1.2.6.dist-info}/LICENSE.md +0 -0
- {maco-1.2.5.dist-info → maco-1.2.6.dist-info}/WHEEL +0 -0
- {maco-1.2.5.dist-info → maco-1.2.6.dist-info}/entry_points.txt +0 -0
- {maco-1.2.5.dist-info → maco-1.2.6.dist-info}/top_level.txt +0 -0
demo_extractors/elfy.py
CHANGED
demo_extractors/limit_other.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from io import BytesIO
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import List, Optional
|
|
3
3
|
|
|
4
4
|
from demo_extractors import shared
|
|
5
5
|
from maco import extractor, model, yara
|
|
@@ -27,6 +27,10 @@ class LimitOther(extractor.Extractor):
|
|
|
27
27
|
# the tests that do direct importing
|
|
28
28
|
import httpx
|
|
29
29
|
|
|
30
|
+
# use httpx so it doesn't get deleted by auto linter
|
|
31
|
+
if not httpx.__name__:
|
|
32
|
+
raise Exception("wow I really want to use this library in a useful way")
|
|
33
|
+
|
|
30
34
|
# use a custom model that inherits from ExtractorModel
|
|
31
35
|
# this model defines what can go in the 'other' dict
|
|
32
36
|
tmp = shared.MyCustomModel(family="specify_other")
|
demo_extractors/nothing.py
CHANGED
maco/base_test.py
CHANGED
|
@@ -32,7 +32,7 @@ class BaseTest(unittest.TestCase):
|
|
|
32
32
|
# I recommend something like os.path.join(__file__, "../../extractors")
|
|
33
33
|
# if your extractors are in a folder 'extractors' next to a folder of tests
|
|
34
34
|
path: str = None
|
|
35
|
-
create_venv: bool=False
|
|
35
|
+
create_venv: bool = False
|
|
36
36
|
|
|
37
37
|
@classmethod
|
|
38
38
|
def setUpClass(cls) -> None:
|
maco/cli.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""CLI example of how extractors can be executed."""
|
|
2
|
+
|
|
2
3
|
import argparse
|
|
3
4
|
import base64
|
|
4
5
|
import binascii
|
|
@@ -150,6 +151,7 @@ def process_filesystem(
|
|
|
150
151
|
logger.info(f"{num_analysed} analysed, {num_hits} hits, {num_extracted} extracted")
|
|
151
152
|
return num_analysed, num_hits, num_extracted
|
|
152
153
|
|
|
154
|
+
|
|
153
155
|
def main():
|
|
154
156
|
parser = argparse.ArgumentParser(description="Run extractors over samples.")
|
|
155
157
|
parser.add_argument("extractors", type=str, help="path to extractors")
|
|
@@ -165,7 +167,8 @@ def main():
|
|
|
165
167
|
parser.add_argument(
|
|
166
168
|
"--base64",
|
|
167
169
|
action="store_true",
|
|
168
|
-
help="Include base64 encoded binary data in output
|
|
170
|
+
help="Include base64 encoded binary data in output "
|
|
171
|
+
"(can be large, consider printing to file rather than console)",
|
|
169
172
|
)
|
|
170
173
|
parser.add_argument("--logfile", type=str, help="file to log output")
|
|
171
174
|
parser.add_argument("--include", type=str, help="comma separated extractors to run")
|
|
@@ -179,7 +182,9 @@ def main():
|
|
|
179
182
|
parser.add_argument(
|
|
180
183
|
"--create_venv",
|
|
181
184
|
action="store_true",
|
|
182
|
-
help="Creates venvs for every requirements.txt found (only applies when extractor path is a directory).
|
|
185
|
+
help="Creates venvs for every requirements.txt found (only applies when extractor path is a directory). "
|
|
186
|
+
"This runs much slower than the alternative but may be necessary "
|
|
187
|
+
"when there are many extractors with conflicting dependencies.",
|
|
183
188
|
)
|
|
184
189
|
args = parser.parse_args()
|
|
185
190
|
inc = args.include.split(",") if args.include else []
|
|
@@ -225,7 +230,7 @@ def main():
|
|
|
225
230
|
pretty=args.pretty,
|
|
226
231
|
force=args.force,
|
|
227
232
|
include_base64=args.base64,
|
|
228
|
-
create_venv=args.create_venv
|
|
233
|
+
create_venv=args.create_venv,
|
|
229
234
|
)
|
|
230
235
|
|
|
231
236
|
|
maco/collector.py
CHANGED
|
@@ -4,6 +4,7 @@ import inspect
|
|
|
4
4
|
import logging
|
|
5
5
|
import logging.handlers
|
|
6
6
|
import os
|
|
7
|
+
import sys
|
|
7
8
|
from multiprocessing import Manager, Process, Queue
|
|
8
9
|
from tempfile import NamedTemporaryFile
|
|
9
10
|
from types import ModuleType
|
|
@@ -48,6 +49,15 @@ class Collector:
|
|
|
48
49
|
create_venv: bool = False,
|
|
49
50
|
):
|
|
50
51
|
"""Discover and load extractors from file system."""
|
|
52
|
+
# maco requires the extractor to be imported directly, so ensure they are available on the path
|
|
53
|
+
full_path_extractors = os.path.abspath(path_extractors)
|
|
54
|
+
full_path_above_extractors = os.path.dirname(full_path_extractors)
|
|
55
|
+
# Modify the PATH so we can recognize this new package on import
|
|
56
|
+
if full_path_extractors not in sys.path:
|
|
57
|
+
sys.path.insert(1, full_path_extractors)
|
|
58
|
+
if full_path_above_extractors not in sys.path:
|
|
59
|
+
sys.path.insert(1, full_path_above_extractors)
|
|
60
|
+
|
|
51
61
|
path_extractors = os.path.realpath(path_extractors)
|
|
52
62
|
self.path: str = path_extractors
|
|
53
63
|
self.extractors: Dict[str, Dict[str, str]] = {}
|
|
@@ -89,7 +99,7 @@ class Collector:
|
|
|
89
99
|
|
|
90
100
|
# multiprocess logging is awkward - set up a queue to ensure we can log
|
|
91
101
|
logging_queue = Queue()
|
|
92
|
-
queue_handler = logging.handlers.QueueListener(logging_queue
|
|
102
|
+
queue_handler = logging.handlers.QueueListener(logging_queue, *logging.getLogger().handlers)
|
|
93
103
|
queue_handler.start()
|
|
94
104
|
|
|
95
105
|
# Find the extractors within the given directory
|
maco/model/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
from maco.model.model import *
|
|
1
|
+
from maco.model.model import * # noqa: F403
|
maco/model/model.py
CHANGED
|
@@ -59,31 +59,48 @@ class CategoryEnum(str, Enum):
|
|
|
59
59
|
# Malware related to an Advanced Persistent Threat (APT) group.
|
|
60
60
|
apt = "apt"
|
|
61
61
|
|
|
62
|
-
# A backdoor Trojan gives malicious users remote control over the infected computer.
|
|
62
|
+
# A backdoor Trojan gives malicious users remote control over the infected computer.
|
|
63
|
+
# They enable the author to do anything they wish on the infected computer including
|
|
64
|
+
# sending, receiving, launching and deleting files, displaying data and rebooting the computer.
|
|
65
|
+
# Backdoor Trojans are often used to unite a group of victim computers to form a botnet or
|
|
66
|
+
# zombie network that can be used for criminal purposes.
|
|
63
67
|
backdoor = "backdoor"
|
|
64
68
|
|
|
65
|
-
# Trojan Banker programs are designed to steal your account data for online banking systems,
|
|
69
|
+
# Trojan Banker programs are designed to steal your account data for online banking systems,
|
|
70
|
+
# e-payment systems and credit or debit cards.
|
|
66
71
|
banker = "banker"
|
|
67
72
|
|
|
68
|
-
# A malware variant that modifies the boot sectors of a hard drive, including the Master Boot Record (MBR)
|
|
73
|
+
# A malware variant that modifies the boot sectors of a hard drive, including the Master Boot Record (MBR)
|
|
74
|
+
# and Volume Boot Record (VBR).
|
|
69
75
|
bootkit = "bootkit"
|
|
70
76
|
|
|
71
|
-
# A malicious bot is self-propagating malware designed to infect a host and connect back to a central server
|
|
77
|
+
# A malicious bot is self-propagating malware designed to infect a host and connect back to a central server
|
|
78
|
+
# or servers that act as a command and control (C&C) center for an entire network of compromised devices,
|
|
79
|
+
# or botnet.
|
|
72
80
|
bot = "bot"
|
|
73
81
|
|
|
74
|
-
# A browser hijacker is defined as a form of unwanted software that modifies a web browser's settings without
|
|
82
|
+
# A browser hijacker is defined as a form of unwanted software that modifies a web browser's settings without
|
|
83
|
+
# the user's permission. The result is the placement of unwanted advertising into the browser,
|
|
84
|
+
# and possibly the replacement of an existing home page or search page with the hijacker page.
|
|
75
85
|
browser_hijacker = "browser_hijacker"
|
|
76
86
|
|
|
77
|
-
# Trojan bruteforcer are trying to brute force website in order to achieve something else
|
|
87
|
+
# Trojan bruteforcer are trying to brute force website in order to achieve something else
|
|
88
|
+
# (EX: Finding WordPress websites with default credentials).
|
|
78
89
|
bruteforcer = "bruteforcer"
|
|
79
90
|
|
|
80
|
-
# A type of trojan that can use your PC to 'click' on websites or applications.
|
|
91
|
+
# A type of trojan that can use your PC to 'click' on websites or applications.
|
|
92
|
+
# They are usually used to make money for a malicious hacker by clicking on online advertisements
|
|
93
|
+
# and making it look like the website gets more traffic than it does.
|
|
94
|
+
# They can also be used to skew online polls, install programs on your PC, or make unwanted software
|
|
95
|
+
# appear more popular than it is.
|
|
81
96
|
clickfraud = "clickfraud"
|
|
82
97
|
|
|
83
98
|
# Cryptocurrency mining malware.
|
|
84
99
|
cryptominer = "cryptominer"
|
|
85
100
|
|
|
86
|
-
# These programs conduct DoS (Denial of Service) attacks against a targeted web address.
|
|
101
|
+
# These programs conduct DoS (Denial of Service) attacks against a targeted web address.
|
|
102
|
+
# By sending multiple requests from your computer and several other infected computers,
|
|
103
|
+
# the attack can overwhelm the target address leading to a denial of service.
|
|
87
104
|
ddos = "ddos"
|
|
88
105
|
|
|
89
106
|
# Trojan Downloaders can download and install new versions of malicious programs in the target system.
|
|
@@ -92,49 +109,66 @@ class CategoryEnum(str, Enum):
|
|
|
92
109
|
# These programs are used by hackers in order to install malware or to prevent the detection of malicious programs.
|
|
93
110
|
dropper = "dropper"
|
|
94
111
|
|
|
95
|
-
# Exploit kits are programs that contain data or code that takes advantage of a vulnerability
|
|
112
|
+
# Exploit kits are programs that contain data or code that takes advantage of a vulnerability
|
|
113
|
+
# within an application that is running in the target system.
|
|
96
114
|
exploitkit = "exploitkit"
|
|
97
115
|
|
|
98
|
-
# Trojan FakeAV programs simulate the activity of antivirus software.
|
|
116
|
+
# Trojan FakeAV programs simulate the activity of antivirus software.
|
|
117
|
+
# They are designed to extort money in return for the detection and removal of threat, even though the
|
|
118
|
+
# threats that they report are actually non-existent.
|
|
99
119
|
fakeav = "fakeav"
|
|
100
120
|
|
|
101
121
|
# A type of tool that can be used to allow and maintain unauthorized access to your PC.
|
|
102
122
|
hacktool = "hacktool"
|
|
103
123
|
|
|
104
|
-
# A program that collects your personal information, such as your browsing history,
|
|
124
|
+
# A program that collects your personal information, such as your browsing history,
|
|
125
|
+
# and uses it without adequate consent.
|
|
105
126
|
infostealer = "infostealer"
|
|
106
127
|
|
|
107
|
-
# A keylogger monitors and logs every keystroke it can identify.
|
|
128
|
+
# A keylogger monitors and logs every keystroke it can identify.
|
|
129
|
+
# Once installed, the virus either keeps track of all the keys and stores the information locally,
|
|
130
|
+
# after which the hacker needs physical access to the computer to retrieve the information,
|
|
131
|
+
# or the logs are sent over the internet back to the hacker.
|
|
108
132
|
keylogger = "keylogger"
|
|
109
133
|
|
|
110
134
|
# A program that loads another application / memory space.
|
|
111
135
|
loader = "loader"
|
|
112
136
|
|
|
113
|
-
# A type of malware that hides its code and purpose to make it more difficult for
|
|
137
|
+
# A type of malware that hides its code and purpose to make it more difficult for
|
|
138
|
+
# security software to detect or remove it.
|
|
114
139
|
obfuscator = "obfuscator"
|
|
115
140
|
|
|
116
|
-
# Point-of-sale malware is usually a type of malware that is used by cybercriminals to target point of sale (POS)
|
|
141
|
+
# Point-of-sale malware is usually a type of malware that is used by cybercriminals to target point of sale (POS)
|
|
142
|
+
# and payment terminals with the intent to obtain credit card and debit card information.
|
|
117
143
|
pos = "pos"
|
|
118
144
|
|
|
119
|
-
# This type of trojan allows unauthorized parties to use the infected computer as a proxy server
|
|
145
|
+
# This type of trojan allows unauthorized parties to use the infected computer as a proxy server
|
|
146
|
+
# to access the Internet anonymously.
|
|
120
147
|
proxy = "proxy"
|
|
121
148
|
|
|
122
149
|
# A program that can be used by a remote hacker to gain access and control of an infected machine.
|
|
123
150
|
rat = "rat"
|
|
124
151
|
|
|
125
|
-
# This type of malware can modify data in the target computer so the operating system
|
|
152
|
+
# This type of malware can modify data in the target computer so the operating system
|
|
153
|
+
# will stop running correctly or the data is no longer accessible.
|
|
154
|
+
# The criminal will only restore the computer state or data after a ransom is paid to them
|
|
155
|
+
# (mostly using cryptocurrency).
|
|
126
156
|
ransomware = "ransomware"
|
|
127
157
|
|
|
128
158
|
# A reverse proxy is a server that receives requests from the internet and forwards them to a small set of servers.
|
|
129
159
|
reverse_proxy = "reverse_proxy"
|
|
130
160
|
|
|
131
|
-
# Rootkits are designed to conceal certain objects or activities in the system.
|
|
161
|
+
# Rootkits are designed to conceal certain objects or activities in the system.
|
|
162
|
+
# Often their main purpose is to prevent malicious programs being detected
|
|
163
|
+
# in order to extend the period in which programs can run on an infected computer.
|
|
132
164
|
rootkit = "rootkit"
|
|
133
165
|
|
|
134
|
-
# This type of malware scan the internet / network(s) / system(s) / service(s) to collect information.
|
|
166
|
+
# This type of malware scan the internet / network(s) / system(s) / service(s) to collect information.
|
|
167
|
+
# That information could be used later to perpetuate an cyber attack.
|
|
135
168
|
scanner = "scanner"
|
|
136
169
|
|
|
137
|
-
# Scareware is a form of malware which uses social engineering to cause shock, anxiety,
|
|
170
|
+
# Scareware is a form of malware which uses social engineering to cause shock, anxiety,
|
|
171
|
+
# or the perception of a threat in order to manipulate users into buying unwanted software.
|
|
138
172
|
scareware = "scareware"
|
|
139
173
|
|
|
140
174
|
# Malware that is sending spam.
|
maco/utils.py
CHANGED
|
@@ -46,6 +46,7 @@ UV_BIN = find_uv_bin()
|
|
|
46
46
|
PIP_CMD = f"{UV_BIN} pip"
|
|
47
47
|
VENV_CREATE_CMD = f"{UV_BIN} venv"
|
|
48
48
|
|
|
49
|
+
|
|
49
50
|
class Base64Decoder(json.JSONDecoder):
|
|
50
51
|
def __init__(self, *args, **kwargs):
|
|
51
52
|
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
|
|
@@ -179,11 +180,9 @@ def scan_for_extractors(root_directory: str, scanner: yara.Rules, logger: Logger
|
|
|
179
180
|
for pattern in [RELATIVE_FROM_IMPORT_RE, RELATIVE_FROM_RE]:
|
|
180
181
|
for match in pattern.findall(data):
|
|
181
182
|
depth = match.count(".")
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
1,
|
|
186
|
-
)
|
|
183
|
+
abspath = ".".join(split[depth - 1 : split.index(package) + 1][::-1])
|
|
184
|
+
abspath += "." if pattern == RELATIVE_FROM_RE else ""
|
|
185
|
+
data = data.replace(f"from {match}", f"from {abspath}", 1)
|
|
187
186
|
f.write(data)
|
|
188
187
|
|
|
189
188
|
if scanner.match(path):
|
|
@@ -222,7 +221,12 @@ def _install_required_packages(create_venv: bool, directories: List[str], python
|
|
|
222
221
|
subprocess.run(cmd.split(" ") + [venv_path], capture_output=True, env=env)
|
|
223
222
|
|
|
224
223
|
# Install/Update the packages in the environment
|
|
225
|
-
install_command = PIP_CMD.split(" ") + ["install"
|
|
224
|
+
install_command = PIP_CMD.split(" ") + ["install"]
|
|
225
|
+
# When running locally, only install packages to required spec.
|
|
226
|
+
# This prevents issues during maco development and building extractors against local libraries.
|
|
227
|
+
if create_venv:
|
|
228
|
+
# when running in custom virtual environment, always upgrade packages.
|
|
229
|
+
install_command.append("-U")
|
|
226
230
|
|
|
227
231
|
# Update the pip install command depending on where the dependencies are coming from
|
|
228
232
|
if "requirements.txt" in req_files:
|
|
@@ -307,8 +311,10 @@ def register_extractors(
|
|
|
307
311
|
parent_directory = os.path.dirname(current_directory)
|
|
308
312
|
if venvs and package_name in sys.modules:
|
|
309
313
|
# this may happen as part of testing if some part of the extractor code was directly imported
|
|
310
|
-
logger.warning(
|
|
311
|
-
|
|
314
|
+
logger.warning(
|
|
315
|
+
f"Looks like {package_name} is already loaded. "
|
|
316
|
+
"If your maco extractor overlaps an existing package name this could cause problems."
|
|
317
|
+
)
|
|
312
318
|
|
|
313
319
|
try:
|
|
314
320
|
# Modify the PATH so we can recognize this new package on import
|
|
@@ -383,6 +389,7 @@ def register_extractors(
|
|
|
383
389
|
# We were able to find all the extractor files
|
|
384
390
|
break
|
|
385
391
|
|
|
392
|
+
|
|
386
393
|
def proxy_logging(queue: multiprocessing.Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
|
|
387
394
|
"""Ensures logging is set up correctly for a child process and then executes the callback."""
|
|
388
395
|
logger = logging.getLogger()
|
|
@@ -391,6 +398,7 @@ def proxy_logging(queue: multiprocessing.Queue, callback: Callable[[ModuleType,
|
|
|
391
398
|
logger.addHandler(qh)
|
|
392
399
|
callback(*args, **kwargs, logger=logger)
|
|
393
400
|
|
|
401
|
+
|
|
394
402
|
def import_extractors(
|
|
395
403
|
extractor_module_callback: Callable[[ModuleType, str], bool],
|
|
396
404
|
*,
|
|
@@ -416,6 +424,7 @@ def import_extractors(
|
|
|
416
424
|
# holds cached extractors when not running in venv mode
|
|
417
425
|
_loaded_extractors: Dict[str, Extractor] = {}
|
|
418
426
|
|
|
427
|
+
|
|
419
428
|
def run_extractor(
|
|
420
429
|
sample_path,
|
|
421
430
|
module_name,
|
|
@@ -438,7 +447,7 @@ def run_extractor(
|
|
|
438
447
|
extractor = _loaded_extractors[key]
|
|
439
448
|
if extractor.yara_compiled:
|
|
440
449
|
matches = extractor.yara_compiled.match(sample_path)
|
|
441
|
-
loaded = extractor.run(open(sample_path,
|
|
450
|
+
loaded = extractor.run(open(sample_path, "rb"), matches=matches)
|
|
442
451
|
else:
|
|
443
452
|
# execute extractor in child process with separate virtual environment
|
|
444
453
|
# Write temporary script in the same directory as extractor to resolve relative imports
|
|
@@ -477,7 +486,7 @@ def run_extractor(
|
|
|
477
486
|
try:
|
|
478
487
|
# Load results and return them
|
|
479
488
|
output.seek(0)
|
|
480
|
-
loaded =
|
|
489
|
+
loaded = json.load(output, cls=json_decoder)
|
|
481
490
|
except Exception as e:
|
|
482
491
|
# If there was an error raised during runtime, then propagate
|
|
483
492
|
delim = f'File "{module_path}"'
|
maco/yara.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: maco
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Author: sl-govau
|
|
5
5
|
Maintainer: cccs-rs
|
|
6
6
|
License: MIT License
|
|
@@ -38,7 +38,7 @@ Requires-Dist: yara-x==0.11.0
|
|
|
38
38
|
|
|
39
39
|
# Maco - Malware config extractor framework
|
|
40
40
|
|
|
41
|
-
## Maco is a framework for
|
|
41
|
+
## Maco is a framework for <ins>ma</ins>lware <ins>co</ins>nfig extractors.
|
|
42
42
|
|
|
43
43
|
It aims to solve two problems:
|
|
44
44
|
|
|
@@ -272,3 +272,15 @@ run Complex extractor from rules ['ComplexAlt']
|
|
|
272
272
|
The demo extractors are designed to trigger when run over the '`demo_extractors`' folder.
|
|
273
273
|
|
|
274
274
|
e.g. `maco demo_extractors demo_extractors`
|
|
275
|
+
|
|
276
|
+
# Contributions
|
|
277
|
+
|
|
278
|
+
Please use ruff to format and lint PRs. This may be the cause of PR test failures.
|
|
279
|
+
|
|
280
|
+
Ruff will attempt to fix most issues, but some may require manual resolution.
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
pip install ruff
|
|
284
|
+
ruff format
|
|
285
|
+
ruff check --fix
|
|
286
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
demo_extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
demo_extractors/elfy.py,sha256=Jo_GKExCeFOKGENJnNM_9ONfJO7LQFucCNz0ryTAo9U,765
|
|
3
|
+
demo_extractors/limit_other.py,sha256=BWjeyOxB75kw4eRla5zvSzdcXtELOS8R6hc71rLPh1s,1295
|
|
4
|
+
demo_extractors/nothing.py,sha256=MNPlb0IsBjrlU5e438JlJ4DIKoBpBRAaYY3JhD3yHqk,601
|
|
5
|
+
demo_extractors/requirements.txt,sha256=E0tD6xBZldq6sQGTHng6k88lBeASOhmLJcdcjpcqBNE,6
|
|
6
|
+
demo_extractors/shared.py,sha256=2P1cyuRbHDvM9IRt3UZnwdyhxx7OWqNC83xLyV8Y190,305
|
|
7
|
+
demo_extractors/complex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
demo_extractors/complex/complex.py,sha256=tXrzj_zWIXbTOwj7Lezapk-qkrM-lfwcyjd5m-BYzdg,2322
|
|
9
|
+
demo_extractors/complex/complex_utils.py,sha256=aec8kJsYUrMPo-waihkVLt-0QpiOPkw7dDqfT9MNuHk,123
|
|
10
|
+
maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
maco/base_test.py,sha256=cjGLEy2c69wl9sjn74QFz7X-VxWOfdin4W8MvYsXc4Q,2718
|
|
12
|
+
maco/cli.py,sha256=NTzV8eu9V0qQNttRo592j-Rdzac7q1NAMraqJF2h_6k,8171
|
|
13
|
+
maco/collector.py,sha256=LraWYlCA72FCmQP0dHWc-ekd7R1SxR6h6rMD95_6mMs,7077
|
|
14
|
+
maco/extractor.py,sha256=uGSGiCQ4jd8jFmfw2T99BGcY5iQJzXHcG_RoTIxClTE,2802
|
|
15
|
+
maco/utils.py,sha256=vo8zGSoFP0k2APUlQXmLssdrVrknjS2YcpvbRM78J68,20480
|
|
16
|
+
maco/yara.py,sha256=8RVaGyeUWY5f8_wfQ25lDX1bcXsb_VoSja85ZC2SqGw,2913
|
|
17
|
+
maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
|
|
18
|
+
maco/model/model.py,sha256=4uY88WphbP3iu-L2WjuYwtgZCS_wNul_hr0bAVuTpvc,23740
|
|
19
|
+
model_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
model_setup/maco/base_test.py,sha256=cjGLEy2c69wl9sjn74QFz7X-VxWOfdin4W8MvYsXc4Q,2718
|
|
21
|
+
model_setup/maco/cli.py,sha256=NTzV8eu9V0qQNttRo592j-Rdzac7q1NAMraqJF2h_6k,8171
|
|
22
|
+
model_setup/maco/collector.py,sha256=LraWYlCA72FCmQP0dHWc-ekd7R1SxR6h6rMD95_6mMs,7077
|
|
23
|
+
model_setup/maco/extractor.py,sha256=uGSGiCQ4jd8jFmfw2T99BGcY5iQJzXHcG_RoTIxClTE,2802
|
|
24
|
+
model_setup/maco/utils.py,sha256=vo8zGSoFP0k2APUlQXmLssdrVrknjS2YcpvbRM78J68,20480
|
|
25
|
+
model_setup/maco/yara.py,sha256=8RVaGyeUWY5f8_wfQ25lDX1bcXsb_VoSja85ZC2SqGw,2913
|
|
26
|
+
model_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
|
|
27
|
+
model_setup/maco/model/model.py,sha256=4uY88WphbP3iu-L2WjuYwtgZCS_wNul_hr0bAVuTpvc,23740
|
|
28
|
+
pipelines/publish.yaml,sha256=xt3WNU-5kIICJgKIiiE94M3dWjS3uEiun-n4OmIssK8,1471
|
|
29
|
+
pipelines/test.yaml,sha256=btJVI-R39UBeYosGu7TOpU6V9ogFW3FT3ROtWygQGQ0,1472
|
|
30
|
+
tests/data/example.txt.cart,sha256=j4ZdDnFNVq7lb-Qi4pY4evOXKQPKG-GSg-n-uEqPhV0,289
|
|
31
|
+
tests/data/trigger_complex.txt,sha256=uqnLSrnyDGCmXwuPmZ2s8vdhH0hJs8DxvyaW_tuYY24,64
|
|
32
|
+
tests/data/trigger_complex.txt.cart,sha256=Z7qF1Zi640O45Znkl9ooP2RhSLAEqY0NRf51d-q7utU,345
|
|
33
|
+
tests/extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
tests/extractors/basic.py,sha256=r5eLCL6Ynr14nCBgtbLvUbm0NdrXizyc9c-4xBCNShU,828
|
|
35
|
+
tests/extractors/basic_longer.py,sha256=1ClU2QD-Y0TOl_loNFvEqIEpTR5TSVJ6zg9ZmC-ESJo,860
|
|
36
|
+
tests/extractors/test_basic.py,sha256=FLKekfSGM69HaiF7Vu_7D7KDXHZko-9hZkMO8_DoyYA,697
|
|
37
|
+
tests/extractors/bob/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
tests/extractors/bob/bob.py,sha256=G5aOoz58J0ZQK2_lA7HRxAzeLzBxssWxBTZcv1pSbi8,176
|
|
39
|
+
maco-1.2.6.dist-info/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
|
|
40
|
+
maco-1.2.6.dist-info/METADATA,sha256=-ZxVnBbAHn-iGDizJJa8knrTf4DUArPzANp-SVqDzZ4,15855
|
|
41
|
+
maco-1.2.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
42
|
+
maco-1.2.6.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
|
|
43
|
+
maco-1.2.6.dist-info/top_level.txt,sha256=iMRwuzmrHA3zSwiSeMIl6FWhzRpn_st-I4fAv-kw5_o,49
|
|
44
|
+
maco-1.2.6.dist-info/RECORD,,
|
model_setup/maco/base_test.py
CHANGED
|
@@ -32,7 +32,7 @@ class BaseTest(unittest.TestCase):
|
|
|
32
32
|
# I recommend something like os.path.join(__file__, "../../extractors")
|
|
33
33
|
# if your extractors are in a folder 'extractors' next to a folder of tests
|
|
34
34
|
path: str = None
|
|
35
|
-
create_venv: bool=False
|
|
35
|
+
create_venv: bool = False
|
|
36
36
|
|
|
37
37
|
@classmethod
|
|
38
38
|
def setUpClass(cls) -> None:
|
model_setup/maco/cli.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""CLI example of how extractors can be executed."""
|
|
2
|
+
|
|
2
3
|
import argparse
|
|
3
4
|
import base64
|
|
4
5
|
import binascii
|
|
@@ -150,6 +151,7 @@ def process_filesystem(
|
|
|
150
151
|
logger.info(f"{num_analysed} analysed, {num_hits} hits, {num_extracted} extracted")
|
|
151
152
|
return num_analysed, num_hits, num_extracted
|
|
152
153
|
|
|
154
|
+
|
|
153
155
|
def main():
|
|
154
156
|
parser = argparse.ArgumentParser(description="Run extractors over samples.")
|
|
155
157
|
parser.add_argument("extractors", type=str, help="path to extractors")
|
|
@@ -165,7 +167,8 @@ def main():
|
|
|
165
167
|
parser.add_argument(
|
|
166
168
|
"--base64",
|
|
167
169
|
action="store_true",
|
|
168
|
-
help="Include base64 encoded binary data in output
|
|
170
|
+
help="Include base64 encoded binary data in output "
|
|
171
|
+
"(can be large, consider printing to file rather than console)",
|
|
169
172
|
)
|
|
170
173
|
parser.add_argument("--logfile", type=str, help="file to log output")
|
|
171
174
|
parser.add_argument("--include", type=str, help="comma separated extractors to run")
|
|
@@ -179,7 +182,9 @@ def main():
|
|
|
179
182
|
parser.add_argument(
|
|
180
183
|
"--create_venv",
|
|
181
184
|
action="store_true",
|
|
182
|
-
help="Creates venvs for every requirements.txt found (only applies when extractor path is a directory).
|
|
185
|
+
help="Creates venvs for every requirements.txt found (only applies when extractor path is a directory). "
|
|
186
|
+
"This runs much slower than the alternative but may be necessary "
|
|
187
|
+
"when there are many extractors with conflicting dependencies.",
|
|
183
188
|
)
|
|
184
189
|
args = parser.parse_args()
|
|
185
190
|
inc = args.include.split(",") if args.include else []
|
|
@@ -225,7 +230,7 @@ def main():
|
|
|
225
230
|
pretty=args.pretty,
|
|
226
231
|
force=args.force,
|
|
227
232
|
include_base64=args.base64,
|
|
228
|
-
create_venv=args.create_venv
|
|
233
|
+
create_venv=args.create_venv,
|
|
229
234
|
)
|
|
230
235
|
|
|
231
236
|
|
model_setup/maco/collector.py
CHANGED
|
@@ -4,6 +4,7 @@ import inspect
|
|
|
4
4
|
import logging
|
|
5
5
|
import logging.handlers
|
|
6
6
|
import os
|
|
7
|
+
import sys
|
|
7
8
|
from multiprocessing import Manager, Process, Queue
|
|
8
9
|
from tempfile import NamedTemporaryFile
|
|
9
10
|
from types import ModuleType
|
|
@@ -48,6 +49,15 @@ class Collector:
|
|
|
48
49
|
create_venv: bool = False,
|
|
49
50
|
):
|
|
50
51
|
"""Discover and load extractors from file system."""
|
|
52
|
+
# maco requires the extractor to be imported directly, so ensure they are available on the path
|
|
53
|
+
full_path_extractors = os.path.abspath(path_extractors)
|
|
54
|
+
full_path_above_extractors = os.path.dirname(full_path_extractors)
|
|
55
|
+
# Modify the PATH so we can recognize this new package on import
|
|
56
|
+
if full_path_extractors not in sys.path:
|
|
57
|
+
sys.path.insert(1, full_path_extractors)
|
|
58
|
+
if full_path_above_extractors not in sys.path:
|
|
59
|
+
sys.path.insert(1, full_path_above_extractors)
|
|
60
|
+
|
|
51
61
|
path_extractors = os.path.realpath(path_extractors)
|
|
52
62
|
self.path: str = path_extractors
|
|
53
63
|
self.extractors: Dict[str, Dict[str, str]] = {}
|
|
@@ -89,7 +99,7 @@ class Collector:
|
|
|
89
99
|
|
|
90
100
|
# multiprocess logging is awkward - set up a queue to ensure we can log
|
|
91
101
|
logging_queue = Queue()
|
|
92
|
-
queue_handler = logging.handlers.QueueListener(logging_queue
|
|
102
|
+
queue_handler = logging.handlers.QueueListener(logging_queue, *logging.getLogger().handlers)
|
|
93
103
|
queue_handler.start()
|
|
94
104
|
|
|
95
105
|
# Find the extractors within the given directory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
from maco.model.model import *
|
|
1
|
+
from maco.model.model import * # noqa: F403
|
model_setup/maco/model/model.py
CHANGED
|
@@ -59,31 +59,48 @@ class CategoryEnum(str, Enum):
|
|
|
59
59
|
# Malware related to an Advanced Persistent Threat (APT) group.
|
|
60
60
|
apt = "apt"
|
|
61
61
|
|
|
62
|
-
# A backdoor Trojan gives malicious users remote control over the infected computer.
|
|
62
|
+
# A backdoor Trojan gives malicious users remote control over the infected computer.
|
|
63
|
+
# They enable the author to do anything they wish on the infected computer including
|
|
64
|
+
# sending, receiving, launching and deleting files, displaying data and rebooting the computer.
|
|
65
|
+
# Backdoor Trojans are often used to unite a group of victim computers to form a botnet or
|
|
66
|
+
# zombie network that can be used for criminal purposes.
|
|
63
67
|
backdoor = "backdoor"
|
|
64
68
|
|
|
65
|
-
# Trojan Banker programs are designed to steal your account data for online banking systems,
|
|
69
|
+
# Trojan Banker programs are designed to steal your account data for online banking systems,
|
|
70
|
+
# e-payment systems and credit or debit cards.
|
|
66
71
|
banker = "banker"
|
|
67
72
|
|
|
68
|
-
# A malware variant that modifies the boot sectors of a hard drive, including the Master Boot Record (MBR)
|
|
73
|
+
# A malware variant that modifies the boot sectors of a hard drive, including the Master Boot Record (MBR)
|
|
74
|
+
# and Volume Boot Record (VBR).
|
|
69
75
|
bootkit = "bootkit"
|
|
70
76
|
|
|
71
|
-
# A malicious bot is self-propagating malware designed to infect a host and connect back to a central server
|
|
77
|
+
# A malicious bot is self-propagating malware designed to infect a host and connect back to a central server
|
|
78
|
+
# or servers that act as a command and control (C&C) center for an entire network of compromised devices,
|
|
79
|
+
# or botnet.
|
|
72
80
|
bot = "bot"
|
|
73
81
|
|
|
74
|
-
# A browser hijacker is defined as a form of unwanted software that modifies a web browser's settings without
|
|
82
|
+
# A browser hijacker is defined as a form of unwanted software that modifies a web browser's settings without
|
|
83
|
+
# the user's permission. The result is the placement of unwanted advertising into the browser,
|
|
84
|
+
# and possibly the replacement of an existing home page or search page with the hijacker page.
|
|
75
85
|
browser_hijacker = "browser_hijacker"
|
|
76
86
|
|
|
77
|
-
# Trojan bruteforcer are trying to brute force website in order to achieve something else
|
|
87
|
+
# Trojan bruteforcer are trying to brute force website in order to achieve something else
|
|
88
|
+
# (EX: Finding WordPress websites with default credentials).
|
|
78
89
|
bruteforcer = "bruteforcer"
|
|
79
90
|
|
|
80
|
-
# A type of trojan that can use your PC to 'click' on websites or applications.
|
|
91
|
+
# A type of trojan that can use your PC to 'click' on websites or applications.
|
|
92
|
+
# They are usually used to make money for a malicious hacker by clicking on online advertisements
|
|
93
|
+
# and making it look like the website gets more traffic than it does.
|
|
94
|
+
# They can also be used to skew online polls, install programs on your PC, or make unwanted software
|
|
95
|
+
# appear more popular than it is.
|
|
81
96
|
clickfraud = "clickfraud"
|
|
82
97
|
|
|
83
98
|
# Cryptocurrency mining malware.
|
|
84
99
|
cryptominer = "cryptominer"
|
|
85
100
|
|
|
86
|
-
# These programs conduct DoS (Denial of Service) attacks against a targeted web address.
|
|
101
|
+
# These programs conduct DoS (Denial of Service) attacks against a targeted web address.
|
|
102
|
+
# By sending multiple requests from your computer and several other infected computers,
|
|
103
|
+
# the attack can overwhelm the target address leading to a denial of service.
|
|
87
104
|
ddos = "ddos"
|
|
88
105
|
|
|
89
106
|
# Trojan Downloaders can download and install new versions of malicious programs in the target system.
|
|
@@ -92,49 +109,66 @@ class CategoryEnum(str, Enum):
|
|
|
92
109
|
# These programs are used by hackers in order to install malware or to prevent the detection of malicious programs.
|
|
93
110
|
dropper = "dropper"
|
|
94
111
|
|
|
95
|
-
# Exploit kits are programs that contain data or code that takes advantage of a vulnerability
|
|
112
|
+
# Exploit kits are programs that contain data or code that takes advantage of a vulnerability
|
|
113
|
+
# within an application that is running in the target system.
|
|
96
114
|
exploitkit = "exploitkit"
|
|
97
115
|
|
|
98
|
-
# Trojan FakeAV programs simulate the activity of antivirus software.
|
|
116
|
+
# Trojan FakeAV programs simulate the activity of antivirus software.
|
|
117
|
+
# They are designed to extort money in return for the detection and removal of threat, even though the
|
|
118
|
+
# threats that they report are actually non-existent.
|
|
99
119
|
fakeav = "fakeav"
|
|
100
120
|
|
|
101
121
|
# A type of tool that can be used to allow and maintain unauthorized access to your PC.
|
|
102
122
|
hacktool = "hacktool"
|
|
103
123
|
|
|
104
|
-
# A program that collects your personal information, such as your browsing history,
|
|
124
|
+
# A program that collects your personal information, such as your browsing history,
|
|
125
|
+
# and uses it without adequate consent.
|
|
105
126
|
infostealer = "infostealer"
|
|
106
127
|
|
|
107
|
-
# A keylogger monitors and logs every keystroke it can identify.
|
|
128
|
+
# A keylogger monitors and logs every keystroke it can identify.
|
|
129
|
+
# Once installed, the virus either keeps track of all the keys and stores the information locally,
|
|
130
|
+
# after which the hacker needs physical access to the computer to retrieve the information,
|
|
131
|
+
# or the logs are sent over the internet back to the hacker.
|
|
108
132
|
keylogger = "keylogger"
|
|
109
133
|
|
|
110
134
|
# A program that loads another application / memory space.
|
|
111
135
|
loader = "loader"
|
|
112
136
|
|
|
113
|
-
# A type of malware that hides its code and purpose to make it more difficult for
|
|
137
|
+
# A type of malware that hides its code and purpose to make it more difficult for
|
|
138
|
+
# security software to detect or remove it.
|
|
114
139
|
obfuscator = "obfuscator"
|
|
115
140
|
|
|
116
|
-
# Point-of-sale malware is usually a type of malware that is used by cybercriminals to target point of sale (POS)
|
|
141
|
+
# Point-of-sale malware is usually a type of malware that is used by cybercriminals to target point of sale (POS)
|
|
142
|
+
# and payment terminals with the intent to obtain credit card and debit card information.
|
|
117
143
|
pos = "pos"
|
|
118
144
|
|
|
119
|
-
# This type of trojan allows unauthorized parties to use the infected computer as a proxy server
|
|
145
|
+
# This type of trojan allows unauthorized parties to use the infected computer as a proxy server
|
|
146
|
+
# to access the Internet anonymously.
|
|
120
147
|
proxy = "proxy"
|
|
121
148
|
|
|
122
149
|
# A program that can be used by a remote hacker to gain access and control of an infected machine.
|
|
123
150
|
rat = "rat"
|
|
124
151
|
|
|
125
|
-
# This type of malware can modify data in the target computer so the operating system
|
|
152
|
+
# This type of malware can modify data in the target computer so the operating system
|
|
153
|
+
# will stop running correctly or the data is no longer accessible.
|
|
154
|
+
# The criminal will only restore the computer state or data after a ransom is paid to them
|
|
155
|
+
# (mostly using cryptocurrency).
|
|
126
156
|
ransomware = "ransomware"
|
|
127
157
|
|
|
128
158
|
# A reverse proxy is a server that receives requests from the internet and forwards them to a small set of servers.
|
|
129
159
|
reverse_proxy = "reverse_proxy"
|
|
130
160
|
|
|
131
|
-
# Rootkits are designed to conceal certain objects or activities in the system.
|
|
161
|
+
# Rootkits are designed to conceal certain objects or activities in the system.
|
|
162
|
+
# Often their main purpose is to prevent malicious programs being detected
|
|
163
|
+
# in order to extend the period in which programs can run on an infected computer.
|
|
132
164
|
rootkit = "rootkit"
|
|
133
165
|
|
|
134
|
-
# This type of malware scan the internet / network(s) / system(s) / service(s) to collect information.
|
|
166
|
+
# This type of malware scan the internet / network(s) / system(s) / service(s) to collect information.
|
|
167
|
+
# That information could be used later to perpetuate an cyber attack.
|
|
135
168
|
scanner = "scanner"
|
|
136
169
|
|
|
137
|
-
# Scareware is a form of malware which uses social engineering to cause shock, anxiety,
|
|
170
|
+
# Scareware is a form of malware which uses social engineering to cause shock, anxiety,
|
|
171
|
+
# or the perception of a threat in order to manipulate users into buying unwanted software.
|
|
138
172
|
scareware = "scareware"
|
|
139
173
|
|
|
140
174
|
# Malware that is sending spam.
|
model_setup/maco/utils.py
CHANGED
|
@@ -46,6 +46,7 @@ UV_BIN = find_uv_bin()
|
|
|
46
46
|
PIP_CMD = f"{UV_BIN} pip"
|
|
47
47
|
VENV_CREATE_CMD = f"{UV_BIN} venv"
|
|
48
48
|
|
|
49
|
+
|
|
49
50
|
class Base64Decoder(json.JSONDecoder):
|
|
50
51
|
def __init__(self, *args, **kwargs):
|
|
51
52
|
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
|
|
@@ -179,11 +180,9 @@ def scan_for_extractors(root_directory: str, scanner: yara.Rules, logger: Logger
|
|
|
179
180
|
for pattern in [RELATIVE_FROM_IMPORT_RE, RELATIVE_FROM_RE]:
|
|
180
181
|
for match in pattern.findall(data):
|
|
181
182
|
depth = match.count(".")
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
1,
|
|
186
|
-
)
|
|
183
|
+
abspath = ".".join(split[depth - 1 : split.index(package) + 1][::-1])
|
|
184
|
+
abspath += "." if pattern == RELATIVE_FROM_RE else ""
|
|
185
|
+
data = data.replace(f"from {match}", f"from {abspath}", 1)
|
|
187
186
|
f.write(data)
|
|
188
187
|
|
|
189
188
|
if scanner.match(path):
|
|
@@ -222,7 +221,12 @@ def _install_required_packages(create_venv: bool, directories: List[str], python
|
|
|
222
221
|
subprocess.run(cmd.split(" ") + [venv_path], capture_output=True, env=env)
|
|
223
222
|
|
|
224
223
|
# Install/Update the packages in the environment
|
|
225
|
-
install_command = PIP_CMD.split(" ") + ["install"
|
|
224
|
+
install_command = PIP_CMD.split(" ") + ["install"]
|
|
225
|
+
# When running locally, only install packages to required spec.
|
|
226
|
+
# This prevents issues during maco development and building extractors against local libraries.
|
|
227
|
+
if create_venv:
|
|
228
|
+
# when running in custom virtual environment, always upgrade packages.
|
|
229
|
+
install_command.append("-U")
|
|
226
230
|
|
|
227
231
|
# Update the pip install command depending on where the dependencies are coming from
|
|
228
232
|
if "requirements.txt" in req_files:
|
|
@@ -307,8 +311,10 @@ def register_extractors(
|
|
|
307
311
|
parent_directory = os.path.dirname(current_directory)
|
|
308
312
|
if venvs and package_name in sys.modules:
|
|
309
313
|
# this may happen as part of testing if some part of the extractor code was directly imported
|
|
310
|
-
logger.warning(
|
|
311
|
-
|
|
314
|
+
logger.warning(
|
|
315
|
+
f"Looks like {package_name} is already loaded. "
|
|
316
|
+
"If your maco extractor overlaps an existing package name this could cause problems."
|
|
317
|
+
)
|
|
312
318
|
|
|
313
319
|
try:
|
|
314
320
|
# Modify the PATH so we can recognize this new package on import
|
|
@@ -383,6 +389,7 @@ def register_extractors(
|
|
|
383
389
|
# We were able to find all the extractor files
|
|
384
390
|
break
|
|
385
391
|
|
|
392
|
+
|
|
386
393
|
def proxy_logging(queue: multiprocessing.Queue, callback: Callable[[ModuleType, str], None], *args, **kwargs):
|
|
387
394
|
"""Ensures logging is set up correctly for a child process and then executes the callback."""
|
|
388
395
|
logger = logging.getLogger()
|
|
@@ -391,6 +398,7 @@ def proxy_logging(queue: multiprocessing.Queue, callback: Callable[[ModuleType,
|
|
|
391
398
|
logger.addHandler(qh)
|
|
392
399
|
callback(*args, **kwargs, logger=logger)
|
|
393
400
|
|
|
401
|
+
|
|
394
402
|
def import_extractors(
|
|
395
403
|
extractor_module_callback: Callable[[ModuleType, str], bool],
|
|
396
404
|
*,
|
|
@@ -416,6 +424,7 @@ def import_extractors(
|
|
|
416
424
|
# holds cached extractors when not running in venv mode
|
|
417
425
|
_loaded_extractors: Dict[str, Extractor] = {}
|
|
418
426
|
|
|
427
|
+
|
|
419
428
|
def run_extractor(
|
|
420
429
|
sample_path,
|
|
421
430
|
module_name,
|
|
@@ -438,7 +447,7 @@ def run_extractor(
|
|
|
438
447
|
extractor = _loaded_extractors[key]
|
|
439
448
|
if extractor.yara_compiled:
|
|
440
449
|
matches = extractor.yara_compiled.match(sample_path)
|
|
441
|
-
loaded = extractor.run(open(sample_path,
|
|
450
|
+
loaded = extractor.run(open(sample_path, "rb"), matches=matches)
|
|
442
451
|
else:
|
|
443
452
|
# execute extractor in child process with separate virtual environment
|
|
444
453
|
# Write temporary script in the same directory as extractor to resolve relative imports
|
|
@@ -477,7 +486,7 @@ def run_extractor(
|
|
|
477
486
|
try:
|
|
478
487
|
# Load results and return them
|
|
479
488
|
output.seek(0)
|
|
480
|
-
loaded =
|
|
489
|
+
loaded = json.load(output, cls=json_decoder)
|
|
481
490
|
except Exception as e:
|
|
482
491
|
# If there was an error raised during runtime, then propagate
|
|
483
492
|
delim = f'File "{module_path}"'
|
model_setup/maco/yara.py
CHANGED
pipelines/test.yaml
CHANGED
|
@@ -7,6 +7,27 @@ pool:
|
|
|
7
7
|
vmImage: "ubuntu-22.04"
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
|
+
- job: style_test
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
Python3_12:
|
|
14
|
+
python.version: "3.12"
|
|
15
|
+
timeoutInMinutes: 10
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- task: UsePythonVersion@0
|
|
19
|
+
displayName: Set python version
|
|
20
|
+
inputs:
|
|
21
|
+
versionSpec: "$(python.version)"
|
|
22
|
+
|
|
23
|
+
- script: |
|
|
24
|
+
python -m pip install -U tox
|
|
25
|
+
displayName: Install tox
|
|
26
|
+
|
|
27
|
+
- script: |
|
|
28
|
+
python -m tox -e style
|
|
29
|
+
displayName: "Run style tests"
|
|
30
|
+
|
|
10
31
|
- job: run_test
|
|
11
32
|
strategy:
|
|
12
33
|
matrix:
|
tests/extractors/bob/bob.py
CHANGED
maco-1.2.5.dist-info/RECORD
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
demo_extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
demo_extractors/elfy.py,sha256=AAFr5i1aivPwO4nycyXJEud57EpVNA-5k_2GicWesbY,771
|
|
3
|
-
demo_extractors/limit_other.py,sha256=8Z7X0cXUyZuK3MhDtObMWmdruRj5hgFdDi_VVGXqRx4,1123
|
|
4
|
-
demo_extractors/nothing.py,sha256=3aeQJTY-dakmVXmyfmrRM8YCQVT7q3bq880DFH1Ol_Y,607
|
|
5
|
-
demo_extractors/requirements.txt,sha256=E0tD6xBZldq6sQGTHng6k88lBeASOhmLJcdcjpcqBNE,6
|
|
6
|
-
demo_extractors/shared.py,sha256=2P1cyuRbHDvM9IRt3UZnwdyhxx7OWqNC83xLyV8Y190,305
|
|
7
|
-
demo_extractors/complex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
demo_extractors/complex/complex.py,sha256=tXrzj_zWIXbTOwj7Lezapk-qkrM-lfwcyjd5m-BYzdg,2322
|
|
9
|
-
demo_extractors/complex/complex_utils.py,sha256=aec8kJsYUrMPo-waihkVLt-0QpiOPkw7dDqfT9MNuHk,123
|
|
10
|
-
maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
maco/base_test.py,sha256=EPxCun9Tv91V-lFpaenn14tPyW17TPvXVH4AjE3t6js,2716
|
|
12
|
-
maco/cli.py,sha256=fIeUXOgOxcecmAkl6OAdnjBKqk1gBPv1ryWe50pT60g,8135
|
|
13
|
-
maco/collector.py,sha256=Vlo7KcJC7TKZFTElv8i_f_hvWEnlWCRzOP1xOc9x7vk,6532
|
|
14
|
-
maco/extractor.py,sha256=uGSGiCQ4jd8jFmfw2T99BGcY5iQJzXHcG_RoTIxClTE,2802
|
|
15
|
-
maco/utils.py,sha256=K41c-H7naaoiEYf0WNfP054IxwvHPujsbmmzgTizuLU,20159
|
|
16
|
-
maco/yara.py,sha256=vPzCqauVp52ivcTdt8zwrYqDdkLutGlesma9DhKPzHw,2925
|
|
17
|
-
maco/model/__init__.py,sha256=SJrwdn12wklUFm2KoIgWjX_KgvJxCM7Ca9ntXOneuzc,31
|
|
18
|
-
maco/model/model.py,sha256=ngen4ViyLdRo_z_TqZBjw2DN0NrRLpuxOy15-6QmtNw,23536
|
|
19
|
-
model_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
model_setup/maco/base_test.py,sha256=EPxCun9Tv91V-lFpaenn14tPyW17TPvXVH4AjE3t6js,2716
|
|
21
|
-
model_setup/maco/cli.py,sha256=fIeUXOgOxcecmAkl6OAdnjBKqk1gBPv1ryWe50pT60g,8135
|
|
22
|
-
model_setup/maco/collector.py,sha256=Vlo7KcJC7TKZFTElv8i_f_hvWEnlWCRzOP1xOc9x7vk,6532
|
|
23
|
-
model_setup/maco/extractor.py,sha256=uGSGiCQ4jd8jFmfw2T99BGcY5iQJzXHcG_RoTIxClTE,2802
|
|
24
|
-
model_setup/maco/utils.py,sha256=K41c-H7naaoiEYf0WNfP054IxwvHPujsbmmzgTizuLU,20159
|
|
25
|
-
model_setup/maco/yara.py,sha256=vPzCqauVp52ivcTdt8zwrYqDdkLutGlesma9DhKPzHw,2925
|
|
26
|
-
model_setup/maco/model/__init__.py,sha256=SJrwdn12wklUFm2KoIgWjX_KgvJxCM7Ca9ntXOneuzc,31
|
|
27
|
-
model_setup/maco/model/model.py,sha256=ngen4ViyLdRo_z_TqZBjw2DN0NrRLpuxOy15-6QmtNw,23536
|
|
28
|
-
pipelines/publish.yaml,sha256=xt3WNU-5kIICJgKIiiE94M3dWjS3uEiun-n4OmIssK8,1471
|
|
29
|
-
pipelines/test.yaml,sha256=3KOoo-8SqP_bTAscsz5V3xxnuL91J-62mTjnQD1Btag,1019
|
|
30
|
-
tests/data/example.txt.cart,sha256=j4ZdDnFNVq7lb-Qi4pY4evOXKQPKG-GSg-n-uEqPhV0,289
|
|
31
|
-
tests/data/trigger_complex.txt,sha256=uqnLSrnyDGCmXwuPmZ2s8vdhH0hJs8DxvyaW_tuYY24,64
|
|
32
|
-
tests/data/trigger_complex.txt.cart,sha256=Z7qF1Zi640O45Znkl9ooP2RhSLAEqY0NRf51d-q7utU,345
|
|
33
|
-
tests/extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
-
tests/extractors/basic.py,sha256=r5eLCL6Ynr14nCBgtbLvUbm0NdrXizyc9c-4xBCNShU,828
|
|
35
|
-
tests/extractors/basic_longer.py,sha256=1ClU2QD-Y0TOl_loNFvEqIEpTR5TSVJ6zg9ZmC-ESJo,860
|
|
36
|
-
tests/extractors/test_basic.py,sha256=FLKekfSGM69HaiF7Vu_7D7KDXHZko-9hZkMO8_DoyYA,697
|
|
37
|
-
tests/extractors/bob/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
tests/extractors/bob/bob.py,sha256=Gy5p8KssJX87cwa9vVv8UBODF_ulbUteZXh15frW2hs,247
|
|
39
|
-
maco-1.2.5.dist-info/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
|
|
40
|
-
maco-1.2.5.dist-info/METADATA,sha256=cJ7x_shBhDgKVjkq_e2d94aj3qiUzi0lt7f3lPO334U,15610
|
|
41
|
-
maco-1.2.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
42
|
-
maco-1.2.5.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
|
|
43
|
-
maco-1.2.5.dist-info/top_level.txt,sha256=iMRwuzmrHA3zSwiSeMIl6FWhzRpn_st-I4fAv-kw5_o,49
|
|
44
|
-
maco-1.2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|