diff --git a/README.md b/README.md index 8eb3c9214..658b1bb8f 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Currently CAPE has specific packages dumping configuration and payloads for the - Sedreco - Cerber - Ursnif +- TrickBot CAPE has config parsers/decoders for the following malware families, whose payloads are extracted by a behavioural package: - RedLeaf @@ -36,7 +37,6 @@ CAPE has config parsers/decoders for the following malware families, whose paylo - HttpBrowser - Enfal - PoisonIvy -- TrickBot - RCSession/Screech CAPE also has Yara signatures to detect payloads that are extracted by a behavioural package. This list is growing, and includes: diff --git a/analyzer/windows/modules/packages/TrickBot.py b/analyzer/windows/modules/packages/TrickBot.py new file mode 100644 index 000000000..885df5263 --- /dev/null +++ b/analyzer/windows/modules/packages/TrickBot.py @@ -0,0 +1,45 @@ +# Copyright (C) 2010-2015 Cuckoo Foundation, Optiv, Inc. (brad.spengler@optiv.com) +# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org +# See the file 'docs/LICENSE' for copying permission. + +import os +import shutil +from subprocess import call +from lib.common.abstracts import Package + +class TrickBot(Package): + """TrickBot package (derived from Dump-on-API)""" + + def __init__(self, options={}, config=None): + """@param options: options dict.""" + self.config = config + self.options = options + self.pids = [] + self.options["dll"] = "DumpOnAPI.dll" + self.options["dll_64"] = "DumpOnAPI_x64.dll" + self.options["dump-on-api"] = "SetUnhandledExceptionFilter" + + def start(self, path): + args = self.options.get("arguments") + appdata = self.options.get("appdata") + runasx86 = self.options.get("runasx86") + + # If the file doesn't have an extension, add .exe + # See CWinApp::SetCurrentHandles(), it will throw + # an exception that will crash the app if it does + # not find an extension on the main exe's filename + if "." not in os.path.basename(path): + new_path = path + ".exe" + os.rename(path, new_path) + path = new_path + + if appdata: + # run the executable from the APPDATA directory, required for some malware + basepath = os.getenv('APPDATA') + newpath = os.path.join(basepath, os.path.basename(path)) + shutil.copy(path, newpath) + path = newpath + if runasx86: + # ignore the return value, user must have CorFlags.exe installed in the guest VM + call(["CorFlags.exe", path, "/32bit+"]) + return self.execute(path, args, path) diff --git a/data/yara/CAPE/TrickBot.yar b/data/yara/CAPE/TrickBot.yar index 1a001f87e..647abc3da 100644 --- a/data/yara/CAPE/TrickBot.yar +++ b/data/yara/CAPE/TrickBot.yar @@ -12,7 +12,8 @@ rule TrickBot $str2 = "group_tag" ascii wide $str3 = "client_id" ascii wide $code1 = {8A 11 88 54 35 F8 46 41 4F 89 4D F0 83 FE 04 0F 85 7E 00 00 00 8A 1D ?? ?? ?? ?? 33 F6 8D 49 00 33 C9 84 DB 74 1F 8A 54 35 F8 8A C3 8D 64 24 00} - $code2 = {0F B6 54 24 49 0F B6 44 24 48 48 83 C6 03 C0 E0 02 0F B6 CA C0 E2 04 C0 F9 04 33 DB 80 E1 03 02 C8 88 4C 24 40 0F B6 4C 24 4A 0F B6 C1 C0 E1 06 02 4C 24 4B C0 F8 02 88 4C 24 42 24 0F} + $code2 = {8B 4D FC 8A D1 02 D2 8A C5 C0 F8 04 02 D2 24 03 02 C2 88 45 08 8A 45 FE 8A D0 C0 FA 02 8A CD C0 E1 04 80 E2 0F 32 D1 8B 4D F8 C0 E0 06 02 45 FF 88 55 09 66 8B 55 08 66 89 11 88 41 02} + $code3 = {0F B6 54 24 49 0F B6 44 24 48 48 83 C6 03 C0 E0 02 0F B6 CA C0 E2 04 C0 F9 04 33 DB 80 E1 03 02 C8 88 4C 24 40 0F B6 4C 24 4A 0F B6 C1 C0 E1 06 02 4C 24 4B C0 F8 02 88 4C 24 42 24 0F} condition: any of ($ua*) or all of ($str*) or any of ($code*) } diff --git a/modules/reporting/submitCAPE.py b/modules/reporting/submitCAPE.py index ff2cf7f7a..f4e84a2d3 100644 --- a/modules/reporting/submitCAPE.py +++ b/modules/reporting/submitCAPE.py @@ -34,7 +34,7 @@ "Cerber", "Compression", "Compression_dll", "Compression_doc", "Compression_zip", "DumpOnAPI", "Doppelganging", "EvilGrab", "Extraction", "Extraction_dll", "Extraction_regsvr", "Extraction_zip", "Extraction_ps1", "Injection", "Injection_dll", "Injection_doc", "Injection_pdf", "Injection_zip", "Injection_ps1", "PlugX", "PlugXPayload", "PlugX_dll", "PlugX_doc", - "PlugX_zip", "Sedreco", "Sedreco_dll", "Shellcode-Extraction", "UPX", "UPX_dll", "Ursnif" + "PlugX_zip", "Sedreco", "Sedreco_dll", "Shellcode-Extraction", "TrickBot", "UPX", "UPX_dll", "Ursnif" ]; def pirpi_password(strings): @@ -77,6 +77,9 @@ def process_cape_yara(self, cape_yara, detections): self.task_options_stack.append("CAPE_var1={0}".format(decrypt64_2)) detections.add('Ursnif') + if cape_yara["name"] == "TrickBot": + detections.add('TrickBot') + def run(self, results): self.task_options_stack = [] self.task_options = None @@ -261,6 +264,9 @@ def run(self, results): if 'Cerber' in detections: package = 'Cerber' + if 'TrickBot' in detections: + package = 'TrickBot' + if 'Ursnif' in detections: package = 'Ursnif'