Skip to content

Instantly share code, notes, and snippets.

@LloydLabs
Last active March 4, 2024 19:28
Show Gist options
  • Save LloydLabs/d4e0ffba3ba6ccce17fafc08d9118385 to your computer and use it in GitHub Desktop.
Save LloydLabs/d4e0ffba3ba6ccce17fafc08d9118385 to your computer and use it in GitHub Desktop.
import sys
from typing import Dict, List
import malduck
import pefile
import yara
from capstone import CS_ARCH_X86, CS_MODE_64, Cs
from capstone.x86 import X86_INS_RET
from qiling import *
from qiling.const import QL_VERBOSE
from unicorn.x86_const import UC_X86_REG_RCX, UC_X86_REG_RDX
def _emotet_end_emu(ql: Qiling, address: int, size: int) -> None:
buf = ql.mem.read(address, size)
md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
for _ in filter(lambda x: x.id == X86_INS_RET, md.disasm(buf, address)):
ql.stop()
def _emotet_get_c2_pair(addr: int) -> Dict:
ip_buf = ql.mem.map_anywhere(0x4)
port_buf = ql.mem.map_anywhere(0x4)
ql.reg.write(UC_X86_REG_RCX, ip_buf)
ql.reg.write(UC_X86_REG_RDX, port_buf)
ql.hook_code(_emotet_end_emu)
ql.run(begin=addr)
c2_port = malduck.u16(ql.mem.read(port_buf, 4), offset=2)
c2_ip = malduck.ipv4(bytes(ql.mem.read(ip_buf, 4)))
if c2_ip == "0.0.0.0":
return
return {"ip": c2_ip, "port": c2_port}
def _emotet_get_c2s(ql: Qiling, path: str) -> List:
with open(path, 'rb') as f:
data = f.read()
addresses = []
pe = pefile.PE(data=data)
rule = yara.compile(source="rule load {strings: $load = {48 8D 05 ?? ?? ?? ?? 48 89 81 ?? ?? 00} condition: $load}")
matches = rule.match(data=data)
for off, _, _ in matches[0].strings:
addr = ((pe.get_rva_from_offset(off) + malduck.int32(data, offset=off + 3)) + 7) + pe.OPTIONAL_HEADER.ImageBase
if pair := _emotet_get_c2_pair(addr):
addresses.append(pair)
return addresses
if __name__ == "__main__":
if len(sys.argv) != 2:
print("emo_x64_dump.py <name>")
sys.exit(0)
ql = Qiling([sys.argv[1]], "rootfs/x8664_windows", verbose=QL_VERBOSE.DISABLED)
print(_emotet_get_c2s(ql, sys.argv[1]))
@kuax
Copy link

kuax commented May 25, 2022

I see, thanks for the feedback! In my analysis I could clearly see those were Emotet, but was surprised none of the usual sandboxes seemed to have picked it up (at least on VT)...
Another very interesting example is e17d5db1856c406f8fa55b0ec282959cf8eda1c9b697f85d47b329d4d80f4cea with only 9 detections on VT, but again it seems to me that this is clearly Emotet. I wish I had the RE skills to understand why it doesn't get picked up, what does it do so differently etc 🥲🤷🏻‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment