CAPE-parsers 0.1.51__py3-none-any.whl → 0.1.52__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.
@@ -14,15 +14,12 @@ RULE_SOURCE = """rule MonsterV2Config
14
14
  author = "doomedraven,YungBinary"
15
15
  strings:
16
16
  $chunk_1 = {
17
- 41 B8 ?? ?? ?? ??
18
- 48 8D 15 ?? ?? ?? ??
19
- 48 8B CB
20
- E8 ?? ?? ?? ??
21
- 48 8D 83 ?? ?? ?? ??
22
- 48 89 44 24 ??
23
- 48 89 6C 24 ??
24
- 4C 8B C7
25
- 48 8D 54 24 ??
17
+ 41 B8 0E 04 00 00
18
+ 48 8D 15 ?? ?? ?? 00
19
+ 48 8B C?
20
+ E8 ?? ?? ?? ?? [3-17]
21
+ 4C 8B C?
22
+ 48 8D 54 24 28
26
23
  48 8B CE
27
24
  E8 ?? ?? ?? ??
28
25
  }
@@ -0,0 +1,52 @@
1
+ """
2
+ Description: MyKings AKA Smominru config parser
3
+ Author: x.com/YungBinary
4
+ """
5
+
6
+ from contextlib import suppress
7
+ import json
8
+ import re
9
+ import base64
10
+
11
+
12
+ def contains_non_printable(byte_array):
13
+ for byte in byte_array:
14
+ if not chr(byte).isprintable():
15
+ return True
16
+ return False
17
+
18
+
19
+ def extract_base64_strings(data: bytes, minchars: int, maxchars: int) -> list:
20
+ pattern = b"([A-Za-z0-9+/=]{" + str(minchars).encode() + b"," + str(maxchars).encode() + b"})\x00{4}"
21
+ strings = []
22
+ for string in re.findall(pattern, data):
23
+ decoded_string = base64_and_printable(string.decode())
24
+ if decoded_string:
25
+ strings.append(decoded_string)
26
+ return strings
27
+
28
+
29
+ def base64_and_printable(b64_string: str):
30
+ with suppress(Exception):
31
+ decoded_bytes = base64.b64decode(b64_string)
32
+ if not contains_non_printable(decoded_bytes):
33
+ return decoded_bytes.decode('ascii')
34
+
35
+
36
+ def extract_config(data: bytes) -> dict:
37
+ config_dict = {}
38
+ with suppress(Exception):
39
+ cncs = extract_base64_strings(data, 12, 60)
40
+ if cncs:
41
+ # as they don't have schema they going under raw
42
+ config_dict["raw"] = {"CNCs": cncs}
43
+ return config_dict
44
+
45
+ return {}
46
+
47
+
48
+ if __name__ == "__main__":
49
+ import sys
50
+
51
+ with open(sys.argv[1], "rb") as f:
52
+ print(json.dumps(extract_config(f.read()), indent=4))
@@ -0,0 +1,75 @@
1
+ """
2
+ Description: Winos 4.0 "OnlineModule" config parser
3
+ Author: x.com/YungBinary
4
+ """
5
+
6
+ from contextlib import suppress
7
+ import re
8
+
9
+
10
+ CONFIG_KEY_MAP = {
11
+ "dd": "execution_delay_seconds",
12
+ "cl": "communication_interval_seconds",
13
+ "bb": "version",
14
+ "bz": "comment",
15
+ "jp": "keylogger",
16
+ "bh": "end_bluescreen",
17
+ "ll": "anti_traffic_monitoring",
18
+ "dl": "entrypoint",
19
+ "sh": "process_daemon",
20
+ "kl": "process_hollowing"
21
+ }
22
+
23
+
24
+ def find_config(data):
25
+ start = ":db|".encode("utf-16le")
26
+ end = ":1p|".encode("utf-16le")
27
+ pattern = re.compile(re.escape(start) + b".*?" + re.escape(end), re.DOTALL)
28
+ match = pattern.search(data)
29
+ if match:
30
+ return match.group(0).decode("utf-16le")
31
+
32
+
33
+ def extract_config(data: bytes) -> dict:
34
+ config_dict = {}
35
+ final_config = {}
36
+
37
+ with suppress(Exception):
38
+ config = find_config(data)
39
+ if not config:
40
+ return config_dict
41
+
42
+ # Reverse the config string, which is delimited by '|'
43
+ config = config[::-1]
44
+ # Remove leading/trailing pipes and split into key/value pairs
45
+ elements = [element for element in config.strip('|').split('|') if ':' in element]
46
+ # Split each element for key : value in a dictionary
47
+ config_dict = dict(element.split(':', 1) for element in elements)
48
+ if config_dict:
49
+ # Handle extraction and formatting of CNCs
50
+ for i in range(1, 4):
51
+ p, o, t = config_dict.get(f"p{i}"), config_dict.get(f"o{i}"), config_dict.get(f"t{i}")
52
+ if p and p != "127.0.0.1" and o:
53
+ protocol = {"0": "udp", "1": "tcp"}.get(t)
54
+ if protocol:
55
+ cnc = f"{protocol}://{p}:{o}"
56
+ final_config.setdefault("CNCs", []).append(cnc)
57
+
58
+ if "CNCs" not in final_config:
59
+ return {}
60
+
61
+ final_config["CNCs"] = list(set(final_config["CNCs"]))
62
+ # Extract campaign ID
63
+ final_config["campaign_id"] = "default" if config_dict["fz"] == "\u9ed8\u8ba4" else config_dict["fz"]
64
+
65
+ # Map keys, e.g. dd -> execution_delay_seconds
66
+ final_config["raw"] = {v: config_dict[k] for k, v in CONFIG_KEY_MAP.items() if k in config_dict}
67
+
68
+ return final_config
69
+
70
+
71
+ if __name__ == "__main__":
72
+ import sys
73
+
74
+ with open(sys.argv[1], "rb") as f:
75
+ print(extract_config(f.read()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CAPE-parsers
3
- Version: 0.1.51
3
+ Version: 0.1.52
4
4
  Summary: CAPE: Malware Configuration Extraction
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -12,7 +12,8 @@ cape_parsers/CAPE/community/Fareit.py,sha256=OyKeZdcvyAhjxZgJqkDPJHP4Npv1ArvTHJZ
12
12
  cape_parsers/CAPE/community/KoiLoader.py,sha256=F2gsgCvrVuwxY1bg8rlexsjCjikAP5HIGGOqU8zhT8E,4008
13
13
  cape_parsers/CAPE/community/LokiBot.py,sha256=355kqLx0LNMr8XcGfPL7cxG8QZalcmE7ttVBqoWtTWE,5754
14
14
  cape_parsers/CAPE/community/Lumma.py,sha256=Iqd9yvt3g0FeV_bYRmL1RKp4C1H92qeGg4fXivVDSxw,12206
15
- cape_parsers/CAPE/community/MonsterV2.py,sha256=eVEs4VIeS3PiZtRjNb69itmDq2Zkbrpn5k3M68GujiI,2995
15
+ cape_parsers/CAPE/community/MonsterV2.py,sha256=cFxhYxo7FruTMmFY3OtBO-E0hDyxfsC3zWX3BlcB-qI,2915
16
+ cape_parsers/CAPE/community/MyKings.py,sha256=bcypBMJf6Jeg0yrHZ-J-XjnhHvFbb-lpDF_zwW63gOk,1397
16
17
  cape_parsers/CAPE/community/NanoCore.py,sha256=8QZnf1AcY9481kSfsf3SHQShwPLn97peGAf8_xEasQc,6230
17
18
  cape_parsers/CAPE/community/Nighthawk.py,sha256=8ss8yvslrwUt53zV6U0xuwGKU3hgYfOt13S5lkOVpNo,12105
18
19
  cape_parsers/CAPE/community/Njrat.py,sha256=GiwSENBB43RUqyJ7zT7ZPkPUYqo8Ew4kd5MJUj0jzdc,4702
@@ -23,6 +24,7 @@ cape_parsers/CAPE/community/Snake.py,sha256=v_MAPmg86ZdgGOkzc9GVHbi-lu4nLa1_0Lp9
23
24
  cape_parsers/CAPE/community/SparkRAT.py,sha256=OVDty_1i9PTGuEumT0BHoDn0bD2UtdhHVNjThah80pg,2140
24
25
  cape_parsers/CAPE/community/Stealc.py,sha256=18EkQ-lMMAreKV5vA9xLBmOK5B4JtYcBwVqNfof4K2A,5321
25
26
  cape_parsers/CAPE/community/VenomRAT.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
27
+ cape_parsers/CAPE/community/WinosStager.py,sha256=6jkfTJiVdz6oyyqTjh3I4qunYgXbD4qXS_bd-uogwGA,2407
26
28
  cape_parsers/CAPE/community/XWorm.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
27
29
  cape_parsers/CAPE/community/XenoRAT.py,sha256=0-FRT3d2x63KQ_cs1xmKFj7x0JRf7ID6QDc_DvBa0PM,1003
28
30
  cape_parsers/CAPE/community/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -108,7 +110,7 @@ cape_parsers/utils/blzpack_lib.so,sha256=5PJtnggw8fV5q4DlhwMJk4ZadvC3fFTsVTNZKvE
108
110
  cape_parsers/utils/dotnet_utils.py,sha256=pzQGbCqccz7DRv8T_i1JURlrKDIlDT2axxViiFF9hsU,1672
109
111
  cape_parsers/utils/lznt1.py,sha256=X-BmJtP6AwYSl0ORg5dfSt-NIuXbHrtCO5kUaaJI2C8,4066
110
112
  cape_parsers/utils/strings.py,sha256=a-nbvP9jYST7b6t_H37Ype-fK2jEmQr-wMF5a4i04e4,3062
111
- cape_parsers-0.1.51.dist-info/METADATA,sha256=vSKRRgEfohGbql5yBH3B_8mkBBWfhBNutBqb1xQ_jaE,1826
112
- cape_parsers-0.1.51.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
113
- cape_parsers-0.1.51.dist-info/licenses/LICENSE,sha256=88c01_HLG8WPj7R7aU_b-O-UoF38vrrifvcko4KDxcE,1069
114
- cape_parsers-0.1.51.dist-info/RECORD,,
113
+ cape_parsers-0.1.52.dist-info/METADATA,sha256=c354f-gNdv6cYW0XkKCvLw0tjVbE8flYpLsW1TrS7zw,1826
114
+ cape_parsers-0.1.52.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
115
+ cape_parsers-0.1.52.dist-info/licenses/LICENSE,sha256=88c01_HLG8WPj7R7aU_b-O-UoF38vrrifvcko4KDxcE,1069
116
+ cape_parsers-0.1.52.dist-info/RECORD,,