【问题标题】:Hook ZwTerminateProcess in x64 Driver (Without SSDT)在 x64 驱动程序中挂钩 ZwTerminateProcess(无 SSDT)
【发布时间】:2013-12-31 09:12:18
【问题描述】:

我找到并阅读了这个问题,但我没有找到答案SSDT hooking alternative in x64 systems

我想保护我的应用程序不被其他程序终止。在 32 位版本的 Windows 中,我使用 SSDT hooking 来挂钩 ZwTerminateProcessZwOpenProcess。我现在必须升级我的程序以在 64 位版本的 windows 中使用。 不幸的是,在 64 位窗口中,我们不能使用 SSDT 挂钩 (Because Patch Guard (KPP)),请注意,在这种情况下我不想绕过 PG,我只能使用内核模式挂钩。例如,我不希望我的程序开始被以下代码终止(偶数):

NTSTATUS drvTerminateProcess( ULONG ulProcessID )
{
    NTSTATUS          ntStatus = STATUS_SUCCESS;
    HANDLE            hProcess;
    OBJECT_ATTRIBUTES ObjectAttributes;
    CLIENT_ID         ClientId;

    DbgPrint( "drvTerminateProcess( %u )", ulProcessID );

    InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL ); 

    ClientId.UniqueProcess = (HANDLE)ulProcessID;
    ClientId.UniqueThread  = NULL;

    __try
    {
        ntStatus = ZwOpenProcess( &hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &ClientId );
        if( NT_SUCCESS(ntStatus) )
        {
            ntStatus = ZwTerminateProcess( hProcess, 0 );
            if( !NT_SUCCESS(ntStatus) )
                DbgPrint( "ZwTerminateProcess failed with status : %08X\n", ntStatus );

            ZwClose( hProcess );
        }
        else
            DbgPrint( "ZwOpenProcess failed with status : %08X\n", ntStatus );
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        ntStatus = STATUS_UNSUCCESSFUL;
        DbgPrint( "Exception caught in drvTerminateProcess()" );
    }

    return ntStatus;
}

为了完成这项工作,我使用了以下函数 (NewZwOpenProcess) 并将其替换为 SSDT 中的原始 ZwOpenProcess,但在 x64 窗口中我不知道该怎么做:( :

NTSTATUS NewZwOpenProcess(
        OUT PHANDLE ProcessHandle,
        IN ACCESS_MASK DesiredAccess,
        IN POBJECT_ATTRIBUTES ObjectAttributes,
        IN PCLIENT_ID ClientId OPTIONAL)
{
        HANDLE ProcessId;

    __try 
    {
            ProcessId = ClientId->UniqueProcess;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
       return STATUS_INVALID_PARAMETER;
    }
   
   if (ProcessId == (HANDLE)11) //Check if the PID matches our protected process PID (My programm)
    {
     return STATUS_ACCESS_DENIED; 
    }
  else 
    return OldZwOpenProcess(ProcessHandle, DesiredAccess,ObjectAttributes, ClientId);
}

有什么想法吗??

(如果我的英语不好,请见谅)

【问题讨论】:

  • 这就是我们喜欢 Patch Guard 的原因。
  • @HansPassant :),是的,我们喜欢 PG,但我正在开发安全软件,保护我的程序对我来说很重要。
  • 微软开发了 PG,所以你不再需要这些无聊的黑客了。
  • @HansPassant 是的,你是对的,但是 PG 只防止 rootkits 和内核模式恶意软件,而不是用于用户土地防御。

标签: 64-bit hook driver sql-server-data-tools kernel-mode


【解决方案1】:

我找到了答案,我使用内核模式回调。

#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();

我的测试结果:

【讨论】:

  • 谢谢分享,告诉我,你用的是什么版本的WDK?
  • @navossoc 不客气,WINDDK 版本 7600.16385.1
  • 我已经尝试过此代码,但 ObRegisterCallbacks 返回 STATUS_ACCESS_DENIED,即使我已经签署了我的驱动程序。请帮帮我,
  • @Behrooz,您的解决方案也适用于 Windows 32 位?
  • @Behrooz,你能分享你使用的 .inf 文件吗?
【解决方案2】:

有人可以做“ObUnregisterCallbacks”,甚至注册他们自己的,以防止你检测到它。

【讨论】:

  • 并且您自己的代码可以验证回调是否仍然存在。这是大多数体面的 AV 或 AC 所做的,他们尝试再次注册回调,如果操作成功,则意味着回调已被删除,所以惩罚!
【解决方案3】:

感谢您的代码,我在 win10 x64 成功测试它。 顺便说一句,我发现 ObRegisterCallbacks 返回 STATUS_ACCESS_DENIED 即使我已经签署了我的驱动程序。 所以我问了很多人,然后我找到了解决方案。 将此文本附加到您的“源”文件中: LINKER_FLAGS=/完整性检查

然后您可以重建并退出您的驱动程序。它是在 bbs.pediy.com 中找到的

【讨论】:

    【解决方案4】:

    看起来不需要 .inf 文件。只是 SC CREATE ServiceName type= kernel binPath= pathtoyourfile.

    【讨论】:

      猜你喜欢
      • 2011-08-03
      • 2018-12-15
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多