icedid/icedid.py (39 lines of code) (raw):
import logging
from malduck import xor
from malduck.extractor import Extractor
from malduck.procmem import ProcessMemory
from malduck.yara import YaraRuleMatch
from ..utils import Config, get_rule_metadata
log = logging.getLogger(__name__)
class IcedID(Extractor):
family: str = "IcedID"
yara_rules = ("icedid",)
@Extractor.rule
def icedid(self, p: ProcessMemory, match: YaraRuleMatch) -> Config | bool:
_info: Config = get_rule_metadata(match)
return _info
@Extractor.extractor("config_decryption")
def icedid_config(self, p: ProcessMemory, addr: int):
log.info(
"[+] IcedID loader config decryption YARA signature matched @ %X", addr
)
conf: Config = {}
conf[self.family] = {}
try:
hit = p.uint32v(addr - 3)
if not hit:
return conf
config_location = hit + addr + 1
config_blob = p.readv(config_location, 250)
key = config_blob[:32]
conf["key"] = key.hex()
data = config_blob[64:96]
decrypted_config = xor(key, data)
campaign_id = decrypted_config[:4]
campaign_id = int.from_bytes(campaign_id, "little")
raw = decrypted_config[4:]
domains = [x.decode("UTF-8") for x in raw.split(b"\x00")]
conf[self.family] = {"domains": domains, "campaign_id": campaign_id}
except Exception as err:
log.error(err)
return conf