CAPE-parsers 0.1.47__py3-none-any.whl → 0.1.49__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,213 @@
1
+ import base64
2
+ import yara
3
+ import pefile
4
+ import json
5
+ import struct
6
+ import re
7
+
8
+
9
+ RULE_SOURCE_KEY = """
10
+ rule Amadey_Key_String
11
+ {
12
+ meta:
13
+ author = "YungBinary"
14
+ description = "Find decryption key in Amadey."
15
+ strings:
16
+ $chunk_1 = {
17
+ 6A 20
18
+ 68 ?? ?? ?? ??
19
+ B9 ?? ?? ?? ??
20
+ E8 ?? ?? ?? ??
21
+ 68 ?? ?? ?? ??
22
+ E8 ?? ?? ?? ??
23
+ 59
24
+ C3
25
+ }
26
+ condition:
27
+ $chunk_1
28
+ }
29
+ """
30
+
31
+ RULE_SOURCE_ENCODED_STRINGS = """
32
+ rule Amadey_Encoded_Strings
33
+ {
34
+ meta:
35
+ author = "YungBinary"
36
+ description = "Find encoded strings in Amadey."
37
+ strings:
38
+ $chunk_1 = {
39
+ 6A ??
40
+ 68 ?? ?? ?? ??
41
+ B9 ?? ?? ?? ??
42
+ E8 ?? ?? ?? ??
43
+ 68 ?? ?? ?? ??
44
+ E8 ?? ?? ?? ??
45
+ 59
46
+ C3
47
+ }
48
+ condition:
49
+ $chunk_1
50
+ }
51
+ """
52
+
53
+
54
+ def contains_non_printable(byte_array):
55
+ for byte in byte_array:
56
+ if not chr(byte).isprintable():
57
+ return True
58
+ return False
59
+
60
+
61
+ def yara_scan_generator(raw_data, rule_source):
62
+ yara_rules = yara.compile(source=rule_source)
63
+ matches = yara_rules.match(data=raw_data)
64
+
65
+ for match in matches:
66
+ for block in match.strings:
67
+ for instance in block.instances:
68
+ yield instance.offset, block.identifier
69
+
70
+
71
+ def get_keys(pe, data):
72
+ image_base = pe.OPTIONAL_HEADER.ImageBase
73
+ keys = []
74
+ for offset, _ in yara_scan_generator(data, RULE_SOURCE_KEY):
75
+ try:
76
+ key_string_rva = struct.unpack('i', data[offset + 3 : offset + 7])[0]
77
+ key_string_dword_offset = pe.get_offset_from_rva(key_string_rva - image_base)
78
+ key_string = pe.get_string_from_data(key_string_dword_offset, data)
79
+
80
+ if b"=" not in key_string:
81
+ keys.append(key_string.decode())
82
+
83
+ if len(keys) == 2:
84
+ return keys
85
+
86
+ except Exception:
87
+ continue
88
+
89
+ return []
90
+
91
+
92
+ def get_encoded_strings(pe, data):
93
+ encoded_strings = []
94
+ image_base = pe.OPTIONAL_HEADER.ImageBase
95
+ for offset, _ in yara_scan_generator(data, RULE_SOURCE_ENCODED_STRINGS):
96
+
97
+ try:
98
+ encoded_string_size = data[offset + 1]
99
+ encoded_string_rva = struct.unpack('i', data[offset + 3 : offset + 7])[0]
100
+ encoded_string_dword_offset = pe.get_offset_from_rva(encoded_string_rva - image_base)
101
+ encoded_string = pe.get_string_from_data(encoded_string_dword_offset, data)
102
+
103
+ # Make sure the string matches length from operand
104
+ if encoded_string_size != len(encoded_string):
105
+ continue
106
+
107
+ encoded_strings.append(encoded_string.decode())
108
+
109
+ except Exception:
110
+ continue
111
+
112
+ return encoded_strings
113
+
114
+
115
+ def decode_amadey_string(key: str, encoded_str: str) -> bytes:
116
+ """
117
+ Decode Amadey encoded strings that look like base64
118
+ """
119
+ alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "
120
+
121
+ decoded = ""
122
+ for i in range(len(encoded_str)):
123
+ if encoded_str[i] == "=":
124
+ decoded += "="
125
+ continue
126
+
127
+ index_1 = alphabet.index(encoded_str[i % len(encoded_str)])
128
+ index_2 = alphabet.index(key[i % len(key)])
129
+
130
+ index_result = (index_1 + (0x3F - index_2) + 0x3F) % 0x3F
131
+
132
+ decoded += alphabet[index_result]
133
+
134
+ decoded = base64.b64decode(decoded)
135
+
136
+ return decoded
137
+
138
+
139
+ def find_campaign_id(data):
140
+ pattern = br'\x00\x00\x00([0-9a-f]{6})\x00\x00'
141
+ matches = re.findall(pattern, data)
142
+ if matches:
143
+ return matches[0]
144
+
145
+
146
+ def extract_config(data):
147
+ pe = pefile.PE(data=data, fast_load=True)
148
+ # image_base = pe.OPTIONAL_HEADER.ImageBase
149
+
150
+ keys = get_keys(pe, data)
151
+ if not keys:
152
+ return {}
153
+
154
+ decode_key = keys[0]
155
+ rc4_key = keys[1]
156
+ encoded_strings = get_encoded_strings(pe, data)
157
+
158
+ decoded_strings = []
159
+ for encoded_string in encoded_strings:
160
+ try:
161
+ decoded_string = decode_amadey_string(decode_key, encoded_string)
162
+ if not decoded_string or contains_non_printable(decoded_string):
163
+ continue
164
+ decoded_strings.append(decoded_string.decode())
165
+ except Exception:
166
+ continue
167
+
168
+ if not decoded_strings:
169
+ return {}
170
+
171
+ decoded_strings = decoded_strings[:10]
172
+ final_config = {}
173
+ version = ""
174
+ install_dir = ""
175
+ install_file = ""
176
+ version_pattern = r"^\d+\.\d{1,2}$"
177
+ install_dir_pattern = r"^[0-9a-f]{10}$"
178
+
179
+ for i in range(len(decoded_strings)):
180
+ s = decoded_strings[i]
181
+ if s.endswith(".php"):
182
+ c2 = decoded_strings[i-1]
183
+ final_config.setdefault("CNCs", []).append(f"http://{c2}{s}")
184
+ elif re.match(version_pattern, s):
185
+ version = s
186
+ elif re.match(install_dir_pattern, s):
187
+ install_dir = s
188
+ elif s.endswith(".exe"):
189
+ install_file = s
190
+
191
+ if version:
192
+ final_config["version"] = version
193
+ if install_dir:
194
+ final_config.setdefault("raw", {})["install_dir"] = install_dir
195
+ if install_file:
196
+ final_config.setdefault("raw", {})["install_file"] = install_file
197
+
198
+ final_config["cryptokey"] = rc4_key
199
+ final_config["cryptokey_type"] = "RC4"
200
+
201
+ campaign_id = find_campaign_id(data)
202
+ if campaign_id:
203
+ final_config["campaign_id"] = campaign_id.decode()
204
+
205
+ return final_config
206
+
207
+
208
+
209
+ if __name__ == "__main__":
210
+ import sys
211
+
212
+ with open(sys.argv[1], "rb") as f:
213
+ print(json.dumps(extract_config(f.read()), indent=4))
@@ -360,11 +360,11 @@ class cobaltstrikeConfig:
360
360
  if parsed_setting == "Not Found" and quiet:
361
361
  continue
362
362
  if not isinstance(parsed_setting, list):
363
- log.debug("{: <{width}} - {val}".format(conf_name, width=COLUMN_WIDTH - 3, val=parsed_setting))
363
+ log.debug("{: <{width}} - {val}".format(conf_name, width=COLUMN_WIDTH - 3, val=parsed_setting)) # noqa: G001
364
364
  elif parsed_setting == []:
365
- log.debug("{: <{width}} - {val}".format(conf_name, width=COLUMN_WIDTH - 3, val="Empty"))
365
+ log.debug("{: <{width}} - {val}".format(conf_name, width=COLUMN_WIDTH - 3, val="Empty")) # noqa: G001
366
366
  else:
367
- log.debug("{: <{width}} - {val}".format(conf_name, width=COLUMN_WIDTH - 3, val=parsed_setting[0]))
367
+ log.debug("{: <{width}} - {val}".format(conf_name, width=COLUMN_WIDTH - 3, val=parsed_setting[0])) # noqa: G001
368
368
  for val in parsed_setting[1:]:
369
369
  log.debug(" " * COLUMN_WIDTH, end="")
370
370
  print(val)
@@ -23,7 +23,7 @@
23
23
  import re
24
24
  import struct
25
25
  import sys
26
-
26
+ from contextlib import suppress
27
27
  import pefile
28
28
  from Cryptodome.Cipher import DES3
29
29
  from Cryptodome.Util.Padding import unpad
@@ -128,7 +128,8 @@ def decoder(data):
128
128
  else:
129
129
  x = bytearray(img)
130
130
 
131
- url_re = rb"https?:\/\/[a-zA-Z0-9\/\.:?\-_]+"
131
+ # ToDo add \.php
132
+ url_re = rb"https?:\/\/[a-zA-Z0-9\/\.:?\-_]+\.php"
132
133
  urls = re.findall(url_re, x)
133
134
  if not urls:
134
135
  for i in range(len(x)):
@@ -144,21 +145,23 @@ def decoder(data):
144
145
  confs = find_conf(img)
145
146
  if iv and iv not in (b"", -1) and confs != []:
146
147
  for conf in confs:
147
- try:
148
+ with suppress(ValueError):
148
149
  dec = DES3.new(key, DES3.MODE_CBC, iv)
149
150
  temp = dec.decrypt(conf)
150
151
  temp = unpad(temp, 8)
151
- urls.append(b"http://" + temp)
152
- except ValueError:
153
- # wrong padding
154
- pass
152
+ if not temp.endswith(b".php"):
153
+ continue
154
+ urls.append("http://" + temp.decod())
155
155
  return urls
156
156
 
157
157
 
158
158
  def extract_config(filebuf):
159
159
 
160
160
  urls = decoder(filebuf)
161
- return {"CNCs": [url.decode() for url in urls]}
161
+ if urls:
162
+ return {"CNCs": urls}
163
+ else:
164
+ return {}
162
165
 
163
166
 
164
167
  if __name__ == "__main__":
@@ -318,7 +318,7 @@ def extract_config(data):
318
318
  decoded_c2 = chacha20_xor(encrypted_string, key, nonce, counter).split(b"\x00", 1)[0]
319
319
  if contains_non_printable(decoded_c2):
320
320
  break
321
- config.setdefault("CNCs", []).append(decoded_c2.decode())
321
+ config.setdefault("CNCs", []).append("https://" + decoded_c2.decode())
322
322
  encrypted_strings_offset = encrypted_strings_offset + step_size
323
323
  counter += 2
324
324
 
@@ -351,7 +351,7 @@ def extract_config(data):
351
351
  decrypted = chacha20_xor(c2_encrypted, key, nonce, counter)
352
352
  c2 = extract_c2_domain(decrypted)
353
353
  if c2 is not None and len(c2) > 10:
354
- config["CNCs"].append(c2.decode())
354
+ config["CNCs"].append("https://" + c2.decode())
355
355
  break
356
356
 
357
357
  except Exception:
@@ -384,7 +384,7 @@ def extract_config(data):
384
384
  decoded_c2 = xor_data(encoded_c2, xor_key)
385
385
 
386
386
  if not contains_non_printable(decoded_c2):
387
- config.setdefault("CNCs", []).append(decoded_c2.decode())
387
+ config.setdefault("CNCs", []).append("https://" + decoded_c2.decode())
388
388
  except Exception as e:
389
389
  print(e)
390
390
  continue
@@ -133,7 +133,7 @@ def extract_config(data):
133
133
  try:
134
134
  dotnet_file = dnfile.dnPE(data=data)
135
135
  except Exception as e:
136
- log.debug(f"Exception when attempting to parse .NET file: {e}")
136
+ log.debug("Exception when attempting to parse .NET file: %s", str(e))
137
137
  log.debug(traceback.format_exc())
138
138
 
139
139
  # ldstr, stsfld
@@ -165,7 +165,7 @@ def extract_config(data):
165
165
  else:
166
166
  user_strings[field_name] = string_index
167
167
  except Exception as e:
168
- log.debug(f"There was an exception parsing user strings: {e}")
168
+ log.debug("There was an exception parsing user strings: %s", str(e))
169
169
  log.debug(traceback.format_exc())
170
170
 
171
171
  if c2_type is None:
@@ -1,6 +1,7 @@
1
1
  import struct
2
2
  import pefile
3
3
  import yara
4
+ import ipaddress
4
5
  from contextlib import suppress
5
6
 
6
7
 
@@ -42,6 +43,13 @@ def yara_scan(raw_data):
42
43
  yield block.identifier, instance.offset
43
44
 
44
45
 
46
+ def _is_ip(ip):
47
+ try:
48
+ ipaddress.ip_address(ip)
49
+ return True
50
+ except Exception:
51
+ return False
52
+
45
53
  def xor_data(data, key):
46
54
  decoded = bytearray()
47
55
  for i in range(len(data)):
@@ -67,6 +75,8 @@ def parse_text(data):
67
75
  for line in lines:
68
76
  if line.startswith("http") and "://" in line:
69
77
  domain = line
78
+ elif _is_ip(line):
79
+ domain = line
70
80
  if line.startswith("/") and line[-4] == ".":
71
81
  uri = line
72
82
 
@@ -0,0 +1,93 @@
1
+ import json
2
+ import struct
3
+ from contextlib import suppress
4
+ from typing import Any, Dict, Tuple
5
+
6
+ import pefile
7
+ from Cryptodome.Cipher import AES
8
+ from Cryptodome.Util.Padding import unpad
9
+
10
+
11
+ def parse_blob(data: bytes):
12
+ """
13
+ Parse the blob according to the scheme:
14
+ - 32 bytes = AES key
15
+ - Next 16 bytes = IV
16
+ - Next 2 DWORDs (8 bytes total) = XOR to get cipher data size
17
+ - Remaining bytes = cipher data of that size
18
+ """
19
+ offset = 0
20
+ aes_key = data[offset:offset + 32]
21
+ offset += 32
22
+ iv = data[offset:offset + 16]
23
+ offset += 16
24
+ dword1, dword2 = struct.unpack_from("<II", data, offset)
25
+ cipher_size = dword1 ^ dword2
26
+ offset += 8
27
+ cipher_data = data[offset:offset + cipher_size]
28
+ return aes_key, iv, cipher_data
29
+
30
+
31
+ def decrypt(data: bytes) -> Tuple[bytes, bytes, bytes]:
32
+ aes_key, iv, cipher_data = parse_blob(data)
33
+ cipher = AES.new(aes_key, AES.MODE_CBC, iv)
34
+ plaintext_padded = cipher.decrypt(cipher_data)
35
+ return aes_key, iv, unpad(plaintext_padded, AES.block_size)
36
+
37
+
38
+ def extract_config(data: bytes) -> Dict[str, Any]:
39
+ cfg: Dict[str, Any] = {}
40
+ plaintext = ""
41
+ pe = pefile.PE(data=data, fast_load=True)
42
+ try:
43
+ data_section = [s for s in pe.sections if s.Name.find(b".data") != -1][0]
44
+ except IndexError:
45
+ return cfg
46
+
47
+ if not data_section:
48
+ return cfg
49
+
50
+ data = data_section.get_data()
51
+ block_size = 4096
52
+ zeros = b"\x00" * block_size
53
+ offset = data.find(zeros)
54
+ if offset == -1:
55
+ return cfg
56
+
57
+ while offset > 0:
58
+ with suppress(Exception):
59
+ aes_key, iv, plaintext = decrypt(data[offset : offset + block_size])
60
+ if plaintext and b"conf" in plaintext:
61
+ break
62
+
63
+ offset -= 1
64
+
65
+ if plaintext:
66
+ parsed = json.loads(plaintext.decode("utf-8", errors="ignore").rstrip("\x00"))
67
+ conf = parsed.get("conf", {})
68
+ build = parsed.get("build", {})
69
+ if conf:
70
+ cfg = {
71
+ "CNCs": conf.get("hosts"),
72
+ "user_agent": conf.get("useragents"),
73
+ "version": build.get("ver"),
74
+ "build": build.get("build_id"),
75
+ "cryptokey": aes_key.hex(),
76
+ "cryptokey_type": "AES",
77
+ "raw": {
78
+ "iv": iv.hex(),
79
+ "anti_vm": conf.get("anti_vm"),
80
+ "anti_dbg": conf.get("anti_dbg"),
81
+ "self_del": conf.get("self_del"),
82
+ "run_delay": conf.get("run_delay"),
83
+ }
84
+ }
85
+
86
+ return cfg
87
+
88
+
89
+ if __name__ == "__main__":
90
+ import sys
91
+
92
+ with open(sys.argv[1], "rb") as f:
93
+ print(extract_config(f.read()))
@@ -50,7 +50,7 @@ def extract_key_data(data, pe, key_match):
50
50
  # Read arbitrary number of byes from key offset and split on null bytes to extract key
51
51
  key = data[key_offset : key_offset + 0x40].split(b"\x00")[0]
52
52
  except Exception as e:
53
- log.debug(f"There was an exception extracting the key: {e}")
53
+ log.debug("There was an exception extracting the key: %s", str(e))
54
54
  log.debug(traceback.format_exc())
55
55
  return False
56
56
  return key
@@ -70,7 +70,7 @@ def extract_config_data(data, pe, config_match):
70
70
  )
71
71
  campaign_id_ct = data[campaign_id_offset : campaign_id_offset + 0x10]
72
72
  except Exception as e:
73
- log.debug(f"There was an exception extracting the campaign id: {e}")
73
+ log.debug("There was an exception extracting the campaign id: %s", str(e))
74
74
  log.debug(traceback.format_exc())
75
75
  return False, False, False
76
76
 
@@ -84,7 +84,7 @@ def extract_config_data(data, pe, config_match):
84
84
  )
85
85
  botnet_id_ct = data[botnet_id_offset : botnet_id_offset + 0x10]
86
86
  except Exception as e:
87
- log.debug(f"There was an exception extracting the botnet id: {e}")
87
+ log.debug("There was an exception extracting the botnet id: %s", str(e))
88
88
  log.debug(traceback.format_exc())
89
89
  return False, False, False
90
90
 
@@ -99,7 +99,7 @@ def extract_config_data(data, pe, config_match):
99
99
  c2s_offset = pe.get_offset_from_rva(c2s_rva + int.from_bytes(config_match.group("c2s"), byteorder="little"))
100
100
  c2s_ct = data[c2s_offset : c2s_offset + 0x400]
101
101
  except Exception as e:
102
- log.debug(f"There was an exception extracting the C2s: {e}")
102
+ log.debug("There was an exception extracting the C2s: %s", str(e))
103
103
  log.debug(traceback.format_exc())
104
104
  return False, False, False
105
105
 
@@ -243,7 +243,7 @@ def extract_config(data):
243
243
  if c2s:
244
244
  cfg["CNCs"] = list(ARC4.new(key).decrypt(c2s).split(b"\x00")[0].decode().split(","))
245
245
  except Exception as e:
246
- log.error("This is broken: %s", str(e), exc_info=True)
246
+ log.exception("This is broken: %s", str(e))
247
247
 
248
248
  if not cfg:
249
249
  cfg = extract_2024(pe, data)
@@ -211,7 +211,7 @@ def extract_config(filebuf):
211
211
  config.setdefault("raw", {})[k] = v
212
212
 
213
213
  except Exception as e:
214
- logger.error(f"Caught an exception: {e}")
214
+ logger.error("Caught an exception: %s", str(e))
215
215
 
216
216
  return config
217
217
 
cape_parsers/__init__.py CHANGED
@@ -129,7 +129,7 @@ def load_malwareconfig_parsers() -> Tuple[bool, dict, ModuleType]:
129
129
  except ImportError:
130
130
  log.info("Missed RATDecoders -> poetry run pip install malwareconfig")
131
131
  except Exception as e:
132
- log.error(e, exc_info=True)
132
+ log.exception(e)
133
133
  return False, False, False
134
134
 
135
135
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: CAPE-parsers
3
- Version: 0.1.47
3
+ Version: 0.1.49
4
4
  Summary: CAPE: Malware Configuration Extraction
5
5
  License: MIT
6
6
  Keywords: cape,parsers,malware,configuration
@@ -1,37 +1,39 @@
1
1
  cape_parsers/CAPE/__init__.py,sha256=JcY8WPKzUFYgexwV1eyKIuT1JyNZzMJjBynlPSzxY_I,7
2
2
  cape_parsers/CAPE/community/AgentTesla.py,sha256=rHhTmINQ0bGZEiJ5NhCKPhGobcifq3FDWZItgHTpBC8,3796
3
+ cape_parsers/CAPE/community/Amadey.py,sha256=IUyt909q9IDQPPip6UW9uD16rJMD_gvkwvNZ8NHTW-k,5577
3
4
  cape_parsers/CAPE/community/Arkei.py,sha256=k36qHxdo5yPa9V1cg7EImSWP06kMog0rBda4KXqLKCY,3783
4
5
  cape_parsers/CAPE/community/AsyncRAT.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
5
6
  cape_parsers/CAPE/community/AuroraStealer.py,sha256=C0j9SZDJRi107PbfYZ9G168MCyqYItrI-XK5k0Bp4tE,2632
6
7
  cape_parsers/CAPE/community/Carbanak.py,sha256=Smi_vTWDfWxYBQa661ZIy0624IYJA22LMHAJEQbstpk,5607
7
- cape_parsers/CAPE/community/CobaltStrikeBeacon.py,sha256=Z40uxQ_OExtky7dIC372golAiuW9bR-_5TDBMBqsCo0,19427
8
+ cape_parsers/CAPE/community/CobaltStrikeBeacon.py,sha256=U4Q0ObCrPRpiO5B5fBmkgr63jXdizujNth8v6kUPnEQ,19466
8
9
  cape_parsers/CAPE/community/CobaltStrikeStager.py,sha256=HLxROBjz453uHNq1bPz0VSAhtyWDfz79ZacTPdjuWmY,7535
9
10
  cape_parsers/CAPE/community/DCRat.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
10
11
  cape_parsers/CAPE/community/Fareit.py,sha256=OyKeZdcvyAhjxZgJqkDPJHP4Npv1ArvTHJZ5F0C1Iac,1875
11
12
  cape_parsers/CAPE/community/KoiLoader.py,sha256=F2gsgCvrVuwxY1bg8rlexsjCjikAP5HIGGOqU8zhT8E,4008
12
- cape_parsers/CAPE/community/LokiBot.py,sha256=YGYfQ7Wr8PA2QW37yfoyh5cFAz2zxgOmpHOHIvy9CsM,5657
13
- cape_parsers/CAPE/community/Lumma.py,sha256=Hz72U6i2apU6N5gj5IXnZ9HkbOqKDvW1EMnIge8sNQc,12167
13
+ cape_parsers/CAPE/community/LokiBot.py,sha256=355kqLx0LNMr8XcGfPL7cxG8QZalcmE7ttVBqoWtTWE,5754
14
+ cape_parsers/CAPE/community/Lumma.py,sha256=Iqd9yvt3g0FeV_bYRmL1RKp4C1H92qeGg4fXivVDSxw,12206
14
15
  cape_parsers/CAPE/community/NanoCore.py,sha256=8QZnf1AcY9481kSfsf3SHQShwPLn97peGAf8_xEasQc,6230
15
16
  cape_parsers/CAPE/community/Nighthawk.py,sha256=8ss8yvslrwUt53zV6U0xuwGKU3hgYfOt13S5lkOVpNo,12105
16
17
  cape_parsers/CAPE/community/Njrat.py,sha256=GiwSENBB43RUqyJ7zT7ZPkPUYqo8Ew4kd5MJUj0jzdc,4702
17
18
  cape_parsers/CAPE/community/PhemedroneStealer.py,sha256=Z7_PdxC8bmd6P3AqOm7AHVRrbEVuREwMWbyLVHaAhK0,7095
18
19
  cape_parsers/CAPE/community/QuasarRAT.py,sha256=dzVInOc-BPVRdArk92oEY4PKq1AEW04NUToL8UV-UGk,146
19
20
  cape_parsers/CAPE/community/README.md,sha256=SHgVQraCdp033IQjM4Cm6t70U4kULn1MfSwTq3rsZv8,22
20
- cape_parsers/CAPE/community/Snake.py,sha256=-x3Bfhs2HAuxNakUnAX1mm-mgtarJkD9U_fucmVY3u4,6638
21
+ cape_parsers/CAPE/community/Snake.py,sha256=v_MAPmg86ZdgGOkzc9GVHbi-lu4nLa1_0Lp90qiCg8s,6650
21
22
  cape_parsers/CAPE/community/SparkRAT.py,sha256=OVDty_1i9PTGuEumT0BHoDn0bD2UtdhHVNjThah80pg,2140
22
- cape_parsers/CAPE/community/Stealc.py,sha256=RddvMmFmq85J3pCqtpACT1n6k02P1_GsxXIidtveNa4,5102
23
+ cape_parsers/CAPE/community/Stealc.py,sha256=A00EEMSubZGLhgRWhL_HWDZBu-EsLWrpBv_-JR3-yZE,5302
23
24
  cape_parsers/CAPE/community/VenomRAT.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
24
25
  cape_parsers/CAPE/community/XWorm.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
25
26
  cape_parsers/CAPE/community/XenoRAT.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
26
27
  cape_parsers/CAPE/community/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
28
  cape_parsers/CAPE/community/monsterv2.py,sha256=eVEs4VIeS3PiZtRjNb69itmDq2Zkbrpn5k3M68GujiI,2995
28
29
  cape_parsers/CAPE/core/AdaptixBeacon.py,sha256=40wMfrXt-7UG30WsLC5GxUtG6tSUaaP1OT-ntWzPZn0,2956
30
+ cape_parsers/CAPE/core/AuraStealer.py,sha256=6mbS1MNsaULpTAlh2vNeZPQy6faYm8BMu0OQh5Vb0eI,2702
29
31
  cape_parsers/CAPE/core/Azorult.py,sha256=YkMIhC6zRTxEkLVMUdr2MMsbV9iAnZ8hUS8be9GZ5N4,2150
30
32
  cape_parsers/CAPE/core/BitPaymer.py,sha256=HQwoE0o7HMiXItxE08vBenf2ZWMxZp84-Hf_1eZ8QdE,3050
31
33
  cape_parsers/CAPE/core/BlackDropper.py,sha256=sCSu2T5oPvcFHlSAzSsLj_gCv2Tldl0UPguwy0MVg6A,3282
32
34
  cape_parsers/CAPE/core/Blister.py,sha256=wprcJMHixv4JHGqBjQeu26BJ6HgXeBMobh10Y-H6-Xg,18173
33
35
  cape_parsers/CAPE/core/BruteRatel.py,sha256=_hFAYLbOsHdekWPOMXRmIYNXTNeNQSs3LZqh7xAVI2U,1147
34
- cape_parsers/CAPE/core/BumbleBee.py,sha256=qyfvRw1pkc3lPsSrwg8y2W6_ciW3sluijdYcHe27iHY,10062
36
+ cape_parsers/CAPE/core/BumbleBee.py,sha256=8a15OLAoNKs377ehdgx8R6kCAsJeG-_itt8xc_EMQes,10075
35
37
  cape_parsers/CAPE/core/DarkGate.py,sha256=ppSRDfw-u2NltzQlrVvRwqxGaprShuv5CrwbNbnSvaw,3477
36
38
  cape_parsers/CAPE/core/DoppelPaymer.py,sha256=LPAQ-7imcAWFciAd7Qb_r6js2PdIsTt9fRdYKoEkFMg,2537
37
39
  cape_parsers/CAPE/core/DridexLoader.py,sha256=8NKppvGz7tVXnNTGEgS7R3LGn5vtW4xslQYbo38wQUg,7087
@@ -47,7 +49,7 @@ cape_parsers/CAPE/core/QakBot.py,sha256=SmXRuwOiaDLL7uN9RwCiQP62P3ctxGJ6y54zJG9y
47
49
  cape_parsers/CAPE/core/Quickbind.py,sha256=5A077RFQQOL8dtr2Q9vmlTKsWk96JkRWuHGseApyTmU,3675
48
50
  cape_parsers/CAPE/core/README.md,sha256=Zd84WEUj9NzKzGnVZV1jx6gMiEOtz01m32B7xEuS91k,17
49
51
  cape_parsers/CAPE/core/RedLine.py,sha256=bZeKLvxaS6HDpWY4RDXtSEBt93qTNzZG5iE6FNS0dOY,5734
50
- cape_parsers/CAPE/core/Remcos.py,sha256=nKn_4lwjX7xGkLGFmt3WAG1HEgmKCncIbkv7Je7W6vM,9477
52
+ cape_parsers/CAPE/core/Remcos.py,sha256=MIpO2FwehBGIhO7hS0TT2hdDsgvxlI5ps4rAwyFwdTY,9483
51
53
  cape_parsers/CAPE/core/Rhadamanthys.py,sha256=mx7kEF1e8LJZbwh2uUwU56ZKgrpLqZvYVDoqm-Dvl9w,6075
52
54
  cape_parsers/CAPE/core/SmokeLoader.py,sha256=ruQ_GDiZvqtGxUTbN2N6fajUYWkIylFTvMXijgZ8L20,3890
53
55
  cape_parsers/CAPE/core/Socks5Systemz.py,sha256=jSt6QejL5K99dIB3qdItvUHL28w6N60xuwc8EQHM5Mk,783
@@ -60,7 +62,7 @@ cape_parsers/CAPE/core/test_cape.py,sha256=CrmghlO43hpnTLv0X8Dw4hTcrVHuJ0X20dPXc
60
62
  cape_parsers/RATDecoders/README.md,sha256=SHgVQraCdp033IQjM4Cm6t70U4kULn1MfSwTq3rsZv8,22
61
63
  cape_parsers/RATDecoders/__init__.py,sha256=JcY8WPKzUFYgexwV1eyKIuT1JyNZzMJjBynlPSzxY_I,7
62
64
  cape_parsers/RATDecoders/test_rats.py,sha256=swkWvbnCd6_2aUP6MnIF4hyPL8zsdhtjlsBfx5Phgk4,610
63
- cape_parsers/__init__.py,sha256=1xtenBXY23B8jf2x1fQ103qYFy0lBW12SN3HFJL7YfE,6243
65
+ cape_parsers/__init__.py,sha256=yInPN6GBAPBgIDGTXVgWB1wrRZ3yJsMk0ywcWAGvop0,6232
64
66
  cape_parsers/deprecated/BackOffLoader.py,sha256=gIwNDsWm1xGR9whKEEj1eTBB1-KTLY0_yNE50xVScKo,1402
65
67
  cape_parsers/deprecated/BackOffPOS.py,sha256=lG7a_bXD3Exaoy-_lHpa90yiv_DesICFqClhqS_d8nk,1486
66
68
  cape_parsers/deprecated/BlackNix.py,sha256=NPqXiHWt_UtLm35gi58UriEJRt_L_UWGfS8jvblAECM,2667
@@ -106,7 +108,7 @@ cape_parsers/utils/blzpack_lib.so,sha256=5PJtnggw8fV5q4DlhwMJk4ZadvC3fFTsVTNZKvE
106
108
  cape_parsers/utils/dotnet_utils.py,sha256=pzQGbCqccz7DRv8T_i1JURlrKDIlDT2axxViiFF9hsU,1672
107
109
  cape_parsers/utils/lznt1.py,sha256=X-BmJtP6AwYSl0ORg5dfSt-NIuXbHrtCO5kUaaJI2C8,4066
108
110
  cape_parsers/utils/strings.py,sha256=a-nbvP9jYST7b6t_H37Ype-fK2jEmQr-wMF5a4i04e4,3062
109
- cape_parsers-0.1.47.dist-info/LICENSE,sha256=88c01_HLG8WPj7R7aU_b-O-UoF38vrrifvcko4KDxcE,1069
110
- cape_parsers-0.1.47.dist-info/METADATA,sha256=yygn1v4WJRq1aonL5anru3gnpJgkmQIAox6a_70zbKk,1753
111
- cape_parsers-0.1.47.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
112
- cape_parsers-0.1.47.dist-info/RECORD,,
111
+ cape_parsers-0.1.49.dist-info/LICENSE,sha256=88c01_HLG8WPj7R7aU_b-O-UoF38vrrifvcko4KDxcE,1069
112
+ cape_parsers-0.1.49.dist-info/METADATA,sha256=JiiD9noZxpf8bqsPWQRJ2siYMcHkqo6VrpkwYD2r3MU,1753
113
+ cape_parsers-0.1.49.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
114
+ cape_parsers-0.1.49.dist-info/RECORD,,