From 4d332ab4fcb12cca53a84343c5a64a3bc76bfbd3 Mon Sep 17 00:00:00 2001 From: kevross33 Date: Sat, 28 Feb 2026 17:16:36 +0000 Subject: [PATCH 1/4] Add MalformedDllLoading signature for DLL checks Added a new signature class for detecting malformed DLL loading attempts, including checks for hex escapes and API strings in filenames. --- .../windows/dynamic_function_loading.py | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/modules/signatures/windows/dynamic_function_loading.py b/modules/signatures/windows/dynamic_function_loading.py index 41467e31..0121b77a 100644 --- a/modules/signatures/windows/dynamic_function_loading.py +++ b/modules/signatures/windows/dynamic_function_loading.py @@ -15,7 +15,7 @@ # along with this program.If not, see . from lib.cuckoo.common.abstracts import Signature - +import re class dynamic_function_loading(Signature): name = "dynamic_function_loading" @@ -52,3 +52,44 @@ def on_complete(self): elif self.loadctr > 20: self.severity = 2 return True + + +class MalformedDllLoading(Signature): + name = "malformed_dll_loading" + description = "Attempts to load a DLL with a heavily malformed name or decoded API name, indicative an error in the API hashing routine" + severity = 3 + confidence = 40 + categories = ["evasion", "stealth"] + authors = ["Kevin Ross", "Gemini"] + minimum = "1.3" + evented = True + ttps = ["T1027"] + + filter_apinames = {"LdrGetDllHandle", "LdrLoadDll", "LoadLibraryA", "LoadLibraryW", "LoadLibraryExA", "LoadLibraryExW"} + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.ret = False + self.malformed_dlls = set() + + def on_call(self, call, process): + filename = self.get_argument(call, "FileName") or self.get_argument(call, "lpLibFileName") + if not filename or not isinstance(filename, str): + return + + # Check if the filename contains massive amounts of raw hex escapes (\x). + # This occurs when CAPE dumps unprintable bytes that the malware accidentally passed. + hex_escape_count = len(re.findall(r"\\x[0-9a-fA-F]{2,4}", filename)) + + # Check if they accidentally passed known API strings to a DLL loader + api_strings = ["Rtl", "NtQuery", "GetSystem", "MachinePreferred", "Filemark"] + is_api_name = any(api in filename for api in api_strings) and (".dll" not in filename.lower()) + + if hex_escape_count >= 4 or is_api_name: + if filename not in self.malformed_dlls: + self.malformed_dlls.add(filename) + self.mark_call() + self.ret = True + + def on_complete(self): + return self.ret From 7e596451b67825351f99cb1d5c750b104e3a8503 Mon Sep 17 00:00:00 2001 From: kevross33 Date: Sat, 28 Feb 2026 17:19:12 +0000 Subject: [PATCH 2/4] Enhance MalformedDllLoading signature details Updated description and categories to include anti-sandbox and anti-emulation. --- modules/signatures/windows/dynamic_function_loading.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/signatures/windows/dynamic_function_loading.py b/modules/signatures/windows/dynamic_function_loading.py index 0121b77a..226ba3e0 100644 --- a/modules/signatures/windows/dynamic_function_loading.py +++ b/modules/signatures/windows/dynamic_function_loading.py @@ -56,10 +56,10 @@ def on_complete(self): class MalformedDllLoading(Signature): name = "malformed_dll_loading" - description = "Attempts to load a DLL with a heavily malformed name or decoded API name, indicative an error in the API hashing routine" + description = "Attempts to load a DLL with a heavily malformed name or decoded API name, indicative an error in the API hashing routine or anti-sandbox/emulation" severity = 3 confidence = 40 - categories = ["evasion", "stealth"] + categories = ["evasion", "stealth", "anti-sandbox", "anti-emulation"] authors = ["Kevin Ross", "Gemini"] minimum = "1.3" evented = True From a65686b9e5b16ebe6e19d21fd7cf010d7edc571d Mon Sep 17 00:00:00 2001 From: Kevin O'Reilly Date: Fri, 6 Mar 2026 16:22:13 +0000 Subject: [PATCH 3/4] Update modules/signatures/windows/dynamic_function_loading.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- modules/signatures/windows/dynamic_function_loading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/dynamic_function_loading.py b/modules/signatures/windows/dynamic_function_loading.py index 226ba3e0..5ec3c926 100644 --- a/modules/signatures/windows/dynamic_function_loading.py +++ b/modules/signatures/windows/dynamic_function_loading.py @@ -87,7 +87,7 @@ def on_call(self, call, process): if hex_escape_count >= 4 or is_api_name: if filename not in self.malformed_dlls: - self.malformed_dlls.add(filename) + self.malformed_dlls.add(filename) self.mark_call() self.ret = True From 2b01851d5358b2e0682fd049d7c29f2807ec8f84 Mon Sep 17 00:00:00 2001 From: kevross33 Date: Sat, 7 Mar 2026 22:40:36 +0000 Subject: [PATCH 4/4] Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- modules/signatures/windows/dynamic_function_loading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/dynamic_function_loading.py b/modules/signatures/windows/dynamic_function_loading.py index 5ec3c926..ceb5536d 100644 --- a/modules/signatures/windows/dynamic_function_loading.py +++ b/modules/signatures/windows/dynamic_function_loading.py @@ -79,7 +79,7 @@ def on_call(self, call, process): # Check if the filename contains massive amounts of raw hex escapes (\x). # This occurs when CAPE dumps unprintable bytes that the malware accidentally passed. - hex_escape_count = len(re.findall(r"\\x[0-9a-fA-F]{2,4}", filename)) + hex_escape_count = len(re.findall(r"\\x[0-9a-fA-F]{2}", filename)) # Check if they accidentally passed known API strings to a DLL loader api_strings = ["Rtl", "NtQuery", "GetSystem", "MachinePreferred", "Filemark"]