diff --git a/capemon.vcxproj b/capemon.vcxproj index e01a1f7..f98b0c7 100644 --- a/capemon.vcxproj +++ b/capemon.vcxproj @@ -477,12 +477,12 @@ + true true - false + true true - false diff --git a/hook_misc.c b/hook_misc.c index e532d1c..5286d37 100644 --- a/hook_misc.c +++ b/hook_misc.c @@ -36,6 +36,7 @@ along with this program. If not, see . extern char *our_process_name; extern void ProcessMessage(DWORD ProcessId, DWORD ThreadId); extern const char* GetLanguageName(LANGID langID); +extern NTSTATUS pNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength); extern BOOL TraceRunning; @@ -44,6 +45,11 @@ extern BOOL Trace(struct _EXCEPTION_POINTERS* ExceptionInfo); LPTOP_LEVEL_EXCEPTION_FILTER TopLevelExceptionFilter; BOOL PlugXConfigDumped, CompressedPE; DWORD ExportAddress; +struct BlockInputThreadInstance { + BOOL CurrentlyBlockedInput; + DWORD BlockInputThreadID; +}; +static struct BlockInputThreadInstance BlockInputInstances[256]; //Should be enough for most situations HOOKDEF(HHOOK, WINAPI, SetWindowsHookExA, __in int idHook, @@ -424,13 +430,37 @@ HOOKDEF(NTSTATUS, WINAPI, NtClose, LOQ_ntstatus("system", "ps", "Handle", Handle, "Alert", "Tried to close Cuckoo's log handle"); return ret; } - ret = Old_NtClose(Handle); + //https://anti-debug.checkpoint.com/techniques/object-handles.html + ULONG Size = 0; + ULONG Size2 = 0; + NTSTATUS Status = pNtQueryObject(Handle, 0, &Size, sizeof(Size), &Size); + void* Buff = (void*)calloc(1, Size); + BOOLEAN valid_handle; + if (!Buff) + valid_handle = NT_SUCCESS(pNtQueryObject(Handle, 0, Buff, Size, &Size2)); + else + valid_handle = FALSE; + if (!g_config.no_stealth && valid_handle) + { + __try + { + Old_NtClose(Handle); + ret = STATUS_SUCCESS; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + ret = STATUS_SUCCESS; + } + } + else + ret = Old_NtClose(Handle); LOQ_ntstatus("system", "p", "Handle", Handle); if(NT_SUCCESS(ret)) { remove_file_from_log_tracking(Handle); DumpSectionViewsForHandle(Handle); file_close(Handle); } + free(Buff); return ret; } @@ -796,6 +826,22 @@ HOOKDEF(NTSTATUS, WINAPI, NtQueryInformationProcess, ) { NTSTATUS ret = Old_NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); LOQ_ntstatus("process", "ib", "ProcessInformationClass", ProcessInformationClass, "ProcessInformation", ProcessInformationLength, ProcessInformation); + //https://anti-debug.checkpoint.com/techniques/debug-flags.html#using-win32-api-checkremotedebuggerpresent + if (!g_config.no_stealth && ProcessInformationClass == ProcessDebugPort) + { + if (ProcessInformationLength >= sizeof(HANDLE)) + *(HANDLE*)ProcessInformation = 0; + } + else if (!g_config.no_stealth && ProcessInformationClass == ProcessDebugFlags) + { + if (ProcessInformationLength >= sizeof(ULONG)) + *(ULONG*)ProcessInformation = 1; + } + else if (!g_config.no_stealth && ProcessInformationClass == ProcessDebugObjectHandle) + { + if (ProcessInformationLength >= sizeof(HANDLE)) + *(HANDLE*)ProcessInformation = 0; + } return ret; } @@ -832,7 +878,12 @@ HOOKDEF(NTSTATUS, WINAPI, NtQuerySystemInformation, PLARGE_INTEGER perf_info = (PLARGE_INTEGER)SystemInformation; perf_info->HighPart |= 2; } - + //https://anti-debug.checkpoint.com/techniques/debug-flags.html#using-win32-api-checkremotedebuggerpresent + if (!g_config.no_stealth && SystemInformationClass == SystemKernelDebuggerInformation) + { + PSYSTEM_KERNEL_DEBUGGER_INFORMATION perf_info = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION)SystemInformation; + perf_info->DebuggerNotPresent = 1; + } return ret; } @@ -1961,3 +2012,89 @@ HOOKDEF(ULONG, __fastcall, vDbgPrintExWithPrefixInternal, return Old_vDbgPrintExWithPrefixInternal(Prefix, ComponentId, Level, Format, arglist, HandleBreakpoint); } + +HOOKDEF(BOOL, WINAPI, NtDebugActiveProcess, + _In_ HANDLE ProcessHandle, + _In_ HANDLE DebugObjectHandle +){ + DWORD pid = pid_from_process_handle(ProcessHandle); + DWORD debug_pid = pid_from_process_handle(DebugObjectHandle); + BOOL ret = Old_NtDebugActiveProcess(ProcessHandle, DebugObjectHandle); + LOQ_bool("misc", "ll", "ProcessID", pid, "DebugObject", debug_pid); + //https://anti-debug.checkpoint.com/techniques/interactive.html + if (!g_config.no_stealth && is_protected_pid(pid) && g_config.debugger) + ret = TRUE; + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, DbgUiDebugActiveProcess, + _In_ HANDLE ProcessHandle +){ + DWORD pid = pid_from_process_handle(ProcessHandle); + NTSTATUS ret = Old_DbgUiDebugActiveProcess(ProcessHandle); + LOQ_ntstatus("misc", "l", "ProcessID", pid); + //https://anti-debug.checkpoint.com/techniques/interactive.html + if (!g_config.no_stealth && is_protected_pid(pid) && g_config.debugger) + return TRUE; + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, GenerateConsoleCtrlEvent, + _In_ DWORD dwCtrlEvent, + _In_ DWORD dwProcessGroupId +){ + //https://anti-debug.checkpoint.com/techniques/interactive.html + //Assuming the ProcessGroupID is the pid in this case make sense because it would be a case where it's targeted specifically ? + NTSTATUS ret = Old_GenerateConsoleCtrlEvent(dwCtrlEvent,dwProcessGroupId); + LOQ_ntstatus("misc", "ll", "CtrlEvent", dwCtrlEvent, "ProcessGroupID", dwProcessGroupId); + if (!g_config.no_stealth && g_config.debugger && is_protected_pid(dwProcessGroupId)) { + ret = TRUE; + } + return ret; +} + +//https://anti-debug.checkpoint.com/techniques/interactive.html +HOOKDEF(BOOL, WINAPI, BlockInput, + _In_ BOOL fBlockIt +){ + BOOL ret; + if(!g_config.no_stealth) + { + + int length = sizeof(BlockInputInstances) / sizeof(struct BlockInputThreadInstance); + DWORD ThreadId = GetCurrentThreadId(); + BOOL found = FALSE; + int index = 0; + BOOL CurrentState = FALSE; + //Don't run the real deal since it's an effective way to block a debugger and a way to detect hooking. + for(int i=0;i5*sizeof(void *)) + { + LOQ_bool("windows","p", "lpEnumFunc", lpEnumFunc); + } + else LOQ_bool("windows", ""); return ret; } diff --git a/hooks.c b/hooks.c index 2f32106..73676c4 100644 --- a/hooks.c +++ b/hooks.c @@ -417,6 +417,10 @@ hook_t full_hooks[] = { HOOK(oleaut32, VarBstrCat), HOOK_NOTAIL(usp10, ScriptIsComplex, 3), HOOK_NOTAIL(inseng,DownloadFile,3), + HOOK(ntdll, DbgUiDebugActiveProcess), + HOOK(ntdll, NtDebugActiveProcess), + HOOK(Kernel32, GenerateConsoleCtrlEvent), + HOOK(User32, BlockInput), #ifndef _WIN64 HOOK(ntdll, RtlDosPathNameToNtPathName_U), HOOK(ntdll, NtQueryLicenseValue), @@ -1333,6 +1337,10 @@ hook_t office_hooks[] = { HOOK(oleaut32, VarBstrCat), HOOK_NOTAIL(usp10, ScriptIsComplex, 3), HOOK_NOTAIL(inseng,DownloadFile,3), + HOOK(ntdll, DbgUiDebugActiveProcess), + HOOK(ntdll, NtDebugActiveProcess), + HOOK(Kernel32, GenerateConsoleCtrlEvent), + HOOK(User32, BlockInput), #ifndef _WIN64 HOOK(ntdll, RtlDosPathNameToNtPathName_U), HOOK(ntdll, NtQueryLicenseValue), diff --git a/hooks.h b/hooks.h index 58502ac..5c8bd6a 100644 --- a/hooks.h +++ b/hooks.h @@ -3737,4 +3737,22 @@ HOOKDEF(ULONG, __fastcall, vDbgPrintExWithPrefixInternal, __in BOOLEAN HandleBreakpoint ); +HOOKDEF(BOOL, WINAPI, NtDebugActiveProcess, + _In_ HANDLE ProcessHandle, + _In_ HANDLE DebugObjectHandle +); + +HOOKDEF(NTSTATUS, WINAPI, DbgUiDebugActiveProcess, + _In_ HANDLE ProcessHandle +); + +HOOKDEF(NTSTATUS, WINAPI, GenerateConsoleCtrlEvent, + _In_ DWORD dwCtrlEvent, + _In_ DWORD dwProcessGroupId +); + +HOOKDEF(BOOL, WINAPI, BlockInput, + _In_ BOOL fBlockIt +); + #include "hook_vbscript.h" diff --git a/misc.c b/misc.c index e224e72..806ce32 100644 --- a/misc.c +++ b/misc.c @@ -37,7 +37,7 @@ static _NtQueryInformationProcess pNtQueryInformationProcess; static _NtQueryInformationThread pNtQueryInformationThread; static _RtlGenRandom pRtlGenRandom; static _NtQueryAttributesFile pNtQueryAttributesFile; -static _NtQueryObject pNtQueryObject; +_NtQueryObject pNtQueryObject; static _NtQueryKey pNtQueryKey; static _NtDelayExecution pNtDelayExecution; static _NtQuerySystemInformation pNtQuerySystemInformation; diff --git a/ntapi.h b/ntapi.h index 69eed2a..81816ba 100644 --- a/ntapi.h +++ b/ntapi.h @@ -271,6 +271,11 @@ typedef struct _SYSTEM_PROCESS_INFORMATION { SYSTEM_THREAD Threads[0]; } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; +typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { + BOOLEAN DebuggerEnabled; + BOOLEAN DebuggerNotPresent; +} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; + typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; @@ -312,7 +317,8 @@ typedef enum _SYSTEM_INFORMATION_CLASS { SystemVdmBopInformation, SystemFileCacheInformation, SystemInterruptInformation = 23, - SystemExceptionInformation = 33 + SystemExceptionInformation = 33, + SystemKernelDebuggerInformation = 35 } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_BASIC_INFORMATION {