tools/icedid/gzip-variant/extract_payloads_from_core.py (77 lines of code) (raw):

# coding: utf-8 import yara import capstone import argparse import pathlib import lief import os from nightmare.malware.icedid import crypto from nightmare import utils RULES = yara.compile(os.path.join(os.path.dirname(__file__), "core_payloads.yar")) SIZE = 0x100 def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("input", type=str, help="Input file") parser.add_argument("output", type=pathlib.Path, help="Output directory") return parser.parse_args() def find_browser_hook_payloads(pe: lief.Binary, address) -> list[tuple[int, int]]: cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) cs.detail = True code = bytes(pe.get_content_from_virtual_address(address, SIZE)) instructions = list(cs.disasm(code, address, SIZE)) result = list() for i, instruction in enumerate(instructions): if 2 == len(result): break if "lea" == instruction.mnemonic: payload_address = ( instruction.operands[1].mem.disp + instruction.address + instruction.size ) size = instructions[i + 1].operands[1].imm result.append((payload_address, size)) return result def get_browser_hook_payloads(pe: lief.Binary, address: int) -> list[bytes]: result = list() payloads_info = find_browser_hook_payloads(pe, address) if not payloads_info: raise RuntimeError("Failed to find browser hook payloads' location") elif 1 == len(payloads_info): print("Only 1/2 browser hook payloads' location has been found") for i, (payload_address, payload_size) in enumerate(payloads_info): if not ( payload := crypto.decrypt_0( bytes( pe.get_content_from_virtual_address(payload_address, payload_size) ) ) ): print(f"Failed to decrypt payload #{i}.") continue result.append(payload) return result def get_payloads(path: str) -> dict[str, bytes]: result = dict() if not (match := RULES.match(path)): raise RuntimeError("Failed to find core's functions") core = lief.parse(path) for string in match[0].strings: match string.identifier: case "$browser_hook_payloads_decryption": for i, payload in enumerate( get_browser_hook_payloads( core, core.offset_to_virtual_address(string.instances[0].offset) + core.imagebase, ) ): result[f"browser_hook_payload_{i}.cpe"] = payload case _: continue return result def main() -> None: args = parse_arguments() args.output.mkdir(exist_ok=True) utils.write_files(args.output, get_payloads(args.input)) if __name__ == "__main__": main()