⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 臭氧层主动防御系统驱动源代码!臭氧层主动防御系统驱动源代码!
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2004 Security Architects Corporation. All rights reserved.
 *
 * Module Name:
 *
 *		process.c
 *
 * Abstract:
 *
 *		This module defines various types used by process and thread hooking routines.
 *
 * Author:
 *
 *		Eugene Tsyrklevich 23-Feb-2004
 *
 * Revision History:
 *
 *		None.
 */


#include <NTDDK.h>
#include "process.h"
#include "driver.h"
#include "policy.h"
#include "hookproc.h"
#include "userland.h"
#include "procname.h"
#include "accessmask.h"
#include "learn.h"
#include "misc.h"
#include "i386.h"
#include "log.h"


#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, InitProcessEntries)
#pragma alloc_text (PAGE, ProcessPostBootup)
#endif


fpZwCreateProcess	OriginalNtCreateProcess = NULL;
fpZwCreateProcessEx	OriginalNtCreateProcessEx = NULL;
fpZwOpenProcess		OriginalNtOpenProcess = NULL;

fpZwCreateThread	OriginalNtCreateThread = NULL;
fpZwOpenThread		OriginalNtOpenThread = NULL;


BOOLEAN				AllowProcessesWithPoliciesOnly = FALSE;

WCHAR				OzoneInstallPath[MAX_PATH];
USHORT				OzoneInstallPathSize = 0;


/* XXX this will not work on 64-bit architectures, due to assumption of size of ulong, pointers, etc */
typedef struct _CONTROL_AREA {      // must be quadword sized.
	ULONG	data[9];
    PFILE_OBJECT FilePointer;
} CONTROL_AREA, *PCONTROL_AREA;

typedef struct _SEGMENT {
    struct _CONTROL_AREA *ControlArea;
} SEGMENT, *PSEGMENT;

typedef struct _SECTION {
	ULONG_PTR	data[5];
    PSEGMENT Segment;
} SECTION, *PSECTION;



/*
 * rand()
 *
 * Description:
 *		Returns a random number that is calculated by XOR'ing together often changing system values.
 *
 * Parameters:
 *		randval - An optional random value.
 *
 * Returns:
 *		A random ULONG value.
 */

ULONG
rand(ULONG randval)
{
	LARGE_INTEGER	perf, TickCount;
	ULONG			r;


	KeQueryPerformanceCounter(&perf);
//	KdPrint(("perf: %d %d\n", perf.LowPart, perf.HighPart));

	KeQueryTickCount(&TickCount);
//	KdPrint(("tick: %d %d\n", TickCount.LowPart, TickCount.HighPart));

//	KdPrint(("int: %I64d\n", KeQueryInterruptTime()));

	r = randval ^
		perf.LowPart ^ perf.HighPart ^
		TickCount.HighPart ^ TickCount.LowPart ^
		(ULONG) KeQueryInterruptTime();

//	KdPrint(("rand = %x\n", r));


	return r;
}



/*
 * PostProcessNtCreateProcess()
 *
 * Description:
 *		This function is called by the mediated NtCreateProcess() system service.
 *		It is responsible for saving the information about the newly created process in a
 *		global process hash table.
 *
 * Parameters:
 *		ProcessHandle - process object handle initialized by NtCreateProcess().
 *		SectionHandle - specifies a handle to an image section that grants SECTION_MAP_EXECUTE
 *		    access. If this value is zero, the new process inherits the address space from the process
 *		    referred to by InheritFromProcessHandle. In Windows 2000 the lowest bit specifies
 *		    (when set) that the process should not be associated with the job of the
 *		    InheritFromProcessHandle process.
 *
 * Returns:
 *		ULONG indicating an action to take (ACTION_DENY to disallow process createion, ACTION_PERMIT to allow).
 */

ULONG
PostProcessNtCreateProcess(PHANDLE ProcessHandle, HANDLE SectionHandle)
{
	NTSTATUS					status, rc;
	PIMAGE_PID_ENTRY			p, prev, NewProcess;
	ULONG						ProcessId, Size;
	PULONG_PTR					Base;
	UNICODE_STRING				usPath;
	ANSI_STRING					asPath;
	KIRQL						irql;
	PROCESS_BASIC_INFORMATION	ProcessBasicInfo;
	CHAR						ProcessPathUnresolved[MAX_PATH];
	CHAR						PROCESSNAME[MAX_PATH];
	PCHAR						FunctionName = "PostProcessNtCreateProcess";


	if (ProcessHandle == NULL)
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_WARNING, ("%s: ProcessHandle is NULL\n", FunctionName));
		return ACTION_NONE;
	}


	/*
	 * Try to retrieve the image name from a section object
	 */

	if (!SectionHandle)
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_WARNING, ("%s: SectionHandle is NULL\n", FunctionName));
		return ACTION_NONE;
	}


	do
	{
		PSECTION		SectionToMap;
		PSEGMENT		seg;
		PCONTROL_AREA	pca;
		PFILE_OBJECT	pfo;


		status = ObReferenceObjectByHandle(
					SectionHandle,
					0,
					0,
					KernelMode,
					(PSECTION *) &SectionToMap,
					NULL
					);

/* macro shortcut for bailing out of PostProcessNtCreateProcess do {} while loop in case of an error */

#define	ABORT_PostProcessNtCreateProcess(msg)													\
		{																						\
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("Error occurred in %s:", FunctionName));	\
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, (msg));										\
			return ACTION_NONE; /* XXX */														\
		}

		if (! NT_SUCCESS(status))
			
			ABORT_PostProcessNtCreateProcess(("ObReferenceObjectByHandle(SectionHandle) failed"));


		if (SectionToMap == NULL)

			ABORT_PostProcessNtCreateProcess(("SectionToMap is NULL"));


		if ( (seg = ((PSECTION)SectionToMap)->Segment) == NULL)

			ABORT_PostProcessNtCreateProcess(("Segment is NULL"));

		if ( (pca = seg->ControlArea) == NULL)

			ABORT_PostProcessNtCreateProcess(("ControlArea is NULL"));


		if ( (pfo = pca->FilePointer) == NULL)

			ABORT_PostProcessNtCreateProcess(("FilePointer is NULL"));


		usPath = pfo->FileName;

		if (usPath.Length == 0)

			ABORT_PostProcessNtCreateProcess(("FileName length is 0"));


		_snprintf(ProcessPathUnresolved, MAX_PATH, "%S", usPath.Buffer);
		ProcessPathUnresolved[MAX_PATH - 1] = 0;


		ObDereferenceObject(SectionToMap);

	} while (0);


	/*
	 * Now verify the executable name against the security policy
	 */

	VerifyExecutableName(ProcessPathUnresolved);


	if (LearningMode == FALSE)
	{
		ACTION_TYPE Action;


		VerifyUserReturnAddress();


		FixupFilename(ProcessPathUnresolved, PROCESSNAME, MAX_PATH);


		/*
		 * We manually inc/dec HookedRoutineRunning since POLICY_CHECK_OPTYPE_NAME() can call
		 * HOOK_ROUTINE_EXIT() which will decrement HookedRoutineRunning and then it will get
		 * decremented the second time in HookedNtCreateProcess()
		 */

#if DBG
		InterlockedIncrement(&HookedRoutineRunning);
#endif

		POLICY_CHECK_OPTYPE_NAME(PROCESS, OP_PROC_EXECUTE);

#if DBG
		InterlockedDecrement(&HookedRoutineRunning);
#endif
	}
	else
	{
		// learning mode
		AddRule(RULE_PROCESS, ProcessPathUnresolved, OP_PROC_EXECUTE);
	}


	/*
	 * retrieve the Process ID
	 */

	status = ZwQueryInformationProcess(*ProcessHandle, ProcessBasicInformation, &ProcessBasicInfo, sizeof(ProcessBasicInfo), &Size);

	if (! NT_SUCCESS(status))
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("PostProcessNtCreateProcess: ZwQueryInformationProcess failed with status %x\n", status));
		return ACTION_NONE;
	}

	ProcessId = ProcessBasicInfo.UniqueProcessId;

	/*
	 * On win2k ProcessId is not available at this stage yet.
	 * ProcessId of 0 will get replaced by a real value in CreateProcessNotifyProc.
	 */


	/* once winlogon.exe executes, we consider the boot process to be complete */
	if (BootingUp == TRUE)
	{
		PCHAR	ProcessName;


		ProcessName = strrchr(ProcessPathUnresolved, '\\');

		if (ProcessName == NULL)
			ProcessName = ProcessPathUnresolved;
		else
			++ProcessName;	/* skip past the slash */

		if (_strnicmp(ProcessName, "winlogon.exe", 12) == 0)
		{
			BootingUp = FALSE;
			InitPostBootup();
		}
	}


	/*
	 * Now create a new process entry and load the associated security policy (if any)
	 */

	NewProcess = CreateNewProcessEntry(ProcessId, CURRENT_PROCESS_PID, &usPath, TRUE);


	if (ProcessInsertImagePidEntry(ProcessId, NewProcess) == FALSE)
	{
		ExFreePoolWithTag(NewProcess, _POOL_TAG);

		return ACTION_NONE;
	}


	/*
	 * Now find and load appropriate security policy.
	 *
	 * Look for a per-user policy first. To do that, we send an SID resolve request
	 * to userland Ozone Agent Service.
	 */

	if (LearningMode == FALSE)
	{
		PSID_RESOLVE_REPLY	pSidResolveReply = NULL;
		PWSTR				UserName = NULL;


 		if (IssueUserlandSidResolveRequest(NewProcess) != FALSE)
		{
			if (NewProcess->UserlandReply)
			{
				pSidResolveReply = (PSID_RESOLVE_REPLY) NewProcess->UserlandReply;

				if (pSidResolveReply->UserNameLength)
				{
					LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("PostProcessNtCreateProcess: SID resolved to %S\n", pSidResolveReply->UserName));
					UserName = pSidResolveReply->UserName;
				}
				else
				{
					LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("PostProcessNtCreateProcess(): SID resolve error\n"));
				}
			}
		}


		if (! FindAndLoadSecurityPolicy(&NewProcess->SecPolicy, usPath.Buffer, UserName))
		{
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_WARNING, ("%d PostProcessNtCreateProcess(): no policy, %d, %S\n", CURRENT_PROCESS_PID, ProcessId, usPath.Buffer));

			//XXX have an option where only processes with existing policies (even if they are empty.. policy_default: allow) are allowed to run
			//interactive session is excluded?!?!
			if (AllowProcessesWithPoliciesOnly == TRUE)
			{
				ExFreePoolWithTag(NewProcess, _POOL_TAG);
				return ACTION_DENY;
			}
		}
		else
		{
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_WARNING, ("%d PostProcessNtCreateProcess(): with policy, %d, %S\n", CURRENT_PROCESS_PID, ProcessId, usPath.Buffer));
		}


		if (NewProcess->UserlandReply)
		{
			ExFreePoolWithTag(NewProcess->UserlandReply, _POOL_TAG);
			NewProcess->UserlandReply = NULL;
		}
	}


	/*
	 * Stack Buffer Overflow Protection (Part 1).
	 *
	 * 1. Allocate/reserve a random (< 0x4000000) chunk of virtual memory starting at 0xFFFF.
	 * This causes the stack of the main thread to be moved by a random amount.
	 *
	 * (note1: first 64K of memory are allocated as a guard against NULL pointers dereferencing).
	 * (note2: main() is mapped at 0x4000000 and thus we cannot allocate anything that will cause the
	 *		   stack of the main thread to move past the 0x400000 boundary).
	 *
	 *
	 * Stack Buffer Overflow Protection (Part 2).
	 *
	 * 2. Allocate a random (> 4 Megs && < 10 Megs) chunk of virtual memory after the process code segment.
	 * This causes the heap and stacks non-main threads to be moved by a random amount.
	 *
	 * (note: as mentioned above, main() is mapped at 0x4000000, by reserving a large chunk of virtual
	 *		  we force Windows to find the first available address beyond the code segment and reserve
	 *		  a random amount of memory past it causing other thread stacks and heaps to shift).
	 */

#define	ONE_MEGABYTE	(1024 * 1024)

	if (IS_OVERFLOW_PROTECTION_ON(gSecPolicy) && IS_OVERFLOW_PROTECTION_ON(NewProcess->SecPolicy) && LearningMode == FALSE && BootingUp == FALSE)
	{
//XXX verify that the image entry is actually at 4 meg (not true for most of system processes)

		/*
		 * allocate up to 3 megs of virtual address space before the code segment,
		 * this affects main thread stack as well as some heaps
		 */

#define	FIRST_AVAILABLE_ADDRESS	0xFFFF

		Size = PAGE_SIZE + (rand(ProcessId) % (3 * ONE_MEGABYTE));
		Base = (PULONG_PTR) FIRST_AVAILABLE_ADDRESS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -