CAPE-parsers 0.1.61__tar.gz → 0.1.62__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 (119) hide show
  1. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/PKG-INFO +1 -1
  2. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/AsyncRAT.py +2 -1
  3. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/DCRat.py +2 -1
  4. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/LokiBot.py +1 -1
  5. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Stealc.py +3 -0
  6. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/VenomRAT.py +2 -1
  7. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/XWorm.py +2 -1
  8. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/XenoRAT.py +2 -1
  9. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/BumbleBee.py +2 -1
  10. cape_parsers-0.1.62/cape_parsers/CAPE/core/HijackLoader.py +39 -0
  11. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/PikaBot.py +2 -1
  12. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Remcos.py +2 -1
  13. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/TSCookie.py +2 -1
  14. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/blzpack_lib.so +0 -0
  15. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/strings.py +69 -32
  16. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/pyproject.toml +1 -1
  17. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/LICENSE +0 -0
  18. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/README.md +0 -0
  19. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/__init__.py +0 -0
  20. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/AgentTesla.py +0 -0
  21. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Amadey.py +0 -0
  22. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Amatera.py +0 -0
  23. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Arkei.py +0 -0
  24. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/AuroraStealer.py +0 -0
  25. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Carbanak.py +0 -0
  26. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/CobaltStrikeBeacon.py +0 -0
  27. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/CobaltStrikeStager.py +0 -0
  28. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Fareit.py +0 -0
  29. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/KoiLoader.py +0 -0
  30. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Lumma.py +0 -0
  31. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/MonsterV2.py +0 -0
  32. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/MyKings.py +0 -0
  33. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/NanoCore.py +0 -0
  34. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Nighthawk.py +0 -0
  35. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Njrat.py +0 -0
  36. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/PhemedroneStealer.py +0 -0
  37. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/QuasarRAT.py +0 -0
  38. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/README.md +0 -0
  39. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/Snake.py +0 -0
  40. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/SparkRAT.py +0 -0
  41. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/WinosStager.py +0 -0
  42. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/community/__init__.py +0 -0
  43. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/AdaptixBeacon.py +0 -0
  44. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/AuraStealer.py +0 -0
  45. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Azorult.py +0 -0
  46. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/BitPaymer.py +0 -0
  47. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/BlackDropper.py +0 -0
  48. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Blister.py +0 -0
  49. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/BruteRatel.py +0 -0
  50. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/DarkGate.py +0 -0
  51. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/DoppelPaymer.py +0 -0
  52. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/DridexLoader.py +0 -0
  53. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Formbook.py +0 -0
  54. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/GuLoader.py +0 -0
  55. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/IcedID.py +0 -0
  56. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/IcedIDLoader.py +0 -0
  57. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Latrodectus.py +0 -0
  58. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/NitroBunnyDownloader.py +0 -0
  59. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Oyster.py +0 -0
  60. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/PlugX.py +0 -0
  61. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/QakBot.py +0 -0
  62. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Quickbind.py +0 -0
  63. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/README.md +0 -0
  64. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/RedLine.py +0 -0
  65. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Rhadamanthys.py +0 -0
  66. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/SmokeLoader.py +0 -0
  67. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Socks5Systemz.py +0 -0
  68. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/SquirrelWaffle.py +0 -0
  69. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Strrat.py +0 -0
  70. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/WarzoneRAT.py +0 -0
  71. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/Zloader.py +0 -0
  72. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/__init__.py +0 -0
  73. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/CAPE/core/test_cape.py +0 -0
  74. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/RATDecoders/README.md +0 -0
  75. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/RATDecoders/__init__.py +0 -0
  76. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/RATDecoders/test_rats.py +0 -0
  77. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/__init__.py +0 -0
  78. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/BackOffLoader.py +0 -0
  79. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/BackOffPOS.py +0 -0
  80. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/BlackNix.py +0 -0
  81. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/BuerLoader.py +0 -0
  82. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/ChChes.py +0 -0
  83. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Emotet.py +0 -0
  84. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Enfal.py +0 -0
  85. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/EvilGrab.py +0 -0
  86. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Greame.py +0 -0
  87. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Hancitor.py +0 -0
  88. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/HttpBrowser.py +0 -0
  89. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/JavaDropper.py +0 -0
  90. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Nymaim.py +0 -0
  91. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Pandora.py +0 -0
  92. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/PoisonIvy.py +0 -0
  93. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/PredatorPain.py +0 -0
  94. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Punisher.py +0 -0
  95. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/RCSession.py +0 -0
  96. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/REvil.py +0 -0
  97. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/RedLeaf.py +0 -0
  98. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Retefe.py +0 -0
  99. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/Rozena.py +0 -0
  100. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/SmallNet.py +0 -0
  101. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/TrickBot.py +0 -0
  102. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/UrsnifV3.py +0 -0
  103. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/_ShadowTech.py +0 -0
  104. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/_VirusRat.py +0 -0
  105. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/_jRat.py +0 -0
  106. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/unrecom.py +0 -0
  107. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/deprecated/xRAT.py +0 -0
  108. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/malduck/LICENSE +0 -0
  109. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/malduck/README.md +0 -0
  110. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/malduck/__init__.py +0 -0
  111. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/malduck/test_malduck.py +0 -0
  112. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/mwcp/README.md +0 -0
  113. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/mwcp/__init__.py +0 -0
  114. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/mwcp/test_mwcp.py +0 -0
  115. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/__init__.py +0 -0
  116. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/aplib.py +0 -0
  117. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/blzpack.py +0 -0
  118. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/dotnet_utils.py +0 -0
  119. {cape_parsers-0.1.61 → cape_parsers-0.1.62}/cape_parsers/utils/lznt1.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CAPE-parsers
3
- Version: 0.1.61
3
+ Version: 0.1.62
4
4
  Summary: CAPE: Malware Configuration Extraction
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -27,5 +27,6 @@ def extract_config(data: bytes):
27
27
 
28
28
 
29
29
  if __name__ == "__main__":
30
- data = open(sys.argv[1], "rb").read()
30
+ with open(sys.argv[1], "rb") as f:
31
+ data = f.read()
31
32
  print(extract_config(data))
@@ -27,5 +27,6 @@ def extract_config(data: bytes):
27
27
 
28
28
 
29
29
  if __name__ == "__main__":
30
- data = open(sys.argv[1], "rb").read()
30
+ with open(sys.argv[1], "rb") as f:
31
+ data = f.read()
31
32
  print(extract_config(data))
@@ -151,7 +151,7 @@ def decoder(data):
151
151
  temp = unpad(temp, 8)
152
152
  if not temp.endswith(b".php"):
153
153
  continue
154
- urls.append("http://" + temp.decod())
154
+ urls.append("http://" + temp.decode())
155
155
  return urls
156
156
 
157
157
 
@@ -150,6 +150,9 @@ def extract_config(data):
150
150
  if botnet_id:
151
151
  config_dict.setdefault("botnet", botnet_id)
152
152
 
153
+ if "CNCs" not in config_dict:
154
+ return {}
155
+
153
156
  return config_dict
154
157
 
155
158
 
@@ -27,5 +27,6 @@ def extract_config(data: bytes):
27
27
 
28
28
 
29
29
  if __name__ == "__main__":
30
- data = open(sys.argv[1], "rb").read()
30
+ with open(sys.argv[1], "rb") as f:
31
+ data = f.read()
31
32
  print(extract_config(data))
@@ -27,5 +27,6 @@ def extract_config(data: bytes):
27
27
 
28
28
 
29
29
  if __name__ == "__main__":
30
- data = open(sys.argv[1], "rb").read()
30
+ with open(sys.argv[1], "rb") as f:
31
+ data = f.read()
31
32
  print(extract_config(data))
@@ -27,5 +27,6 @@ def extract_config(data: bytes):
27
27
 
28
28
 
29
29
  if __name__ == "__main__":
30
- data = open(sys.argv[1], "rb").read()
30
+ with open(sys.argv[1], "rb") as f:
31
+ data = f.read()
31
32
  print(extract_config(data))
@@ -254,4 +254,5 @@ def extract_config(data):
254
254
  if __name__ == "__main__":
255
255
  import sys
256
256
 
257
- print(extract_config(open(sys.argv[1], "rb").read()))
257
+ with open(sys.argv[1], "rb") as f:
258
+ print(extract_config(f.read()))
@@ -0,0 +1,39 @@
1
+ from contextlib import suppress
2
+
3
+ try:
4
+ from cape_parsers.utils.strings import extract_strings
5
+ except ImportError as e:
6
+ print(f"Problem importing extract_strings: {e}")
7
+
8
+ import logging
9
+ log = logging.getLogger(__name__)
10
+
11
+
12
+ def extract_config(data: bytes):
13
+ config = {}
14
+
15
+ with suppress(Exception):
16
+ if data[:2] == b"MZ":
17
+ return
18
+
19
+ header_data = data[:1024]
20
+ lines = extract_strings(data=header_data, minchars=3, dedup=False)
21
+
22
+ if len(lines) < 4:
23
+ return None
24
+
25
+ if '\\' in lines[2]:
26
+ config.setdefault("raw", {})["directory"] = (lines[1].strip() + '\\' + lines[0].strip()).replace(' ', ' ')
27
+ config.setdefault("raw", {})["inject_dll"] = lines[2].strip()
28
+ if '.exe' in lines[3]:
29
+ config.setdefault("raw", {})["exe_name"] = lines[3].strip()
30
+
31
+ if config:
32
+ config.setdefault("raw", config)
33
+ return config
34
+
35
+ if __name__ == "__main__":
36
+ import sys
37
+
38
+ with open(sys.argv[1], "rb") as f:
39
+ print(extract_config(f.read()))
@@ -183,4 +183,5 @@ def extract_config(filebuf):
183
183
  if __name__ == "__main__":
184
184
  import sys
185
185
 
186
- print(extract_config(sys.argv[1]))
186
+ with open(sys.argv[1], "rb") as f:
187
+ print(extract_config(f.read()))
@@ -219,4 +219,5 @@ def extract_config(filebuf):
219
219
  if __name__ == "__main__":
220
220
  import sys
221
221
 
222
- print(extract_config(open(sys.argv[1], "rb").read()))
222
+ with open(sys.argv[1], "rb") as f:
223
+ print(extract_config(f.read()))
@@ -85,7 +85,8 @@ def decode_resource(rc_data, key_end, fname):
85
85
  enc_data = rc_data[:-RC4_KEY_LENGTH]
86
86
  rc4key = rc_data[-RC4_KEY_LENGTH:-4] + key_end
87
87
  dec_data = rc4(enc_data, rc4key)
88
- open(fname, "wb").write(dec_data)
88
+ with open(fname, "wb") as f:
89
+ f.write(dec_data.encode("utf-8") if isinstance(dec_data, str) else dec_data)
89
90
  except Exception:
90
91
  return
91
92
  return dec_data
@@ -1,18 +1,10 @@
1
1
  # Copyright (C) 2010-2015 Cuckoo Foundation, Optiv, Inc. (brad.spengler@optiv.com)
2
2
  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
3
3
  # See the file 'docs/LICENSE' for copying permission.
4
+ import yara
4
5
  import logging
5
6
  from pathlib import Path
6
7
 
7
- try:
8
- import re2 as re
9
-
10
- HAVE_RE2 = True
11
- except ImportError:
12
- import re
13
-
14
- HAVE_RE2 = False
15
-
16
8
 
17
9
  log = logging.getLogger(__name__)
18
10
 
@@ -66,41 +58,86 @@ def bytes2str(convert):
66
58
  return convert
67
59
 
68
60
 
69
- def extract_strings(filepath: str = False, data: bytes = False, on_demand: bool = False, dedup: bool = False, minchars: int = 0):
70
- """Extract strings from analyzed file.
71
- @return: list of printable strings.
72
- """
61
+ def extract_strings(filepath: str = False, data: bytes = False, dedup: bool = False, minchars: int = 5):
62
+ """Extract ASCII and UTF-16LE strings from a file or byte string using YARA.
73
63
 
74
- nulltermonly = False
64
+ Args:
65
+ filepath: Path to the file to extract strings from.
66
+ data: Byte string to extract strings from. If filepath is provided, this is ignored.
67
+ dedup: If True, duplicate strings are removed.
68
+ minchars: Minimum length of strings to extract.
69
+
70
+ Returns:
71
+ A list of extracted strings.
72
+ """
75
73
  if minchars == 0:
76
74
  minchars = 5
77
75
 
78
76
  if filepath:
79
77
  p = Path(filepath)
80
78
  if not p.exists():
81
- log.error("Sample file doesn't exist: %s", filepath)
82
- return
83
- try:
84
- data = p.read_bytes()
85
- except (IOError, OSError) as e:
86
- log.error("Error reading file: %s", e)
87
- return
79
+ return []
80
+ data = p.read_bytes()
81
+
82
+ if not data or not isinstance(data, bytes):
83
+ return []
84
+
85
+ rule_source = r"""
86
+ rule GetStrings {
87
+ strings:
88
+ $s = /[\x20-\x7e]{""" + str(int(minchars)) + r""",}/ ascii wide
89
+ condition:
90
+ $s
91
+ }
92
+ """
88
93
 
89
- if not data:
90
- return
94
+ try:
95
+ rule = yara.compile(source=rule_source)
96
+ matches = rule.match(data=data)
97
+ except yara.Error:
98
+ return []
91
99
 
92
- endlimit = b"8192" if not HAVE_RE2 else b""
93
- if nulltermonly:
94
- apat = b"([\x20-\x7e]{" + str(minchars).encode() + b"," + endlimit + b"})\x00"
95
- upat = b"((?:[\x20-\x7e][\x00]){" + str(minchars).encode() + b"," + endlimit + b"})\x00\x00"
96
- else:
97
- apat = b"[\x20-\x7e]{" + str(minchars).encode() + b"," + endlimit + b"}"
98
- upat = b"(?:[\x20-\x7e][\x00]){" + str(minchars).encode() + b"," + endlimit + b"}"
100
+ all_instances = [
101
+ {
102
+ 'offset': instance.offset,
103
+ 'data': instance.matched_data,
104
+ 'length': len(instance.matched_data),
105
+ }
106
+ for match in matches
107
+ for string_match in match.strings
108
+ for instance in string_match.instances
109
+ ]
99
110
 
100
- strings = [bytes2str(string) for string in re.findall(apat, data)]
101
- strings.extend(str(ws.decode("utf-16le")) for ws in re.findall(upat, data))
111
+ all_instances.sort(key=lambda x: x['offset'])
112
+
113
+ strings = []
114
+ last_end_offset = -1
115
+
116
+ for inst in all_instances:
117
+ current_start = inst['offset']
118
+ current_end = current_start + inst['length']
119
+
120
+ if current_start < last_end_offset:
121
+ continue
122
+
123
+ val = inst['data']
124
+ decoded = None
125
+
126
+ if b"\x00" in val:
127
+ try:
128
+ decoded = val.decode("utf-16le")
129
+ except UnicodeDecodeError:
130
+ pass
131
+
132
+ if not decoded:
133
+ decoded = val.decode("ascii", errors="ignore")
134
+
135
+ if decoded:
136
+ strings.append(decoded)
137
+ last_end_offset = current_end
102
138
 
103
139
  if dedup:
104
140
  strings = list(set(strings))
105
141
 
106
142
  return strings
143
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "CAPE-parsers"
3
- version = "0.1.61"
3
+ version = "0.1.62"
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