Skip to content

Infinite-Loop #15

@Bix3

Description

@Bix3

Hello, i did some testing with the library, it seems good so far, altough i have a little error.

I modified the ExHook like this, the reason is, that the given sample can only activate on processes which are already running. so i moved the code for activation to the
"InitTarget" Function, which works so far. on the main i activate it on a process ("activator.exe") trough which i can then send a command (syscall 1032) once i want it to activate on another process ("notepad.exe").
the whole thing works on my cloudvm running windows server datacenter 2019 1809 build. But when i test on my bare metal pc's (win10 pro/home 1803/1909) on none of them it works completely it initializes successfully on the activator.exe but when that thing sends the 1032 syscall it gets stuck forever in the kernel code spamming the dbgprintf of the Systemwideexceptionhandler and Sysexitintercept.

#include "NtInternals.h"
#include "ByePG.h"

void SysExitIntercept(PETHREAD Thread);
LONG SystemWideExceptionHandler(CONTEXT* ContextRecord, EXCEPTION_RECORD* ExceptionRecord);
SYSTEM_PROCESS_INFORMATION* QueryProcessInformation();
NTSTATUS InitTarget(wchar_t name[255]);


extern "C" NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
	UNREFERENCED_PARAMETER(DriverObject);
	UNREFERENCED_PARAMETER(RegistryPath);
	
	NTSTATUS Status = ByePgInitialize(SystemWideExceptionHandler, FALSE);
	if (!NT_SUCCESS(Status)) return Status;
	
	return InitTarget(L"activator.exe");
}



#define kprintf(...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __VA_ARGS__)

void SysExitIntercept(PETHREAD Thread)
{	
	kprintf("\n1");
	// Get trap frame
	//
	KTRAP_FRAME* TrapFrame = PsGetBaseTrapFrame(Thread);
	KTRAP_FRAME* ThrTrapFrame = PsGetTrapFrame(Thread);
	if (TrapFrame != ThrTrapFrame) return;

	// Check if it's a service frame
	//
	if (TrapFrame->ExceptionActive == 2)
	{
		kprintf("\n2");
		kprintf("SYSCALL %d [%p, %p, %p, %p]\n", PsGetSystemCallNumber(Thread), TrapFrame->Rcx, TrapFrame->Rdx, TrapFrame->R8, TrapFrame->R9);
				
		if (PsGetSystemCallNumber(Thread) == 1032)
		{
			kprintf("\n3");

			InitTarget("notepad.exe");
		
			return;
		}
		kprintf("\n4");
	}
	kprintf("\n5");
	return;
}

LONG SystemWideExceptionHandler(CONTEXT* ContextRecord, EXCEPTION_RECORD* ExceptionRecord)
{
	// Only handle exceptions raised at <= DISPATCH_LEVEL (ignoring EFLAGS.IF)
	//
	kprintf("\n6");
	if (KeGetCurrentIrql() > DISPATCH_LEVEL) return EXCEPTION_EXECUTE_HANDLER;
	kprintf("\n7");
	// Access violation
	//
	if (ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION)
	{
		kprintf("\n8");
		/*
			KiCopyCountersWorker proc near
				mov     [rsp+arg_0], rbx
				mov     [rsp+arg_18], rsi
				push    rdi
				sub     rsp, 30h
				mov     rdi, rdx
				mov     rsi, rcx
				mov     rbx, [rdx+8]	<-- Exception occurs here
		*/

		// Verify that it was raised at target instruction
		//
		if (MmIsAddressValid(ExceptionRecord->ExceptionAddress))
		{
			kprintf("\n9");
			UCHAR* Instruction = (UCHAR*)ExceptionRecord->ExceptionAddress;
			if (Instruction[3] == 0x08)
			{
				kprintf("\n10");
				/*
					jmp     short $+2		<-- Epilogue start
					mov     rbx, [rsp+38h+arg_0]
					mov     rsi, [rsp+38h+arg_18]
					add     rsp, 30h
					pop     rdi
					retn
				KiCopyCountersWorker endp
				*/

				// Skip to epilogue
				//
				while (Instruction[0] != 0xEB ||
					Instruction[1] != 0x00) Instruction++;
				ContextRecord->Rip = (ULONG64)Instruction + 2;
				kprintf("\n11");
				// Inject a call to our routine
				//
				ContextRecord->Rsp -= 0x8;
				*(ULONG64*)ContextRecord->Rsp = ContextRecord->Rip;
				ContextRecord->Rip = (ULONG64)&SysExitIntercept;
				kprintf("\n12");
				// Continue execution
				//
				return EXCEPTION_CONTINUE_EXECUTION;
			}
		}
	}
	kprintf("\n13");
	return EXCEPTION_EXECUTE_HANDLER;
}

SYSTEM_PROCESS_INFORMATION* QueryProcessInformation()
{
	// Allocate buffer of estimated size
	//
	ULONG BufferSize = 0x10000;
	void* Buffer = ExAllocatePool(NonPagedPool, BufferSize);

	while (true)
	{
		// Try to query system information
		//
		NTSTATUS Status = ZwQuerySystemInformation(SystemProcessInformation, Buffer, BufferSize, &BufferSize);

		// If size is too small:
		//
		if (Status == STATUS_INFO_LENGTH_MISMATCH)
		{
			ExFreePool(Buffer);
			Buffer = ExAllocatePool(NonPagedPool, BufferSize);
		}
		else
		{
			// If failed, free the buffer and return nullptr:
			//
			if (!NT_SUCCESS(Status))
			{
				ExFreePool(Buffer);
				return nullptr;
			}
			// Else cast the buffer to relevant type and return it:
			//
			else
			{
				return PSYSTEM_PROCESS_INFORMATION(Buffer);
			}
		}
	}
}


NTSTATUS InitTarget(wchar_t name[255])
{

	UNICODE_STRING TargetImageName;
	RtlInitUnicodeString(&TargetImageName, name);
	
	SYSTEM_PROCESS_INFORMATION* Spi = QueryProcessInformation();
	if (void* Buffer = Spi)
	{
		// Iterate each process
		//
		while (Spi->NextEntryOffset)
		{
			// If matches target image:
			//
			if (!RtlCompareUnicodeString(&Spi->ImageName, &TargetImageName, FALSE))
			{
				// Resolve EPROCESS
				//
				PEPROCESS Process = nullptr;
				PsLookupProcessByProcessId(Spi->UniqueProcessId, &Process);
				if (Process)
				{
					kprintf("Target process instance [PID: %llu, EPROCESS: %p]\n", Spi->UniqueProcessId, Process);

					// Iterate each thread
					//
					for (int i = 0; i < Spi->NumberOfThreads; i++)
					{
						// Resolve ETHREAD
						//
						PETHREAD Thread = nullptr;
						PsLookupThreadByThreadId(Spi->Threads[i].ClientId.UniqueThread, &Thread);
						if (Thread)
						{
							kprintf("-- Thread [TID: %llu, ETHREAD: %p]\n", Spi->Threads[i].ClientId.UniqueThread, Thread);

							// Set CycleProfiling flag
							//
							DISPATCHER_HEADER* DpcHdr = (DISPATCHER_HEADER*)Thread;
							DpcHdr->CycleProfiling = 1;

							// Dereference ETHREAD
							//
							ObDereferenceObject(Thread);
						}
					}

					// Dereference EPROCESS
					//
					ObDereferenceObject(Process);
				}
			}

			Spi = PSYSTEM_PROCESS_INFORMATION((char*)Spi + Spi->NextEntryOffset);
		}

		// Free the buffer and report success
		//
		ExFreePool(Buffer);
		return STATUS_SUCCESS;
	}
	else
	{
		return STATUS_UNSUCCESSFUL;
	}

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions