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
