Skip to content

Instantly share code, notes, and snippets.

@FernandoDoming
Created January 26, 2024 18:49
Show Gist options
  • Save FernandoDoming/0599de3ef6e8d8fe0cfb747b09e9d099 to your computer and use it in GitHub Desktop.
Save FernandoDoming/0599de3ef6e8d8fe0cfb747b09e9d099 to your computer and use it in GitHub Desktop.
import logging
import yara
import struct
import pefile
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
yaraf = "/opt/CAPEv2/data/yara/CAPE/QuantLoader.yar"
decrypt_config_offsets = {
"cnc1": (148, 152),
"url_param1": (176, 180),
"url_param2": (224, 228),
"url_param3": (281, 285),
"url_param4": (329, 333),
"url_param5": (424, 428),
}
def read_cstr(data, offset):
_str = b""
i = offset
while data[i] != 0:
_str += data[i:i+1]
i += 1
return _str
def decode(data, key):
result = list()
m = bytes(data)
k = bytes(key)
for i, value in enumerate(m):
result.append(value - k[i % len(k)])
return bytes(result)
def extract_config(data):
config = {}
rule = yara.compile(filepath=yaraf)
matches = rule.match(data=data)
pe = pefile.PE(data=data, fast_load=False)
image_base = pe.OPTIONAL_HEADER.ImageBase
for m in matches:
# $decryptstring
for str_match in m.strings:
match_id = str_match[1]
rawdata = str_match[2]
if match_id != "$decryptstring":
continue
key_vaddr = struct.unpack("<I", rawdata[59:63])[0]
key_offset = pe.get_offset_from_rva(key_vaddr - image_base)
key = read_cstr(data, key_offset)
key = key[1:] + b"\x00"
config["string_key"] = key
# $configdecrypt
for str_match in m.strings:
match_id = str_match[1]
rawdata = str_match[2]
if match_id != "$configdecrypt":
continue
for ioc, offset in decrypt_config_offsets.items():
try:
vaddr = struct.unpack("<I", rawdata[offset[0]:offset[1]])[0]
offset = pe.get_offset_from_rva(vaddr - image_base)
_str = read_cstr(data, offset)
_str = decode(_str, config["string_key"])
if _str:
config[ioc] = _str
except Exception:
continue
return config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment