zloader/zloader.py (39 lines of code) (raw):
import logging
from malduck import rc4
from malduck.extractor import Extractor
from malduck.procmem import ProcessMemory
from malduck.yara import YaraRuleMatch
from ..utils import Config, get_rule_metadata
# A Code Cleanup / Port of kevoreilly's ZLoader Configuration to Malduck
# https://github.com/kevoreilly/CAPEv2/blob/master/modules/processing/parsers/mwcp/Zloader.py
log = logging.getLogger(__name__)
__author__ = "c3rb3ru5"
__version__ = "1.0.0"
class ZLoader(Extractor):
"""
A ZLoader Configuration Extractor
"""
family: str = "zloader"
yara_rules = ("zloader",)
@Extractor.rule
def zloader(self, p: ProcessMemory, match: YaraRuleMatch) -> Config | bool:
_info: Config = get_rule_metadata(match)
return _info
@Extractor.extractor("decrypt_conf")
def decrypt_conf(self, p: ProcessMemory, addr: int) -> Config | bool:
conf: Config = {"family": self.family, self.family: {}}
try:
key_addr = p.uint32v(addr + 21)
if not key_addr:
return conf
key = p.asciiz(key_addr)
data_offset = p.uint32v(addr + 26)
if not data_offset:
return conf
config_encrypted = p.readv(addr=data_offset).split(b"\0\0")[0]
config_raw = rc4(key, config_encrypted)
config_items = list(filter(None, config_raw.split(b"\x00\x00")))
for i in range(0, len(config_items)):
config_items[i] = config_items[i].strip(b"\x00")
conf[self.family]["name"] = config_items[1].decode("utf-8")
conf[self.family]["campaign_id"] = config_items[2].decode("utf-8")
conf[self.family]["urls"] = [config_items[3].decode("utf-8")]
except Exception as error:
log.warning(error)
return False
return conf