From 94f6ab5ca972783ce59b7680e3997043f48fa2c4 Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Thu, 26 Jun 2025 10:21:45 +0300
Subject: [PATCH 1/8] Filtering Processes Before Injection
---
CAPE/Injection.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
CAPE/Injection.h | 3 ++-
config.c | 8 +++++++-
config.h | 3 +++
hook_process.c | 2 +-
5 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/CAPE/Injection.c b/CAPE/Injection.c
index 248b0836..e7e1af43 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 54d4f650..23684e0a 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 e0715656..85c87b1b 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 c10ceae3..43373cc3 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 6b342b5d..dad7c957 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);
From 14b39615238e3fb076bb3e606b69a6225e1b646b Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Sun, 6 Jul 2025 00:18:08 +0300
Subject: [PATCH 2/8] Testing Getting Blocked Processes By name
---
CAPE/Injection.c | 106 +++++++++++++++++++++++++++++++----------------
CAPE/Injection.h | 2 +-
2 files changed, 72 insertions(+), 36 deletions(-)
diff --git a/CAPE/Injection.c b/CAPE/Injection.c
index e7e1af43..18db568e 100644
--- a/CAPE/Injection.c
+++ b/CAPE/Injection.c
@@ -53,6 +53,7 @@ PINJECTIONINFO GetInjectionInfo(DWORD ProcessId)
DWORD CurrentProcessId;
PINJECTIONINFO CurrentInjectionInfo = InjectionInfoList;
+
while (CurrentInjectionInfo)
{
CurrentProcessId = CurrentInjectionInfo->ProcessId;
@@ -1128,49 +1129,84 @@ void ProcessMessage(DWORD ProcessId, DWORD ThreadId)
return;
}
- if (g_config.single_process)
- {
- DebugOutput("ProcessMessage: Skipping monitoring process %d as single-process mode set.", ProcessId);
- return;
- }
-
- // Add injection filtering logic here to prevent false positives
+ // Injection filtering logic based on process name and desired access
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;
+ // Get process name for filtering
+ char processName[MAX_PATH] = {0};
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, ProcessId);
+ if (hProcess) {
+ char processPath[MAX_PATH];
+ if (GetProcessImageFileName(hProcess, processPath, MAX_PATH)) {
+ char *fileName = strrchr(processPath, '\\');
+ if (fileName) {
+ strncpy(processName, fileName + 1, MAX_PATH - 1);
+ }
+ }
+ CloseHandle(hProcess);
}
- // 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;
+ // Process name filtering - exclude system processes
+ const char *systemProcesses[] = {
+ "services.exe", "svchost.exe", "WmiPrvSE.exe", "wininit.exe",
+ "winlogon.exe", "lsass.exe", "csrss.exe", "smss.exe",
+ "explorer.exe", "dwm.exe", "conhost.exe", "audiodg.exe"
+ };
- // 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;
+ for (int i = 0; i < sizeof(systemProcesses) / sizeof(systemProcesses[0]); i++) {
+ if (!_stricmp(processName, systemProcesses[i])) {
+ DebugOutput("ProcessMessage: INJECTION BLOCKED - System process: %s (PID %d)", processName, ProcessId);
+ if (CurrentInjectionInfo)
+ DebugOutput("ProcessMessage: processhandle: 0x%x", CurrentInjectionInfo->ProcessHandle);
+ else
+ DebugOutput("ProcessMessage: processhandle: not set for process %s (PID %d)", processName, ProcessId);
+
+ // if (CurrentInjectionInfo->DesiredAccess)
+ // DebugOutput("ProcessMessage: DesiredAccess: 0x%x", CurrentInjectionInfo->DesiredAccess);
+ // else
+ // DebugOutput("ProcessMessage: DesiredAccess: not set for process %s (PID %d)", processName, ProcessId);
+ // return;
}
}
- // Log the access pattern for analysis
- if (DesiredAccess) {
- BOOL bHighRisk = (DesiredAccess & MALICIOUS_FLAGS) != 0;
- BOOL bAllAccess = (DesiredAccess == PROCESS_ALL_ACCESS);
+ // // Desired access filtering
+ // if (CurrentInjectionInfo && CurrentInjectionInfo->DesiredAccess) {
+ // ACCESS_MASK DesiredAccess = CurrentInjectionInfo->DesiredAccess;
- 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);
- }
+ // // 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 & MALICIOUS_FLAGS)) {
+ // if (DesiredAccess & LEGITIMATE_FLAGS) {
+ // DebugOutput("ProcessMessage: INJECTION BLOCKED - Legitimate access pattern 0x%x for %s (PID %d)",
+ // DesiredAccess, processName, ProcessId);
+ // return;
+ // }
+ // }
+
+ // // Log the access pattern for analysis
+ // 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 %s (PID %d) (%s)",
+ // DesiredAccess, processName, ProcessId, bAllAccess ? "ALL_ACCESS" : "INJECTION_FLAGS");
+ // } else {
+ // DebugOutput("ProcessMessage: INJECTION ALLOWED - Unknown access pattern 0x%x for %s (PID %d)",
+ // DesiredAccess, processName, ProcessId);
+ // }
+ // } else {
+ // // No access info available (process created, not opened)
+ // DebugOutput("ProcessMessage: INJECTION ALLOWED - Process created (not opened) %s (PID %d)", processName, ProcessId);
+ // }
+ }
+
+ if (g_config.single_process)
+ {
+ DebugOutput("ProcessMessage: Skipping monitoring process %d as single-process mode set.", ProcessId);
+ return;
}
if (g_config.standalone)
diff --git a/CAPE/Injection.h b/CAPE/Injection.h
index 23684e0a..ddd74397 100644
--- a/CAPE/Injection.h
+++ b/CAPE/Injection.h
@@ -45,7 +45,6 @@ typedef struct InjectionInfo
{
DWORD ProcessId;
HANDLE ProcessHandle;
- ACCESS_MASK DesiredAccess;
DWORD InitialThreadId;
DWORD_PTR ImageBase;
DWORD_PTR EntryPoint;
@@ -55,6 +54,7 @@ typedef struct InjectionInfo
unsigned int BufferSizeOfImage;
HANDLE SectionHandle;
BOOL DontMonitor;
+ ACCESS_MASK DesiredAccess;
// struct InjectionSectionView *SectionViewList;
struct InjectionInfo *NextInjectionInfo;
} INJECTIONINFO, *PINJECTIONINFO;
From d81c6e4c14634ccb129e7572c49f9455cb2c9b7a Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Sun, 6 Jul 2025 00:18:28 +0300
Subject: [PATCH 3/8] Adding Filter Injection Flag
---
config.c | 6 +++---
config.h | 2 --
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/config.c b/config.c
index 85c87b1b..23455ea8 100644
--- a/config.c
+++ b/config.c
@@ -1254,10 +1254,10 @@ void parse_config_line(char* line)
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
+ else if (!stricmp(key, "filter-system-injection")) { //When set to 1 this will enable filtering of system injection based on process names and access patterns
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");
+ DebugOutput("System injection filtering enabled.\n");
}
else if (!stricmp(key, "dump-config-region")) {
g_config.dump_config_region = value[0] == '1';
@@ -1410,7 +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.filter_system_injection = 1;
g_config.unpacker = 1;
g_config.api_cap = 5000;
g_config.api_rate_cap = 1;
diff --git a/config.h b/config.h
index 43373cc3..815cb007 100644
--- a/config.h
+++ b/config.h
@@ -167,8 +167,6 @@ struct _g_config {
// behavioural payload extraction options
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?
From 79bdc5e59096cf7dc651eda1d2caff5e390441a8 Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Sun, 6 Jul 2025 00:20:16 +0300
Subject: [PATCH 4/8] Revert "Adding Filter Injection Flag"
This reverts commit d81c6e4c14634ccb129e7572c49f9455cb2c9b7a.
---
config.c | 6 +++---
config.h | 2 ++
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/config.c b/config.c
index 23455ea8..85c87b1b 100644
--- a/config.c
+++ b/config.c
@@ -1254,10 +1254,10 @@ void parse_config_line(char* line)
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 names and access patterns
+ 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.\n");
+ 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';
@@ -1410,7 +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;
+ 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 815cb007..43373cc3 100644
--- a/config.h
+++ b/config.h
@@ -167,6 +167,8 @@ struct _g_config {
// behavioural payload extraction options
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?
From 331ffb04bce054ab80bc181bea107752cb98af69 Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Sun, 6 Jul 2025 00:20:23 +0300
Subject: [PATCH 5/8] Revert "Testing Getting Blocked Processes By name"
This reverts commit 14b39615238e3fb076bb3e606b69a6225e1b646b.
---
CAPE/Injection.c | 106 ++++++++++++++++-------------------------------
CAPE/Injection.h | 2 +-
2 files changed, 36 insertions(+), 72 deletions(-)
diff --git a/CAPE/Injection.c b/CAPE/Injection.c
index 18db568e..e7e1af43 100644
--- a/CAPE/Injection.c
+++ b/CAPE/Injection.c
@@ -53,7 +53,6 @@ PINJECTIONINFO GetInjectionInfo(DWORD ProcessId)
DWORD CurrentProcessId;
PINJECTIONINFO CurrentInjectionInfo = InjectionInfoList;
-
while (CurrentInjectionInfo)
{
CurrentProcessId = CurrentInjectionInfo->ProcessId;
@@ -1129,84 +1128,49 @@ void ProcessMessage(DWORD ProcessId, DWORD ThreadId)
return;
}
- // Injection filtering logic based on process name and desired access
+ if (g_config.single_process)
+ {
+ DebugOutput("ProcessMessage: Skipping monitoring process %d as single-process mode set.", ProcessId);
+ return;
+ }
+
+ // Add injection filtering logic here to prevent false positives
if (g_config.filter_system_injection) {
- // Get process name for filtering
- char processName[MAX_PATH] = {0};
- HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, ProcessId);
- if (hProcess) {
- char processPath[MAX_PATH];
- if (GetProcessImageFileName(hProcess, processPath, MAX_PATH)) {
- char *fileName = strrchr(processPath, '\\');
- if (fileName) {
- strncpy(processName, fileName + 1, MAX_PATH - 1);
- }
- }
- CloseHandle(hProcess);
+ ACCESS_MASK DesiredAccess = 0;
+
+ // Get the access flags used to open this process (reuse existing CurrentInjectionInfo)
+ if (CurrentInjectionInfo && CurrentInjectionInfo->DesiredAccess) {
+ DesiredAccess = CurrentInjectionInfo->DesiredAccess;
}
- // Process name filtering - exclude system processes
- const char *systemProcesses[] = {
- "services.exe", "svchost.exe", "WmiPrvSE.exe", "wininit.exe",
- "winlogon.exe", "lsass.exe", "csrss.exe", "smss.exe",
- "explorer.exe", "dwm.exe", "conhost.exe", "audiodg.exe"
- };
+ // 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;
- for (int i = 0; i < sizeof(systemProcesses) / sizeof(systemProcesses[0]); i++) {
- if (!_stricmp(processName, systemProcesses[i])) {
- DebugOutput("ProcessMessage: INJECTION BLOCKED - System process: %s (PID %d)", processName, ProcessId);
- if (CurrentInjectionInfo)
- DebugOutput("ProcessMessage: processhandle: 0x%x", CurrentInjectionInfo->ProcessHandle);
- else
- DebugOutput("ProcessMessage: processhandle: not set for process %s (PID %d)", processName, ProcessId);
-
- // if (CurrentInjectionInfo->DesiredAccess)
- // DebugOutput("ProcessMessage: DesiredAccess: 0x%x", CurrentInjectionInfo->DesiredAccess);
- // else
- // DebugOutput("ProcessMessage: DesiredAccess: not set for process %s (PID %d)", processName, ProcessId);
- // return;
+ // 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;
}
}
- // // Desired access filtering
- // if (CurrentInjectionInfo && CurrentInjectionInfo->DesiredAccess) {
- // ACCESS_MASK 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 & MALICIOUS_FLAGS)) {
- // if (DesiredAccess & LEGITIMATE_FLAGS) {
- // DebugOutput("ProcessMessage: INJECTION BLOCKED - Legitimate access pattern 0x%x for %s (PID %d)",
- // DesiredAccess, processName, ProcessId);
- // return;
- // }
- // }
+ // Log the access pattern for analysis
+ if (DesiredAccess) {
+ BOOL bHighRisk = (DesiredAccess & MALICIOUS_FLAGS) != 0;
+ BOOL bAllAccess = (DesiredAccess == PROCESS_ALL_ACCESS);
- // // Log the access pattern for analysis
- // 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 %s (PID %d) (%s)",
- // DesiredAccess, processName, ProcessId, bAllAccess ? "ALL_ACCESS" : "INJECTION_FLAGS");
- // } else {
- // DebugOutput("ProcessMessage: INJECTION ALLOWED - Unknown access pattern 0x%x for %s (PID %d)",
- // DesiredAccess, processName, ProcessId);
- // }
- // } else {
- // // No access info available (process created, not opened)
- // DebugOutput("ProcessMessage: INJECTION ALLOWED - Process created (not opened) %s (PID %d)", processName, ProcessId);
- // }
- }
-
- if (g_config.single_process)
- {
- DebugOutput("ProcessMessage: Skipping monitoring process %d as single-process mode set.", ProcessId);
- return;
+ 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)
diff --git a/CAPE/Injection.h b/CAPE/Injection.h
index ddd74397..23684e0a 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;
@@ -54,7 +55,6 @@ typedef struct InjectionInfo
unsigned int BufferSizeOfImage;
HANDLE SectionHandle;
BOOL DontMonitor;
- ACCESS_MASK DesiredAccess;
// struct InjectionSectionView *SectionViewList;
struct InjectionInfo *NextInjectionInfo;
} INJECTIONINFO, *PINJECTIONINFO;
From 3280f4e897fc4b30ccf7b584d95f35bcf85632d0 Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Wed, 9 Jul 2025 05:51:00 +0300
Subject: [PATCH 6/8] Filtering EXPLORER opened with specific access masks by
MSOffice APPs
---
CAPE/Injection.c | 77 ++++++++++++++++++++++--------------------------
CAPE/Injection.h | 2 +-
config.c | 11 ++++---
config.h | 4 +--
hook_process.c | 6 ++++
hook_window.c | 39 ++++++++++++++++++------
6 files changed, 81 insertions(+), 58 deletions(-)
diff --git a/CAPE/Injection.c b/CAPE/Injection.c
index e7e1af43..f6631528 100644
--- a/CAPE/Injection.c
+++ b/CAPE/Injection.c
@@ -31,7 +31,7 @@ along with this program.If not, see .
#include "Shlwapi.h"
#pragma comment(lib, "shlwapi.lib")
-#pragma warning(push )
+#pragma warning(push)
#pragma warning(disable : 4996)
extern _NtMapViewOfSection pNtMapViewOfSection;
@@ -46,6 +46,37 @@ extern char *our_process_name;
extern void hook_disable();
extern void hook_enable();
+BOOL is_system_process(DWORD ProcessId)
+{
+ char processName[MAX_PATH] = {0};
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, ProcessId);
+ if (hProcess) {
+ char processPath[MAX_PATH];
+ if (GetProcessImageFileName(hProcess, processPath, MAX_PATH)) {
+ char *fileName = strrchr(processPath, '\\');
+ if (fileName) {
+ strncpy(processName, fileName + 1, MAX_PATH - 1);
+ }
+ }
+ CloseHandle(hProcess);
+ }
+
+ // Process name filtering - exclude system processes
+ const char *systemProcesses[] = {
+ "services.exe", "svchost.exe", "WmiPrvSE.exe", "wininit.exe",
+ "winlogon.exe", "lsass.exe", "csrss.exe", "smss.exe",
+ "explorer.exe", "dwm.exe", "conhost.exe", "audiodg.exe"
+ };
+
+ for (int i = 0; i < sizeof(systemProcesses) / sizeof(systemProcesses[0]); i++) {
+ if (!_stricmp(processName, systemProcesses[i])) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
//**************************************************************************************
PINJECTIONINFO GetInjectionInfo(DWORD ProcessId)
//**************************************************************************************
@@ -53,6 +84,7 @@ PINJECTIONINFO GetInjectionInfo(DWORD ProcessId)
DWORD CurrentProcessId;
PINJECTIONINFO CurrentInjectionInfo = InjectionInfoList;
+
while (CurrentInjectionInfo)
{
CurrentProcessId = CurrentInjectionInfo->ProcessId;
@@ -685,6 +717,7 @@ PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid, ACCESS_MASK DesiredAcc
if (Pid == GetCurrentProcessId())
return NULL;
+
CurrentInjectionInfo = GetInjectionInfo(Pid);
@@ -694,7 +727,6 @@ PCHAR OpenProcessHandler(HANDLE ProcessHandle, DWORD Pid, ACCESS_MASK DesiredAcc
if (CurrentInjectionInfo)
{
CurrentInjectionInfo->ProcessHandle = ProcessHandle;
- CurrentInjectionInfo->DesiredAccess = DesiredAccess;
CurrentInjectionInfo->EntryPoint = (DWORD_PTR)NULL;
CurrentInjectionInfo->ImageDumped = FALSE;
@@ -1127,52 +1159,13 @@ void ProcessMessage(DWORD ProcessId, DWORD ThreadId)
DebugOutput("ProcessMessage: Skipping monitoring process %d", ProcessId);
return;
}
-
+
if (g_config.single_process)
{
DebugOutput("ProcessMessage: Skipping monitoring process %d as single-process mode set.", ProcessId);
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;
diff --git a/CAPE/Injection.h b/CAPE/Injection.h
index 23684e0a..03055511 100644
--- a/CAPE/Injection.h
+++ b/CAPE/Injection.h
@@ -45,7 +45,6 @@ typedef struct InjectionInfo
{
DWORD ProcessId;
HANDLE ProcessHandle;
- ACCESS_MASK DesiredAccess;
DWORD InitialThreadId;
DWORD_PTR ImageBase;
DWORD_PTR EntryPoint;
@@ -73,3 +72,4 @@ void MapSectionViewHandler(HANDLE ProcessHandle, HANDLE SectionHandle, PVOID Bas
void UnmapSectionViewHandler(PVOID BaseAddress);
void WriteMemoryHandler(HANDLE ProcessHandle, LPVOID BaseAddress, LPCVOID Buffer, SIZE_T NumberOfBytesWritten);
void TerminateHandler();
+BOOL is_system_process(DWORD ProcessId);
diff --git a/config.c b/config.c
index 85c87b1b..63294ef6 100644
--- a/config.c
+++ b/config.c
@@ -1254,10 +1254,10 @@ void parse_config_line(char* line)
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
+ else if (!stricmp(key, "filter-system-injection")) { //When set to 1 this will enable filtering of system injection based on process names and access patterns
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");
+ DebugOutput("System injection filtering enabled.\n");
}
else if (!stricmp(key, "dump-config-region")) {
g_config.dump_config_region = value[0] == '1';
@@ -1410,7 +1410,10 @@ 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.filter_system_injection = 1;
+ g_config.filter_system_safe_process_pid = 0;
+
g_config.unpacker = 1;
g_config.api_cap = 5000;
g_config.api_rate_cap = 1;
@@ -1681,4 +1684,4 @@ void read_config(void)
}
return;
-}
+}
\ No newline at end of file
diff --git a/config.h b/config.h
index 43373cc3..9e11d85a 100644
--- a/config.h
+++ b/config.h
@@ -168,9 +168,9 @@ struct _g_config {
int unpacker;
int injection;
- // filter system injection based on process access rights
int filter_system_injection;
-
+ int filter_system_safe_process_pid;
+
// should we dump each process on exit/analysis timeout?
int procdump;
int procmemdump;
diff --git a/hook_process.c b/hook_process.c
index dad7c957..fb679350 100644
--- a/hook_process.c
+++ b/hook_process.c
@@ -519,13 +519,19 @@ HOOKDEF(NTSTATUS, WINAPI, NtOpenProcess,
ret = Old_NtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
+ if (is_system_process(pid))
+ g_config.filter_system_safe_process_pid = pid;
+
+
if (NT_SUCCESS(ret) && g_config.injection)
ProcessName = OpenProcessHandler(*ProcessHandle, pid, DesiredAccess);
if (ProcessName)
LOQ_ntstatus("process", "Phis", "ProcessHandle", ProcessHandle, "DesiredAccess", DesiredAccess, "ProcessIdentifier", pid, "ProcessName", ProcessName);
+
else
LOQ_ntstatus("process", "Phi", "ProcessHandle", ProcessHandle, "DesiredAccess", DesiredAccess, "ProcessIdentifier", pid);
+
return ret;
}
diff --git a/hook_window.c b/hook_window.c
index 8bf7b296..f528c4e1 100644
--- a/hook_window.c
+++ b/hook_window.c
@@ -23,10 +23,13 @@ along with this program. If not, see .
#include "pipe.h"
#include "log.h"
+
#define StringAtomSize 0x100
+extern void DebugOutput(_In_ LPCTSTR lpOutputString, ...);
extern void ProcessMessage(DWORD ProcessId, DWORD ThreadId);
extern void DumpSectionViewsForPid(DWORD Pid);
+extern BOOL is_system_process(DWORD ProcessId);
typedef DWORD (WINAPI * __GetWindowThreadProcessId)(
__in HWND hWnd,
@@ -189,6 +192,7 @@ HOOKDEF(BOOL, WINAPI, PostMessageW,
return ret;
}
+
HOOKDEF(BOOL, WINAPI, PostThreadMessageA,
_In_ DWORD idThread,
_In_ UINT Msg,
@@ -198,17 +202,22 @@ HOOKDEF(BOOL, WINAPI, PostThreadMessageA,
BOOL ret = Old_PostThreadMessageA(idThread, Msg, wParam, lParam);
DWORD pid = GetThreadProcessId(idThread);
+
+ LOQ_bool("windows", "iii", "ProcessId", pid, "ThreadId", idThread, "Message", Msg);
if (pid && pid != GetCurrentProcessId()) {
DumpSectionViewsForPid(pid);
- ProcessMessage(pid, 0);
+ // ProcessMessage(pid, 0);
}
-
- LOQ_bool("windows", "iii", "ProcessId", pid, "ThreadId", idThread, "Message", Msg);
+ if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ return FALSE;
+ }
+ ProcessMessage(pid, 0);
return ret;
}
+
HOOKDEF(BOOL, WINAPI, PostThreadMessageW,
_In_ DWORD idThread,
_In_ UINT Msg,
@@ -218,13 +227,17 @@ HOOKDEF(BOOL, WINAPI, PostThreadMessageW,
BOOL ret = Old_PostThreadMessageW(idThread, Msg, wParam, lParam);
DWORD pid = GetThreadProcessId(idThread);
+ LOQ_bool("windows", "iii", "ProcessId", pid, "ThreadId", idThread, "Message", Msg);
+
if (pid && pid != GetCurrentProcessId()) {
DumpSectionViewsForPid(pid);
- ProcessMessage(pid, 0);
+ // ProcessMessage(pid, 0);
}
-
- LOQ_bool("windows", "iii", "ProcessId", pid, "ThreadId", idThread, "Message", Msg);
+ if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ return FALSE;
+ }
+ ProcessMessage(pid, 0);
return ret;
}
@@ -274,8 +287,12 @@ HOOKDEF(BOOL, WINAPI, SendNotifyMessageA,
our_GetWindowThreadProcessId(hWnd, &pid);
if (pid != GetCurrentProcessId()) {
DumpSectionViewsForPid(pid);
- ProcessMessage(pid, 0);
+ //ProcessMessage(pid, 0);
+ }
+ if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ return FALSE;
}
+ ProcessMessage(pid, 0);
}
set_lasterrors(&lasterror);
@@ -301,8 +318,12 @@ HOOKDEF(BOOL, WINAPI, SendNotifyMessageW,
our_GetWindowThreadProcessId(hWnd, &pid);
if (pid != GetCurrentProcessId()) {
DumpSectionViewsForPid(pid);
- ProcessMessage(pid, 0);
+ // ProcessMessage(pid, 0);
+ }
+ if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ return FALSE;
}
+ ProcessMessage(pid, 0);
}
set_lasterrors(&lasterror);
@@ -524,4 +545,4 @@ HOOKDEF(int, WINAPI, MessageBoxTimeoutW,
else
LOQ_zero("windows", "uui", "Text", lpszText, "Caption", lpszCaption, "Timeout", dwTimeout);
return ret;
-}
+}
\ No newline at end of file
From 8cfc2d33a449ae318f87c9becaad9ef95f0305b2 Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Wed, 9 Jul 2025 12:34:10 +0300
Subject: [PATCH 7/8] Update hook_process.c
---
hook_process.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/hook_process.c b/hook_process.c
index fb679350..45d45b7f 100644
--- a/hook_process.c
+++ b/hook_process.c
@@ -518,9 +518,18 @@ HOOKDEF(NTSTATUS, WINAPI, NtOpenProcess,
}
ret = Old_NtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
-
- if (is_system_process(pid))
- g_config.filter_system_safe_process_pid = pid;
+
+
+ if (g_config.filter_system_injection) {
+ ACCESS_MASK legitimate_flags = PROCESS_QUERY_INFORMATION |
+ PROCESS_QUERY_LIMITED_INFORMATION |
+ PROCESS_VM_READ | PROCESS_DUP_HANDLE |
+ SYNCHRONIZE;
+
+ if ((DesiredAccess & ~legitimate_flags) == 0 && is_system_process(pid)) {
+ g_config.filter_system_safe_process_pid = pid;
+ }
+ }
if (NT_SUCCESS(ret) && g_config.injection)
From eb337d6c79f8f5af08b4e0022d403ed8f3d85216 Mon Sep 17 00:00:00 2001
From: Mohannad Raafat <62453654+para0x0dise@users.noreply.github.com>
Date: Wed, 9 Jul 2025 13:23:31 +0300
Subject: [PATCH 8/8] Update hook_window.c
---
hook_window.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/hook_window.c b/hook_window.c
index f528c4e1..db07884d 100644
--- a/hook_window.c
+++ b/hook_window.c
@@ -29,7 +29,6 @@ along with this program. If not, see .
extern void DebugOutput(_In_ LPCTSTR lpOutputString, ...);
extern void ProcessMessage(DWORD ProcessId, DWORD ThreadId);
extern void DumpSectionViewsForPid(DWORD Pid);
-extern BOOL is_system_process(DWORD ProcessId);
typedef DWORD (WINAPI * __GetWindowThreadProcessId)(
__in HWND hWnd,
@@ -209,7 +208,7 @@ HOOKDEF(BOOL, WINAPI, PostThreadMessageA,
DumpSectionViewsForPid(pid);
// ProcessMessage(pid, 0);
}
- if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ if (g_config.filter_system_injection && pid == g_config.filter_system_safe_process_pid) {
return FALSE;
}
ProcessMessage(pid, 0);
@@ -234,7 +233,7 @@ HOOKDEF(BOOL, WINAPI, PostThreadMessageW,
DumpSectionViewsForPid(pid);
// ProcessMessage(pid, 0);
}
- if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ if (g_config.filter_system_injection && pid == g_config.filter_system_safe_process_pid) {
return FALSE;
}
ProcessMessage(pid, 0);
@@ -289,7 +288,7 @@ HOOKDEF(BOOL, WINAPI, SendNotifyMessageA,
DumpSectionViewsForPid(pid);
//ProcessMessage(pid, 0);
}
- if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ if (g_config.filter_system_injection && pid == g_config.filter_system_safe_process_pid) {
return FALSE;
}
ProcessMessage(pid, 0);
@@ -320,7 +319,7 @@ HOOKDEF(BOOL, WINAPI, SendNotifyMessageW,
DumpSectionViewsForPid(pid);
// ProcessMessage(pid, 0);
}
- if (g_config.filter_system_injection && is_system_process(pid) && pid == g_config.filter_system_safe_process_pid) {
+ if (g_config.filter_system_injection && pid == g_config.filter_system_safe_process_pid) {
return FALSE;
}
ProcessMessage(pid, 0);