maya-umbrella 0.16.0__py2.py3-none-any.whl → 0.17.0__py2.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.
@@ -1 +1 @@
1
- __version__ = "0.16.0"
1
+ __version__ = "0.17.0"
@@ -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
- for script_node in cmds.ls(type="script"):
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
- for script_node in cmds.ls(type="script"):
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
- for script_job in cmds.scriptJob(listJobs=True):
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)
@@ -4,9 +4,11 @@ import os
4
4
  # Import local modules
5
5
  from maya_umbrella.filesystem import check_virus_by_signature
6
6
  from maya_umbrella.filesystem import check_virus_file_by_signature
7
+ from maya_umbrella.filesystem import read_file
7
8
  from maya_umbrella.maya_funs import check_reference_node_exists
8
9
  from maya_umbrella.maya_funs import cmds
9
10
  from maya_umbrella.maya_funs import get_attr_value
11
+ from maya_umbrella.signatures import MAYA_SECURE_SYSTEM_SCRIPTNODE_SIGNATURES
10
12
  from maya_umbrella.signatures import MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES
11
13
  from maya_umbrella.vaccine import AbstractVaccine
12
14
 
@@ -18,38 +20,143 @@ class Vaccine(AbstractVaccine):
18
20
 
19
21
  def collect_infected_nodes(self):
20
22
  """Collect all bad nodes related to the virus."""
21
- for script_node in cmds.ls(type="script"):
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
+
22
34
  if check_reference_node_exists(script_node):
23
35
  continue
24
36
  for attr_name in ("before", "after"):
25
37
  script_string = get_attr_value(script_node, attr_name)
26
38
  if not script_string:
27
39
  continue
40
+ # Check both signature sets
28
41
  if check_virus_by_signature(script_string, MAYA_SECURE_SYSTEM_VIRUS_SIGNATURES):
29
42
  self.report_issue(script_node)
30
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)
31
108
 
32
109
  def collect_issues(self):
33
110
  """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
- )
111
+ self.collect_malicious_files()
41
112
  self.collect_infected_user_setup_py()
42
113
  self.collect_infected_nodes()
114
+ self.collect_infected_network_nodes()
43
115
 
44
116
  def collect_infected_user_setup_py(self):
45
- """Collect all bad userSetup.py files related to the virus."""
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
+ """
46
122
  user_setup_py_files = [
47
123
  os.path.join(self.api.local_script_path, "userSetup.py"),
48
124
  os.path.join(self.api.user_script_path, "userSetup.py"),
49
125
  ]
50
126
 
51
127
  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)
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
  Metadata-Version: 2.4
2
2
  Name: maya_umbrella
3
- Version: 0.16.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
@@ -1,5 +1,5 @@
1
1
  maya_umbrella/__init__.py,sha256=rcCnFWmELeJsGoKvLHyzC_GmZu-eT1QXjQCHRGj6HuQ,529
2
- maya_umbrella/__version__.py,sha256=3Msc5baw88UJubVj5AVFB8tExkT2OFIsNWe2leaoHhc,23
2
+ maya_umbrella/__version__.py,sha256=XpM3lncCzPBIwMSvDN7i10pke_c6KdJtVLZYbCiaTRw,23
3
3
  maya_umbrella/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  maya_umbrella/_vendor/atomicwrites/LICENSE,sha256=h4Mp8L2HitAVEpzovagvSB6G7C6Agx6QnA1nFx2SLnM,1069
5
5
  maya_umbrella/_vendor/atomicwrites/__init__.py,sha256=myvxvKRBb7vebPTSUiAopsRrvsm6VojiAvET1xohT-4,6970
@@ -27,14 +27,14 @@ maya_umbrella/locales/zh_CN.json,sha256=eQbsZsUj87B5HhHi_usTNGzwo01MLjkHKM11KWhh
27
27
  maya_umbrella/log.py,sha256=SLgBPpnDpkDhOU94UHNPqanhKr6aZiJn4XdwIsoXD4M,1355
28
28
  maya_umbrella/maya_funs.py,sha256=_4LaMO4cRTCcbgNj2ei7UtSLAnCRY_ylHiLGKgvM4sE,3652
29
29
  maya_umbrella/scanner.py,sha256=1-GY-Jx1iECnAo-L2Lw5e5t5zaQsMwWDH0A4TOjlIww,4428
30
- maya_umbrella/signatures.py,sha256=FkQ5VpiP7tTrF0K7H6sFVe_E3RB9uImZGPldxyRpegk,1148
30
+ maya_umbrella/signatures.py,sha256=tQjBMTMS-fWiKJ8smjGbJLQRb39C-ATuYMFzCz9P144,1878
31
31
  maya_umbrella/vaccine.py,sha256=aBW6pdT4tD4OMBPZ-d3E4_n16Rylz-2gb7JWzMZVPK0,1022
32
32
  maya_umbrella/vaccines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  maya_umbrella/vaccines/vaccine1.py,sha256=WLo1uJElTLSjVCf5CBtRNU4HKs63my5mkHiGqTfnNEE,489
34
- maya_umbrella/vaccines/vaccine2.py,sha256=qYiI_-BSojgN7j4esYCGBDLeyBSneDOGUwZhKHccxh8,2170
35
- maya_umbrella/vaccines/vaccine3.py,sha256=vcjGt0jZxBDb7iCUMmBWBQGPZD3BFH96gL6pPxNwDr0,3676
36
- maya_umbrella/vaccines/vaccine4.py,sha256=IftMSf9CM6NJ9FmTXeRTYQ3qiYVrRSzJxMyHDdE2tQc,2272
37
- maya_umbrella-0.16.0.dist-info/METADATA,sha256=SUh-TwBxhm_2qBT31CjGKOIKhnntvG4erDd5hpu1gNg,14128
38
- maya_umbrella-0.16.0.dist-info/WHEEL,sha256=MICUlqIgkuEnKh9OWy254Ca7q2MHOW-q0u36TZR60nU,92
39
- maya_umbrella-0.16.0.dist-info/licenses/LICENSE,sha256=tJf0Pz8q_65AjEkm3872K1cl4jGil28vJO5Ko_LhUqc,1060
40
- maya_umbrella-0.16.0.dist-info/RECORD,,
34
+ maya_umbrella/vaccines/vaccine2.py,sha256=wZNfxdHiqnx6cmDHCjdzp5zqqqUbE0mQVHHOjBIUyug,2357
35
+ maya_umbrella/vaccines/vaccine3.py,sha256=U-Sik0t4PCKHsXn4T4SUOlPHaM3pDJqfq8EAArPVznA,4047
36
+ maya_umbrella/vaccines/vaccine4.py,sha256=fFFikRn4TCphiuC9yJCVNOd7HWJP-eUtpykH-Gs1dM4,6833
37
+ maya_umbrella-0.17.0.dist-info/METADATA,sha256=umDhmFAwxRJIx7qahWMVzesmjg1TX41sQq963vslojA,14128
38
+ maya_umbrella-0.17.0.dist-info/WHEEL,sha256=1-QUqDxcpG1saiflGXqu9XhixW9lXrgRMoc4ROvffFU,92
39
+ maya_umbrella-0.17.0.dist-info/licenses/LICENSE,sha256=tJf0Pz8q_65AjEkm3872K1cl4jGil28vJO5Ko_LhUqc,1060
40
+ maya_umbrella-0.17.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.1
2
+ Generator: poetry-core 2.3.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2.py3-none-any