From f6e11eac6c4a206ff8ba14d2b6bf00d5965b626e Mon Sep 17 00:00:00 2001 From: kevross33 Date: Mon, 29 Dec 2025 13:01:25 +0000 Subject: [PATCH 1/7] NEEDS TESTING: Syscall Signature (fresh ntdll load) So this needs testing please as I don't have a current CAPE until i am back in office/have new home lab PC in a few weeks. The logic of this is that the Windows loader should take care of NTDLL. Loading a fresh NTDLL into itself from disk likely is then to begin parsing it for syscall instruction for doing that or to bypass hooking. Here are two samples that do this for testing each element: 1) AgentTesla https://capesandbox.com/analysis/46120/ This uses NTCreateFile on ntdll to load it and then NtReadFile to read it into memory. 2) LUMMA https://capesandbox.com/analysis/46359/ This uses NTCreateFile on ntdll to load it then maps in into its memory with NTCreateSection before changing the memory protections on it (likely to then patch it and remove hooks). --- modules/signatures/windows/antiedr_syscall.py | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 modules/signatures/windows/antiedr_syscall.py diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py new file mode 100644 index 00000000..daf46cb7 --- /dev/null +++ b/modules/signatures/windows/antiedr_syscall.py @@ -0,0 +1,69 @@ +# Copyright (C) 2025 Kevin Ross +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from lib.cuckoo.common.abstracts import Signature + + +class Suspicious_NTDLL_DiskLoad(Signature): + name = "suspicious_ntdll_disk_load" + description = "Loads clean ntdll.dll from disk (possibly for syscall/anti-EDR)" + severity = 3 + categories = [""syscall", "anti-edr", "unhooking"] + authors = ["Kevin Ross"] + minimum = "1.3" + evented = True + ttps = ["T1106"] # MITRE v6,7,8 + + filter_apinames = set(["NtCreateFile", "NtCreateSection", "NtOpenFile", "NtProtectVirtualMemory", "NtReadFile"]) + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.ret = False + self.filehandle = "" + self.mapped = False + + def on_call(self, call, process): + if call["api"] in ["NtCreateFile", "NtOpenFile"]: + filename = self.get_argument(call, "FileName") + if filename.lower() == "c:\windows\system32\ntdll.dll": + filehandle = self.get_argument(call, "FileHandle") + self.filehandle == filehandle + self.mark_call() + self.ret = True + + if call["api"] == ("NtReadFile"): + filehandle = self.get_argument(call, "FileHandle") + handlename = self.get_argument(call, "HandleName") + if filehandle == self.filehandle and "ntdll.dll" in handlename.lower(): + self.mark_call() + + if call["api"] == ("NtCreateSection"): + filehandle = self.get_argument(call, "FileHandle") + filename = self.get_argument(call, "FileName") + if filehandle == self.filehandle and "ntdll.dll" in filename.lower: + self.mapped = True + self.mark_call() + + if call["api"] == ("NtProtectVirtualMemory"): + if self.mapped: + modulename = self.get_argument(call, "ModuleName") + if modulename.lower == "ntdll.dll": + protection = self.get_argument(call, "NewAccessProtection") + # 0x40 PAGE_EXECUTE_READWRITE, 0x80 PAGE_EXECUTE_WRITECOPY, 0x04 PAGE_READWRITE + if protection in ["0x00000040", "0x00000080", "0x00000004"]: + self.mark_call() + + def on_complete(self): + return self.ret From 0319c1e420a7b20f58128d661fee790ae0e6877c Mon Sep 17 00:00:00 2001 From: kevross33 Date: Mon, 29 Dec 2025 13:04:35 +0000 Subject: [PATCH 2/7] Fix formatting in Suspicious_NTDLL_DiskLoad class --- modules/signatures/windows/antiedr_syscall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py index daf46cb7..a46f3cb4 100644 --- a/modules/signatures/windows/antiedr_syscall.py +++ b/modules/signatures/windows/antiedr_syscall.py @@ -20,7 +20,7 @@ class Suspicious_NTDLL_DiskLoad(Signature): name = "suspicious_ntdll_disk_load" description = "Loads clean ntdll.dll from disk (possibly for syscall/anti-EDR)" severity = 3 - categories = [""syscall", "anti-edr", "unhooking"] + categories = ["syscall", "anti-edr", "unhooking"] authors = ["Kevin Ross"] minimum = "1.3" evented = True From 343747bbd181d4a3858a7bdab85c444dbb571a1b Mon Sep 17 00:00:00 2001 From: kevross33 Date: Mon, 29 Dec 2025 13:05:21 +0000 Subject: [PATCH 3/7] Update modules/signatures/windows/antiedr_syscall.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- modules/signatures/windows/antiedr_syscall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py index a46f3cb4..f2c043b8 100644 --- a/modules/signatures/windows/antiedr_syscall.py +++ b/modules/signatures/windows/antiedr_syscall.py @@ -37,7 +37,7 @@ def __init__(self, *args, **kwargs): def on_call(self, call, process): if call["api"] in ["NtCreateFile", "NtOpenFile"]: filename = self.get_argument(call, "FileName") - if filename.lower() == "c:\windows\system32\ntdll.dll": + if filename and filename.lower().endswith(r"\system32\ntdll.dll"): filehandle = self.get_argument(call, "FileHandle") self.filehandle == filehandle self.mark_call() From c7e6917f0b54dc73f6cb7e90682c9a85c2b11714 Mon Sep 17 00:00:00 2001 From: kevross33 Date: Mon, 29 Dec 2025 13:05:29 +0000 Subject: [PATCH 4/7] Update modules/signatures/windows/antiedr_syscall.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- modules/signatures/windows/antiedr_syscall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py index f2c043b8..25570b4d 100644 --- a/modules/signatures/windows/antiedr_syscall.py +++ b/modules/signatures/windows/antiedr_syscall.py @@ -39,7 +39,7 @@ def on_call(self, call, process): filename = self.get_argument(call, "FileName") if filename and filename.lower().endswith(r"\system32\ntdll.dll"): filehandle = self.get_argument(call, "FileHandle") - self.filehandle == filehandle + self.filehandle = filehandle self.mark_call() self.ret = True From 101cb57fa9a01bd42c996ccae83b8b0250ef4d96 Mon Sep 17 00:00:00 2001 From: kevross33 Date: Mon, 29 Dec 2025 13:05:56 +0000 Subject: [PATCH 5/7] Update modules/signatures/windows/antiedr_syscall.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- modules/signatures/windows/antiedr_syscall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py index 25570b4d..f05cb635 100644 --- a/modules/signatures/windows/antiedr_syscall.py +++ b/modules/signatures/windows/antiedr_syscall.py @@ -46,7 +46,7 @@ def on_call(self, call, process): if call["api"] == ("NtReadFile"): filehandle = self.get_argument(call, "FileHandle") handlename = self.get_argument(call, "HandleName") - if filehandle == self.filehandle and "ntdll.dll" in handlename.lower(): + if self.filehandle and filehandle == self.filehandle and handlename and "ntdll.dll" in handlename.lower(): self.mark_call() if call["api"] == ("NtCreateSection"): From e9480a5b4b5acb92bc567ac127d1a858f259352c Mon Sep 17 00:00:00 2001 From: kevross33 Date: Mon, 29 Dec 2025 13:07:40 +0000 Subject: [PATCH 6/7] Update antiedr_syscall.py --- modules/signatures/windows/antiedr_syscall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py index f05cb635..ce516ba3 100644 --- a/modules/signatures/windows/antiedr_syscall.py +++ b/modules/signatures/windows/antiedr_syscall.py @@ -59,7 +59,7 @@ def on_call(self, call, process): if call["api"] == ("NtProtectVirtualMemory"): if self.mapped: modulename = self.get_argument(call, "ModuleName") - if modulename.lower == "ntdll.dll": + if modulename and modulename.lower() == "ntdll.dll": protection = self.get_argument(call, "NewAccessProtection") # 0x40 PAGE_EXECUTE_READWRITE, 0x80 PAGE_EXECUTE_WRITECOPY, 0x04 PAGE_READWRITE if protection in ["0x00000040", "0x00000080", "0x00000004"]: From ef4913928baf1bc3d49c2c06ebc22b748c59a51d Mon Sep 17 00:00:00 2001 From: doomedraven Date: Fri, 2 Jan 2026 23:26:51 +0100 Subject: [PATCH 7/7] Update antiedr_syscall.py --- modules/signatures/windows/antiedr_syscall.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/signatures/windows/antiedr_syscall.py b/modules/signatures/windows/antiedr_syscall.py index ce516ba3..8e670dda 100644 --- a/modules/signatures/windows/antiedr_syscall.py +++ b/modules/signatures/windows/antiedr_syscall.py @@ -50,11 +50,11 @@ def on_call(self, call, process): self.mark_call() if call["api"] == ("NtCreateSection"): - filehandle = self.get_argument(call, "FileHandle") - filename = self.get_argument(call, "FileName") - if filehandle == self.filehandle and "ntdll.dll" in filename.lower: - self.mapped = True - self.mark_call() + filehandle = self.get_argument(call, "FileHandle") + filename = self.get_argument(call, "FileName") + if filehandle == self.filehandle and "ntdll.dll" in filename.lower(): + self.mapped = True + self.mark_call() if call["api"] == ("NtProtectVirtualMemory"): if self.mapped: