#include "precomp.h" #include typedef NTKERNELAPI NTSTATUS(__stdcall* fpPsSetCreateProcessNotifyRoutineEx)(__in PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine, __in BOOLEAN Remove); typedef struct _PROCESS_INFO_ENTRY { RTL_BALANCED_LINKS Links; // AVL Æ®¸® ³ëµå ¿¬°á¿ë (Çʼö) HANDLE ProcessId; // Key (PID´Â 64ºñÆ®¿¡¼­ HANDLE·Î °ü¸®ÇÏ´Â°Ô ¾ÈÀü) WCHAR ProcessName[260]; // Value 1 WCHAR ProcessPath[512]; // Value 2 } PROCESS_INFO_ENTRY, * PPROCESS_INFO_ENTRY; // Àü¿ª º¯¼ö static RTL_AVL_TABLE g_ProcessTable; static KSPIN_LOCK g_TableLock; static BOOLEAN g_IsTableInitialized = FALSE; static NTSTATUS s_ntstatus = STATUS_UNSUCCESSFUL; static BOOLEAN bIsVistaLater = FALSE; static fpPsSetCreateProcessNotifyRoutineEx pPsSetCreateProcessNotifyRoutineEx = NULL; // Â÷´Ü ±ÔÄ¢À» °ü¸®ÇÒ ³»ºÎ ¸®½ºÆ® ³ëµå ±¸Á¶Ã¼ typedef struct _PROCESS_CREATE_BLOCK_RULE_NODE { LIST_ENTRY ListEntry; BS1FLT_PROCESS_CREATE_BLOCK_RULE Rule; } PROCESS_CREATE_BLOCK_RULE_NODE, * PPROCESS_CREATE_BLOCK_RULE_NODE; static LIST_ENTRY g_BlockRuleListHead; static KSPIN_LOCK g_BlockRuleLock; static BOOLEAN g_IsBlockRuleInit = FALSE; //// ============================================================= VOID InitBlockRuleList() { if (g_IsBlockRuleInit) return; InitializeListHead(&g_BlockRuleListHead); KeInitializeSpinLock(&g_BlockRuleLock); g_IsBlockRuleInit = TRUE; } NTSTATUS AddBlockRule(WCHAR* pProcName, WCHAR* pCmdLine, WCHAR* ParentProcessName) { PPROCESS_CREATE_BLOCK_RULE_NODE pNode = NULL; KIRQL oldIrql; if (!g_IsBlockRuleInit) InitBlockRuleList(); pNode = (PPROCESS_CREATE_BLOCK_RULE_NODE)ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESS_CREATE_BLOCK_RULE_NODE), 'blkR'); if (!pNode) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(pNode, sizeof(PROCESS_CREATE_BLOCK_RULE_NODE)); if (pProcName) RtlStringCchCopyW(pNode->Rule.ProcessName, 260, pProcName); if (pCmdLine) RtlStringCchCopyW(pNode->Rule.CommandLine, 512, pCmdLine); if (ParentProcessName) RtlStringCchCopyW(pNode->Rule.ParentProcessName, 50, ParentProcessName); KeAcquireSpinLock(&g_BlockRuleLock, &oldIrql); InsertTailList(&g_BlockRuleListHead, &pNode->ListEntry); KeReleaseSpinLock(&g_BlockRuleLock, oldIrql); return STATUS_SUCCESS; } VOID ClearBlockRules() { KIRQL oldIrql; PLIST_ENTRY pEntry; PPROCESS_CREATE_BLOCK_RULE_NODE pNode; if (!g_IsBlockRuleInit) return; KeAcquireSpinLock(&g_BlockRuleLock, &oldIrql); while (!IsListEmpty(&g_BlockRuleListHead)) { pEntry = RemoveHeadList(&g_BlockRuleListHead); pNode = CONTAINING_RECORD(pEntry, PROCESS_CREATE_BLOCK_RULE_NODE, ListEntry); ExFreePoolWithTag(pNode, 'blkR'); } KeReleaseSpinLock(&g_BlockRuleLock, oldIrql); } BOOLEAN IsProcessBlocked(PUNICODE_STRING pImageName, PUNICODE_STRING pCommandLine, PWSTR parentNameStr) { KIRQL oldIrql; PLIST_ENTRY pEntry; PPROCESS_CREATE_BLOCK_RULE_NODE pNode; BOOLEAN bBlocked = FALSE; WCHAR* pFileName = NULL; UNICODE_STRING usUpcaseCmd = { 0 }; BOOLEAN bMatch = TRUE; if (!g_IsBlockRuleInit || !pImageName || !pImageName->Buffer) return FALSE; pFileName = wcsrchr(pImageName->Buffer, L'\\'); if (pFileName) pFileName++; else pFileName = pImageName->Buffer; if (pCommandLine && pCommandLine->Buffer && pCommandLine->Length > 0) { RtlUpcaseUnicodeString(&usUpcaseCmd, pCommandLine, TRUE); } KeAcquireSpinLock(&g_BlockRuleLock, &oldIrql); for (pEntry = g_BlockRuleListHead.Flink; pEntry != &g_BlockRuleListHead; pEntry = pEntry->Flink) { bMatch = TRUE; pNode = CONTAINING_RECORD(pEntry, PROCESS_CREATE_BLOCK_RULE_NODE, ListEntry); // ParentProcessName °Ë»ç (°ªÀÌ ºñ¾îÀÖÁö ¾Ê°í '*'°¡ ¾Æ´Ò ¶§¸¸ ºñ±³) if (pNode->Rule.ParentProcessName[0] != L'\0' && pNode->Rule.ParentProcessName[0] != L'*') { if (!parentNameStr || _wcsicmp(pNode->Rule.ParentProcessName, parentNameStr) != 0) { bMatch = FALSE; } } // ProcessName °Ë»ç (°ªÀÌ ºñ¾îÀÖÁö ¾Ê°í '*'°¡ ¾Æ´Ò ¶§¸¸ ºñ±³) if (bMatch && pNode->Rule.ProcessName[0] != L'\0' && pNode->Rule.ProcessName[0] != L'*') { if (!pFileName || _wcsicmp(pNode->Rule.ProcessName, pFileName) != 0) { bMatch = FALSE; } } // CommandLine °Ë»ç (°ªÀÌ ºñ¾îÀÖÁö ¾ÊÀ» ¶§¸¸ ºñ±³) if (bMatch && pNode->Rule.CommandLine[0] != L'\0') { if (usUpcaseCmd.Buffer == NULL) { bMatch = FALSE; } else { if (wcsstr(usUpcaseCmd.Buffer, pNode->Rule.CommandLine) == NULL) { bMatch = FALSE; } } } if (bMatch) { bBlocked = TRUE; break; } } KeReleaseSpinLock(&g_BlockRuleLock, oldIrql); if (usUpcaseCmd.Buffer) { RtlFreeUnicodeString(&usUpcaseCmd); } return bBlocked; } // ºñ±³ ÇÔ¼ö (std::less¿Í À¯»ç) RTL_GENERIC_COMPARE_RESULTS NTAPI ProcessTableCompare( _In_ PRTL_AVL_TABLE Table, _In_ PVOID FirstStruct, _In_ PVOID SecondStruct ) { UNREFERENCED_PARAMETER(Table); PPROCESS_INFO_ENTRY p1 = (PPROCESS_INFO_ENTRY)FirstStruct; PPROCESS_INFO_ENTRY p2 = (PPROCESS_INFO_ENTRY)SecondStruct; // ÇÚµé(PID) °ª ÀÚü¸¦ ºñ±³ if (p1->ProcessId < p2->ProcessId) { return GenericLessThan; } else if (p1->ProcessId > p2->ProcessId) { return GenericGreaterThan; } return GenericEqual; } PVOID NTAPI ProcessTableAllocate( _In_ PRTL_AVL_TABLE Table, _In_ CLONG ByteSize ) { UNREFERENCED_PARAMETER(Table); return ExAllocatePoolWithTag(NonPagedPool, ByteSize, 'proc'); } VOID NTAPI ProcessTableFree( _In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer ) { UNREFERENCED_PARAMETER(Table); ExFreePoolWithTag(Buffer, 'proc'); } // ============================================================= // [3] Map °ü¸® ÇÔ¼ö (Init, Add, Find, Remove) // ============================================================= // ÃʱâÈ­ VOID InitProcessMap() { if (!g_IsTableInitialized) { KeInitializeSpinLock(&g_TableLock); // AVL Å×À̺í ÃʱâÈ­ (Äݹé ÇÔ¼ö µî·Ï) RtlInitializeGenericTableAvl( &g_ProcessTable, ProcessTableCompare, ProcessTableAllocate, ProcessTableFree, NULL ); g_IsTableInitialized = TRUE; } } // Á¤¸® (¸ðµç ³ëµå »èÁ¦) VOID CleanupProcessMap() { if (g_IsTableInitialized) { KIRQL oldIrql; PVOID pElement; // ¶ôÀ» °É°í Çϳª¾¿ Áö¿ì°Å³ª, ´õ È¿À²ÀûÀÎ ¹æ¹ýÀº ¾Æ·¡¿Í °°½À´Ï´Ù. // µå¶óÀ̹ö ¾ð·Îµå ½Ã¿¡´Â ¶ô ¾øÀ̵µ ¾ÈÀüÇÏ´Ù¸é ¶ô Á¦°Å °¡´É KeAcquireSpinLock(&g_TableLock, &oldIrql); // Å×À̺íÀÌ ºô ¶§±îÁö ¹Ýº¹ »èÁ¦ while (!RtlIsGenericTableEmptyAvl(&g_ProcessTable)) { // ·çÆ® ³ëµå(ȤÀº ÀÓÀÇÀÇ ³ëµå)¸¦ °¡Á®¿Í¼­ »èÁ¦ pElement = RtlGetElementGenericTableAvl(&g_ProcessTable, 0); if (pElement) { RtlDeleteElementGenericTableAvl(&g_ProcessTable, pElement); } } KeReleaseSpinLock(&g_TableLock, oldIrql); g_IsTableInitialized = FALSE; } } // ÇÁ·Î¼¼½º Á¤º¸ Ãß°¡ (Insert) VOID AddProcessInfo(HANDLE ProcessId, _In_ PCUNICODE_STRING ProcessPath, _In_ PWCHAR processParameter, _In_ PWCHAR parentProcessName ) { if (!g_IsTableInitialized) return; PROCESS_INFO_ENTRY newItem = { 0 }; newItem.ProcessId = ProcessId; // Key ¼³Á¤ // µ¥ÀÌÅÍ º¹»ç if (ProcessPath && ProcessPath->Buffer) { RtlStringCchCopyW(newItem.ProcessPath, 512, ProcessPath->Buffer); WCHAR* name = wcsrchr(newItem.ProcessPath, L'\\'); if (name) name++; else name = newItem.ProcessPath; RtlStringCchCopyW(newItem.ProcessName, 260, name); } else { RtlStringCchCopyW(newItem.ProcessName, 260, L"Unknown"); } KIRQL oldIrql; KeAcquireSpinLock(&g_TableLock, &oldIrql); // Å×ÀÌºí¿¡ »ðÀÔ (ÀÌ¹Ì Á¸ÀçÇÏ¸é ¾÷µ¥ÀÌÆ®Çϰųª ¹«½ÃµÊ) // RtlInsertElementGenericTableAvlÀº ³»ºÎÀûÀ¸·Î AllocateRoutineÀ» È£ÃâÇÏ¿© ¸Þ¸ð¸®¸¦ º¹»çÇÕ´Ï´Ù. // µû¶ó¼­ Áö¿ªº¯¼ö newItemÀ» ³Ñ°ÜÁ൵ ¾ÈÀüÇÕ´Ï´Ù. RtlInsertElementGenericTableAvl(&g_ProcessTable, &newItem, sizeof(PROCESS_INFO_ENTRY), NULL); KeReleaseSpinLock(&g_TableLock, oldIrql); SetProcessLog(LOG_PROCESS_MONITOR, 1, 0, 0, newItem.ProcessName, processParameter, parentProcessName); } // ÇÁ·Î¼¼½º Á¤º¸ »èÁ¦ (Remove) VOID RemoveProcessInfo(HANDLE ProcessId) { if (!g_IsTableInitialized) return; PROCESS_INFO_ENTRY searchKey = { 0 }; searchKey.ProcessId = ProcessId; // °Ë»öÇÒ Key¸¸ ¼³Á¤ KIRQL oldIrql; KeAcquireSpinLock(&g_TableLock, &oldIrql); // »èÁ¦ (Key¸¦ ±â¹ÝÀ¸·Î ã¾Æ¼­ »èÁ¦ÇÔ) RtlDeleteElementGenericTableAvl(&g_ProcessTable, &searchKey); KeReleaseSpinLock(&g_TableLock, oldIrql); } // PID·Î Á¤º¸ Á¶È¸ (Find) BOOLEAN GetProcessInfoByPid(HANDLE ProcessId, WCHAR* pOutName, ULONG NameLen, WCHAR* pOutPath, ULONG PathLen) { if (!g_IsTableInitialized) return FALSE; PROCESS_INFO_ENTRY searchKey = { 0 }; searchKey.ProcessId = ProcessId; BOOLEAN bFound = FALSE; KIRQL oldIrql; KeAcquireSpinLock(&g_TableLock, &oldIrql); // °Ë»ö PPROCESS_INFO_ENTRY pEntry = (PPROCESS_INFO_ENTRY)RtlLookupElementGenericTableAvl(&g_ProcessTable, &searchKey); if (pEntry) { if (pOutName) RtlStringCchCopyW(pOutName, NameLen, pEntry->ProcessName); if (pOutPath) RtlStringCchCopyW(pOutPath, PathLen, pEntry->ProcessPath); bFound = TRUE; } KeReleaseSpinLock(&g_TableLock, oldIrql); return bFound; } VOID UserNotifyEvent() { { HANDLE rptEventHandle; PKEVENT rptEvent; UNICODE_STRING name; RtlInitUnicodeString(&name, PROCESS_TERMINATE_NOTIFY_KERNEL_EVENT_NAME); rptEvent = IoCreateNotificationEvent(&name, &rptEventHandle); if (rptEvent) { KeSetEvent(rptEvent, FALSE, FALSE); ZwClose(rptEventHandle); } } } VOID TerminateProcessNotify(HANDLE ulProcessId) { //BOOLEAN Is = FALSE; ULONG state = 0; PROCESS_INFO_ENTRY newItem = { 0 }; /// ÇÁ·Î¼¼½º ¾ÆÀ̵𠸮½ºÆ® Á¦°Å state = PgRemovePid(HandleToULong(ulProcessId)); if (GetProcessInfoByPid(ulProcessId, newItem.ProcessName, ARRAYSIZE(newItem.ProcessName), newItem.ProcessPath, ARRAYSIZE(newItem.ProcessPath))) { RemoveProcessInfo(ulProcessId); KLogEx(DEBUG_TRACE_INFO, "TERMINATE pid(%d), (%S)\n", HandleToULong(ulProcessId), newItem.ProcessName); SetProcessLog(LOG_PROCESS_MONITOR, 0, 0, 0, newItem.ProcessName, newItem.ProcessPath, NULL); } //if (state & (PG_PID_WHITE | PG_PID_GREEN)) //{ // /// Á¾·á ÇÁ·Î¼¼½º ¾ÆÀ̵ð µî·Ï // SetExitPid(ulProcessId); // /// À¯Àú °øÀ¯ À̺¥Æ® ½Ã±×³Î // UserNotifyEvent(); //} } VOID IsWhiteProcess(ULONG hProcessId) { UNICODE_STRING ProcessPath = { 0, }; ULONG ulType = 0; /// ÇÁ·Î¼¼½º À̸§À» ¾ò´Â´Ù. if (!NT_SUCCESS(UGetCurrentStackProcessImageName(hProcessId, &ProcessPath))) { return; } /// Á¤ÀÇµÈ Çã¿ë ÇÁ·Î¼¼½º ÀÎÁö È®ÀÎ KLogEx(DEBUG_TRACE_INFO, "ProcessCreate, Pid(%d), %S(%d)\n", hProcessId, ProcessPath.Buffer, ProcessPath.Length); if (!IsAllowProcessName(ProcessPath.Buffer, ProcessPath.Length, &ulType)) { /// Á¤ÀÇ ¾ÈµÈ ÇÁ·Î¼¼½º Á¤Ã¥¿¡ µû¸¥ Â÷´Ü PgAddPid(hProcessId, PG_PID_BLACK); } else { /// Çã¿ë ÇÁ·Î¼¼½º µî·Ï PgAddPid(hProcessId, ulType); } UStrFree(&ProcessPath); return; } typedef struct _PROCESS_MESSAGE { ULONG ProcessId; WCHAR ProcessName[260]; WCHAR ProcessPath[512]; } PROCESS_MESSAGE, * PPROCESS_MESSAGE; #define SCANNER_MESSAGE_SIZE (sizeof(FILTER_MESSAGE_HEADER) + sizeof(PROCESS_MESSAGE)) typedef struct _KILL_CONTEXT { WORK_QUEUE_ITEM WorkItem; HANDLE ProcessId; } KILL_CONTEXT, * PKILL_CONTEXT; // [ÀÛ¾÷ÀÚ ½º·¹µå] ½ÇÁ¦ ÇÁ·Î¼¼½º¸¦ Á¾·áÇÏ´Â ÇÔ¼ö VOID KillProcessWorker(PVOID Context) { PKILL_CONTEXT pContext = (PKILL_CONTEXT)Context; NTSTATUS status; HANDLE hProcess = NULL; OBJECT_ATTRIBUTES oa; CLIENT_ID clientId; if (!pContext) return; InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); clientId.UniqueProcess = pContext->ProcessId; clientId.UniqueThread = NULL; // 1. ÇÁ·Î¼¼½º ÇÚµé ¿­±â status = ZwOpenProcess(&hProcess, 0x1, &oa, &clientId); if (NT_SUCCESS(status)) { // 2. ÇÁ·Î¼¼½º °­Á¦ Á¾·á (Exit Code: 0À¸·Î ÇÏ¿© ¿À·ù ¸Þ½ÃÁö ÃÖ¼ÒÈ­) ZwTerminateProcess(hProcess, 0); ZwClose(hProcess); KLogEx(DEBUG_TRACE_INFO, "[Blocking] Silent Kill PID(%d) Success\n", HandleToULong(pContext->ProcessId)); } else { KLogEx(DEBUG_TRACE_ERROR, "[Blocking] Silent Kill Failed PID(%d) Status(0x%x)\n", HandleToULong(pContext->ProcessId), status); } // ¸Þ¸ð¸® ÇØÁ¦ ExFreePoolWithTag(pContext, 'kill'); } // [Å¥ »ðÀÔ] Á¾·á ÀÛ¾÷À» ½Ã½ºÅÛ Å¥¿¡ µî·ÏÇÏ´Â ÇÔ¼ö VOID ScheduleSilentKill(HANDLE ProcessId) { PKILL_CONTEXT pContext = (PKILL_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KILL_CONTEXT), 'kill'); if (pContext) { pContext->ProcessId = ProcessId; // WorkItem ÃʱâÈ­ ¹× ´ë±â¿­ µî·Ï (DelayedWorkQueue »ç¿ë) ExInitializeWorkItem(&pContext->WorkItem, KillProcessWorker, pContext); ExQueueWorkItem(&pContext->WorkItem, DelayedWorkQueue); } } VOID CreateProcessNotifyEx(PEPROCESS pEprocess, HANDLE hProcessId, PPS_CREATE_NOTIFY_INFO pCreateInfo) { UNICODE_STRING parameter = { 0, }; UNICODE_STRING imageFileName = { 0, }; //NTSTATUS status = 0; UNREFERENCED_PARAMETER(pEprocess); if (!g_bs1Flt.IsAttached) return; // ÇÁ·Î¼¼½º Á¾·á if (!pCreateInfo) { //KLogEx(" Terminate %d\n", HandleToULong(hProcessId)); TerminateProcessNotify(hProcessId); } else { if (pCreateInfo->CommandLine && pCreateInfo->CommandLine->Buffer) { if (!NT_SUCCESS(UStrNew(¶meter, pCreateInfo->CommandLine->MaximumLength + 10))) { return; } UStrCopy(¶meter, (PUNICODE_STRING)pCreateInfo->CommandLine); //EXCEL.EXE" /automation -Embedding if (wcsstr(parameter.Buffer, L"EXCEL.EXE\" /automation -Embedding")) { PgAddPid(HandleToULong(hProcessId), PG_PID_ALLOW); } } if (!g_bs1Flt.IsProcessCreate) { UStrFree(¶meter); return; } //PROCESS_MESSAGE msg = { 0, }; //msg.ProcessId = (ULONG)(ULONG_PTR)hProcessId; //if (pCreateInfo->ImageFileName && pCreateInfo->ImageFileName->Buffer) //{ // RtlStringCchCopyW(msg.ProcessPath, 512, pCreateInfo->ImageFileName->Buffer); // wchar_t* name = wcsrchr(msg.ProcessPath, L'\\'); // if (name) // name++; // else // name = msg.ProcessPath; // RtlStringCchCopyW(msg.ProcessName, 260, name); //} //else //{ // RtlStringCchCopyW(msg.ProcessName, 260, L"Unknown"); //} //KLogEx(DEBUG_TRACE_INFO, "Create pid(%d), (%S)\n", msg.ProcessId, msg.ProcessName); // //if (g_bs1Flt.ClientPort) //{ // LARGE_INTEGER timeout; // timeout.QuadPart = (LONGLONG)-10 * 1000 * 1000; //3 seconds // // status = FltSendMessage(g_bs1Flt.Filter, &g_bs1Flt.ClientPort, &msg, sizeof(msg), NULL, NULL, &timeout); // KLogEx(DEBUG_TRACE_ERROR, "FltSendMessage, status(%x)\n", status); //} HANDLE parentPid = pCreateInfo->ParentProcessId; WCHAR parentNameStrW[100] = { 0, }; wchar_t curProcessPath[260] = { 0, }; //UGetProcessNameFromPid if (!NT_SUCCESS(UGetProcessFullPathFromPid(parentPid, curProcessPath, sizeof(curProcessPath), parentNameStrW, sizeof(parentNameStrW)))) { RtlStringCbPrintfW(parentNameStrW, sizeof(parentNameStrW), L"Unknown Parent(%p)", parentPid); } if (pCreateInfo->ImageFileName && pCreateInfo->ImageFileName->Buffer) { if (!NT_SUCCESS(UStrNew(&imageFileName, pCreateInfo->ImageFileName->MaximumLength + 10))) return; UStrCopy(&imageFileName, (PUNICODE_STRING)pCreateInfo->ImageFileName); KLogEx(DEBUG_TRACE_INFO, "CREATE pid(%d), (%S)\n", HandleToULong(hProcessId), imageFileName.Buffer); } if (IsProcessBlocked(&imageFileName, ¶meter, parentNameStrW)) { KLogEx(DEBUG_TRACE_INFO, "[BLOCK] Blocked by Rule: PID(%d) Image(%wZ) Cmd(%wZ) PraentName(%S)\n", HandleToULong(hProcessId), pCreateInfo->ImageFileName, pCreateInfo->CommandLine, parentNameStrW); // ÇÁ·Î¼¼½º »ý¼º Â÷´Ü (Á¢±Ù °ÅºÎ ¸®ÅÏ) pCreateInfo->CreationStatus = STATUS_UNSUCCESSFUL;//STATUS_ACCESS_DENIED; //ScheduleSilentKill(hProcessId); //pCreateInfo->CreationStatus = STATUS_SUCCESS; SetProcessLog(LOG_PROCESS_BLOCK, 2, 0, 0, imageFileName.Buffer, parameter.Buffer, parentNameStrW); } else { AddProcessInfo(hProcessId, &imageFileName, parameter.Buffer, parentNameStrW); } UStrFree(&imageFileName); UStrFree(¶meter); // // IsWhiteProcess(hProcessId); } } VOID CreateProcessNotify(IN HANDLE ParentId, IN HANDLE hProcessId, IN BOOLEAN Create) { UNREFERENCED_PARAMETER(ParentId); if (!g_bs1Flt.IsAttached) { return; } if (Create == FALSE) { //KLogEx(" Terminate %d\n", HandleToULong(hProcessId)); TerminateProcessNotify(hProcessId); } else { // »ý¼ºµÈ ÇÁ·Î¼¼½º üũ //KLogEx(" Create %d\n", HandleToULong(hProcessId)); // IsWhiteProcess(hProcessId); } } NTSTATUS InitProcessNotify() { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING funcname = { 0, }; InitProcessMap(); InitBlockRuleList(); RtlInitUnicodeString(&funcname, L"PsSetCreateProcessNotifyRoutineEx"); pPsSetCreateProcessNotifyRoutineEx = (fpPsSetCreateProcessNotifyRoutineEx)MmGetSystemRoutineAddress(&funcname); if (pPsSetCreateProcessNotifyRoutineEx) { bIsVistaLater = TRUE; status = pPsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx, FALSE); } else { status = PsSetCreateProcessNotifyRoutine(CreateProcessNotify, FALSE); } KLogEx(DEBUG_TRACE_INFO, "status(%x), (%p)\n", status, pPsSetCreateProcessNotifyRoutineEx); s_ntstatus = status; return status; } VOID CleanupProcessNotify() { if (bIsVistaLater) { if(NT_SUCCESS(s_ntstatus)) pPsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx, TRUE); } else { if (NT_SUCCESS(s_ntstatus)) PsSetCreateProcessNotifyRoutine(CreateProcessNotify, TRUE); } CleanupProcessMap(); ClearBlockRules(); } DWORD GetProcessNotifyStatus() { KLogEx(DEBUG_TRACE_INFO, "status = %x\n", s_ntstatus); return s_ntstatus; }