From 87a8cb466cca1a72fa784bf8946348952531aa8d Mon Sep 17 00:00:00 2001 From: "Tim Shelton (redsand)" Date: Thu, 28 Jun 2018 14:54:20 +0000 Subject: [PATCH 1/6] Adds more AntiDebug/AntiVM Checks, Adds some malicious API call checks and removes ssh defunct from remote sniffer. --- modules/auxiliary/sniffer.py | 2 +- modules/signatures/CAPE.py | 319 ++++++++++++++++++++++++++++++++++- 2 files changed, 319 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/sniffer.py b/modules/auxiliary/sniffer.py index 28678ba01..bc25f445b 100644 --- a/modules/auxiliary/sniffer.py +++ b/modules/auxiliary/sniffer.py @@ -123,7 +123,7 @@ def start(self): f.close() remote_output = subprocess.check_output(['scp', '-q', "/tmp/%d.sh" % self.task.id, remote_host + ":/tmp/%d.sh" % self.task.id ], stderr=DEVNULL) - remote_output = subprocess.check_output(['ssh', remote_host, 'nohup', "/bin/bash", '/tmp/%d.sh' % self.task.id, '>','/tmp/log','2>','/tmp/err','&' ], stderr=subprocess.STDOUT) + remote_output = subprocess.check_output(['ssh', remote_host, 'nohup', "/bin/bash", '/tmp/%d.sh' % self.task.id, '>','/tmp/log','2>','/tmp/err' ], stderr=subprocess.STDOUT) self.pid = subprocess.check_output(['ssh', remote_host, 'cat', '/tmp/%d.pid' % self.task.id ], stderr=DEVNULL).strip() log.info("Started remote sniffer @ %s with (interface=%s, host=%s, " diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index 408d7f0e7..cb96136c8 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -446,12 +446,329 @@ class CAPE_AntiDebugSetUnhandledExceptionFilter(Signature): def __init__(self, *args, **kwargs): Signature.__init__(self, *args, **kwargs) - self.lastprocess = None filter_apinames = set(["SetUnhandledExceptionFilter"]) def on_call(self, call, process): if call["api"] == "SetUnhandledExceptionFilter": return True + + +class CAPE_AntiDebugAddVectoredExceptionHandler(Signature): + name = "AddVectoredExceptionHandler" + description = "CAPE detection: Anti-Debug AddVectoredExceptionHandler" + severity = 3 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + + filter_apinames = set(["AddVectoredExceptionHandler"]) + + def on_call(self, call, process): + if call["api"] == "AddVectoredExceptionHandler": + return True + +# XXX: not sure this will work since NtSetInformationThread is looked up via LdrDll +# also needs hooking and logging inside capemon +""" +class CAPE_AntiDebugNtSetInformationThread(Signature): + name = "NtSetInformationThread" + description = "CAPE detection: Anti-Debug NtSetInformationThread" + severity = 3 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + + filter_apinames = set(["NtSetInformationThread"]) + + def on_call(self, call, process): + if call["api"] == "NtSetInformationThread": + # check arg 2 if it equals 0x11, if so then trigger + return True +""" + + +# XXX: Currently does not work, needs hook monitor around NtCreateThreadEx +""" +class CAPE_AntiDebugNtCreateThreadEx(Signature): + name = "NtCreateThreadEx" + description = "CAPE detection: Anti-Debug NtCreateThreadEx" + severity = 3 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + + filter_apinames = set(["NtCreateThreadEx"]) + + def on_call(self, call, process): + if call["api"] == "NtCreateThreadEx": + # check arg CreateFlags & THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER == TRUE then we're hiding from the debugger + return True +""" + + +class CAPE_AntiDebugDebugActiveProcess(Signature): + name = "DebugActiveProcess" + description = "CAPE detection: Anti-Debug DebugActiveProcess" + severity = 3 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + + filter_apinames = set(["DebugActiveProcess"]) + + def on_call(self, call, process): + if call["api"] == "DebugActiveProcess": + return True + + +class CAPE_AntiDebugCheckRemoteDebuggerPresent(Signature): + # https://www.apriorit.com/dev-blog/367-anti-reverse-engineering-protection-techniques-to-use-before-releasing-software + name = "CheckRemoteDebuggerPresent" + description = "CAPE detection: Anti-Debug CheckRemoteDebuggerPresent" + severity = 3 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + + filter_apinames = set(["CheckRemoteDebuggerPresent", "NtQueryInformationProcess"]) + + def on_call(self, call, process): + if call["api"] == "CheckRemoteDebuggerPresent": + return True + elif call["api"] == "NtQueryInformationProcess": + # looks like capemon is missing hook on this function to inspect arguments + # need to verify the argument (_In_ UINT ProcessInformationClass,) equals 7 + # would like to also verify argument 3 ( _Out_ PVOID ProcessInformation) is not null + + # other examples to monitor are: + # - ProcessDebugObjectHandle 0x1E + # - ProcessDebugFlags 0x1F + # - ProcessBasicInformation 0x00 + return True + + + +""" +XXX: MISSING CHECK - redsand +CONTEXT ctx = {}; +ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; +SetThreadContext(GetCurrentThread(), &ctx); + +Check if Malware is clearing debug registers. This function should be hooked and monitored as well +Also hook NtSetContextThread as this is the underlying Nt WINAPI function. + +""" + + +class CAPE_AntiDebugGetTickCount(Signature): + name = "GetTickCount" + description = "CAPE detection: Anti-Debug GetTickCount" + severity = 1 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + + filter_apinames = set(["GetTickCount"]) + + def on_call(self, call, process): + if call["api"] == "GetTickCount": + return True + +class CAPE_AntiDebugOutputDebugString(Signature): + name = "OutputDebugString" + description = "CAPE detection: Anti-Debug OutputDebugString" + severity = 3 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.set_err = False + self.output = False + + filter_apinames = set(["OutputDebugStringA", "OutputDebugStringW", "SetLastError", "GetLastError"]) + + def on_call(self, call, process): + if call["api"] == "OutputDebugStringA" or call["api"] == "OutputDebugStringW": + if self.set_err: + self.output = True + else: + self.output = False + elif call["api"] == "SetLastError": + self.output = False + self.set_err = True + elif call["api"] == "GetLastError": + if not self.set_err or not self.output: + self.set_err = self.output = False + elif self.set_err and self.output: + return True + + +class CAPE_AnomalousDynamicFunctionLoading(Signature): + name = "AnomalousDynamicFunctionLoading" + description = "CAPE detection: Anomalous Dynamic Function Loading" + severity = 1 + categories = ["anti-debug"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.dll_loaded = False + self.loadctr = 0 + self.list = [ ] + + filter_apinames = set(["LdrGetProcedureAddress", "LdrLoadDll"]) + + def on_call(self, call, process): + if call["api"] == "LdrLoadDll": + self.dll_loaded = True + elif self.dll_loaded and call["api"] == "LdrGetProcedureAddress": + self.loadctr += 1 + self.data.append({"DynamicLoader" : "%s/%s" % (self.get_argument(call, "ModuleName"), self.get_argument(call, "FunctionName")) }) + + def on_complete(self): + if self.loadctr > 8: + if self.loadctr > 20: + self.severity = 3 + elif self.loadctr > 10: + self.severity = 2 + return True + +class CAPE_MaliciousDynamicFunctionLoading(Signature): + name = "MaliciousDynamicFunctionLoading" + description = "CAPE detection: Possible Malicious Dynamic Function Loading" + severity = 3 + categories = ["malware"] + authors = ["redsand"] + minimum = "1.3" + evented = True + malicious_functions = [ "LookupAccountNameLocalW", "LookupAccountNameLocalA", "LookupAccountSidW", "LookupAccountSidA", + "LookupAccountSidLocalW", "LookupAccountSidLocalA", "CoTaskMemAlloc", "CoTaskMemFree", + "LookupAccountNameW", "LookupAccountNameA", "NetLocalGroupGetMembers", "SamConnect", "SamLookupNamesInDomain", + "OpenProcessToken", "SetThreadToken", "DuplicateTokenEx", "AdjustTokenPrivileges", "OpenThreadToken", + ] + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.dll_loaded = False + self.loadctr = 0 + self.list = [ ] + + filter_apinames = set(["LdrGetProcedureAddress", "LdrLoadDll"]) + + def on_call(self, call, process): + if call["api"] == "LdrLoadDll": + self.dll_loaded = True + elif self.dll_loaded and call["api"] == "LdrGetProcedureAddress": + arg = self.get_argument(call, "FunctionName") + if arg in malicious_functions: + self.data.append({"SuspiciousDynamicFunction" : "%s/%s" % (self.get_argument(call, "ModuleName"), self.get_argument(call, "FunctionName")) }) + + def on_complete(self): + if self.loadctr > 0: + return True + + +class CAPE_AnomalousDeleteFile(Signature): + name = "AnomalousDeleteFile" + description = "CAPE detection: Anomalous File Deletion Behavior (10+)" + severity = 1 + categories = ["malware"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.loadctr = 0 + self.list = [ ] + + filter_apinames = set(["NtDeleteFile", "DeleteFileA", "DeleteFileW"]) + + def on_call(self, call, process): + if call["api"] == "NtDeleteFile" or call["api"] == "DeleteFileA" or call["api"] == "DeleteFileW": + self.loadctr += 1 + self.data.append({"DynamicLoader" : "%s/%s" % (self.get_argument(call, "ModuleName"), self.get_argument(call, "FunctionName")) }) + def on_complete(self): + if self.loadctr > 10: + return True + + +class CAPE_ThemeInitApiHookInject(Signature): + name = "ThemeInitApiHookInject" + description = "CAPE detection: Possible ThemeInitApiHook Injecttion" + severity = 1 + categories = ["injection"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.loadctr = 0 + self.list = [ ] + + filter_apinames = set(["ThemeInitApiHook"]) + + def on_call(self, call, process): + if call["api"] == "ThemeInitApiHook": + self.loadctr += 1 + self.data.append({"Injection" : "%s/%s" % (self.get_argument(call, "ModuleName"), self.get_argument(call, "FunctionName")) }) + def on_complete(self): + if self.loadctr > 0: + return True + + +class CAPE_MoveFileOnReboot(Signature): + name = "MoveFileOnReboot" + description = "CAPE detection: Scheduled File Move On Reboot" + severity = 1 + categories = ["malware"] + authors = ["redsand"] + minimum = "1.3" + evented = True + + def __init__(self, *args, **kwargs): + Signature.__init__(self, *args, **kwargs) + self.match = False + + filter_apinames = set(["MoveFileWithProgressTransactedW", "MoveFileWithProgressTransactedA"]) + + def on_call(self, call, process): + if call["api"] == "MoveFileWithProgressTransactedW" or call["api"] == "MoveFileWithProgressTransactedA": + if self.get_argument(call, "Flags") == "MOVEFILE_DELAY_UNTIL_REBOOT": + self.data.append({"File Rename" : "Old: %s -> New: %s" % (self.get_argument(call, "ExistingFileName"), self.get_argument(call, "NewFileName")) }) + self.match = True + def on_complete(self): + return self.match From 412b042cebd5e70c3c6d422b0a2d8466189a9b29 Mon Sep 17 00:00:00 2001 From: "Tim Shelton (redsand)" Date: Thu, 28 Jun 2018 14:59:03 +0000 Subject: [PATCH 2/6] Fixing erros in sigs, along with speilling mistake --- modules/signatures/CAPE.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index cb96136c8..f6d7faac6 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -725,7 +725,7 @@ def on_complete(self): class CAPE_ThemeInitApiHookInject(Signature): name = "ThemeInitApiHookInject" - description = "CAPE detection: Possible ThemeInitApiHook Injecttion" + description = "CAPE detection: Possible ThemeInitApiHook Injection" severity = 1 categories = ["injection"] authors = ["redsand"] @@ -765,8 +765,8 @@ def __init__(self, *args, **kwargs): def on_call(self, call, process): if call["api"] == "MoveFileWithProgressTransactedW" or call["api"] == "MoveFileWithProgressTransactedA": - if self.get_argument(call, "Flags") == "MOVEFILE_DELAY_UNTIL_REBOOT": - self.data.append({"File Rename" : "Old: %s -> New: %s" % (self.get_argument(call, "ExistingFileName"), self.get_argument(call, "NewFileName")) }) + if self.get_raw_argument(call, "Flags") == 0x4: # 0x00000004 + self.data.append({"File Move on Reboot" : "Old: %s -> New: %s" % (self.get_argument(call, "ExistingFileName"), self.get_argument(call, "NewFileName")) }) self.match = True def on_complete(self): return self.match From f52b58c618d0f3f99c74622d3bfd126147be1bea Mon Sep 17 00:00:00 2001 From: "Tim Shelton (redsand)" Date: Thu, 28 Jun 2018 15:01:26 +0000 Subject: [PATCH 3/6] fixing false positive --- modules/signatures/CAPE.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index f6d7faac6..e06b0beb6 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -537,7 +537,7 @@ def on_call(self, call, process): if call["api"] == "DebugActiveProcess": return True - +XXX: THIS IS INCOMPLETE, SEE MISSING HOOK ON NtQueryInformationProcess class CAPE_AntiDebugCheckRemoteDebuggerPresent(Signature): # https://www.apriorit.com/dev-blog/367-anti-reverse-engineering-protection-techniques-to-use-before-releasing-software name = "CheckRemoteDebuggerPresent" @@ -565,7 +565,9 @@ def on_call(self, call, process): # - ProcessDebugObjectHandle 0x1E # - ProcessDebugFlags 0x1F # - ProcessBasicInformation 0x00 - return True + + # dont trigger false positive + return False From 1f39a44d803db679a4e7ef545d4e42e4a7b713c4 Mon Sep 17 00:00:00 2001 From: "Tim Shelton (redsand)" Date: Thu, 28 Jun 2018 16:54:50 +0000 Subject: [PATCH 4/6] Adjusting severity to avoid false positives in scoring of unknown malware --- modules/signatures/CAPE.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index e06b0beb6..bfdd84c9b 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -438,7 +438,7 @@ def on_call(self, call, process): class CAPE_AntiDebugSetUnhandledExceptionFilter(Signature): name = "SetUnhandledExceptionFilter" description = "CAPE detection: Anti-Debug SetUnhandledExceptionFilter" - severity = 3 + severity = 1 categories = ["anti-debug"] authors = ["redsand"] minimum = "1.3" @@ -457,7 +457,7 @@ def on_call(self, call, process): class CAPE_AntiDebugAddVectoredExceptionHandler(Signature): name = "AddVectoredExceptionHandler" description = "CAPE detection: Anti-Debug AddVectoredExceptionHandler" - severity = 3 + severity = 1 categories = ["anti-debug"] authors = ["redsand"] minimum = "1.3" @@ -478,7 +478,7 @@ def on_call(self, call, process): class CAPE_AntiDebugNtSetInformationThread(Signature): name = "NtSetInformationThread" description = "CAPE detection: Anti-Debug NtSetInformationThread" - severity = 3 + severity = 2 categories = ["anti-debug"] authors = ["redsand"] minimum = "1.3" @@ -501,7 +501,7 @@ def on_call(self, call, process): class CAPE_AntiDebugNtCreateThreadEx(Signature): name = "NtCreateThreadEx" description = "CAPE detection: Anti-Debug NtCreateThreadEx" - severity = 3 + severity = 1 categories = ["anti-debug"] authors = ["redsand"] minimum = "1.3" @@ -522,7 +522,7 @@ def on_call(self, call, process): class CAPE_AntiDebugDebugActiveProcess(Signature): name = "DebugActiveProcess" description = "CAPE detection: Anti-Debug DebugActiveProcess" - severity = 3 + severity = 2 categories = ["anti-debug"] authors = ["redsand"] minimum = "1.3" @@ -604,7 +604,7 @@ def on_call(self, call, process): class CAPE_AntiDebugOutputDebugString(Signature): name = "OutputDebugString" description = "CAPE detection: Anti-Debug OutputDebugString" - severity = 3 + severity = 2 categories = ["anti-debug"] authors = ["redsand"] minimum = "1.3" @@ -659,16 +659,14 @@ def on_call(self, call, process): def on_complete(self): if self.loadctr > 8: - if self.loadctr > 20: - self.severity = 3 - elif self.loadctr > 10: + elif self.loadctr > 20: self.severity = 2 return True class CAPE_MaliciousDynamicFunctionLoading(Signature): name = "MaliciousDynamicFunctionLoading" description = "CAPE detection: Possible Malicious Dynamic Function Loading" - severity = 3 + severity = 1 categories = ["malware"] authors = ["redsand"] minimum = "1.3" @@ -703,7 +701,7 @@ def on_complete(self): class CAPE_AnomalousDeleteFile(Signature): name = "AnomalousDeleteFile" description = "CAPE detection: Anomalous File Deletion Behavior (10+)" - severity = 1 + severity = 2 categories = ["malware"] authors = ["redsand"] minimum = "1.3" From 639329cfc662c94582e73176bfe0a87e35394a32 Mon Sep 17 00:00:00 2001 From: "Tim Shelton (redsand)" Date: Thu, 28 Jun 2018 16:58:17 +0000 Subject: [PATCH 5/6] missing comment --- modules/signatures/CAPE.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index bfdd84c9b..7b18377c8 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -537,7 +537,7 @@ def on_call(self, call, process): if call["api"] == "DebugActiveProcess": return True -XXX: THIS IS INCOMPLETE, SEE MISSING HOOK ON NtQueryInformationProcess +# XXX: THIS IS INCOMPLETE, SEE MISSING HOOK ON NtQueryInformationProcess class CAPE_AntiDebugCheckRemoteDebuggerPresent(Signature): # https://www.apriorit.com/dev-blog/367-anti-reverse-engineering-protection-techniques-to-use-before-releasing-software name = "CheckRemoteDebuggerPresent" From d5de8a370d8e5d1e232f4bb8d324e77d61523c6e Mon Sep 17 00:00:00 2001 From: "Tim Shelton (redsand)" Date: Thu, 28 Jun 2018 17:00:03 +0000 Subject: [PATCH 6/6] derp --- modules/signatures/CAPE.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/signatures/CAPE.py b/modules/signatures/CAPE.py index 7b18377c8..a1d5e1ec6 100644 --- a/modules/signatures/CAPE.py +++ b/modules/signatures/CAPE.py @@ -658,10 +658,11 @@ def on_call(self, call, process): self.data.append({"DynamicLoader" : "%s/%s" % (self.get_argument(call, "ModuleName"), self.get_argument(call, "FunctionName")) }) def on_complete(self): - if self.loadctr > 8: - elif self.loadctr > 20: - self.severity = 2 - return True + if self.loadctr < 8: + return False + elif self.loadctr > 20: + self.severity = 2 + return True class CAPE_MaliciousDynamicFunctionLoading(Signature): name = "MaliciousDynamicFunctionLoading"