maya-umbrella 0.15.0__tar.gz → 0.17.0__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.
Potentially problematic release.
This version of maya-umbrella might be problematic. Click here for more details.
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/PKG-INFO +30 -1
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/README.md +29 -0
- maya_umbrella-0.17.0/maya_umbrella/__version__.py +1 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/filesystem.py +45 -1
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/signatures.py +13 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/vaccines/vaccine2.py +5 -1
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/vaccines/vaccine3.py +10 -2
- maya_umbrella-0.17.0/maya_umbrella/vaccines/vaccine4.py +162 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/pyproject.toml +2 -2
- maya_umbrella-0.15.0/maya_umbrella/__version__.py +0 -1
- maya_umbrella-0.15.0/maya_umbrella/vaccines/vaccine4.py +0 -55
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/LICENSE +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/__init__.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/__init__.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/atomicwrites/LICENSE +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/atomicwrites/__init__.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/atomicwrites.pyi +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/six/__init__.pyi +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/six/moves/__init__.pyi +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/six/moves/configparser.pyi +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/six.LICENSE +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/six.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/vendor.txt +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/cleaner.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/collector.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/constants.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/defender.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/__init__.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/delete_turtle.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/delete_unknown_plugin_node.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/fix_model_panel.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/fix_no_scene_name.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/fix_on_model_change_3dc.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/i18n.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/locales/en_US.json +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/locales/zh_CN.json +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/log.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/maya_funs.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/scanner.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/vaccine.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/vaccines/__init__.py +0 -0
- {maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/vaccines/vaccine1.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maya_umbrella
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Summary: A better Autodesk Maya antivirus tool detects and removes malicious.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -36,6 +36,7 @@ Description-Content-Type: text/markdown
|
|
|
36
36
|
[](https://pepy.tech/project/maya-umbrella)
|
|
37
37
|
[](https://pepy.tech/project/maya-umbrella)
|
|
38
38
|
[](https://pepy.tech/project/maya-umbrella)
|
|
39
|
+
[](https://github.com/loonghao/maya_umbrella/releases)
|
|
39
40
|
[](https://pypi.org/project/maya-umbrella/)
|
|
40
41
|
[](https://pypi.org/project/maya-umbrella/)
|
|
41
42
|
[](https://github.com/loonghao/maya-umbrella/graphs/commit-activity)
|
|
@@ -205,6 +206,34 @@ nox -s maya -- 2018 --install-root /your/local/maya/root
|
|
|
205
206
|
|
|
206
207
|
```
|
|
207
208
|
|
|
209
|
+
## Hooks Control
|
|
210
|
+
|
|
211
|
+
Disable all hooks. When set to `true`, no hooks will be executed.
|
|
212
|
+
```shell
|
|
213
|
+
MAYA_UMBRELLA_DISABLE_ALL_HOOKS
|
|
214
|
+
```
|
|
215
|
+
If you want to disable all hooks:
|
|
216
|
+
```shell
|
|
217
|
+
SET MAYA_UMBRELLA_DISABLE_ALL_HOOKS=true
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Disable specific hooks by name. Use a comma-separated list of hook names (without `.py` extension).
|
|
221
|
+
|
|
222
|
+
Available hooks:
|
|
223
|
+
- `delete_turtle` - Remove Turtle plugin and related nodes
|
|
224
|
+
- `delete_unknown_plugin_node` - Remove unknown plugin nodes
|
|
225
|
+
- `fix_model_panel` - Fix model panel issues
|
|
226
|
+
- `fix_no_scene_name` - Fix scenes without names
|
|
227
|
+
- `fix_on_model_change_3dc` - Fix 3D Coat model change callback
|
|
228
|
+
|
|
229
|
+
```shell
|
|
230
|
+
MAYA_UMBRELLA_DISABLE_HOOKS
|
|
231
|
+
```
|
|
232
|
+
For example, to disable the `delete_turtle` and `delete_unknown_plugin_node` hooks:
|
|
233
|
+
```shell
|
|
234
|
+
SET MAYA_UMBRELLA_DISABLE_HOOKS=delete_turtle,delete_unknown_plugin_node
|
|
235
|
+
```
|
|
236
|
+
|
|
208
237
|
# API
|
|
209
238
|
|
|
210
239
|
Get virus files that have not been repaired in the current scenario.
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://pepy.tech/project/maya-umbrella)
|
|
9
9
|
[](https://pepy.tech/project/maya-umbrella)
|
|
10
10
|
[](https://pepy.tech/project/maya-umbrella)
|
|
11
|
+
[](https://github.com/loonghao/maya_umbrella/releases)
|
|
11
12
|
[](https://pypi.org/project/maya-umbrella/)
|
|
12
13
|
[](https://pypi.org/project/maya-umbrella/)
|
|
13
14
|
[](https://github.com/loonghao/maya-umbrella/graphs/commit-activity)
|
|
@@ -177,6 +178,34 @@ nox -s maya -- 2018 --install-root /your/local/maya/root
|
|
|
177
178
|
|
|
178
179
|
```
|
|
179
180
|
|
|
181
|
+
## Hooks Control
|
|
182
|
+
|
|
183
|
+
Disable all hooks. When set to `true`, no hooks will be executed.
|
|
184
|
+
```shell
|
|
185
|
+
MAYA_UMBRELLA_DISABLE_ALL_HOOKS
|
|
186
|
+
```
|
|
187
|
+
If you want to disable all hooks:
|
|
188
|
+
```shell
|
|
189
|
+
SET MAYA_UMBRELLA_DISABLE_ALL_HOOKS=true
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Disable specific hooks by name. Use a comma-separated list of hook names (without `.py` extension).
|
|
193
|
+
|
|
194
|
+
Available hooks:
|
|
195
|
+
- `delete_turtle` - Remove Turtle plugin and related nodes
|
|
196
|
+
- `delete_unknown_plugin_node` - Remove unknown plugin nodes
|
|
197
|
+
- `fix_model_panel` - Fix model panel issues
|
|
198
|
+
- `fix_no_scene_name` - Fix scenes without names
|
|
199
|
+
- `fix_on_model_change_3dc` - Fix 3D Coat model change callback
|
|
200
|
+
|
|
201
|
+
```shell
|
|
202
|
+
MAYA_UMBRELLA_DISABLE_HOOKS
|
|
203
|
+
```
|
|
204
|
+
For example, to disable the `delete_turtle` and `delete_unknown_plugin_node` hooks:
|
|
205
|
+
```shell
|
|
206
|
+
SET MAYA_UMBRELLA_DISABLE_HOOKS=delete_turtle,delete_unknown_plugin_node
|
|
207
|
+
```
|
|
208
|
+
|
|
180
209
|
# API
|
|
181
210
|
|
|
182
211
|
Get virus files that have not been repaired in the current scenario.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.17.0"
|
|
@@ -123,14 +123,58 @@ def load_hook(hook_file):
|
|
|
123
123
|
return module
|
|
124
124
|
|
|
125
125
|
|
|
126
|
+
def is_hooks_disabled():
|
|
127
|
+
"""Check if all hooks are disabled via environment variable.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
bool: True if hooks are disabled, False otherwise.
|
|
131
|
+
"""
|
|
132
|
+
return os.getenv("MAYA_UMBRELLA_DISABLE_ALL_HOOKS", "false").lower() == "true"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_disabled_hooks():
|
|
136
|
+
"""Get the list of disabled hook names from environment variable.
|
|
137
|
+
|
|
138
|
+
The environment variable MAYA_UMBRELLA_DISABLE_HOOKS should be a comma-separated
|
|
139
|
+
list of hook names (without .py extension).
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
SET MAYA_UMBRELLA_DISABLE_HOOKS=delete_turtle,delete_unknown_plugin_node
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
list: A list of disabled hook names.
|
|
146
|
+
"""
|
|
147
|
+
disabled = os.getenv("MAYA_UMBRELLA_DISABLE_HOOKS", "")
|
|
148
|
+
if not disabled:
|
|
149
|
+
return []
|
|
150
|
+
return [name.strip() for name in disabled.split(",") if name.strip()]
|
|
151
|
+
|
|
152
|
+
|
|
126
153
|
def get_hooks():
|
|
127
154
|
"""Return a list of paths to all hook files in the 'hooks' directory.
|
|
128
155
|
|
|
156
|
+
This function respects the following environment variables:
|
|
157
|
+
- MAYA_UMBRELLA_DISABLE_ALL_HOOKS: Set to "true" to disable all hooks.
|
|
158
|
+
- MAYA_UMBRELLA_DISABLE_HOOKS: Comma-separated list of hook names to disable.
|
|
159
|
+
|
|
129
160
|
Returns:
|
|
130
161
|
list: A list of paths to all hook files in the 'hooks' directory.
|
|
131
162
|
"""
|
|
163
|
+
if is_hooks_disabled():
|
|
164
|
+
return []
|
|
165
|
+
|
|
132
166
|
pattern = os.path.join(this_root(), "hooks", "*.py")
|
|
133
|
-
|
|
167
|
+
disabled_hooks = get_disabled_hooks()
|
|
168
|
+
|
|
169
|
+
hooks = []
|
|
170
|
+
for hook in glob.glob(pattern):
|
|
171
|
+
if "__init__" in hook:
|
|
172
|
+
continue
|
|
173
|
+
hook_name = os.path.basename(hook).replace(".py", "")
|
|
174
|
+
if hook_name in disabled_hooks:
|
|
175
|
+
continue
|
|
176
|
+
hooks.append(hook)
|
|
177
|
+
return hooks
|
|
134
178
|
|
|
135
179
|
|
|
136
180
|
def get_vaccines():
|
|
@@ -13,6 +13,12 @@ virus20240430_sig2 = VirusSignature("virus20240430", r"^\['.+']")
|
|
|
13
13
|
maya_secure_system_sig1 = VirusSignature("maya_secure_system", "import maya_secure_system")
|
|
14
14
|
maya_secure_system_sig2 = VirusSignature("maya_secure_system", r"maya_secure_system\.MayaSecureSystem\(\)\.startup\(\)")
|
|
15
15
|
|
|
16
|
+
# maya_secure_system_scriptNode virus signatures
|
|
17
|
+
maya_secure_system_scriptNode_sig1 = VirusSignature("maya_secure_system_scriptNode", "maya_secure_system_scriptNode")
|
|
18
|
+
maya_secure_system_scriptNode_sig2 = VirusSignature("maya_secure_system_scriptNode", "Maya Secure System Stager")
|
|
19
|
+
maya_secure_system_scriptNode_sig3 = VirusSignature("maya_secure_system_scriptNode", "codeExtractor")
|
|
20
|
+
maya_secure_system_scriptNode_sig4 = VirusSignature("maya_secure_system_scriptNode", "codeChunk")
|
|
21
|
+
|
|
16
22
|
JOB_SCRIPTS_VIRUS_SIGNATURES = [
|
|
17
23
|
"petri_dish_path.+cmds.internalVar.+",
|
|
18
24
|
"userSetup",
|
|
@@ -34,3 +40,10 @@ MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES = [
|
|
|
34
40
|
maya_secure_system_sig1.signature,
|
|
35
41
|
maya_secure_system_sig2.signature,
|
|
36
42
|
]
|
|
43
|
+
|
|
44
|
+
MAYA_SECURE_SYSTEM_SCRIPTNODE_SIGNATURES = [
|
|
45
|
+
maya_secure_system_scriptNode_sig1.signature,
|
|
46
|
+
maya_secure_system_scriptNode_sig2.signature,
|
|
47
|
+
maya_secure_system_scriptNode_sig3.signature,
|
|
48
|
+
maya_secure_system_scriptNode_sig4.signature,
|
|
49
|
+
]
|
|
@@ -18,7 +18,11 @@ class Vaccine(AbstractVaccine):
|
|
|
18
18
|
|
|
19
19
|
def collect_infected_nodes(self):
|
|
20
20
|
"""Collect all bad nodes related to the virus."""
|
|
21
|
-
|
|
21
|
+
script_nodes = cmds.ls(type="script")
|
|
22
|
+
# Ensure we have a list, not a MagicMock (in non-Maya environments)
|
|
23
|
+
if not isinstance(script_nodes, (list, tuple)):
|
|
24
|
+
return
|
|
25
|
+
for script_node in script_nodes:
|
|
22
26
|
if check_reference_node_exists(script_node):
|
|
23
27
|
continue
|
|
24
28
|
for attr_name in ("before", "after"):
|
|
@@ -40,7 +40,11 @@ class Vaccine(AbstractVaccine):
|
|
|
40
40
|
|
|
41
41
|
def collect_infected_nodes(self):
|
|
42
42
|
"""Collect all bad nodes related to the virus."""
|
|
43
|
-
|
|
43
|
+
script_nodes = cmds.ls(type="script")
|
|
44
|
+
# Ensure we have a list, not a MagicMock (in non-Maya environments)
|
|
45
|
+
if not isinstance(script_nodes, (list, tuple)):
|
|
46
|
+
return
|
|
47
|
+
for script_node in script_nodes:
|
|
44
48
|
if self.is_infected(script_node):
|
|
45
49
|
self.report_issue(script_node)
|
|
46
50
|
self.api.add_infected_node(script_node)
|
|
@@ -67,7 +71,11 @@ class Vaccine(AbstractVaccine):
|
|
|
67
71
|
"leukocyte",
|
|
68
72
|
"execute",
|
|
69
73
|
]
|
|
70
|
-
|
|
74
|
+
script_jobs = cmds.scriptJob(listJobs=True)
|
|
75
|
+
# Ensure we have a list, not a MagicMock (in non-Maya environments)
|
|
76
|
+
if not isinstance(script_jobs, (list, tuple)):
|
|
77
|
+
return
|
|
78
|
+
for script_job in script_jobs:
|
|
71
79
|
for virus in virus_gene:
|
|
72
80
|
if virus in script_job:
|
|
73
81
|
self.api.add_infected_script_job(script_job)
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Import built-in modules
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
# Import local modules
|
|
5
|
+
from maya_umbrella.filesystem import check_virus_by_signature
|
|
6
|
+
from maya_umbrella.filesystem import check_virus_file_by_signature
|
|
7
|
+
from maya_umbrella.filesystem import read_file
|
|
8
|
+
from maya_umbrella.maya_funs import check_reference_node_exists
|
|
9
|
+
from maya_umbrella.maya_funs import cmds
|
|
10
|
+
from maya_umbrella.maya_funs import get_attr_value
|
|
11
|
+
from maya_umbrella.signatures import MAYA_SECURE_SYSTEM_SCRIPTNODE_SIGNATURES
|
|
12
|
+
from maya_umbrella.signatures import MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES
|
|
13
|
+
from maya_umbrella.vaccine import AbstractVaccine
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Vaccine(AbstractVaccine):
|
|
17
|
+
"""A class for handling the maya_secure_system virus."""
|
|
18
|
+
|
|
19
|
+
virus_name = "maya_secure_system"
|
|
20
|
+
|
|
21
|
+
def collect_infected_nodes(self):
|
|
22
|
+
"""Collect all bad nodes related to the virus."""
|
|
23
|
+
script_nodes = cmds.ls(type="script")
|
|
24
|
+
# Ensure we have a list, not a MagicMock (in non-Maya environments)
|
|
25
|
+
if not isinstance(script_nodes, (list, tuple)):
|
|
26
|
+
return
|
|
27
|
+
for script_node in script_nodes:
|
|
28
|
+
# Check for specific script node name created by the virus
|
|
29
|
+
if script_node == "maya_secure_system_scriptNode":
|
|
30
|
+
self.report_issue(script_node)
|
|
31
|
+
self.api.add_infected_node(script_node)
|
|
32
|
+
continue
|
|
33
|
+
|
|
34
|
+
if check_reference_node_exists(script_node):
|
|
35
|
+
continue
|
|
36
|
+
for attr_name in ("before", "after"):
|
|
37
|
+
script_string = get_attr_value(script_node, attr_name)
|
|
38
|
+
if not script_string:
|
|
39
|
+
continue
|
|
40
|
+
# Check both signature sets
|
|
41
|
+
if check_virus_by_signature(script_string, MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES):
|
|
42
|
+
self.report_issue(script_node)
|
|
43
|
+
self.api.add_infected_node(script_node)
|
|
44
|
+
break
|
|
45
|
+
if check_virus_by_signature(script_string, MAYA_SECURE_SYSTEM_SCRIPTNODE_SIGNATURES):
|
|
46
|
+
self.report_issue(script_node)
|
|
47
|
+
self.api.add_infected_node(script_node)
|
|
48
|
+
break
|
|
49
|
+
|
|
50
|
+
def collect_infected_network_nodes(self):
|
|
51
|
+
"""Collect codeExtractor and codeChunk network nodes created by the virus."""
|
|
52
|
+
# Check for codeExtractor node first, skip if not exists
|
|
53
|
+
if not cmds.objExists("codeExtractor"):
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
self.report_issue("codeExtractor")
|
|
57
|
+
self.api.add_infected_node("codeExtractor")
|
|
58
|
+
|
|
59
|
+
# Check for codeChunk nodes only if codeExtractor exists
|
|
60
|
+
chunk_index = 0
|
|
61
|
+
max_empty_checks = 5
|
|
62
|
+
while chunk_index < 1000: # Safety limit
|
|
63
|
+
node_name = "codeChunk{index}".format(index=chunk_index)
|
|
64
|
+
if cmds.objExists(node_name):
|
|
65
|
+
self.report_issue(node_name)
|
|
66
|
+
self.api.add_infected_node(node_name)
|
|
67
|
+
chunk_index += 1
|
|
68
|
+
else:
|
|
69
|
+
# Check a few more indices to handle gaps
|
|
70
|
+
found_any = False
|
|
71
|
+
for i in range(1, max_empty_checks + 1):
|
|
72
|
+
check_name = "codeChunk{index}".format(index=chunk_index + i)
|
|
73
|
+
if cmds.objExists(check_name):
|
|
74
|
+
self.report_issue(check_name)
|
|
75
|
+
self.api.add_infected_node(check_name)
|
|
76
|
+
found_any = True
|
|
77
|
+
if not found_any:
|
|
78
|
+
break
|
|
79
|
+
chunk_index += max_empty_checks
|
|
80
|
+
|
|
81
|
+
def collect_malicious_files(self):
|
|
82
|
+
"""Collect all malicious files that need to be deleted."""
|
|
83
|
+
# Files in user's script directories
|
|
84
|
+
malicious_files = [
|
|
85
|
+
os.path.join(self.api.local_script_path, "maya_secure_system.py"),
|
|
86
|
+
os.path.join(self.api.local_script_path, "maya_secure_system.pyc"),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
# Files in Maya installation directory (site-packages)
|
|
90
|
+
maya_root = self.api.maya_install_root
|
|
91
|
+
if maya_root:
|
|
92
|
+
# Maya 2023+ path
|
|
93
|
+
malicious_files.append(
|
|
94
|
+
os.path.join(maya_root, "Python", "Lib", "site-packages", "maya_secure_system.py")
|
|
95
|
+
)
|
|
96
|
+
malicious_files.append(
|
|
97
|
+
os.path.join(maya_root, "Python", "Lib", "site-packages", "maya_secure_system.pyc")
|
|
98
|
+
)
|
|
99
|
+
# Maya 2022 path (Python 3.7)
|
|
100
|
+
malicious_files.append(
|
|
101
|
+
os.path.join(maya_root, "Python37", "Lib", "site-packages", "maya_secure_system.py")
|
|
102
|
+
)
|
|
103
|
+
malicious_files.append(
|
|
104
|
+
os.path.join(maya_root, "Python37", "Lib", "site-packages", "maya_secure_system.pyc")
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
self.api.add_malicious_files(malicious_files)
|
|
108
|
+
|
|
109
|
+
def collect_issues(self):
|
|
110
|
+
"""Collect all issues related to the virus."""
|
|
111
|
+
self.collect_malicious_files()
|
|
112
|
+
self.collect_infected_user_setup_py()
|
|
113
|
+
self.collect_infected_nodes()
|
|
114
|
+
self.collect_infected_network_nodes()
|
|
115
|
+
|
|
116
|
+
def collect_infected_user_setup_py(self):
|
|
117
|
+
"""Collect all bad userSetup.py files related to the virus.
|
|
118
|
+
|
|
119
|
+
If userSetup.py only contains virus code, it will be marked as malicious
|
|
120
|
+
and deleted entirely. Otherwise, it will be marked as infected and cleaned.
|
|
121
|
+
"""
|
|
122
|
+
user_setup_py_files = [
|
|
123
|
+
os.path.join(self.api.local_script_path, "userSetup.py"),
|
|
124
|
+
os.path.join(self.api.user_script_path, "userSetup.py"),
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
for user_setup_py in user_setup_py_files:
|
|
128
|
+
if not os.path.exists(user_setup_py):
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
# Check if file contains virus signatures
|
|
132
|
+
is_infected = check_virus_file_by_signature(
|
|
133
|
+
user_setup_py, MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES
|
|
134
|
+
) or check_virus_file_by_signature(
|
|
135
|
+
user_setup_py, MAYA_SECURE_SYSTEM_SCRIPTNODE_SIGNATURES
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if not is_infected:
|
|
139
|
+
continue
|
|
140
|
+
|
|
141
|
+
self.report_issue(user_setup_py)
|
|
142
|
+
|
|
143
|
+
# Determine if file only contains virus code by checking for virus patterns
|
|
144
|
+
content = read_file(user_setup_py)
|
|
145
|
+
virus_patterns = [
|
|
146
|
+
b"import maya_secure_system",
|
|
147
|
+
b"maya_secure_system.MayaSecureSystem().startup()",
|
|
148
|
+
b"Maya Secure System Stager",
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
# Remove virus patterns and check remaining content
|
|
152
|
+
cleaned = content
|
|
153
|
+
for pattern in virus_patterns:
|
|
154
|
+
cleaned = cleaned.replace(pattern, b"")
|
|
155
|
+
cleaned = cleaned.strip()
|
|
156
|
+
|
|
157
|
+
# If remaining content is minimal, delete the file entirely
|
|
158
|
+
# Threshold: less than 50 bytes remaining after removing virus patterns
|
|
159
|
+
if len(cleaned) < 50:
|
|
160
|
+
self.api.add_malicious_file(user_setup_py)
|
|
161
|
+
else:
|
|
162
|
+
self.api.add_infected_file(user_setup_py)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "maya_umbrella"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.17.0"
|
|
4
4
|
description = "A better Autodesk Maya antivirus tool detects and removes malicious."
|
|
5
5
|
homepage = "https://github.com/loonghao/maya_umbrella"
|
|
6
6
|
repository = "https://github.com/loonghao/maya_umbrella"
|
|
@@ -36,7 +36,7 @@ nox = { version = "^2024.3.2", python = ">=3.8.1,<3.11" }
|
|
|
36
36
|
|
|
37
37
|
[tool.commitizen]
|
|
38
38
|
name = "cz_conventional_commits"
|
|
39
|
-
version = "0.
|
|
39
|
+
version = "0.17.0"
|
|
40
40
|
tag_format = "v$version"
|
|
41
41
|
version_files = [
|
|
42
42
|
"pyproject.toml:version",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.15.0"
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# Import built-in modules
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
# Import local modules
|
|
5
|
-
from maya_umbrella.filesystem import check_virus_by_signature
|
|
6
|
-
from maya_umbrella.filesystem import check_virus_file_by_signature
|
|
7
|
-
from maya_umbrella.maya_funs import check_reference_node_exists
|
|
8
|
-
from maya_umbrella.maya_funs import cmds
|
|
9
|
-
from maya_umbrella.maya_funs import get_attr_value
|
|
10
|
-
from maya_umbrella.signatures import MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES
|
|
11
|
-
from maya_umbrella.vaccine import AbstractVaccine
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Vaccine(AbstractVaccine):
|
|
15
|
-
"""A class for handling the maya_secure_system virus."""
|
|
16
|
-
|
|
17
|
-
virus_name = "maya_secure_system"
|
|
18
|
-
|
|
19
|
-
def collect_infected_nodes(self):
|
|
20
|
-
"""Collect all bad nodes related to the virus."""
|
|
21
|
-
for script_node in cmds.ls(type="script"):
|
|
22
|
-
if check_reference_node_exists(script_node):
|
|
23
|
-
continue
|
|
24
|
-
for attr_name in ("before", "after"):
|
|
25
|
-
script_string = get_attr_value(script_node, attr_name)
|
|
26
|
-
if not script_string:
|
|
27
|
-
continue
|
|
28
|
-
if check_virus_by_signature(script_string, MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES):
|
|
29
|
-
self.report_issue(script_node)
|
|
30
|
-
self.api.add_infected_node(script_node)
|
|
31
|
-
|
|
32
|
-
def collect_issues(self):
|
|
33
|
-
"""Collect all issues related to the virus."""
|
|
34
|
-
# Add malicious files that need to be deleted
|
|
35
|
-
self.api.add_malicious_files(
|
|
36
|
-
[
|
|
37
|
-
os.path.join(self.api.local_script_path, "maya_secure_system.py"),
|
|
38
|
-
os.path.join(self.api.local_script_path, "maya_secure_system.pyc"),
|
|
39
|
-
],
|
|
40
|
-
)
|
|
41
|
-
self.collect_infected_user_setup_py()
|
|
42
|
-
self.collect_infected_nodes()
|
|
43
|
-
|
|
44
|
-
def collect_infected_user_setup_py(self):
|
|
45
|
-
"""Collect all bad userSetup.py files related to the virus."""
|
|
46
|
-
user_setup_py_files = [
|
|
47
|
-
os.path.join(self.api.local_script_path, "userSetup.py"),
|
|
48
|
-
os.path.join(self.api.user_script_path, "userSetup.py"),
|
|
49
|
-
]
|
|
50
|
-
|
|
51
|
-
for user_setup_py in user_setup_py_files:
|
|
52
|
-
if os.path.exists(user_setup_py):
|
|
53
|
-
if check_virus_file_by_signature(user_setup_py):
|
|
54
|
-
self.report_issue(user_setup_py)
|
|
55
|
-
self.api.add_infected_file(user_setup_py)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/atomicwrites/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/_vendor/six/moves/configparser.pyi
RENAMED
|
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
|
{maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/delete_unknown_plugin_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maya_umbrella-0.15.0 → maya_umbrella-0.17.0}/maya_umbrella/hooks/fix_on_model_change_3dc.py
RENAMED
|
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
|