Git Product home page Git Product logo

byepg's Introduction

ByePg: Defeating Patchguard using Exception-hooking

ByePg hijacks the HalPrivateDispatchTable table to create a early-bugcheck hook. Utilizing this early-bugcheck hook it collects information about the exception and basically provides a simple interface to register a high-level system-wide exception handler.

A variety of kernel hooks can be implemented using this method completely bypassing PatchGuard and HVCI as it creates an entirely new attack surface, exception-based hooking, which was previously not possible in Windows kernel.

Writeup:

https://blog.can.ac/2019/10/19/byepg-defeating-patchguard-using-exception-hooking/

Project Structure:

  • \ByePgLib contains the base library
  • \ExHook contains a standalone SYSCALL hooking example using ByePg
  • \ExceptionHookingDemo demonstrates the exception handler
  • \InfinityHookFix contains a sample rendering the recent InfinityHook patch by Microsoft useless
  • \FreeSeh contains a SEH-via-ByePg module letting you use SEH in manual mapped images bypassing PatchGuard's inverted function table checks

Result:

ExHook

P.S.

There are many other things that can be done using the base library and many things can be improved, be SEH handling or BugCheck parsing, so I would really appreciate any form of contribution to this repo.

byepg's People

Contributors

can1357 avatar mrexodia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

byepg's Issues

ByePG on Win10x64 19041

I'm currently running ByePG (ExHook) on a VMWare machine with Win10 and WinDBG attached through serial port.

First issue was on finding ntoskrnl base address in Internals::Resolve() but fixed adding a check on valid address in the "if" statement when checking the e_magic fields.

Now I get stuck on ExceptionHandler::Initialize when executing the KeIpiGenericCall. WinDBG froze and I didn't know how to proceed to resolve this.

Edit: It looks like this cope with WinDBG. In fact, running without debugger attached I can see the logs message that let me understand It exits from ByePgInitialise. But at the If statement in ExHook main, it returns. So probably ByePgInitialize returns the wrong value, in fact it return STATUS_DEVICE_NOT_CONNECTED.

Any suggestions?

supports WOW64 syscall hook?

ExHook project is successfully working when target is 64 bit application.

But, 32 bit (WOW64) application is weird.
syscall number looks like invalid.

So, ByePg and ExHook does not supports WOW64 application?

Do you have same bug?
Do you have any solutions?

My environment

OS Windows 10 Pro 1903 18362.30 64bit

Auto restart after ~1 hour

hello im using ExceptionHookingDemo to disarm PG but i got Auto restart with no BSOD after about 1 hour, what can be the reason ?

What does this code mean?

`IHF_EXPORT NTSTATUS FixInfinityHook( void* IfhpInternalGetCpuClock, BOOLEAN Verbose )
{
ClockRedirect = IfhpInternalGetCpuClock;

return ByePgInitialize( [ ] ( CONTEXT* ContextRecord, EXCEPTION_RECORD* ExceptionRecord ) -> LONG
{
	if ( ExceptionRecord->ExceptionCode == ( FAST_FAIL_ETW_CORRUPTION << 32 | KERNEL_SECURITY_CHECK_FAILURE ) )
	{
		ContextRecord->Rsp += 0x28;
		ContextRecord->Rip = ( ULONG64 ) ClockRedirect;
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_EXECUTE_HANDLER;
}, Verbose );

}`
There is no place to call this function.I guess it should be that when the cpu cycle is read, an exception is triggered to enter our callback function. But how do I trigger this exception?
"FAST_FAIL_ETW_CORRUPTION" What does this mean? What does this code have to do with ETW?

Infinite-Loop

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;
	}

}

Any solution for protected ke memory by PG

Hello, it is possible to avoid bsod if you want read\write protected (by PG) memory for loaded modules like ‘win32k.sys’ or ‘win32kbase.sys’ via hooking exception table like in your solution ByePg ?

If yes - can you tell what ExceptionCode is needed to ‘hook’. Or just share some code example for this.

Your example ‘ExHook’ looks closer to this solution, but it is bsod for me on 1903-1909.

Thx for attention anyway.

is it right to bypass mem corrupt ?

hello, i want to hook something but i got auto restart, is this snippet good to bypass mem corrupt guard ? thanks

ByePgInitialize( [ ] ( CONTEXT* ContextRecord, EXCEPTION_RECORD* ExceptionRecord ) -> LONG
	{
		if ( ExceptionRecord->ExceptionCode == ( CRITICAL_STRUCTURE_CORRUPTION << 32 | KERNEL_SECURITY_CHECK_FAILURE ) )
		{
			ContextRecord->Rip++;
			return EXCEPTION_CONTINUE_EXECUTION;
		}
		return EXCEPTION_EXECUTE_HANDLER;
	}, Verbose );

Hooking SwapContext using ByePg... Can it be done ?

Hello all. I've got a detour for SwapContext and want to protect this detour using ByePg. Can ByePg do this with modification to the ByePg source code? I'm receiving a CRITICAL_STRUCTURE_CORRUPTION BugCheck. I'm experimenting on Windows 8.1. Any hint on what to modify would be greatly appreciated.

[UPDATE] Thanks to the nice folks at unknowncheats.me apparently its not possible mainly because KPP clears the stack so that there is no way to continue execution.

ExHook example hangs the machine (Windows 10 version 1607)

Title says all.
It's not the ExHook fault's, according to the debugger it's hangs the machine at https://github.com/can1357/ByePg/blob/master/ByePgLib/ByePg.cpp#L46

Any solutions/workarounds?

Verbose output:

[ByePg] Scanning for undocumented offsets...
[ByePg] Scan finished with status: OK 
[ByePg] -------------------------------
[ByePg] ntoskrnl.exe:             0xFFFFF80336C82000
[ByePg] KiHardwareTrigger:        0xFFFFF80336F88B88
[ByePg] KeBugCheck2:              0xFFFFF80336E50630
[ByePg] KiFreezeExecutionLock:    0xFFFFF80337038300
[ByePg] KiBugCheckActive:         0xFFFFF80336F88B38
[ByePg] KPRCB_Context:            +0x6280
[ByePg] KPRCB_IpiFrozen:          +0x2d08
[ByePg] KPCR_DebuggerSavedIRQL:   +0x5c98
[ByePg] -------------------------------
[ByePg] HAL callback registration status: OK 
[ByePg] -------------------------------

Here's a screenshot of windbg:
image

ExceptionHandler.h: HandleBugCheck fails to handle bugcheck, successfully shows blue screen with bug check 0x7F

Version 10.0.18362 Build 18362

DismantleOS!ExceptionHandler::HandleBugCheck+240 [C:\Users\kunes\Desktop\ByePG-InfHook\ByePgLib\ExceptionHandler.h @ 102]
fffff805`525d16f4 cc int 3

FAULTING_SOURCE_LINE: C:\Users\kunes\Desktop\ByePG-InfHook\ByePgLib\ExceptionHandler.h

FAULTING_SOURCE_FILE: C:\Users\kunes\Desktop\ByePG-InfHook\ByePgLib\ExceptionHandler.h

FAULTING_SOURCE_LINE_NUMBER: 102

FAULTING_SOURCE_CODE:
98: // Failed to handle, try to show blue screen
99: HlCallback = nullptr;
100: ProcessorIpiFrozen() = 0;
101: *KiFreezeExecutionLock = false;
102: return KeBugCheckEx( BugCheckCode, BugCheckArgs[ 0 ], BugCheckArgs[ 1 ], BugCheckArgs[ 2 ], BugCheckArgs[ 3 ] ); <-- FAILS HERE
103: }
104:
105: static void OnFreezeNotification()
106: {
107: FnExceptionCallback Cb = HlCallback;

Can I use ByePG in this case?

I want to hide process by modyifying ActiveProcessLinks, but it causes bsod by PatchGuard. Even I use ByePG, result is same.
Can I use ByePG in this case?

Bsod code is CRITICAL_STRUCTURE_CORRUPTION

This bsod doesn't contain context in bugcheck args.

HalCallbacks::Register() Issue

Hi, i'm newbie....
The "ExHook" test was run on a virtual machine. (Win10 (1809)) The build went well and I loaded the driver via "OSR Loader" but freezing occurred. I checked that HalCallbacks :: Register () freezes while hooking "HalNotifyProcessorFreeze"...
The issue is that freezing takes place as soon as you replace "HalPrivateDispatchTable" + 0x1A8 ("HalpTimerNotifyProcessorFreeze") with a hooking function ("HkHalTimerNotifyProcessorFreeze").
Do you know how to solve the problem?

Freeze point:
이미지 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.