diff --git a/CAPE/Injection.c b/CAPE/Injection.c index 248b083..e7e1af4 100644 --- a/CAPE/Injection.c +++ b/CAPE/Injection.c @@ -677,7 +677,7 @@ void CreateProcessHandler(LPWSTR lpApplicationName, LPWSTR lpCommandLine, LPPROC DebugOutput("CreateProcessHandler: Injection info set for new process %d, ImageBase: 0x%p", CurrentInjectionInfo->ProcessId, CurrentInjectionInfo->ImageBase); } -PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid) +PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid, ACCESS_MASK DesiredAccess) { struct InjectionInfo *CurrentInjectionInfo; char DevicePath[MAX_PATH]; @@ -694,6 +694,7 @@ PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid) if (CurrentInjectionInfo) { CurrentInjectionInfo->ProcessHandle = ProcessHandle; + CurrentInjectionInfo->DesiredAccess = DesiredAccess; CurrentInjectionInfo->EntryPoint = (DWORD_PTR)NULL; CurrentInjectionInfo->ImageDumped = FALSE; @@ -1133,6 +1134,45 @@ void ProcessMessage(DWORD ProcessId, DWORD ThreadId) return; } + // Add injection filtering logic here to prevent false positives + if (g_config.filter_system_injection) { + ACCESS_MASK DesiredAccess = 0; + + // Get the access flags used to open this process (reuse existing CurrentInjectionInfo) + if (CurrentInjectionInfo && CurrentInjectionInfo->DesiredAccess) { + DesiredAccess = CurrentInjectionInfo->DesiredAccess; + } + + // Define malicious injection access patterns + ACCESS_MASK MALICIOUS_FLAGS = PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION; + ACCESS_MASK LEGITIMATE_FLAGS = PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION | + SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_VM_READ; + + // If process was opened with only legitimate flags, don't inject + if (DesiredAccess && !(DesiredAccess & MALICIOUS_FLAGS)) { + if (DesiredAccess & LEGITIMATE_FLAGS) { + DebugOutput("ProcessMessage: INJECTION BLOCKED - Legitimate access pattern 0x%x for PID %d", DesiredAccess, ProcessId); + return; + } + } + + // Log the access pattern for analysis + if (DesiredAccess) { + BOOL bHighRisk = (DesiredAccess & MALICIOUS_FLAGS) != 0; + BOOL bAllAccess = (DesiredAccess == PROCESS_ALL_ACCESS); + + if (bHighRisk || bAllAccess) { + DebugOutput("ProcessMessage: INJECTION ALLOWED - Malicious access pattern 0x%x for PID %d (%s)", + DesiredAccess, ProcessId, bAllAccess ? "ALL_ACCESS" : "INJECTION_FLAGS"); + } else { + DebugOutput("ProcessMessage: INJECTION ALLOWED - Unknown access pattern 0x%x for PID %d", DesiredAccess, ProcessId); + } + } else { + // No access info available (process created, not opened) + DebugOutput("ProcessMessage: INJECTION ALLOWED - Process created (not opened) PID %d", ProcessId); + } + } + if (g_config.standalone) { BOOL Wow64Process; @@ -1194,7 +1234,7 @@ void ProcessMessage(DWORD ProcessId, DWORD ThreadId) swprintf_s(CommandLine, MAX_PATH, L"%s inject %u %u %s", Loader, ProcessId, ThreadId, our_dll_path_w); } #endif - } + } hook_disable(); if (CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfoEx.StartupInfo, &ProcInfo)) { diff --git a/CAPE/Injection.h b/CAPE/Injection.h index 54d4f65..23684e0 100644 --- a/CAPE/Injection.h +++ b/CAPE/Injection.h @@ -45,6 +45,7 @@ typedef struct InjectionInfo { DWORD ProcessId; HANDLE ProcessHandle; + ACCESS_MASK DesiredAccess; DWORD InitialThreadId; DWORD_PTR ImageBase; DWORD_PTR EntryPoint; @@ -66,7 +67,7 @@ PINJECTIONINFO GetInjectionInfoFromHandle(HANDLE ProcessHandle); PINJECTIONINFO CreateInjectionInfo(DWORD ProcessId); BOOL DropInjectionInfo(HANDLE ProcessHandle); void CreateProcessHandler(LPWSTR lpApplicationName, LPWSTR lpCommandLine, LPPROCESS_INFORMATION lpProcessInformation); -PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid); +PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid, ACCESS_MASK DesiredAccess); void ResumeProcessHandler(HANDLE ProcessHandle, DWORD Pid); void MapSectionViewHandler(HANDLE ProcessHandle, HANDLE SectionHandle, PVOID BaseAddress, SIZE_T ViewSize); void UnmapSectionViewHandler(PVOID BaseAddress); diff --git a/config.c b/config.c index e071565..85c87b1 100644 --- a/config.c +++ b/config.c @@ -1249,11 +1249,16 @@ void parse_config_line(char* line) else if (g_config.unpacker == 2) DebugOutput("Active unpacking of payloads enabled\n"); } - else if (!stricmp(key, "injection")) { //When set to 1 this will enable CAPE’s capture of injected payloads between processes + else if (!stricmp(key, "injection")) { //When set to 1 this will enable CAPE�s capture of injected payloads between processes g_config.injection = value[0] == '1'; if (g_config.injection) DebugOutput("Capture of injected payloads enabled.\n"); } + else if (!stricmp(key, "filter-system-injection")) { //When set to 1 this will enable filtering of system injection based on process access rights to reduce false positives + g_config.filter_system_injection = value[0] == '1'; + if (g_config.filter_system_injection) + DebugOutput("System injection filtering enabled - will filter based on process access rights.\n"); + } else if (!stricmp(key, "dump-config-region")) { g_config.dump_config_region = value[0] == '1'; if (g_config.dump_config_region) @@ -1405,6 +1410,7 @@ void read_config(void) g_config.dump_limit = DUMP_LIMIT; g_config.dropped_limit = 0; g_config.injection = 1; + g_config.filter_system_injection = 1; // Enable by default to prevent false positives g_config.unpacker = 1; g_config.api_cap = 5000; g_config.api_rate_cap = 1; diff --git a/config.h b/config.h index c10ceae..43373cc 100644 --- a/config.h +++ b/config.h @@ -168,6 +168,9 @@ struct _g_config { int unpacker; int injection; + // filter system injection based on process access rights + int filter_system_injection; + // should we dump each process on exit/analysis timeout? int procdump; int procmemdump; diff --git a/hook_process.c b/hook_process.c index 6b342b5..dad7c95 100644 --- a/hook_process.c +++ b/hook_process.c @@ -520,7 +520,7 @@ HOOKDEF(NTSTATUS, WINAPI, NtOpenProcess, ret = Old_NtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); if (NT_SUCCESS(ret) && g_config.injection) - ProcessName = OpenProcessHandler(*ProcessHandle, pid); + ProcessName = OpenProcessHandler(*ProcessHandle, pid, DesiredAccess); if (ProcessName) LOQ_ntstatus("process", "Phis", "ProcessHandle", ProcessHandle, "DesiredAccess", DesiredAccess, "ProcessIdentifier", pid, "ProcessName", ProcessName);