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

📄 process.c

📁 臭氧层主动防御系统驱动源代码!臭氧层主动防御系统驱动源代码!
💻 C
📖 第 1 页 / 共 3 页
字号:

		if (! NT_SUCCESS(status))
		{
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%s: ZwQueryInformationProcess failed with status %x\n", FunctionName, status));
			goto done;
		}

		ProcessId = ProcessBasicInfo.UniqueProcessId;

		/*
		 * if ProcessId is 0 then the pid has not been assigned yet and we are the primary thread.
		 * in that case pass our pid (we are still running in the context of the parent process) as the ParentId
		 * to make sure we find the right process (since theoretically there can be more than one process with a
		 * pid of 0)
		 */
		p = FindImagePidEntry(ProcessId, ProcessId == 0 ? CURRENT_PROCESS_PID : 0);

		if (p == NULL)
		{
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d %s: FindImagePidEntry(%d) failed\n", CURRENT_PROCESS_PID, FunctionName, ProcessId));
			goto done;
		}


		/*
		 * Stack Buffer Overflow Protection (Part 3).
		 *
		 * Allocate/reserve a random (< 1024 bytes) part of a thread's stack space.
		 * This causes the least significant 10 bits to be randomized as well.
		 * (without this, the least significant 16 bits are always the same).
		 */

		/* save the stackoffset for now since we are holding a spinlock and cannot touch pageable memory */
//XXX we are not holding the spinlock here but are still accessing various p-> fields
		if (IS_OVERFLOW_PROTECTION_ON(gSecPolicy) && IS_OVERFLOW_PROTECTION_ON(p->SecPolicy))

			StackOffset = (USHORT) (16 + (rand(ThreadContext->Eax) % 63) * 16);


		if (! IS_USERLAND_PROTECTION_ON(gSecPolicy) || ! IS_USERLAND_PROTECTION_ON(p->SecPolicy))
			goto done;


		/* Userland DLL needs to be loaded only once (by the first/main thread) */

		if (p->FirstThread != TRUE)
			goto done;

		p->FirstThread = FALSE;

//XXX investigate MEM_WRITE_WATCH (supported on i386?)


		/*
		 * Inject the userland DLL into the process.
		 *
		 * This is achieved by allocating 1 page of memory in the address space of a "victim" process.
		 * Then the LdrLoadDll(our_dll) code is written to the allocated page and victim's thread EIP
		 * is changed to point to our code.
		 * As soon as the thread executes, it will load our DLL and then jump to the original entry point.
		 *
		 * When not given explicit directions, the Microsoft linker creates each DLL with a
		 * preferred load address of 0x10000000. By loading our DLL first, we cause the rest of
		 * the application DLLs to load at a different address.
		 */

		/* allocate 1 page of commited rwx memory */

		Size = PAGE_SIZE;
		Base = NULL;

		status = ZwAllocateVirtualMemory(ProcessHandle, &Base, 0L, &Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

		if (! NT_SUCCESS(status))
		{
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%s: ZwAllocateVirtualMemory(%x, %x) failed with status %x\n", FunctionName, Base, Size, status));
			goto done;
		}


		status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_ALL_ACCESS, 0, KernelMode, &proc, NULL);

		if (! NT_SUCCESS(status))
		{
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%s: ObReferenceObjectByHandle(ProcessHandle) failed with status %x\n", FunctionName, status));
			goto done;
		}


		try
		{
			ULONG	CodeAddress, DllPathAddress;
			ULONG	ThreadEntryPoint = ThreadContext->Eax;	/* thread entry point is stored in the EAX register */
			PWSTR	InjectDllName = L"ozoneusr.dll";
			USHORT	InjectDllNameSize = (wcslen(InjectDllName) + 1) * sizeof(WCHAR);


			/*
			 * Execute the DLL inject in the memory context of a "victim" process
			 */

			KeAttachProcess(proc);
			{
				/* probe the memory, just in case */
				ProbeForRead(Base, PAGE_SIZE, 1);
				ProbeForWrite(Base, PAGE_SIZE, 1);


				/*
				 * Memory Layout used for DLL injection
				 *
				 * Byte		Value
				 *
				 * 0..4		Original EIP
				 * 4..8		LdrLoadDll() output handle
				 * 8..16	LdrLoadDll() DllName UNICODE_STRING structure 
				 * 16..?	DllName.Buffer WCHAR string
				 * ?..?		DllPath WCHAR string
				 * ....		assembler code (to call LdrLoadDll() and then jmp to the original EIP)
				 */

#define	BASE_PTR					Base
#define	ADDRESS_ORIGINAL_EIP		(BASE_PTR + 0)
#define	ADDRESS_DLL_HANDLE			(BASE_PTR + 4)
#define	ADDRESS_DLL_NAME			(BASE_PTR + 8)


				/* save the original thread entry point */
				* (PULONG) ADDRESS_ORIGINAL_EIP = ThreadEntryPoint;

				/* skip past eip and output handle (8 bytes) */
				InstructionAddress = ADDRESS_DLL_NAME;

				/*
				 * Create a UNICODE_STRING structure
				 */

				* ((PUSHORT) InstructionAddress)++ = InjectDllNameSize;	/* UNICODE_STRING.Length */
				* ((PUSHORT) InstructionAddress)++ = InjectDllNameSize;	/* UNICODE_STRING.MaximumLength */

				/* UNICODE_STRING.Buffer (points to unicode string directly following the buffer) */

				* ((PULONG) InstructionAddress)++ = (ULONG) (InstructionAddress + sizeof(PWSTR));


				/* the actual DllName.Buffer value */

				wcscpy((PWSTR) InstructionAddress, InjectDllName);

				InstructionAddress += InjectDllNameSize;


				/* DllPathValue value */

				DllPathAddress = (ULONG) InstructionAddress;

				wcscpy((PWSTR) InstructionAddress, OzoneInstallPath);

				InstructionAddress += OzoneInstallPathSize;


				CodeAddress = (ULONG) InstructionAddress;


				/*
				 * Generate code that will call LdrLoadDll and then jmp to the original entry point.
				 */

				/*
				 *	NTSTATUS
				 *	LdrLoadDll (
				 *		IN PWSTR DllPath OPTIONAL,
				 *		IN PULONG DllCharacteristics OPTIONAL,
				 *		IN PUNICODE_STRING DllName,
				 *		OUT PVOID *DllHandle
				 *		);
				 *
				 * Save LdrLoadDll parameters on stack (last to first).
				 */

				ASM_PUSH(InstructionAddress, ADDRESS_DLL_HANDLE);		/* DllHandle			*/
				ASM_PUSH(InstructionAddress, ADDRESS_DLL_NAME);			/* DllName				*/
				ASM_PUSH(InstructionAddress, 0);						/* DllCharacteristics	*/
//				ASM_PUSH(InstructionAddress, NULL);						/* DllPath				*/
				ASM_PUSH(InstructionAddress, DllPathAddress);			/* DllPath				*/

				ASM_CALL(InstructionAddress, FindFunctionBase(NTDLL_Base, "LdrLoadDll"));


				//XXX now clear out all the data up to this instruction
				//be careful first 4 bytes are used by the next instruction
				/*
				mov	ecx, 16
				lea edi, Base + 4
				rep	stosw
				*/

				ASM_JMP(InstructionAddress, Base);
			}
			KeDetachProcess();

			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d %s: Replacing original thread entry point %x with %x\n", CURRENT_PROCESS_PID, FunctionName, ThreadContext->Eax, CodeAddress));

			/* hijack the thread instruction pointer (saved in EAX) */
//			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("eip %x eax %x\n", ThreadContext->Eip, ThreadContext->Eax));

			ThreadContext->Eax = (ULONG) CodeAddress;

			ThreadContext->Eip = ThreadContext->Eax;

			ObDereferenceObject(proc);
		}

		except(EXCEPTION_EXECUTE_HANDLER)
		{
			NTSTATUS status = GetExceptionCode();

			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%s: caught an exception. status = 0x%x\n", FunctionName, status));

			KeDetachProcess();

			ObDereferenceObject(proc);
		}
	}


done:

	/*
	 * finally adjust the stack.
	 * could not have done it before since we were holding a spinlock and weren't allowed to access pageable memory
	 */

	if (StackOffset)

		ThreadContext->Esp -= StackOffset;


	ASSERT(OriginalNtCreateThread);

	rc = OriginalNtCreateThread(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle,
								ClientId, ThreadContext, UserStack, CreateSuspended);


	HOOK_ROUTINE_EXIT(rc);
}



/*
 * HookedNtOpenThread()
 *
 * Description:
 *		This function mediates the NtOpenThread() system service in order to XXX
 *		.
 *
 *		NOTE: ZwOpenThread opens a thread object. [NAR]
 *
 * Parameters:
 *		Those of NtOpenThread().
 *
 * Returns:
 *		NTSTATUS returned by NtOpenThread().
 */

NTSTATUS
NTAPI
HookedNtOpenThread
(
	OUT PHANDLE ThreadHandle,
	IN ACCESS_MASK DesiredAccess,
	IN POBJECT_ATTRIBUTES ObjectAttributes,
	IN PCLIENT_ID ClientId
)
{
	CHAR	THREADNAME[MAX_PATH];

	HOOK_ROUTINE_ENTER();


	if (LearningMode == FALSE && GetPathFromOA(ObjectAttributes, THREADNAME, MAX_PATH, RESOLVE_LINKS))
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d HookedNtOpenThread: %s\n", (ULONG) PsGetCurrentProcessId(), THREADNAME));
	}


	if (! IS_BIT_SET(DesiredAccess, THREAD_QUERY_INFORMATION))
	{
		// ClientId->UniqueProcess = 0 if process opens a thread in the same process (wmplayer.exe)
		if (ClientId)
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d HookedNtOpenThread(%d %d): %x\n", (ULONG) PsGetCurrentProcessId(), ClientId->UniqueProcess, ClientId->UniqueThread, DesiredAccess));
		else
			LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("%d HookedNtOpenThread(): %x\n", (ULONG) PsGetCurrentProcessId(), DesiredAccess));
	}

	ASSERT(OriginalNtOpenThread);

	rc = OriginalNtOpenThread(ThreadHandle, DesiredAccess, ObjectAttributes, ClientId);


	HOOK_ROUTINE_EXIT(rc);
}



/*
 * ProcessPostBootup()
 *
 * Description:
 *		Find out where userland Ozone files are installed once the bootup process is complete.
 *		We are unable to read some parts of the registry before the bootup is complete since
 *		they have not been initialized yet.
 *
 *		ProcessPostBootup() might run even before bootup is complete in order to setup up the
 *		default values. When ProcessPostBootup() runs again after bootup, the default values
 *		will be overwritten with the correct ones.
 *
 * Parameters:
 *		None.
 *
 * Returns:
 *		Nothing.
 */

VOID
ProcessPostBootup()
{
	if (ReadStringRegistryValueW(L"\\Registry\\Machine\\Software\\Security Architects\\Ozone Agent", L"InstallPath", OzoneInstallPath, MAX_PATH) == FALSE)
	{
		LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("ProcessPostBootup: Failed to open InstallPath registry key\n"));

		// use the default path
		wcscpy(OzoneInstallPath, L"C:\\Program Files\\Security Architects\\Ozone Agent");
	}

	OzoneInstallPathSize = (wcslen(OzoneInstallPath) + 1) * sizeof(WCHAR);
}



/*
 * InitProcessEntries()
 *
 * Description:
 *		Initializes all the mediated process operation pointers. The "OriginalFunction" pointers
 *		are initialized by InstallSyscallsHooks() that must be called prior to this function.
 *
 *		NOTE: Called once during driver initialization (DriverEntry()).
 *
 * Parameters:
 *		None.
 *
 * Returns:
 *		TRUE to indicate success, FALSE if failed.
 */
/*
VOID
LoadImageNotifyProc
(
    IN PUNICODE_STRING  FullImageName,
    IN HANDLE  ProcessId, // where image is mapped
    IN PIMAGE_INFO  ImageInfo
)
{
	if (FullImageName && ImageInfo)
	{
		KdPrint(("LoadImageNotifyProc: %d %S %x %x\n", ProcessId, FullImageName->Buffer, ImageInfo->ImageBase, ImageInfo->ImageSize));
	}
	else
	{
		KdPrint(("LoadImageNotifyProc: NULL Pointer %x %x\n", FullImageName, ImageInfo));
	}
}
*/

BOOLEAN
InitProcessEntries()
{
//	PsSetLoadImageNotifyRoutine(LoadImageNotifyProc);

	if ( (OriginalNtCreateProcess = (fpZwCreateProcess) ZwCalls[ZW_CREATE_PROCESS_INDEX].OriginalFunction) == NULL)
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("InitProcessEntries: OriginalNtCreateProcess is NULL\n"));
		return FALSE;
	}
	
	if ( (OriginalNtCreateProcessEx = (fpZwCreateProcessEx) ZwCalls[ZW_CREATE_PROCESSEX_INDEX].OriginalFunction) == NULL)
	{
		/* does not exist on Win2K */
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("InitProcessEntries: OriginalNtCreateProcessEx is NULL\n"));
	}

	if ( (OriginalNtOpenProcess = (fpZwOpenProcess) ZwCalls[ZW_OPEN_PROCESS_INDEX].OriginalFunction) == NULL)
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("InitProcessEntries: OriginalNtOpenProcess is NULL\n"));
		return FALSE;
	}

	if ( (OriginalNtCreateThread = (fpZwCreateThread) ZwCalls[ZW_CREATE_THREAD_INDEX].OriginalFunction) == NULL)
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("InitProcessEntries: OriginalNtCreateThread is NULL\n"));
		return FALSE;
	}

	if ( (OriginalNtOpenThread = (fpZwOpenThread) ZwCalls[ZW_OPEN_THREAD_INDEX].OriginalFunction) == NULL)
	{
		LOG(LOG_SS_PROCESS, LOG_PRIORITY_DEBUG, ("InitProcessEntries: OriginalNtOpenThread is NULL\n"));
		return FALSE;
	}


	/*
	 * run ProcessPostBootup() even if we are still booting up, this way we will at least setup
	 * the default values. When ProcessPostBootup() runs again after bootup, the default values
	 * will be overwritten with the correct ones.
	 */

	ProcessPostBootup();


	return TRUE;
}

⌨️ 快捷键说明

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