diff --git a/README.md b/README.md index d3c196487..8eb3c9214 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ The techniques or behaviours that CAPE detects and has packages for include: - Shellcode injection - DLL injection - Process Hollowing + - Process Doppelganging - Decompression of executable modules in memory - Extraction of executable modules or shellcode in memory @@ -38,11 +39,13 @@ CAPE has config parsers/decoders for the following malware families, whose paylo - TrickBot - RCSession/Screech -Many other malware families have their payloads extracted by some of the behavioural packages, with their configuration in the clear in the resulting output. Configuration parsing may then be performed on this by virtue of Yara-based detection, and config parsing based on either of CAPE's config parsing frameworks, the RATDecoders framework from malwareconfig.com and DC3-MWCP (Defense Cyber Crime Center - Malware Configuration Parser). The many parsers/decoders from malwareconfig.com are also included, comprising among many others: Sakula, Trickbot, DarkComet, PredatorPain and PoisonIvy. Thanks to Kevin Breen/TechAnarchy for this framework and parsers (https://github.com/kevthehermit/RATDecoders), and to DC3 for their framework (https://github.com/Defense-Cyber-Crime-Center/DC3-MWCP). - CAPE also has Yara signatures to detect payloads that are extracted by a behavioural package. This list is growing, and includes: - QtBot, ZeroT, WanaCry, Sedreco, NetTraveler, Locky, Emotet, Cerber, Ursnif, Enfal, BadRabbit, Magniber, Redsip, RCSession, Hancitor, Kronos, PetrWrap, Kovter, Azer, Petya, Dreambot, Atlas, NanoLocker, Mole, Codoso, Cryptoshield, Loki, Jaff, Dridex, RedLeaf, ChChes, EvilGrab, HttpBrowser, IcedID, Scarab +Many other malware families have their payloads extracted by some of the behavioural packages, with their configuration in the clear in the resulting output. Configuration parsing may then be performed on this by virtue of Yara-based detection, and config parsing based on either of CAPE's config parsing frameworks, the RATDecoders framework from malwareconfig.com and DC3-MWCP (Defense Cyber Crime Center - Malware Configuration Parser). The many parsers/decoders from malwareconfig.com are also included, comprising among many others: Sakula, Trickbot, DarkComet, PredatorPain and PoisonIvy. Thanks to Kevin Breen/TechAnarchy for this framework and parsers (https://github.com/kevthehermit/RATDecoders), and to DC3 for their framework (https://github.com/Defense-Cyber-Crime-Center/DC3-MWCP). + +A utility package 'DumpOnAPI' is included which allows a module to be dumped when it calls a specific API function which can be specified in the web interface. This can be useful for quickly unpacking/dumping novel samples. + There are a number of other behavioural and malware family packages and parsers currently in the works, so watch this space. Packages can be written based on API hooks, the CAPE debugger, or a combination of both. diff --git a/analyzer/windows/dll/CAPE.dll b/analyzer/windows/dll/CAPE.dll index b12b06de9..367d27a36 100644 Binary files a/analyzer/windows/dll/CAPE.dll and b/analyzer/windows/dll/CAPE.dll differ diff --git a/analyzer/windows/dll/CAPE_x64.dll b/analyzer/windows/dll/CAPE_x64.dll index 22a0c48d8..392531edd 100644 Binary files a/analyzer/windows/dll/CAPE_x64.dll and b/analyzer/windows/dll/CAPE_x64.dll differ diff --git a/analyzer/windows/dll/Doppelganging.dll b/analyzer/windows/dll/Doppelganging.dll new file mode 100644 index 000000000..a3f01711d Binary files /dev/null and b/analyzer/windows/dll/Doppelganging.dll differ diff --git a/analyzer/windows/dll/Doppelganging_x64.dll b/analyzer/windows/dll/Doppelganging_x64.dll new file mode 100644 index 000000000..ff9d311f5 Binary files /dev/null and b/analyzer/windows/dll/Doppelganging_x64.dll differ diff --git a/analyzer/windows/modules/packages/Doppelganging.py b/analyzer/windows/modules/packages/Doppelganging.py new file mode 100644 index 000000000..b83c5d22d --- /dev/null +++ b/analyzer/windows/modules/packages/Doppelganging.py @@ -0,0 +1,44 @@ +# 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 Doppelganging(Package): + """Dump-on-API package.""" + + def __init__(self, options={}, config=None): + """@param options: options dict.""" + self.config = config + self.options = options + self.pids = [] + self.options["dll"] = "Doppelganging.dll" + self.options["dll_64"] = "Doppelganging_x64.dll" + + 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/modules/processing/CAPE.py b/modules/processing/CAPE.py index 3a7483f0c..812e02b98 100644 --- a/modules/processing/CAPE.py +++ b/modules/processing/CAPE.py @@ -56,6 +56,7 @@ COMPRESSION = 1 INJECTION_PE = 3 INJECTION_SHELLCODE = 4 +INJECTION_SECTION = 5 EXTRACTION_PE = 8 EXTRACTION_SHELLCODE = 9 PLUGX_PAYLOAD = 0x10 @@ -232,6 +233,10 @@ def process_file(self, file_path, CAPE_output, append_file): file_info["target_path"] = metastrings[4] file_info["target_process"] = metastrings[4].split("\\")[-1] file_info["target_pid"] = metastrings[5] + if file_info["cape_type_code"] == INJECTION_SECTION: + file_info["cape_type"] = "Injected Section" + if len(metastrings) > 4: + file_info["section_handle"] = metastrings[4] if file_info["cape_type_code"] == EXTRACTION_PE: file_info["cape_type"] = "Extracted PE Image" if len(metastrings) > 4: diff --git a/modules/reporting/submitCAPE.py b/modules/reporting/submitCAPE.py index 7fee40f04..ff2cf7f7a 100644 --- a/modules/reporting/submitCAPE.py +++ b/modules/reporting/submitCAPE.py @@ -31,10 +31,10 @@ log = logging.getLogger(__name__) cape_package_list = [ - "Cerber", "Compression", "Compression_dll", "Compression_doc", "Compression_zip", "DumpOnAPI", "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" + "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" ]; def pirpi_password(strings): @@ -178,6 +178,10 @@ def run(self, results): continue detections.add('Compression') + elif entry["name"] == "Doppelganging": + if report["info"].has_key("package"): + detections.add('Doppelganging') + ##### Specific malware family packages ##### elif entry["name"] == "PlugX": diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index c1063a786..d5caf5f1b 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -402,3 +402,36 @@ def on_call(self, call, process): def on_complete(self): if self.config_copy == True and self.compressed_binary == True: return True + +class CAPE_Doppelganging(Signature): + name = "Doppelganging" + description = "CAPE detection: Process Doppelganging" + severity = 1 + categories = ["injection"] + authors = ["kevoreilly"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.lastprocess = None + + filter_categories = set(["process", "thread", "filesystem",]) + + def on_call(self, call, process): + if process is not self.lastprocess: + self.section_handles = set() + self.lastprocess = process + self.filehandle = None + self.sectionhandle = None + + if call["api"] == "CreateFileTransactedA" or call["api"] == "CreateFileTransactedW": + self.filehandle = self.get_argument(call, "FileHandle") + elif call["api"] == "NtCreateSection": + if self.filehandle and self.filehandle == self.get_argument(call, "FileHandle"): + self.sectionhandle = self.get_argument(call, "SectionHandle") + elif call["api"] == "NtCreateProcessEx": + if self.get_argument(call, "SectionHandle") == self.sectionhandle: + return True + + \ No newline at end of file diff --git a/web/templates/analysis/CAPE/index.html b/web/templates/analysis/CAPE/index.html index b78d50332..17af0c47c 100644 --- a/web/templates/analysis/CAPE/index.html +++ b/web/templates/analysis/CAPE/index.html @@ -67,6 +67,12 @@