📄 procname.c
字号:
/*
* Copyright (c) 2004 Security Architects Corporation. All rights reserved.
*
* Module Name:
*
* procname.c
*
* Abstract:
*
* This module defines various types used by process id to process name conversion routines.
*
* All processes are tracked in a global hash table.
* At startup ZwQuerySystemInformation(SystemProcessesAndThreadsInformation..) is used to
* enumerate all the existing processes. After that NtCreateProcess() is hooked and used
* to keep track of newly created processes while PsSetCreateProcessNotifyRoutine()
* callbacks are used to keep track of terminating processes.
*
* See http://www.microsoft.com/msj/0199/nerd/nerd0199.aspx for more info.
*
* Author:
*
* Eugene Tsyrklevich 23-Feb-2004
*
* Revision History:
*
* 07-Apr-2004 ET - Copied from process.h
*/
#include <NTDDK.h>
#include "procname.h"
#include "hookproc.h"
#include "process.h"
#include "policy.h"
#include "sysinfo.h"
#include "learn.h"
#include "misc.h"
#include "log.h"
void FindProcessNameOffset();
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, InitProcessNameEntries)
#pragma alloc_text (INIT, FindProcessNameOffset)
#pragma alloc_text (INIT, EnumerateExistingProcesses)
#pragma alloc_text (PAGE, RemoveProcessNameEntries)
#endif
ULONG SystemProcessId;
/* 67 * 144 = 10 kilobytes */
IMAGE_PID_ENTRY gImagePidHtbl[IMAGE_PID_HASHTABLE_SIZE];
//XXX investigate KeAcquireInStackQueuedSpinLock
KSPIN_LOCK gImagePidHtblSpinLock;
/*
* FindImagePidEntry()
*
* Description:
* Looks for a process entry in the global process hash table with a specified process id.
*
* Parameters:
* ProcessId - process id of the process to look for.
*
* Returns:
* Pointer to a process entry if one is found, NULL otherwise.
*/
PIMAGE_PID_ENTRY
FindImagePidEntry(ULONG ProcessId, ULONG ParentId)
{
PIMAGE_PID_ENTRY p;
KIRQL irql;
//LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("FindImagePidEntry(%d %d) 1\n", ProcessId, ParentId));
KeAcquireSpinLock(&gImagePidHtblSpinLock, &irql);
//LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("FindImagePidEntry 2\n"));
p = gImagePidHtbl[(ULONG) ProcessId % IMAGE_PID_HASHTABLE_SIZE].next;
while (p)
{
if (p->ProcessId == ProcessId)
{
if (ParentId == 0 || p->ParentId == ParentId)
{
if (ParentId != 0)
{
LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d FindImagePidEntry(%d, %d) found an entry (%d)\n", CURRENT_PROCESS_PID, ProcessId, ParentId, p->ParentId));
}
KeReleaseSpinLock(&gImagePidHtblSpinLock, irql);
return p;
}
LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d FindImagePidEntry: ProcessId %d clash. Parent id %d vs %d\n", CURRENT_PROCESS_PID, ProcessId, ParentId, p->ParentId));
}
p = p->next;
}
KeReleaseSpinLock(&gImagePidHtblSpinLock, irql);
return NULL;
}
/*
* ProcessInsertImagePidEntry()
*
* Description:
* Insert the new process entry into the global process hash table.
*
* Parameters:
* ProcessId - process id of the new process.
* NewProcessEntry - the entry to insert into the hash table.
*
* Returns:
* TRUE to indicate success, FALSE if failed.
*/
BOOLEAN
ProcessInsertImagePidEntry(ULONG ProcessId, PIMAGE_PID_ENTRY NewProcessEntry)
{
PIMAGE_PID_ENTRY p, prev;
KIRQL irql;
//LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("ProcessInsertImagePidEntry(%d %x) 1\n", ProcessId, NewProcessEntry));
KeAcquireSpinLock(&gImagePidHtblSpinLock, &irql);
//LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("ProcessInsertImagePidEntry 2\n"));
prev = &gImagePidHtbl[(ULONG) ProcessId % IMAGE_PID_HASHTABLE_SIZE];
p = prev->next;
while (p)
{
// if an entry with our ProcessId already exists, bail out
if (p->ProcessId == (ULONG) ProcessId)
{
LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d ProcessInsertImagePidEntry: ProcessId (%d) clash. New image name is '%S' (%d). Old image name is '%S' (%d)\n", CURRENT_PROCESS_PID, ProcessId, NewProcessEntry->ImageName, NewProcessEntry->ParentId, p->ImageName, p->ParentId));
if (ProcessId != 0)
{
KeReleaseSpinLock(&gImagePidHtblSpinLock, irql);
return FALSE;
}
}
prev = p;
p = p->next;
}
prev->next = NewProcessEntry;
KeReleaseSpinLock(&gImagePidHtblSpinLock, irql);
return TRUE;
}
/*
* CreateNewProcessEntry()
*
* Description:
* Allocates and initializes a new process entry.
*
* Parameters:
* ProcessId - process id of the new process.
* ProcessName - process image name.
*
* Returns:
* Pointer to a heap allocated IMAGE_PID_ENTRY structure. NULL if failed.
*/
PIMAGE_PID_ENTRY
CreateNewProcessEntry(ULONG ProcessId, ULONG ParentId, PUNICODE_STRING ProcessName, BOOLEAN NewProcess)
{
PIMAGE_PID_ENTRY ProcessEntry;
ASSERT(ProcessName);
ProcessEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof(IMAGE_PID_ENTRY) + ProcessName->Length, _POOL_TAG);
if (ProcessEntry == NULL)
{
LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("CreateNewProcessEntry: Out of memory. Forgeting about process %d (%S)", ProcessId, ProcessName->Buffer));
return NULL;
}
RtlZeroMemory(ProcessEntry, sizeof(IMAGE_PID_ENTRY));
ProcessEntry->ProcessId = ProcessId;
ProcessEntry->ParentId = ParentId;
ProcessEntry->FirstThread = NewProcess;
KeInitializeEvent(&ProcessEntry->UserlandRequestDoneEvent, SynchronizationEvent, FALSE);
wcscpy(ProcessEntry->ImageName, ProcessName->Buffer);
ProcessEntry->ImageName[ ProcessName->Length/sizeof(WCHAR) ] = L'\0';
KeInitializeSpinLock(&ProcessEntry->SecPolicy.SpinLock);
return ProcessEntry;
}
/*
* CreateAndLoadNewProcessEntry()
*
* Description:
* Creates a new process entry and inserts it into the global process hash table.
*
* Parameters:
* ProcessId - process id of the new process.
* ProcessName - process image name.
*
* Returns:
* Pointer to a heap allocated IMAGE_PID_ENTRY structure. NULL if failed.
*/
PIMAGE_PID_ENTRY
CreateAndLoadNewProcessEntry(ULONG ProcessId, PUNICODE_STRING ProcessName, BOOLEAN NewProcess)
{
PIMAGE_PID_ENTRY ProcessEntry;
ASSERT(ProcessName);
ProcessEntry = CreateNewProcessEntry(ProcessId, 0, ProcessName, NewProcess);
if (ProcessEntry == NULL)
return NULL;
if (LearningMode == FALSE && FindAndLoadSecurityPolicy(&ProcessEntry->SecPolicy, ProcessName->Buffer, NULL) == FALSE)
{
LOG(LOG_SS_PROCESS, LOG_PRIORITY_VERBOSE, ("CreateAndLoadNewProcessEntry: Failed to load security policy for %S\n", ProcessName->Buffer));
}
if (ProcessInsertImagePidEntry(ProcessId, ProcessEntry) == FALSE)
{
ExFreePoolWithTag(ProcessEntry, _POOL_TAG);
return NULL;
}
return ProcessEntry;
}
/*
* CreateProcessNotifyProc()
*
* Description:
* PsSetCreateProcessNotifyRoutine() callback. Used to remove process entries from the global
* hashtable of currently running processes. On Windows 2000, this routine also replaces PIDs
* of 0 with the real PIDs. This is necessary since win2k does not assign PIDs at a point
* where process.c!PostProcessNtCreateProcess() is called.
*
* NOTE: PsSetCreateProcessNotifyRoutine() adds a driver-supplied callback routine to,
* or removes it from, a list of routines to be called whenever a process is created or deleted.
*
* Parameters:
* ParentId - the parent process ID.
* ProcessId - process ID that was created / deleted.
* Create - indicates whether the process was created (TRUE) or deleted (FALSE).
*
* Returns:
* Nothing.
*/
VOID
CreateProcessNotifyProc
(
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
)
{
PIMAGE_PID_ENTRY p, prev, tmp;
ULONG RequiredPid;
BOOLEAN FoundNewProcess = FALSE;
KIRQL irql;
LOG(LOG_SS_PROCESS, LOG_PRIORITY_VERBOSE, ("%d CreateProccessNotifyProc(%d, %d, %d)\n", CURRENT_PROCESS_PID, ParentId, ProcessId, Create));
/* if the entry is being removed look for ProcessId, otherwise look for 0 */
RequiredPid = Create == FALSE ? (ULONG) ProcessId : 0;
/*
* find an entry with pid=ProcessId
*/
KeAcquireSpinLock(&gImagePidHtblSpinLock, &irql);
prev = &gImagePidHtbl[(ULONG) RequiredPid % IMAGE_PID_HASHTABLE_SIZE];
p = prev->next;
while (p)
{
if (p->ProcessId != (ULONG) RequiredPid)
{
prev = p;
p = p->next;
continue;
}
if (p->ParentId != 0 && p->ParentId != (ULONG) ParentId)
{
LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d CreateProccessNotifyProc(): ProcessId %d collision. %d vs %d\n", CURRENT_PROCESS_PID, p->ProcessId, p->ParentId, ParentId));
prev = p;
p = p->next;
continue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -