Hook ZwTerminateProcess in x64 Driver (Without SSDT)

I found my answer, I use kernel mode callbacks .

#include <ntddk.h>
#include <common.h>

// coded by Behrooz

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

#include <ntddk.h>

// coded by Behrooz

//-----------------------------------------------
//  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 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: enter image description here


Thanks for you code, and I test it on win10 x64 success. BTW, I was found the ObRegisterCallbacks return STATUS_ACCESS_DENIED even though I have signed my driver. So I asks many peoples, and then I find a solution for it. Append this text in you "source" file: LINKER_FLAGS=/integritycheck

then you can rebuild and resign your driver. It was found in bbs.pediy.com


Someone can do "ObUnregisterCallbacks" and even register their own to prevent you from detecting it.