A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #21728  by 0x7FFFFFFF
 Wed Dec 18, 2013 4:26 pm
Hi all.
I want to protect my application against termination by other programs. In the 32Bit version of windows i used the SSDT hooking for hooking
Code: Select all
ZwTerminateProcess 
or
Code: Select all
ZwOpenProcess 
. I've to upgrade my program to using in 64Bit version of windows now. And unfortunately in the 64bit windows we can't use SSDT hook (Because Patch Guard (KPP)),Notice that i don't want to Bypassing PG in this case and I've to use only kernel mode hooking.

Any idea ?
(Excuse me if my English is bad )
 #21737  by 0x7FFFFFFF
 Thu Dec 19, 2013 3:56 am
Thanks EP

I wrote this code for test:
Code: Select all
#include <ntddk.h>
#include <common.h>

VOID UnloadRoutine(IN PDRIVER_OBJECT DriverObject)
{

	FreeProcFilter();
    DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Unloaded\n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath)
{

    NTSTATUS status = RegisterCallbackFunction();
  if(!NT_SUCCESS(status))
  {
     DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Faild to RegisterCallbackFunction .status : 0x%X \n",status);
  }
    DriverObject->DriverUnload = UnloadRoutine;

    DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Driver Loaded\n");

    return STATUS_SUCCESS; 

}
// 
// PRE OPERATION
//
OB_PREOP_CALLBACK_STATUS ObjectPreCallback(
  IN  PVOID RegistrationContext,
  IN  POB_PRE_OPERATION_INFORMATION OperationInformation
)
{
	LPSTR ProcName;
	// OB_PRE_OPERATION_INFORMATION OpInfo;



UNREFERENCED_PARAMETER(RegistrationContext);


ProcName=GetProcessNameFromPid(PsGetProcessId((PEPROCESS)OperationInformation->Object));
/*
if( !_stricmp(ProcName,"calc.exe") )
{
    if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
     {
       if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
         {
           OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
         }
       if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION)
        {
		  OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_OPERATION;
		}
	   if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & ~PROCESS_VM_READ) == PROCESS_VM_READ)
		{
		 OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_READ;
		}
	  if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE)
		{
		 OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_WRITE;
		}
     }
}*/
	DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"ObjectPreCallback ----> Process Name [%s] \n", ProcName);
   return OB_PREOP_SUCCESS;
} 
//
//POST OPERATION
//

VOID ObjectPostCallback(
  IN  PVOID RegistrationContext,
  IN  POB_POST_OPERATION_INFORMATION OperationInformation
)
{
   DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"PostProcCreateRoutine. \n");
} 
//
// REGISTE CALLBACK FUNCTION 
//

NTSTATUS RegisterCallbackFunction() 
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	UNICODE_STRING Altitude;
	USHORT filterVersion = ObGetFilterVersion();
    USHORT registrationCount = 1;
	OB_OPERATION_REGISTRATION RegisterOperation;
	OB_CALLBACK_REGISTRATION RegisterCallBack;
	REG_CONTEXT RegistrationContext;
	memset(&RegisterOperation, 0, sizeof(OB_OPERATION_REGISTRATION));
	memset(&RegisterCallBack, 0, sizeof(OB_CALLBACK_REGISTRATION));
	memset(&RegistrationContext, 0, sizeof(REG_CONTEXT));
	RegistrationContext.ulIndex = 1;
	RegistrationContext.Version = 120;
	if (filterVersion == OB_FLT_REGISTRATION_VERSION) {
		DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Filter Version is correct.\n");

		RegisterOperation.ObjectType = PsProcessType;
		RegisterOperation.Operations = OB_OPERATION_HANDLE_CREATE;
		RegisterOperation.PreOperation = ObjectPreCallback;
		RegisterOperation.PostOperation = ObjectPostCallback;
		RegisterCallBack.Version = OB_FLT_REGISTRATION_VERSION;
		RegisterCallBack.OperationRegistrationCount = registrationCount;
		RtlInitUnicodeString(&Altitude, L"XXXXXXX");
		RegisterCallBack.Altitude = Altitude;
		RegisterCallBack.RegistrationContext = &RegistrationContext;
		RegisterCallBack.OperationRegistration = &RegisterOperation;
		DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Register Callback Function Entry.\n");

	                             
		ntStatus = ObRegisterCallbacks(&RegisterCallBack, &_CallBacks_Handle);
		if (ntStatus == STATUS_SUCCESS) {
		DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Register Callback Function Successful.\n");
		}
		else {
			if (ntStatus == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION) {
	        	DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Status Filter Instance Altitude Collision.\n");
			}
			if (ntStatus == STATUS_INVALID_PARAMETER) {
		       DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Status Invalid Parameter.\n");
			}
			if (ntStatus == STATUS_ACCESS_DENIED) {
				DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"The callback routines do not reside in a signed kernel binary image.\n");
			}
			if (ntStatus == STATUS_INSUFFICIENT_RESOURCES) {
		       DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Status Allocate Memory Failed.\n");
			}
		      DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Register Callback Function Failed with 0x%08x\n",ntStatus);
		}
	}
	else {
		       DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Filter Version is not supported.\n");
	}
	return ntStatus;
} 
//
// FREE PROC FILTER
//

NTSTATUS FreeProcFilter()
{
	if (NULL != &_CallBacks_Handle) 
	{
		ObUnRegisterCallbacks(_CallBacks_Handle);
	}
	return STATUS_SUCCESS;
}

 
LPSTR GetProcessNameFromPid(HANDLE pid)
{
    PEPROCESS Process;
    if (PsLookupProcessByProcessId(pid, & Process) == STATUS_INVALID_PARAMETER)
    {
        return "pid???";
    }
    return (LPSTR)PsGetProcessImageFileName(Process);

}

common.h :
Code: Select all
#include <ntddk.h>
//-----------------------------------------------
//  Defines
//-----------------------------------------------

//Process Security and Access Rights
#define PROCESS_CREATE_THREAD  (0x0002)
#define PROCESS_CREATE_PROCESS (0x0080)
#define PROCESS_TERMINATE      (0x0001)
#define PROCESS_VM_WRITE       (0x0020)
#define PROCESS_VM_READ        (0x0010)
#define PROCESS_VM_OPERATION   (0x0008)
#define PROCESS_SUSPEND_RESUME (0x0800)


#define NT_DEVICE_NAME      L"\\Device\\BSProcMon"
#define DOS_DEVICE_NAME     L"\\DosDevices\\BSProcMon"

//event for user-mode processes to monitor
#define BSProcMon_Event     L"\\BaseNamedObjects\\BSProcMonProcessEvent" 

#define MAXIMUM_FILENAME_LENGTH 256
//-----------------------------------------------
// callback 
//-----------------------------------------------

PVOID _CallBacks_Handle = NULL;

typedef struct _OB_REG_CONTEXT {
	__in USHORT Version;
	__in UNICODE_STRING Altitude;
	__in USHORT ulIndex;
	OB_OPERATION_REGISTRATION *OperationRegistration;
} REG_CONTEXT, *PREG_CONTEXT;


//-----------------------------------------------
// PID2ProcName 
//-----------------------------------------------
extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process);
 
extern   NTSTATUS PsLookupProcessByProcessId(
     HANDLE ProcessId,
    PEPROCESS *Process
);
typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process);
GET_PROCESS_IMAGE_NAME gGetProcessImageFileName;
 
LPSTR GetProcessNameFromPid(HANDLE pid);



//-----------------------------------------------
//  Forward Declaration
//-----------------------------------------------
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT DriverObject,  
    IN PUNICODE_STRING RegistryPath
    );

VOID UnloadDriver(
    IN PDRIVER_OBJECT DriverObject
    );

OB_PREOP_CALLBACK_STATUS ObjectPreCallback(
  IN  PVOID RegistrationContext,
  IN  POB_PRE_OPERATION_INFORMATION OperationInformation
  );

VOID ObjectPostCallback(
  IN  PVOID RegistrationContext,
  IN  POB_POST_OPERATION_INFORMATION OperationInformation
  );

NTSTATUS RegisterCallbackFunction() ;
NTSTATUS FreeProcFilter();
But when unload driver i get BSOD, any idea ?
 #21738  by R00tKit
 Thu Dec 19, 2013 4:34 pm
How about posting the !analyze -v output ?
anyway check this:
In your soueces file. LINKER _FLAGS=/INTEGRITYCHECK
Along with this your driver will need to be signed.


and msdn dont say ObRegisterCallbacks set CallBacks_Handle to NULL in fail
so
Code: Select all
if (NULL != &_CallBacks_Handle) 
   {
      ObUnRegisterCallbacks(_CallBacks_Handle);
   }
   return STATUS_SUCCESS;
i think must be

Code: Select all
// if the callbacks are active - remove them
    if (bCallbacksInstalled == TRUE)
 {
        ObUnRegisterCallbacks(pCBRegistrationHandle);
        pCBRegistrationHandle = NULL;
        bCallbacksInstalled = FALSE;
    }
 #21742  by 0x7FFFFFFF
 Thu Dec 19, 2013 7:18 pm
Thanks all.

This code run correctly
Code: Select all
#include <ntddk.h>
#include <common.h>
 
 // coded by : B ;)
 
 
 
 
 
VOID UnloadRoutine(IN PDRIVER_OBJECT DriverObject)
{
 
    FreeProcFilter();
    DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Unloaded\n");
}
 
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath)
{
 
    NTSTATUS status = RegisterCallbackFunction();
  if(!NT_SUCCESS(status))
  {
     DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Faild to RegisterCallbackFunction .status : 0x%X \n",status);
  }
    DriverObject->DriverUnload = UnloadRoutine;
 
    DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Driver Loaded\n");
 
    return STATUS_SUCCESS;
 
}
//
// PRE OPERATION
//
OB_PREOP_CALLBACK_STATUS ObjectPreCallback(
  IN  PVOID RegistrationContext,
  IN  POB_PRE_OPERATION_INFORMATION OperationInformation
)
{
    LPSTR ProcName;
    // OB_PRE_OPERATION_INFORMATION OpInfo;
 
 
 
UNREFERENCED_PARAMETER(RegistrationContext);
 
 
ProcName=GetProcessNameFromPid(PsGetProcessId((PEPROCESS)OperationInformation->Object));
 
if( !_stricmp(ProcName,"calc.exe") )
{
    if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
     {
       if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
         {
           OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
         }
       if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION)
        {
          OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_OPERATION;
        }
       if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & ~PROCESS_VM_READ) == PROCESS_VM_READ)
        {
         OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_READ;
        }
      if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE)
        {
         OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_WRITE;
        }
     }
}
    DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"ObjectPreCallback ----> Process Name [%s] \n", ProcName);
   return OB_PREOP_SUCCESS;
}
//
//POST OPERATION
//
 
VOID ObjectPostCallback(
  IN  PVOID RegistrationContext,
  IN  POB_POST_OPERATION_INFORMATION OperationInformation
)
{
   DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"PostProcCreateRoutine. \n");
}
//
// REGISTE CALLBACK FUNCTION
//
 
NTSTATUS RegisterCallbackFunction()
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    UNICODE_STRING Altitude;
    USHORT filterVersion = ObGetFilterVersion();
    USHORT registrationCount = 1;
    OB_OPERATION_REGISTRATION RegisterOperation;
    OB_CALLBACK_REGISTRATION RegisterCallBack;
    REG_CONTEXT RegistrationContext;
    memset(&RegisterOperation, 0, sizeof(OB_OPERATION_REGISTRATION));
    memset(&RegisterCallBack, 0, sizeof(OB_CALLBACK_REGISTRATION));
    memset(&RegistrationContext, 0, sizeof(REG_CONTEXT));
    RegistrationContext.ulIndex = 1;
    RegistrationContext.Version = 120;
    if (filterVersion == OB_FLT_REGISTRATION_VERSION) {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Filter Version is correct.\n");
 
        RegisterOperation.ObjectType = PsProcessType;
        RegisterOperation.Operations = OB_OPERATION_HANDLE_CREATE;
        RegisterOperation.PreOperation = ObjectPreCallback;
        RegisterOperation.PostOperation = ObjectPostCallback;
        RegisterCallBack.Version = OB_FLT_REGISTRATION_VERSION;
        RegisterCallBack.OperationRegistrationCount = registrationCount;
        RtlInitUnicodeString(&Altitude, L"XXXXXXX");
        RegisterCallBack.Altitude = Altitude;
        RegisterCallBack.RegistrationContext = &RegistrationContext;
        RegisterCallBack.OperationRegistration = &RegisterOperation;
        DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Register Callback Function Entry.\n");
 
                                  
        ntStatus = ObRegisterCallbacks(&RegisterCallBack, &_CallBacks_Handle);
        if (ntStatus == STATUS_SUCCESS) {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_INFO_LEVEL,"Register Callback Function Successful.\n");
        }
        else {
            if (ntStatus == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION) {
                DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Status Filter Instance Altitude Collision.\n");
            }
            if (ntStatus == STATUS_INVALID_PARAMETER) {
               DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Status Invalid Parameter.\n");
            }
            if (ntStatus == STATUS_ACCESS_DENIED) {
                DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"The callback routines do not reside in a signed kernel binary image.\n");
            }
            if (ntStatus == STATUS_INSUFFICIENT_RESOURCES) {
               DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Status Allocate Memory Failed.\n");
            }
              DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Register Callback Function Failed with 0x%08x\n",ntStatus);
        }
    }
    else {
               DbgPrintEx( DPFLTR_IHVDRIVER_ID,  DPFLTR_ERROR_LEVEL,"Filter Version is not supported.\n");
    }
    return ntStatus;
}
//
// FREE PROC FILTER
//
 
NTSTATUS FreeProcFilter()
{
    // if the callbacks are active - remove them
    if (NULL != _CallBacks_Handle)
    {
        ObUnRegisterCallbacks(_CallBacks_Handle);
        _CallBacks_Handle=NULL;
    }
    return STATUS_SUCCESS;
}
 
  
LPSTR GetProcessNameFromPid(HANDLE pid)
{
    PEPROCESS Process;
    if (PsLookupProcessByProcessId(pid, & Process) == STATUS_INVALID_PARAMETER)
    {
        return "pid???";
    }
    return (LPSTR)PsGetProcessImageFileName(Process);
 
}

common.h
Code: Select all
#include <ntddk.h>
//-----------------------------------------------
//  Defines
//-----------------------------------------------
 
//Process Security and Access Rights
#define PROCESS_CREATE_THREAD  (0x0002)
#define PROCESS_CREATE_PROCESS (0x0080)
#define PROCESS_TERMINATE      (0x0001)
#define PROCESS_VM_WRITE       (0x0020)
#define PROCESS_VM_READ        (0x0010)
#define PROCESS_VM_OPERATION   (0x0008)
#define PROCESS_SUSPEND_RESUME (0x0800)
 
 
#define NT_DEVICE_NAME      L"\\Device\\BSProcMon"
#define DOS_DEVICE_NAME     L"\\DosDevices\\BSProcMon"
 
//event for user-mode processes to monitor
#define BSProcMon_Event     L"\\BaseNamedObjects\\BSProcMonProcessEvent"
 
#define MAXIMUM_FILENAME_LENGTH 256
//-----------------------------------------------
// callback
//-----------------------------------------------
 
PVOID _CallBacks_Handle = NULL;
 
typedef struct _OB_REG_CONTEXT {
    __in USHORT Version;
    __in UNICODE_STRING Altitude;
    __in USHORT ulIndex;
    OB_OPERATION_REGISTRATION *OperationRegistration;
} REG_CONTEXT, *PREG_CONTEXT;
 
 
//-----------------------------------------------
// PID2ProcName
//-----------------------------------------------
extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process);
  
extern   NTSTATUS PsLookupProcessByProcessId(
     HANDLE ProcessId,
    PEPROCESS *Process
);
typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process);
GET_PROCESS_IMAGE_NAME gGetProcessImageFileName;
  
LPSTR GetProcessNameFromPid(HANDLE pid);
 
 
 
//-----------------------------------------------
//  Forward Declaration
//-----------------------------------------------
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING RegistryPath
    );
 
VOID UnloadDriver(
    IN PDRIVER_OBJECT DriverObject
    );
 
OB_PREOP_CALLBACK_STATUS ObjectPreCallback(
  IN  PVOID RegistrationContext,
  IN  POB_PRE_OPERATION_INFORMATION OperationInformation
  );
 
VOID ObjectPostCallback(
  IN  PVOID RegistrationContext,
  IN  POB_POST_OPERATION_INFORMATION OperationInformation
  );
 
NTSTATUS RegisterCallbackFunction() ;
NTSTATUS FreeProcFilter();
the result of my test :
Image