Created
November 18, 2020 19:12
-
-
Save FernandoDoming/753151d3e2fbf9260dcd58aa23dddec4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (C) 2010-2015 Cuckoo Foundation. | |
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org | |
# This signature was contributed by RedSocks - http://redsocks.nl | |
# See the file 'docs/LICENSE' for copying permission. | |
import struct | |
from builtins import bytes | |
from lib.cuckoo.common.abstracts import Signature | |
class QuantloaderDump(Signature): | |
name = "quantloader_dump" | |
description = "Quantloader detected - Configuration dumped" | |
severity = 5 | |
categories = ["trojan", "loader"] | |
families = ["quantloader"] | |
authors = ["FDD"] | |
minimum = "2.0" | |
procmem = None | |
decrypt_config_offsets = { | |
"cnc1": (148, 152), | |
"url_param1": (176, 180), | |
"url_param2": (224, 228), | |
"url_param3": (281, 285), | |
"url_param4": (329, 333), | |
"url_param5": (424, 428), | |
} | |
# ============== Generic memory management functions ============== | |
def get_region(self, addr): | |
if not self.procmem: | |
return None | |
for region in self.procmem["regions"]: | |
if addr >= int(region["addr"], 16) and addr <= int(region["end"], 16): | |
return region | |
return None | |
def get_region_from_offset(self, offset): | |
if not self.procmem: | |
return None | |
for region in self.procmem["regions"]: | |
if offset >= region["offset"] and offset <= region["offset"] + region["size"]: | |
return region | |
return None | |
def offset_to_rva(self, offset): | |
data = None | |
if not self.procmem: | |
return data | |
region = self.get_region_from_offset(offset) | |
if not region: | |
return data | |
region_offset = offset - region["offset"] | |
rva = int(region["addr"], 16) + region_offset | |
return rva | |
def deref(self, addr, size): | |
data = None | |
if not self.procmem: | |
return data | |
region = self.get_region(addr) | |
if not region: | |
return data | |
rva = addr - int(region["addr"], 16) | |
f = open(self.procmem["file"]) | |
f.seek(region["offset"] + rva) | |
data = f.read(size) | |
f.close() | |
return data | |
def deref_string(self, addr): | |
data = "" | |
p = addr | |
while True: | |
byte = self.deref(p, 1) | |
if byte == '\x00' or byte is None: | |
return data | |
p += 1 | |
data += byte | |
return data | |
def read_offset(self, offset, len): | |
f = open(self.procmem["file"]) | |
f.seek(offset) | |
data = f.read(len) | |
f.close() | |
return data | |
# ============== Malware specific functions ============== | |
def decode(self, data, key): | |
result = list() | |
m = bytes(data) | |
k = bytes(key) | |
for i in range(0, len(m)): | |
result.append(m[i] - k[i % len(k)]) | |
return bytes(result) | |
# ======================== Main =========================== | |
def on_complete(self): | |
config = {} | |
for procmem in self.get_results("procmemory", []): | |
for yara_matches in procmem.get("yara", []): | |
if yara_matches["name"] != "QuantLoaderCfg": | |
continue | |
self.procmem = procmem | |
rawdata = self.read_offset(yara_matches["offsets"]["decryptstring"][0][0], 150) | |
keyaddr = struct.unpack("<I", rawdata[59:63])[0] | |
key = self.deref_string(keyaddr) | |
if not key: | |
continue | |
key = key[1:] + "\x00" | |
config["string_key"] = key | |
cfg_decrypt_addr = yara_matches["offsets"]["configdecrypt"][0][0] | |
asm = self.read_offset(cfg_decrypt_addr, 512) | |
for ioc, offset in self.decrypt_config_offsets.iteritems(): | |
try: | |
addr = struct.unpack("<I", asm[offset[0]:offset[1]])[0] | |
_str = self.deref_string(addr) | |
_str = self.decode(_str, key) | |
if _str: | |
config[ioc] = _str | |
except Exception: | |
continue | |
config["family"] = "quantloader" | |
self.marks.append({ | |
"type": "config", | |
"config": config | |
}) | |
return self.has_marks() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment