CAPE-parsers 0.1.48__tar.gz → 0.1.49__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.
Files changed (114) hide show
  1. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/PKG-INFO +1 -1
  2. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Amadey.py +4 -9
  3. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Stealc.py +10 -0
  4. cape_parsers-0.1.49/cape_parsers/CAPE/core/AuraStealer.py +93 -0
  5. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/pyproject.toml +1 -1
  6. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/LICENSE +0 -0
  7. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/README.md +0 -0
  8. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/__init__.py +0 -0
  9. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/AgentTesla.py +0 -0
  10. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Arkei.py +0 -0
  11. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/AsyncRAT.py +0 -0
  12. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/AuroraStealer.py +0 -0
  13. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Carbanak.py +0 -0
  14. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/CobaltStrikeBeacon.py +0 -0
  15. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/CobaltStrikeStager.py +0 -0
  16. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/DCRat.py +0 -0
  17. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Fareit.py +0 -0
  18. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/KoiLoader.py +0 -0
  19. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/LokiBot.py +0 -0
  20. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Lumma.py +0 -0
  21. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/NanoCore.py +0 -0
  22. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Nighthawk.py +0 -0
  23. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Njrat.py +0 -0
  24. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/PhemedroneStealer.py +0 -0
  25. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/QuasarRAT.py +0 -0
  26. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/README.md +0 -0
  27. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/Snake.py +0 -0
  28. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/SparkRAT.py +0 -0
  29. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/VenomRAT.py +0 -0
  30. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/XWorm.py +0 -0
  31. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/XenoRAT.py +0 -0
  32. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/__init__.py +0 -0
  33. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/community/monsterv2.py +0 -0
  34. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/AdaptixBeacon.py +0 -0
  35. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Azorult.py +0 -0
  36. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/BitPaymer.py +0 -0
  37. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/BlackDropper.py +0 -0
  38. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Blister.py +0 -0
  39. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/BruteRatel.py +0 -0
  40. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/BumbleBee.py +0 -0
  41. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/DarkGate.py +0 -0
  42. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/DoppelPaymer.py +0 -0
  43. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/DridexLoader.py +0 -0
  44. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Formbook.py +0 -0
  45. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/GuLoader.py +0 -0
  46. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/IcedID.py +0 -0
  47. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/IcedIDLoader.py +0 -0
  48. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Latrodectus.py +0 -0
  49. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Oyster.py +0 -0
  50. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/PikaBot.py +0 -0
  51. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/PlugX.py +0 -0
  52. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/QakBot.py +0 -0
  53. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Quickbind.py +0 -0
  54. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/README.md +0 -0
  55. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/RedLine.py +0 -0
  56. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Remcos.py +0 -0
  57. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Rhadamanthys.py +0 -0
  58. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/SmokeLoader.py +0 -0
  59. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Socks5Systemz.py +0 -0
  60. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/SquirrelWaffle.py +0 -0
  61. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Strrat.py +0 -0
  62. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/WarzoneRAT.py +0 -0
  63. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/Zloader.py +0 -0
  64. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/__init__.py +0 -0
  65. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/CAPE/core/test_cape.py +0 -0
  66. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/RATDecoders/README.md +0 -0
  67. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/RATDecoders/__init__.py +0 -0
  68. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/RATDecoders/test_rats.py +0 -0
  69. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/__init__.py +0 -0
  70. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/BackOffLoader.py +0 -0
  71. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/BackOffPOS.py +0 -0
  72. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/BlackNix.py +0 -0
  73. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/BuerLoader.py +0 -0
  74. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/ChChes.py +0 -0
  75. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Emotet.py +0 -0
  76. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Enfal.py +0 -0
  77. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/EvilGrab.py +0 -0
  78. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Greame.py +0 -0
  79. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Hancitor.py +0 -0
  80. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/HttpBrowser.py +0 -0
  81. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/JavaDropper.py +0 -0
  82. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Nymaim.py +0 -0
  83. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Pandora.py +0 -0
  84. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/PoisonIvy.py +0 -0
  85. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/PredatorPain.py +0 -0
  86. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Punisher.py +0 -0
  87. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/RCSession.py +0 -0
  88. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/REvil.py +0 -0
  89. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/RedLeaf.py +0 -0
  90. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Retefe.py +0 -0
  91. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/Rozena.py +0 -0
  92. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/SmallNet.py +0 -0
  93. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/TSCookie.py +0 -0
  94. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/TrickBot.py +0 -0
  95. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/UrsnifV3.py +0 -0
  96. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/_ShadowTech.py +0 -0
  97. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/_VirusRat.py +0 -0
  98. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/_jRat.py +0 -0
  99. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/unrecom.py +0 -0
  100. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/deprecated/xRAT.py +0 -0
  101. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/malduck/LICENSE +0 -0
  102. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/malduck/README.md +0 -0
  103. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/malduck/__init__.py +0 -0
  104. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/malduck/test_malduck.py +0 -0
  105. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/mwcp/README.md +0 -0
  106. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/mwcp/__init__.py +0 -0
  107. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/mwcp/test_mwcp.py +0 -0
  108. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/__init__.py +0 -0
  109. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/aplib.py +0 -0
  110. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/blzpack.py +0 -0
  111. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/blzpack_lib.so +0 -0
  112. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/dotnet_utils.py +0 -0
  113. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/lznt1.py +0 -0
  114. {cape_parsers-0.1.48 → cape_parsers-0.1.49}/cape_parsers/utils/strings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: CAPE-parsers
3
- Version: 0.1.48
3
+ Version: 0.1.49
4
4
  Summary: CAPE: Malware Configuration Extraction
5
5
  License: MIT
6
6
  Keywords: cape,parsers,malware,configuration
@@ -173,25 +173,20 @@ def extract_config(data):
173
173
  version = ""
174
174
  install_dir = ""
175
175
  install_file = ""
176
- ip_pattern = r"^(?:\d{1,3}\.){3}\d{1,3}$"
177
176
  version_pattern = r"^\d+\.\d{1,2}$"
178
177
  install_dir_pattern = r"^[0-9a-f]{10}$"
179
178
 
180
- i = 0
181
- while i < len(decoded_strings):
179
+ for i in range(len(decoded_strings)):
182
180
  s = decoded_strings[i]
183
- if re.match(ip_pattern, s):
184
- if i + 1 < len(decoded_strings):
185
- path = decoded_strings[i+1]
186
- final_config.setdefault("CNCs", []).append(f"http://{s}{path}")
187
- i += 1 # Skip next element as it has been processed
181
+ if s.endswith(".php"):
182
+ c2 = decoded_strings[i-1]
183
+ final_config.setdefault("CNCs", []).append(f"http://{c2}{s}")
188
184
  elif re.match(version_pattern, s):
189
185
  version = s
190
186
  elif re.match(install_dir_pattern, s):
191
187
  install_dir = s
192
188
  elif s.endswith(".exe"):
193
189
  install_file = s
194
- i += 1
195
190
 
196
191
  if version:
197
192
  final_config["version"] = version
@@ -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()))
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "CAPE-parsers"
3
- version = "0.1.48"
3
+ version = "0.1.49"
4
4
  description = "CAPE: Malware Configuration Extraction"
5
5
  authors = ["Kevin O'Reilly <kev@capesandbox.com>", "doomedraven <doomedraven@capesandbox.com>"]
6
6
  license = "MIT"
File without changes
File without changes