CAPE-parsers 0.1.57__tar.gz → 0.1.59__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.
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/PKG-INFO +1 -1
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Amatera.py +92 -61
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/SmokeLoader.py +16 -8
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Zloader.py +151 -44
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/pyproject.toml +1 -1
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/LICENSE +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/README.md +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/AgentTesla.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Amadey.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Arkei.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/AsyncRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/AuroraStealer.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Carbanak.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/CobaltStrikeBeacon.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/CobaltStrikeStager.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/DCRat.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Fareit.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/KoiLoader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/LokiBot.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Lumma.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/MonsterV2.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/MyKings.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/NanoCore.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Nighthawk.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Njrat.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/PhemedroneStealer.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/QuasarRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/README.md +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Snake.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/SparkRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/Stealc.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/VenomRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/WinosStager.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/XWorm.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/XenoRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/AdaptixBeacon.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/AuraStealer.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Azorult.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/BitPaymer.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/BlackDropper.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Blister.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/BruteRatel.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/BumbleBee.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/DarkGate.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/DoppelPaymer.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/DridexLoader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Formbook.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/GuLoader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/IcedID.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/IcedIDLoader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Latrodectus.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/NitroBunnyDownloader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Oyster.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/PikaBot.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/PlugX.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/QakBot.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Quickbind.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/README.md +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/RedLine.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Remcos.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Rhadamanthys.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Socks5Systemz.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/SquirrelWaffle.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/Strrat.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/WarzoneRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/core/test_cape.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/RATDecoders/README.md +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/RATDecoders/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/RATDecoders/test_rats.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/BackOffLoader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/BackOffPOS.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/BlackNix.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/BuerLoader.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/ChChes.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Emotet.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Enfal.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/EvilGrab.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Greame.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Hancitor.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/HttpBrowser.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/JavaDropper.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Nymaim.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Pandora.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/PoisonIvy.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/PredatorPain.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Punisher.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/RCSession.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/REvil.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/RedLeaf.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Retefe.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/Rozena.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/SmallNet.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/TSCookie.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/TrickBot.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/UrsnifV3.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/_ShadowTech.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/_VirusRat.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/_jRat.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/unrecom.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/deprecated/xRAT.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/malduck/LICENSE +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/malduck/README.md +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/malduck/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/malduck/test_malduck.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/mwcp/README.md +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/mwcp/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/mwcp/test_mwcp.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/__init__.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/aplib.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/blzpack.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/blzpack_lib.so +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/dotnet_utils.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/lznt1.py +0 -0
- {cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/utils/strings.py +0 -0
|
@@ -3,11 +3,8 @@ import json
|
|
|
3
3
|
import pefile
|
|
4
4
|
import yara
|
|
5
5
|
import struct
|
|
6
|
-
import re
|
|
7
|
-
import ipaddress
|
|
8
6
|
from contextlib import suppress
|
|
9
7
|
|
|
10
|
-
|
|
11
8
|
DESCRIPTION = "Amatera Stealer parser"
|
|
12
9
|
AUTHOR = "YungBinary"
|
|
13
10
|
|
|
@@ -18,7 +15,7 @@ rule AmateraDecrypt
|
|
|
18
15
|
author = "YungBinary"
|
|
19
16
|
description = "Find Amatera XOR key"
|
|
20
17
|
strings:
|
|
21
|
-
$
|
|
18
|
+
$decrypt_global = {
|
|
22
19
|
A1 ?? ?? ?? ?? // mov eax, dword ptr ds:szXorKey ; "852149723"
|
|
23
20
|
89 45 ?? // mov dword ptr [ebp+xor_key], eax
|
|
24
21
|
8B 0D ?? ?? ?? ?? // mov ecx, dword ptr ds:szXorKey+4 ; "49723"
|
|
@@ -29,12 +26,18 @@ rule AmateraDecrypt
|
|
|
29
26
|
50 // push eax
|
|
30
27
|
E8 // call
|
|
31
28
|
}
|
|
29
|
+
$decrypt_stack = {
|
|
30
|
+
83 EC 1C // sub esp, 1Ch
|
|
31
|
+
56 // push esi
|
|
32
|
+
89 ?? ?? // mov [ebp+var], reg
|
|
33
|
+
C6 45 ?? ?? // mov [ebp+char_1], imm
|
|
34
|
+
C6 45 ?? ?? // mov [ebp+char_2], imm
|
|
35
|
+
}
|
|
32
36
|
condition:
|
|
33
|
-
uint16(0) == 0x5A4D and $
|
|
37
|
+
uint16(0) == 0x5A4D and ($decrypt_global or $decrypt_stack)
|
|
34
38
|
}
|
|
35
39
|
"""
|
|
36
40
|
|
|
37
|
-
|
|
38
41
|
RULE_SOURCE_AES_KEY = """
|
|
39
42
|
rule AmateraAESKey
|
|
40
43
|
{
|
|
@@ -83,28 +86,18 @@ rule AmateraAESKey
|
|
|
83
86
|
}
|
|
84
87
|
"""
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
B64_CHARS = set(b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
|
|
87
90
|
|
|
88
91
|
|
|
89
92
|
def yara_scan(raw_data: bytes, rule_source: str):
|
|
90
93
|
yara_rules = yara.compile(source=rule_source)
|
|
91
94
|
matches = yara_rules.match(data=raw_data)
|
|
92
|
-
|
|
93
95
|
for match in matches:
|
|
94
96
|
for block in match.strings:
|
|
95
97
|
for instance in block.instances:
|
|
96
98
|
return instance.offset
|
|
97
99
|
|
|
98
100
|
|
|
99
|
-
def extract_base64_strings(data: bytes, minchars: int, maxchars: int):
|
|
100
|
-
"""
|
|
101
|
-
Generator that returns ASCII formatted base64 strings
|
|
102
|
-
"""
|
|
103
|
-
apat = b"([A-Za-z0-9+/=]{" + str(minchars).encode() + b"," + str(maxchars).encode() + b"})\x00"
|
|
104
|
-
for s in re.findall(apat, data):
|
|
105
|
-
yield s.decode()
|
|
106
|
-
|
|
107
|
-
|
|
108
101
|
def xor_data(data, key):
|
|
109
102
|
decoded = bytearray()
|
|
110
103
|
for i in range(len(data)):
|
|
@@ -112,68 +105,107 @@ def xor_data(data, key):
|
|
|
112
105
|
return decoded
|
|
113
106
|
|
|
114
107
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
ip_obj = ipaddress.ip_address(ip.decode())
|
|
119
|
-
if ip_obj.is_private:
|
|
120
|
-
return False
|
|
121
|
-
return True
|
|
122
|
-
except Exception:
|
|
123
|
-
return False
|
|
108
|
+
def decode_and_decrypt(data_bytes, xor_key):
|
|
109
|
+
if not data_bytes:
|
|
110
|
+
return ""
|
|
124
111
|
|
|
112
|
+
clean_bytes = data_bytes.rstrip(b"\x00")
|
|
113
|
+
|
|
114
|
+
# Heuristic: Check if valid Base64
|
|
115
|
+
if any(b not in B64_CHARS for b in clean_bytes):
|
|
116
|
+
return clean_bytes.decode("utf-8", errors="ignore")
|
|
125
117
|
|
|
126
|
-
def is_valid_domain(data):
|
|
127
118
|
try:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
119
|
+
decoded = base64.b64decode(clean_bytes, validate=True)
|
|
120
|
+
decrypted = xor_data(decoded, xor_key)
|
|
121
|
+
# Heuristic: Check if result is printable ASCII
|
|
122
|
+
if all(0x20 <= b <= 0x7E for b in decrypted if b != 0):
|
|
123
|
+
return decrypted.decode("utf-8", errors="ignore").rstrip("\x00")
|
|
131
124
|
except Exception:
|
|
132
|
-
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
return clean_bytes.decode("utf-8", errors="ignore")
|
|
133
128
|
|
|
134
129
|
|
|
135
130
|
def extract_config(data):
|
|
136
|
-
"""
|
|
137
|
-
Extract Amatera malware configuration.
|
|
138
|
-
"""
|
|
139
131
|
config_dict = {}
|
|
140
132
|
|
|
141
133
|
with suppress(Exception):
|
|
142
134
|
pe = pefile.PE(data=data)
|
|
143
135
|
image_base = pe.OPTIONAL_HEADER.ImageBase
|
|
144
136
|
|
|
145
|
-
# Identify XOR key decryption routine and extract key
|
|
146
137
|
offset = yara_scan(data, RULE_SOURCE)
|
|
147
|
-
if
|
|
138
|
+
if offset is None:
|
|
148
139
|
return config_dict
|
|
149
|
-
key_str_va = struct.unpack('i', data[offset + 1: offset + 5])[0]
|
|
150
|
-
key_str = pe.get_string_at_rva(key_str_va - image_base, max_length=20) + b'\x00'
|
|
151
140
|
|
|
152
|
-
|
|
141
|
+
key_str = b""
|
|
142
|
+
if data[offset] == 0xA1: # $decrypt_global
|
|
143
|
+
key_str_va = struct.unpack("i", data[offset + 1 : offset + 5])[0]
|
|
144
|
+
key_str = (
|
|
145
|
+
pe.get_string_at_rva(key_str_va - image_base, max_length=20) + b"\x00"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
elif data[offset] == 0x83: # $decrypt_stack
|
|
149
|
+
key_bytes = bytearray()
|
|
150
|
+
# Skip sub/push/mov reg (7 bytes)
|
|
151
|
+
current_idx = offset + 7
|
|
152
|
+
for _ in range(32):
|
|
153
|
+
if data[current_idx] != 0xC6 or data[current_idx + 1] != 0x45:
|
|
154
|
+
break
|
|
155
|
+
val = data[current_idx + 3]
|
|
156
|
+
if val == 0x00:
|
|
157
|
+
break
|
|
158
|
+
key_bytes.append(val)
|
|
159
|
+
current_idx += 4
|
|
160
|
+
key_str = key_bytes + b"\x00"
|
|
161
|
+
|
|
162
|
+
if key_str:
|
|
163
|
+
config_dict["xor_key"] = key_str.rstrip(b"\x00").decode(
|
|
164
|
+
"utf-8", errors="ignore"
|
|
165
|
+
)
|
|
166
|
+
|
|
153
167
|
aes_key_offset = yara_scan(data, RULE_SOURCE_AES_KEY)
|
|
154
|
-
aes_key = bytearray()
|
|
155
168
|
if aes_key_offset:
|
|
169
|
+
aes_key = bytearray()
|
|
156
170
|
aes_block = data[aes_key_offset : aes_key_offset + 131]
|
|
157
171
|
for i in range(0, len(aes_block) - 4, 4):
|
|
158
|
-
aes_key.append(aes_block[i+6])
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
aes_key.append(aes_block[i + 6])
|
|
173
|
+
config_dict["cryptokey"] = aes_key.hex()
|
|
174
|
+
config_dict["cryptokey_type"] = "AES"
|
|
175
|
+
|
|
176
|
+
data_section = next(
|
|
177
|
+
(
|
|
178
|
+
s
|
|
179
|
+
for s in pe.sections
|
|
180
|
+
if s.Name.decode().strip("\x00").lower() == ".data"
|
|
181
|
+
),
|
|
182
|
+
None,
|
|
183
|
+
)
|
|
184
|
+
if data_section:
|
|
185
|
+
# First 16 bytes = 4 pointers
|
|
186
|
+
pointers_raw = pe.get_data(data_section.VirtualAddress, 16)
|
|
187
|
+
if len(pointers_raw) == 16:
|
|
188
|
+
ptrs = struct.unpack("4I", pointers_raw)
|
|
189
|
+
extracted = []
|
|
190
|
+
|
|
191
|
+
for ptr in ptrs:
|
|
192
|
+
rva = ptr - image_base
|
|
193
|
+
if 0 < rva < pe.OPTIONAL_HEADER.SizeOfImage:
|
|
194
|
+
extracted.append(pe.get_string_at_rva(rva))
|
|
195
|
+
else:
|
|
196
|
+
extracted.append(b"")
|
|
197
|
+
|
|
198
|
+
if len(extracted) == 4:
|
|
199
|
+
config_dict["payload_guid_1"] = decode_and_decrypt(
|
|
200
|
+
extracted[0], key_str
|
|
201
|
+
)
|
|
202
|
+
config_dict["payload_guid_2"] = decode_and_decrypt(
|
|
203
|
+
extracted[1], key_str
|
|
204
|
+
)
|
|
205
|
+
config_dict["fake_c2"] = decode_and_decrypt(extracted[2], key_str)
|
|
206
|
+
|
|
207
|
+
real_c2 = decode_and_decrypt(extracted[3], key_str)
|
|
208
|
+
config_dict["CNCs"] = [f"https://{real_c2}"]
|
|
177
209
|
|
|
178
210
|
return config_dict
|
|
179
211
|
|
|
@@ -182,5 +214,4 @@ if __name__ == "__main__":
|
|
|
182
214
|
import sys
|
|
183
215
|
|
|
184
216
|
with open(sys.argv[1], "rb") as f:
|
|
185
|
-
|
|
186
|
-
print(config_json)
|
|
217
|
+
print(json.dumps(extract_config(f.read()), indent=4))
|
|
@@ -14,17 +14,14 @@ rule SmokeLoader
|
|
|
14
14
|
{
|
|
15
15
|
meta:
|
|
16
16
|
author = "kevoreilly"
|
|
17
|
-
description = "SmokeLoader
|
|
18
|
-
cape_type = "SmokeLoader Payload"
|
|
17
|
+
description = "SmokeLoader Config Extraction"
|
|
19
18
|
strings:
|
|
20
|
-
$
|
|
21
|
-
$
|
|
22
|
-
$fetch_c2_64 = {74 ?? B? E8 03 00 00 B9 58 02 00 00 FF [5] 48 FF C? 75 F0 [6-10] 48 8D 05}
|
|
19
|
+
$fetch_c2_64_1 = {74 ?? B? E8 03 00 00 B9 58 02 00 00 FF [5] 48 (FF C?|83 EF 01) 75 (F0|EF) [6-10] 48 8D 05}
|
|
20
|
+
$fetch_c2_64_2 = {74 ?? B? E8 03 00 00 B9 58 02 00 00 FF [5] 48 (FF C?|83 EF 01) 75 (F0|EF) 33 C9 E8}
|
|
23
21
|
$fetch_c2_32 = {8B 96 [2] (00|01) 00 8B CE 5E 8B 14 95 [4] E9}
|
|
24
22
|
condition:
|
|
25
|
-
|
|
23
|
+
any of them
|
|
26
24
|
}
|
|
27
|
-
|
|
28
25
|
"""
|
|
29
26
|
|
|
30
27
|
yara_rules = yara.compile(source=rule_source)
|
|
@@ -69,7 +66,7 @@ def extract_config(filebuf):
|
|
|
69
66
|
continue
|
|
70
67
|
for item in match.strings:
|
|
71
68
|
for instance in item.instances:
|
|
72
|
-
if "$
|
|
69
|
+
if "$fetch_c2_64_1" in item.identifier:
|
|
73
70
|
match_offset = (int(instance.offset) & 0xFFFF) + instance.matched_length
|
|
74
71
|
try:
|
|
75
72
|
c2list_offset = (
|
|
@@ -78,6 +75,17 @@ def extract_config(filebuf):
|
|
|
78
75
|
except Exception:
|
|
79
76
|
break
|
|
80
77
|
delta = 8
|
|
78
|
+
if "$fetch_c2_64_2" in item.identifier:
|
|
79
|
+
match_offset = (int(instance.offset) & 0xFFFF) + instance.matched_length
|
|
80
|
+
try:
|
|
81
|
+
func = (
|
|
82
|
+
struct.unpack("<I", filebuf[match_offset : match_offset + 4])[0] + match_offset + 4
|
|
83
|
+
) & 0xFFFF
|
|
84
|
+
c2list_pointer = struct.unpack("i", filebuf[func+11:func+15])[0]+func+15
|
|
85
|
+
c2list_offset = struct.unpack("H", filebuf[c2list_pointer:c2list_pointer+2])[0]
|
|
86
|
+
except Exception:
|
|
87
|
+
break
|
|
88
|
+
delta = 8
|
|
81
89
|
if "$fetch_c2_32" in item.identifier:
|
|
82
90
|
match_offset = (int(instance[0]) & 0xFFFF) + 12
|
|
83
91
|
try:
|
|
@@ -15,14 +15,15 @@
|
|
|
15
15
|
DESCRIPTION = "Zloader configuration parser"
|
|
16
16
|
AUTHOR = "kevoreilly"
|
|
17
17
|
|
|
18
|
+
import json
|
|
18
19
|
import logging
|
|
20
|
+
import re
|
|
19
21
|
import socket
|
|
20
22
|
import struct
|
|
21
23
|
|
|
22
24
|
import pefile
|
|
23
|
-
from Cryptodome.Cipher import ARC4
|
|
24
|
-
|
|
25
25
|
import yara
|
|
26
|
+
from Cryptodome.Cipher import ARC4
|
|
26
27
|
|
|
27
28
|
log = logging.getLogger(__name__)
|
|
28
29
|
|
|
@@ -59,6 +60,20 @@ rule Zloader2024
|
|
|
59
60
|
condition:
|
|
60
61
|
uint16(0) == 0x5A4D and $conf_1 and 2 of ($confkey_*)
|
|
61
62
|
}
|
|
63
|
+
|
|
64
|
+
rule Zloader2025
|
|
65
|
+
{
|
|
66
|
+
meta:
|
|
67
|
+
author = "enzok"
|
|
68
|
+
description = "Zloader Payload"
|
|
69
|
+
cape_type = "Zloader Payload"
|
|
70
|
+
strings:
|
|
71
|
+
$conf = {4? 01 ?? [4] E8 [4] 4? 8D 15 [4] 4? 89 ?? 4? 89 ?? E8 [4] C7 46 30 00 00 00 00 8B 7E 34}
|
|
72
|
+
$confkey_1 = {4? 01 ?? [2] E8 [4] 4? 8D 15 [4] 4? 89 ?? 4? 89 ?? E8 [4] C7 46 34 00 00 00 00 8B 46 38}
|
|
73
|
+
$confkey_2 = {4? 01 ?? [2] E8 [4] 4? 8D 15 [4] 4? 89 ?? 4? 89 ?? E8 [4] C7 46 38 00 00 00 00 48 83 C4 28}
|
|
74
|
+
condition:
|
|
75
|
+
uint16(0) == 0x5A4D and $conf and all of ($confkey_*)
|
|
76
|
+
}
|
|
62
77
|
"""
|
|
63
78
|
MAX_STRING_SIZE = 32
|
|
64
79
|
|
|
@@ -71,41 +86,73 @@ def decrypt_rc4(key, data):
|
|
|
71
86
|
|
|
72
87
|
|
|
73
88
|
def string_from_offset(data, offset):
|
|
74
|
-
return data[offset
|
|
89
|
+
return data[offset: offset + MAX_STRING_SIZE].split(b"\0", 1)[0]
|
|
90
|
+
|
|
75
91
|
|
|
92
|
+
def parse_config(data, version=None):
|
|
93
|
+
for i in range(len(data) - 3, -1, -1):
|
|
94
|
+
if data[i : i + 3] == b"\x00\x00\x00":
|
|
95
|
+
data = data[:i]
|
|
96
|
+
break
|
|
76
97
|
|
|
77
|
-
def parse_config(data):
|
|
78
98
|
parsed = {}
|
|
79
|
-
|
|
80
|
-
|
|
99
|
+
net_params = []
|
|
100
|
+
dns_ips = []
|
|
101
|
+
tls_sni = ""
|
|
102
|
+
cryptokey = ""
|
|
103
|
+
fields = [part.strip() for part in data.split(b'\x00') if part and part.strip()]
|
|
104
|
+
parsed["botnet"] = fields[0].decode("utf-8") if len(fields) > 0 else ""
|
|
105
|
+
parsed["campaign"] = fields[1].decode("utf-8") if len(fields) > 1 else ""
|
|
81
106
|
c2s = []
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
107
|
+
for f in fields:
|
|
108
|
+
if f.startswith(b"http"):
|
|
109
|
+
f = f.decode("utf-8")
|
|
110
|
+
if "~" in f:
|
|
111
|
+
tls_sni, f = map(str.strip, f.split("~", 1))
|
|
112
|
+
|
|
113
|
+
if f:
|
|
114
|
+
c2s.append(f)
|
|
115
|
+
|
|
116
|
+
elif b"PUBLIC KEY" in f:
|
|
117
|
+
cryptokey = f.decode("utf-8").replace("\n", "")
|
|
118
|
+
|
|
119
|
+
elif version == 3 and b"\x08\x08" in f and len(f) % 4 == 0:
|
|
120
|
+
idx = 0
|
|
121
|
+
for i in range(len(f) // 4):
|
|
122
|
+
dns_ips.append(socket.inet_ntoa(f[idx: idx + 4]))
|
|
123
|
+
idx += 4
|
|
124
|
+
|
|
125
|
+
elif version == 4 and f.startswith(b"[") and f.endswith(b"]"):
|
|
126
|
+
try:
|
|
127
|
+
params = json.loads(f)
|
|
128
|
+
for param in params:
|
|
129
|
+
proto = param.get("proto", "unknown")
|
|
130
|
+
ip = param.get("ip", "")
|
|
131
|
+
port = param.get("port", 0)
|
|
132
|
+
qps = param.get("qps", "")
|
|
133
|
+
net_params.append(f"{proto}, {ip}:{port}, qps={qps}".strip())
|
|
134
|
+
|
|
135
|
+
except json.JSONDecodeError:
|
|
136
|
+
params = None
|
|
137
|
+
|
|
88
138
|
parsed["CNCs"] = c2s
|
|
89
|
-
parsed["cryptokey"] =
|
|
139
|
+
parsed["cryptokey"] = cryptokey
|
|
90
140
|
parsed["cryptokey_type"] = "RSA Public Key"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
dns_ips.append(socket.inet_ntoa(chunk))
|
|
102
|
-
parsed["DNS Servers"] = dns_ips
|
|
141
|
+
raw = parsed["raw"] = {}
|
|
142
|
+
if tls_sni:
|
|
143
|
+
raw["tls sni"] = tls_sni
|
|
144
|
+
|
|
145
|
+
if net_params:
|
|
146
|
+
raw["dns config"] = net_params
|
|
147
|
+
|
|
148
|
+
if dns_ips:
|
|
149
|
+
raw["dns ips"] = dns_ips
|
|
150
|
+
|
|
103
151
|
return parsed
|
|
104
152
|
|
|
105
153
|
|
|
106
154
|
def extract_config(filebuf):
|
|
107
155
|
config = {}
|
|
108
|
-
end_config = {}
|
|
109
156
|
pe = pefile.PE(data=filebuf, fast_load=False)
|
|
110
157
|
image_base = pe.OPTIONAL_HEADER.ImageBase
|
|
111
158
|
matches = yara_rules.match(data=filebuf)
|
|
@@ -113,7 +160,7 @@ def extract_config(filebuf):
|
|
|
113
160
|
return
|
|
114
161
|
conf_type = ""
|
|
115
162
|
decrypt_key = ""
|
|
116
|
-
conf_size =
|
|
163
|
+
conf_size = None
|
|
117
164
|
for match in matches:
|
|
118
165
|
if match.rule == "Zloader":
|
|
119
166
|
for item in match.strings:
|
|
@@ -137,17 +184,23 @@ def extract_config(filebuf):
|
|
|
137
184
|
elif "$decrypt_key_3" == item.identifier:
|
|
138
185
|
decrypt_key = item.instances[0].offset
|
|
139
186
|
kva_s = 3
|
|
187
|
+
break
|
|
188
|
+
|
|
140
189
|
elif match.rule == "Zloader2024":
|
|
141
|
-
conf_size =
|
|
190
|
+
conf_size = None
|
|
142
191
|
rc4_chunk1 = None
|
|
143
192
|
rc4_chunk2 = None
|
|
144
193
|
numchunks = 0
|
|
145
194
|
for item in match.strings:
|
|
146
|
-
|
|
195
|
+
item_id = item.identifier
|
|
196
|
+
if item_id == "$conf_1":
|
|
147
197
|
decrypt_conf = item.instances[0].offset + 6
|
|
148
198
|
conf_size = item.instances[0].offset + 12
|
|
199
|
+
if conf_size > 2048:
|
|
200
|
+
conf_size = 2048
|
|
201
|
+
|
|
149
202
|
conf_type = "3"
|
|
150
|
-
elif
|
|
203
|
+
elif item_id.startswith("$confkey_") and numchunks < 2:
|
|
151
204
|
matched_data = item.instances[0].matched_data[:2]
|
|
152
205
|
if matched_data == b"\x48\x8D":
|
|
153
206
|
offset = 3
|
|
@@ -161,11 +214,32 @@ def extract_config(filebuf):
|
|
|
161
214
|
rc4_chunk2 = chunk_offset
|
|
162
215
|
|
|
163
216
|
numchunks += 1
|
|
217
|
+
break
|
|
218
|
+
|
|
219
|
+
elif match.rule == "Zloader2025":
|
|
220
|
+
conf_size = None
|
|
221
|
+
rc4_chunk1 = None
|
|
222
|
+
rc4_chunk2 = None
|
|
223
|
+
for item in match.strings:
|
|
224
|
+
item_id = item.identifier
|
|
225
|
+
if item_id == "$conf":
|
|
226
|
+
decrypt_conf = item.instances[0].offset + 15
|
|
227
|
+
size_base_offset = item.instances[0].offset + 5
|
|
228
|
+
call_func_offset = item.instances[0].offset + 7
|
|
229
|
+
call_func_size_offset = call_func_offset + 1
|
|
230
|
+
conf_type = "4"
|
|
231
|
+
|
|
232
|
+
elif item_id == "$confkey_1":
|
|
233
|
+
rc4_chunk1 = item.instances[0].offset + 13
|
|
234
|
+
|
|
235
|
+
elif item_id == "$confkey_2":
|
|
236
|
+
rc4_chunk2 = item.instances[0].offset + 13
|
|
237
|
+
break
|
|
164
238
|
|
|
165
239
|
if conf_type == "1":
|
|
166
|
-
va = struct.unpack("I", filebuf[decrypt_conf
|
|
240
|
+
va = struct.unpack("I", filebuf[decrypt_conf: decrypt_conf + 4])[0]
|
|
167
241
|
key = string_from_offset(filebuf, pe.get_offset_from_rva(va - image_base))
|
|
168
|
-
data_offset = pe.get_offset_from_rva(struct.unpack("I", filebuf[decrypt_conf + 5
|
|
242
|
+
data_offset = pe.get_offset_from_rva(struct.unpack("I", filebuf[decrypt_conf + 5: decrypt_conf + 9])[0] - image_base)
|
|
169
243
|
enc_data = filebuf[data_offset:].split(b"\0\0", 1)[0]
|
|
170
244
|
raw = decrypt_rc4(key, enc_data)
|
|
171
245
|
items = list(filter(None, raw.split(b"\x00\x00")))
|
|
@@ -178,15 +252,17 @@ def extract_config(filebuf):
|
|
|
178
252
|
elif len(item) == 16:
|
|
179
253
|
config["cryptokey"] = item
|
|
180
254
|
config["cryptokey_type"] = "RC4"
|
|
255
|
+
|
|
181
256
|
elif conf_type == "2" and decrypt_key:
|
|
182
|
-
|
|
257
|
+
conf_size = 1020
|
|
258
|
+
conf_va = struct.unpack("I", filebuf[decrypt_conf + cva: decrypt_conf + cva + 4])[0]
|
|
183
259
|
conf_offset = pe.get_offset_from_rva(conf_va + pe.get_rva_from_offset(decrypt_conf) + cva + 4)
|
|
184
260
|
# if not conf_size:
|
|
185
261
|
# conf_size = struct.unpack("I", filebuf[decrypt_key + size_s : decrypt_key + size_s + 4])[0]
|
|
186
|
-
key_va = struct.unpack("I", filebuf[decrypt_key + kva_s
|
|
262
|
+
key_va = struct.unpack("I", filebuf[decrypt_key + kva_s: decrypt_key + kva_s + 4])[0]
|
|
187
263
|
key_offset = pe.get_offset_from_rva(key_va + pe.get_rva_from_offset(decrypt_key) + kva_s + 4)
|
|
188
264
|
key = string_from_offset(filebuf, key_offset)
|
|
189
|
-
conf_data = filebuf[conf_offset
|
|
265
|
+
conf_data = filebuf[conf_offset: conf_offset + conf_size]
|
|
190
266
|
raw = decrypt_rc4(key, conf_data)
|
|
191
267
|
items = list(filter(None, raw.split(b"\x00\x00")))
|
|
192
268
|
config["botnet"] = items[0].decode("utf-8")
|
|
@@ -198,25 +274,56 @@ def extract_config(filebuf):
|
|
|
198
274
|
elif b"PUBLIC KEY" in item:
|
|
199
275
|
config["cryptokey"] = item.decode("utf-8").replace("\n", "")
|
|
200
276
|
config["cryptokey_type"] = "RSA Public key"
|
|
277
|
+
|
|
201
278
|
elif conf_type == "3" and rc4_chunk1 and rc4_chunk2:
|
|
202
|
-
conf_va = struct.unpack("I", filebuf[decrypt_conf
|
|
279
|
+
conf_va = struct.unpack("I", filebuf[decrypt_conf: decrypt_conf + 4])[0]
|
|
203
280
|
conf_offset = pe.get_offset_from_rva(conf_va + pe.get_rva_from_offset(decrypt_conf) + 4)
|
|
204
|
-
conf_data = filebuf[conf_offset
|
|
205
|
-
keychunk1_va = struct.unpack("I", filebuf[rc4_chunk1
|
|
281
|
+
conf_data = filebuf[conf_offset: conf_offset + conf_size]
|
|
282
|
+
keychunk1_va = struct.unpack("I", filebuf[rc4_chunk1: rc4_chunk1 + 4])[0]
|
|
206
283
|
keychunk1_offset = pe.get_offset_from_rva(keychunk1_va + pe.get_rva_from_offset(rc4_chunk1) + 4)
|
|
207
|
-
keychunk1 = filebuf[keychunk1_offset
|
|
208
|
-
keychunk2_va = struct.unpack("I", filebuf[rc4_chunk2
|
|
284
|
+
keychunk1 = filebuf[keychunk1_offset: keychunk1_offset + 16]
|
|
285
|
+
keychunk2_va = struct.unpack("I", filebuf[rc4_chunk2: rc4_chunk2 + 4])[0]
|
|
209
286
|
keychunk2_offset = pe.get_offset_from_rva(keychunk2_va + pe.get_rva_from_offset(rc4_chunk2) + 4)
|
|
210
|
-
keychunk2 = filebuf[keychunk2_offset
|
|
287
|
+
keychunk2 = filebuf[keychunk2_offset: keychunk2_offset + 16]
|
|
211
288
|
decrypt_key = bytes(a ^ b for a, b in zip(keychunk1, keychunk2))
|
|
212
289
|
conf = decrypt_rc4(decrypt_key, conf_data)
|
|
213
|
-
|
|
290
|
+
config = parse_config(conf, 3)
|
|
291
|
+
|
|
292
|
+
elif conf_type == "4" and rc4_chunk1 and rc4_chunk2:
|
|
293
|
+
conf_va = struct.unpack("I", filebuf[decrypt_conf: decrypt_conf + 4])[0]
|
|
294
|
+
conf_offset = pe.get_offset_from_rva(conf_va + pe.get_rva_from_offset(decrypt_conf) + 4)
|
|
295
|
+
call_rva = pe.get_rva_from_offset(call_func_offset)
|
|
296
|
+
call_target_rva = call_rva + 5 + struct.unpack("i", filebuf[call_func_size_offset: call_func_size_offset + 4])[0]
|
|
297
|
+
call_target_offset = pe.get_offset_from_rva(call_target_rva)
|
|
298
|
+
function_tail = b"\x5F\x5E\xC3"
|
|
299
|
+
index = filebuf.find(function_tail, call_target_offset)
|
|
300
|
+
if index != -1:
|
|
301
|
+
index += 256
|
|
302
|
+
|
|
303
|
+
function_end_offset = index + len(function_tail)
|
|
304
|
+
function_data = filebuf[call_target_offset: function_end_offset]
|
|
305
|
+
pattern = re.compile(b"\x66\x81\xF1..\x66\x89\x4D.", re.DOTALL)
|
|
306
|
+
key = 0
|
|
307
|
+
for match in pattern.finditer(function_data):
|
|
308
|
+
off = match.start()
|
|
309
|
+
key = struct.unpack_from("<H", function_data, off + 3)[0]
|
|
214
310
|
|
|
215
|
-
|
|
216
|
-
|
|
311
|
+
size_base = struct.unpack_from("<H", filebuf[size_base_offset: size_base_offset + 2])[0]
|
|
312
|
+
conf_size = size_base ^ key & 0xFFFF
|
|
313
|
+
conf_data = filebuf[conf_offset: conf_offset + conf_size]
|
|
314
|
+
keychunk1_va = struct.unpack("I", filebuf[rc4_chunk1: rc4_chunk1 + 4])[0]
|
|
315
|
+
keychunk1_offset = pe.get_offset_from_rva(keychunk1_va + pe.get_rva_from_offset(rc4_chunk1) + 4)
|
|
316
|
+
keychunk1 = filebuf[keychunk1_offset: keychunk1_offset + 16]
|
|
317
|
+
keychunk2_va = struct.unpack("I", filebuf[rc4_chunk2: rc4_chunk2 + 4])[0]
|
|
318
|
+
keychunk2_offset = pe.get_offset_from_rva(keychunk2_va + pe.get_rva_from_offset(rc4_chunk2) + 4)
|
|
319
|
+
keychunk2 = filebuf[keychunk2_offset: keychunk2_offset + 16]
|
|
320
|
+
decrypt_key = bytes(a ^ b for a, b in zip(keychunk1, keychunk2))
|
|
321
|
+
conf = decrypt_rc4(decrypt_key, conf_data)
|
|
322
|
+
config = parse_config(conf, 4)
|
|
217
323
|
|
|
218
324
|
return config
|
|
219
325
|
|
|
326
|
+
|
|
220
327
|
if __name__ == "__main__":
|
|
221
328
|
import sys
|
|
222
329
|
from pathlib import Path
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/CobaltStrikeBeacon.py
RENAMED
|
File without changes
|
{cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/CobaltStrikeStager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cape_parsers-0.1.57 → cape_parsers-0.1.59}/cape_parsers/CAPE/community/PhemedroneStealer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|