363 lines
8.7 KiB
C
363 lines
8.7 KiB
C
|
#include <basedef.h>
|
||
|
#include <vmm.h>
|
||
|
#include <vwin32.h>
|
||
|
#include "ntddpack.h"
|
||
|
#include "except.h"
|
||
|
#include "exvector.h"
|
||
|
|
||
|
#pragma VxD_LOCKED_CODE_SEG
|
||
|
#pragma VxD_LOCKED_DATA_SEG
|
||
|
|
||
|
extern PVOID C_Handle_Trap_1;
|
||
|
extern PVOID C_Handle_Trap_3;
|
||
|
extern DWORD pfnHandler;
|
||
|
extern PVOID pProcessHandle;
|
||
|
|
||
|
BOOL
|
||
|
DriverControl(DWORD dwMessage)
|
||
|
{
|
||
|
switch (dwMessage)
|
||
|
{
|
||
|
case 0:
|
||
|
_asm mov eax, 1
|
||
|
_asm mov esi, offset C_Handle_Trap_1
|
||
|
VMMCall( Hook_PM_Fault );
|
||
|
|
||
|
_asm mov eax, 3
|
||
|
_asm mov esi, offset C_Handle_Trap_3
|
||
|
VMMCall( Hook_PM_Fault );
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
_asm mov eax, 1
|
||
|
_asm mov esi, offset C_Handle_Trap_1
|
||
|
VMMCall( Unhook_PM_Fault );
|
||
|
|
||
|
_asm mov eax, 3
|
||
|
_asm mov esi, offset C_Handle_Trap_3
|
||
|
VMMCall( Unhook_PM_Fault );
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
0;
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
_stdcall
|
||
|
DriverIOControl(DWORD dwService,
|
||
|
DWORD dwDDB,
|
||
|
DWORD hDevice,
|
||
|
PDIOCPARAMETERS pDiocParms)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the dispatch routine for create/open and close requests.
|
||
|
These requests complete successfully.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Pointer to the device object.
|
||
|
|
||
|
Irp - Pointer to the request packet.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status is returned.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PVOID pInputParams;
|
||
|
|
||
|
switch ( dwService )
|
||
|
{
|
||
|
case DIOC_OPEN:
|
||
|
//
|
||
|
// Nothing to do
|
||
|
//
|
||
|
break;
|
||
|
|
||
|
case DIOC_CLOSEHANDLE:
|
||
|
//
|
||
|
// If our client for the except handler is going away, initialize the exception handler data
|
||
|
//
|
||
|
if (pProcessHandle == VWIN32_GetCurrentProcessHandle()) {
|
||
|
pfnHandler = 0;
|
||
|
pProcessHandle = 0;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case INSTALL_RING_3_HANDLER:
|
||
|
//
|
||
|
// See if we already have a client
|
||
|
//
|
||
|
if (pProcessHandle) {
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
pProcessHandle = VWIN32_GetCurrentProcessHandle();
|
||
|
|
||
|
//
|
||
|
// Copy the handler into our global
|
||
|
//
|
||
|
pInputParams = (PVOID)(pDiocParms->lpvInBuffer);
|
||
|
_asm mov eax, pInputParams
|
||
|
_asm mov eax, [eax]
|
||
|
_asm mov pfnHandler, eax
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
//
|
||
|
// Error, Unrecognized IOCTL
|
||
|
//
|
||
|
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Helper function for maintaining context information between ring levels
|
||
|
//
|
||
|
VOID
|
||
|
FillContextRecord(PCRS pcrs,
|
||
|
PCONTEXT pContext)
|
||
|
{
|
||
|
DWORD dwDebugRegister;
|
||
|
|
||
|
//
|
||
|
// Clear trace and direction flags for the exception dispatcher
|
||
|
//
|
||
|
pcrs->Client_EFlags &= ~(TF_MASK | DF_MASK);
|
||
|
|
||
|
//
|
||
|
// Fill context record
|
||
|
//
|
||
|
pContext->Eax = pcrs->Client_EAX;
|
||
|
pContext->Ebx = pcrs->Client_EBX;
|
||
|
pContext->Ecx = pcrs->Client_ECX;
|
||
|
pContext->Edx = pcrs->Client_EDX;
|
||
|
pContext->Esi = pcrs->Client_ESI;
|
||
|
pContext->Edi = pcrs->Client_EDI;
|
||
|
pContext->Eip = pcrs->Client_EIP;
|
||
|
pContext->Ebp = pcrs->Client_EBP;
|
||
|
pContext->Esp = pcrs->Client_ESP;
|
||
|
pContext->SegGs = pcrs->Client_GS;
|
||
|
pContext->SegFs = pcrs->Client_FS;
|
||
|
pContext->SegEs = pcrs->Client_ES;
|
||
|
pContext->SegDs = pcrs->Client_DS;
|
||
|
pContext->SegCs = pcrs->Client_CS;
|
||
|
pContext->EFlags = pcrs->Client_EFlags;
|
||
|
|
||
|
//
|
||
|
// Store the debug registers
|
||
|
//
|
||
|
_asm mov eax, dr0
|
||
|
_asm mov dwDebugRegister, eax
|
||
|
pContext->Dr0 = dwDebugRegister;
|
||
|
_asm mov eax, dr1
|
||
|
_asm mov dwDebugRegister, eax
|
||
|
pContext->Dr1 = dwDebugRegister;
|
||
|
_asm mov eax, dr2
|
||
|
_asm mov dwDebugRegister, eax
|
||
|
pContext->Dr2 = dwDebugRegister;
|
||
|
_asm mov eax, dr3
|
||
|
_asm mov dwDebugRegister, eax
|
||
|
pContext->Dr3 = dwDebugRegister;
|
||
|
_asm mov eax, dr6
|
||
|
_asm mov dwDebugRegister, eax
|
||
|
pContext->Dr6 = dwDebugRegister;
|
||
|
_asm mov eax, dr7
|
||
|
_asm mov dwDebugRegister, eax
|
||
|
pContext->Dr7 = dwDebugRegister;
|
||
|
|
||
|
//
|
||
|
// This is a full context
|
||
|
//
|
||
|
pContext->ContextFlags = (DWORD)-1;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
RestorePCRS(PCRS pcrs,
|
||
|
PCONTEXT pContext)
|
||
|
{
|
||
|
DWORD dwDebugRegister;
|
||
|
|
||
|
//
|
||
|
// Restore pcrs
|
||
|
//
|
||
|
pcrs->Client_EAX = pContext->Eax;
|
||
|
pcrs->Client_EBX = pContext->Ebx;
|
||
|
pcrs->Client_ECX = pContext->Ecx;
|
||
|
pcrs->Client_EDX = pContext->Edx;
|
||
|
pcrs->Client_ESI = pContext->Esi;
|
||
|
pcrs->Client_EDI = pContext->Edi;
|
||
|
pcrs->Client_EIP = pContext->Eip;
|
||
|
pcrs->Client_EBP = pContext->Ebp;
|
||
|
pcrs->Client_ESP = pContext->Esp;
|
||
|
pcrs->Client_GS = pContext->SegGs;
|
||
|
pcrs->Client_FS = pContext->SegFs;
|
||
|
pcrs->Client_ES = pContext->SegEs;
|
||
|
pcrs->Client_DS = pContext->SegDs;
|
||
|
pcrs->Client_CS = pContext->SegCs;
|
||
|
pcrs->Client_EFlags = pContext->EFlags;
|
||
|
|
||
|
//
|
||
|
// Restore the debug registers
|
||
|
//
|
||
|
dwDebugRegister = pContext->Dr0;
|
||
|
_asm mov eax, dwDebugRegister
|
||
|
_asm mov dr0, eax
|
||
|
dwDebugRegister = pContext->Dr1;
|
||
|
_asm mov eax, dwDebugRegister
|
||
|
_asm mov dr1, eax
|
||
|
dwDebugRegister = pContext->Dr2;
|
||
|
_asm mov eax, dwDebugRegister
|
||
|
_asm mov dr2, eax
|
||
|
dwDebugRegister = pContext->Dr3;
|
||
|
_asm mov eax, dwDebugRegister
|
||
|
_asm mov dr3, eax
|
||
|
dwDebugRegister = pContext->Dr6;
|
||
|
_asm mov eax, dwDebugRegister
|
||
|
_asm mov dr6, eax
|
||
|
dwDebugRegister = pContext->Dr7;
|
||
|
_asm mov eax, dwDebugRegister
|
||
|
_asm mov dr7, eax
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Exception dispatching routine
|
||
|
//
|
||
|
BOOL
|
||
|
__cdecl
|
||
|
C_Trap_Exception_Handler(ULONG ExceptionNumber,
|
||
|
PCRS pcrs)
|
||
|
{
|
||
|
DWORD dwException = ExceptionNumber >> 2;
|
||
|
PEXCEPTION_RECORD pExceptionRecord;
|
||
|
PCONTEXT pContextRecord;
|
||
|
PSTACKFRAME pStackFrame;
|
||
|
ULONG Result;
|
||
|
ULONG StackTop;
|
||
|
ULONG Length;
|
||
|
|
||
|
//
|
||
|
// Make sure our current thread is Win32
|
||
|
//
|
||
|
if (FALSE == VWIN32_IsClientWin32()) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure we only handle exceptions for our controlling "process"
|
||
|
//
|
||
|
if (pProcessHandle != VWIN32_GetCurrentProcessHandle()) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If selector isn't flat, we can't handle this exception
|
||
|
//
|
||
|
if ((pcrs->Client_SS != pcrs->Client_DS) ||
|
||
|
(pcrs->Client_SS != pcrs->Client_ES)){
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// See if this is a context set
|
||
|
//
|
||
|
if (SET_CONTEXT == *(DWORD *)(pcrs->Client_EIP)) {
|
||
|
//
|
||
|
// Set the context data
|
||
|
//
|
||
|
pContextRecord = *(DWORD *)(pcrs->Client_ESP + 0x10);
|
||
|
|
||
|
RestorePCRS(pcrs,
|
||
|
pContextRecord);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Move stack pointer down one context record length
|
||
|
//
|
||
|
StackTop = (pcrs->Client_ESP & ~3) - ((sizeof(CONTEXT) + 3) & ~3);
|
||
|
pContextRecord = (PCONTEXT) StackTop;
|
||
|
|
||
|
FillContextRecord(pcrs,
|
||
|
pContextRecord);
|
||
|
|
||
|
//
|
||
|
// Adjust eip for breakpoint exceptions
|
||
|
//
|
||
|
if (3 == dwException) {
|
||
|
pContextRecord->Eip -= 1;
|
||
|
}
|
||
|
|
||
|
Length = (sizeof(EXCEPTION_RECORD) - (EXCEPTION_MAXIMUM_PARAMETERS - 2) *
|
||
|
sizeof(*pExceptionRecord->ExceptionInformation) + 3) & ~3;
|
||
|
|
||
|
//
|
||
|
// We are now at the Exception Record
|
||
|
//
|
||
|
StackTop = StackTop - Length;
|
||
|
pExceptionRecord = (PEXCEPTION_RECORD)StackTop;
|
||
|
|
||
|
pExceptionRecord->ExceptionFlags = 0;
|
||
|
pExceptionRecord->ExceptionRecord = 0;
|
||
|
pExceptionRecord->ExceptionAddress = (PVOID)pcrs->Client_EIP;
|
||
|
pExceptionRecord->NumberParameters = 0;
|
||
|
|
||
|
switch (dwException) {
|
||
|
case 1:
|
||
|
pExceptionRecord->ExceptionCode = STATUS_SINGLE_STEP;
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
pExceptionRecord->ExceptionCode = STATUS_BREAKPOINT;
|
||
|
pExceptionRecord->NumberParameters = 1;
|
||
|
pExceptionRecord->ExceptionInformation[0] = BREAKPOINT_BREAK;
|
||
|
pExceptionRecord->ExceptionAddress = (PVOID)pContextRecord->Eip;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Setup the exception call frame
|
||
|
//
|
||
|
StackTop = StackTop - sizeof(STACKFRAME);
|
||
|
pStackFrame = (PSTACKFRAME) StackTop;
|
||
|
|
||
|
pStackFrame->ExceptPointers.ExceptionRecord = pExceptionRecord;
|
||
|
pStackFrame->ExceptPointers.ContextRecord = pContextRecord;
|
||
|
pStackFrame->pExceptPointers = (PVOID)(StackTop + 0x08);
|
||
|
pStackFrame->RetAddress = (PVOID)0xffecbad7; // App will page fault out if unexpected exception occurs
|
||
|
|
||
|
//
|
||
|
// Transfer control to Ring 3 handler
|
||
|
//
|
||
|
pcrs->Client_ESP = (ULONG)pStackFrame;
|
||
|
pcrs->Client_EIP = (ULONG)pfnHandler;
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
SkipHandler:
|
||
|
|
||
|
//
|
||
|
// We didn't process the exception give it to the next handler
|
||
|
//
|
||
|
return FALSE;
|
||
|
}
|