zoukankan      html  css  js  c++  java
  • 64位内核第二讲,进程保护之对象钩子

             64位内核第二讲,进程保护.

    一丶什么是保护.

    什么是保护. 比如我们安装了xxx杀毒软件.那么此时你用任务管理器关闭.是关闭不了的.原因是内核已经做了保护.

    那么去掉保护的前提就是你要给自己的软件做保护.

    比如我们给计算器做保护. 例如下图.

    做保护.以前的病毒作者.都是想要退出xxx杀毒软件. 什么方法都能做. 所以杀软为了防止这一情况发生,直接把打开进程的API进行HOOK即可.

    但是别忘了.还可以拷贝句柄.所以杀软防不住.只能在内核做保护.

    二丶给软件添加保护熟悉API和结构体

    给软件添加保护很简单. 也是调用API进行操作.

    API:

      ObRegisterCallbacks  注册进程和线程处理回调

    NTSTATUS 
      ObRegisterCallbacks(
        IN POB_CALLBACK_REGISTRATION  CallBackRegistration,
        OUT PVOID  *RegistrationHandle
        );

    第一个是个结构体,我们想要进行的操作都放在这个结构中

    第二个是个二级指针,我们给一个即可

    结构体:

    typedef struct _OB_CALLBACK_REGISTRATION {
      __in USHORT  Version;                  //版本号
      __in USHORT  OperationRegistrationCount;       //回调个数. 可以一次蹙着多个回调. 和最后一个参数绑定的. 如果一次注册多个.则最后一个参数需要给数组保存,最后参数是一个结构体.
      __in UNICODE_STRING  Altitude;            // 指定的驱动程序的Uncode字符串. 可以看WDK文档给.
      __in PVOID  RegistrationContext;           // 回调函数的参数.如果你给可以在这里给.
      __in OB_OPERATION_REGISTRATION  *OperationRegistration;//回调函数信息结构体,如果个数有多个,你需要定义为数组.
    } OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;
    

    结构体中回调函数结构体.

    typedef struct _OB_OPERATION_REGISTRATION {
      __in POBJECT_TYPE  *ObjectType;        //对象的类型.你注册回调函数的类型 PsProcessType 和 PsThreadType 分别是进程回调和线程回调.
      __in OB_OPERATION  Operations;         //注册回调的操作方式, 一个是创建进程. 一个是拷贝进程句柄.  OB_OPERATION_HANDLE_CREATEA  ,OB_OPERATION_HANDLE_DUPLICATE 
      __in POB_PRE_OPERATION_CALLBACK  PreOperation;//创建之前回调函数的地址,在这里给. 每一个回调都包含什么信息在这个结构体中给出.
      __in POB_POST_OPERATION_CALLBACK  PostOperation;//创建之后回调函数的地址. 和上面不一样,一个是创建之前,你的回调回来,一个是创建之后你的回调函数回来.
    } OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;

    回调函数原型

    OB_PREOP_CALLBACK_STATUS 
      ObjectPreCallback(
        __in PVOID  RegistrationContext,    //回调函数的参数,上面通过结构体给的.
        __in POB_PRE_OPERATION_INFORMATION  OperationInformation //进程或者线程创建的信息结构体
        );
    

      

    进程或者线程信息结构体.

    typedef struct _OB_PRE_OPERATION_INFORMATION {
      __in OB_OPERATION  Operation;    //句柄的操作类型, 是上面我们给的.
      union {
        __in ULONG  Flags;
        struct {
          __in ULONG  KernelHandle:1;
          __in ULONG  Reserved:31;
        };
      };
      __in PVOID  Object;        //对象指针,如果你给的是监控进程,那么这个对象就是EPROCESS,如果是线程,那么这个对象就是ETHREAD
      __in POBJECT_TYPE  ObjectType; //对象类型. 可能是PsThreadType 也可能是 PsProcessType
      __out PVOID  CallContext;
      __in POB_PRE_OPERATION_PARAMETERS  Parameters; //创建或者创建之后的参数信息结构体.
    } OB_PRE_OPERATION_INFORMATION, *POB_PRE_OPERATION_INFORMATION;
    

    参数信息结构体

    typedef union _OB_PRE_OPERATION_PARAMETERS {
      __inout OB_PRE_CREATE_HANDLE_INFORMATION  CreateHandleInformation;        //创建句柄,则成员会给这个赋值
      __inout OB_PRE_DUPLICATE_HANDLE_INFORMATION  DuplicateHandleInformation;    //拷贝句柄,则给这个成员赋值.
       } OB_PRE_OPERATION_PARAMETERS, *POB_PRE_OPERATION_PARAMETERS;
    

      

    创建句柄结构体

    typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION {
      __inout ACCESS_MASK  DesiredAccess;                        //创建的权限是什么. 如果我们给 0则没有任何权限,则进程不能创建.
      __in ACCESS_MASK  OriginalDesiredAccess;                     //原始的权限.
    } OB_PRE_CREATE_HANDLE_INFORMATION, *POB_PRE_CREATE_HANDLE_INFORMATION;
    

     

    拷贝句柄结构体信息

      __inout ACCESS_MASK  DesiredAccess;                      //权限,我们自己控制
      __in ACCESS_MASK  OriginalDesiredAccess;                   //原始权限
      __in PVOID  SourceProcess;                           //拷贝句柄的时候,源对象指针.
      __in PVOID  TargetProcess;                           //目的对象指针.
    } OB_PRE_DUPLICATE_HANDLE_INFORMATION, * POB_PRE_DUPLICATE_HANDLE_INFORMATION;
    

    结构体看着挺多,其实挺简单的.

    三丶给软件添加权限保护代码.

    代码直接拷贝编译就可以.我是使用的 WDK7600. 因为没有硬编码的方式.所以高版本WDK只要支持这些函数.就可以编译.

    #include <ntddk.h>   //很多驱动的结构体函数的声明呀.都包含在这里面
    #include <ntdef.h>
    
    #include <wdm.h>
    
    
    
    NTKERNELAPI
    NTSTATUS
    PsLookupProcessByProcessId(
    __in HANDLE ProcessId,
    __deref_out PEPROCESS *Process
    );
    
    PVOID g_pRegistrationHandle;
    
    NTKERNELAPI
    UCHAR * PsGetProcessImageFileName(__in PEPROCESS Process);
    
    EXTERN_C void InstallHook();
    OB_PREOP_CALLBACK_STATUS  ObjectPreCallback(__in PVOID  RegistrationContext,
    __in POB_PRE_OPERATION_INFORMATION  OperationInformation);
    
    
    OB_PREOP_CALLBACK_STATUS  ObjectPreCallback(__in PVOID  RegistrationContext,
    __in POB_PRE_OPERATION_INFORMATION  OperationInformation)
    {
    
    
    PEPROCESS Process;
    UCHAR *pszImageName = NULL;
    
    #define PROCESS_PROTECT 0x1
    Process = (PEPROCESS)OperationInformation->Object;
    pszImageName = PsGetProcessImageFileName(Process);
    
    if (strstr(pszImageName, "calc") != NULL)
    {
    
            if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
            {
                if
                    ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess &
                    PROCESS_PROTECT) == PROCESS_PROTECT)
                {
                    OperationInformation->Parameters->CreateHandleInformation.DesiredAccess
                        &= ~PROCESS_PROTECT;
                }
            }
            if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
            {
                if
                    ((OperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess &
                    PROCESS_PROTECT) == PROCESS_PROTECT)
                {
                    OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &=
                        ~PROCESS_PROTECT;
                }
            }
    
    
    }
    return OB_PREOP_SUCCESS;
    }
    
    void InstallHook()
    {
        NTSTATUS status;
        OB_CALLBACK_REGISTRATION obReg;
        OB_OPERATION_REGISTRATION obOper;
    
        DbgPrint("begin protect calc");
        obOper.ObjectType = PsProcessType;
        obOper.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
        obOper.PreOperation = NULL;
        obOper.PostOperation = NULL;
    
        RtlInitUnicodeString(&obReg.Altitude, L"60000");
        obReg.Version = OB_FLT_REGISTRATION_VERSION;
        obReg.OperationRegistrationCount = 1;
        obReg.RegistrationContext = NULL;
        obOper.PreOperation = (POB_PRE_OPERATION_CALLBACK)&ObjectPreCallback; 
        obReg.OperationRegistration = &obOper;
        
        status = ObRegisterCallbacks(&obReg, &g_pRegistrationHandle);
        DbgPrint("begin protect calc end");
    }
    
    VOID  DriverUnLoad(PDRIVER_OBJECT pDriverObject);
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
    {
    
        pDriverObject->DriverUnload = DriverUnLoad;
    
        DbgPrint("Load Driver Sucess");
        //InstallHook();
        InstallHook();
        //设置通讯的方式
    
        return STATUS_SUCCESS;
    }
    
    
    
    
    //驱动卸载
    
    VOID  DriverUnLoad(PDRIVER_OBJECT pDriverObject)
    {
        ObUnRegisterCallbacks(g_pRegistrationHandle);
        DbgPrint("Unload MyDrive
    ");
    }

    通过上面的代码,我们的计算器则会被保护.那么此时我们编译之后安装驱动那么软件就和刚开始那样,不能进行关闭进程了.

    你如果关闭计算器,重新打开则打开不了了, 

    如果你启动计算器之后,在安驱动,那么计算机就同上图所示,关闭不了了.

     四丶去掉保护.

    去掉保护,那么我们就要逆向 设置对象回调的这个API了.

    那么简单的演示则是用PChunter去掉.我们的程序就可以关闭了.

    如果有时间,则逆向一下,找到数组. 找到表,抹掉即可.

    去掉之后则可以退出了. 包括xxx杀毒.

    代码下载地址: WDK7600 + Notepad++ +x64Check编译. 你可以使用Free编译.我没用.

    链接:https://pan.baidu.com/s/1JDBnsznailhCw513pKsbsQ
    提取码:3uhq

  • 相关阅读:
    【LeetCode】17. Letter Combinations of a Phone Number
    【LeetCode】16. 3Sum Closest
    【LeetCode】15. 3Sum 三个数和为0
    【LeetCode】14. Longest Common Prefix 最长前缀子串
    【LeetCode】13. Roman to Integer 罗马数字转整数
    【LeetCode】12. Integer to Roman 整型数转罗马数
    【LeetCode】11. Container With Most Water
    【LeetCode】10. Regular Expression Matching
    Models of good programmer
    RSA Algorithm
  • 原文地址:https://www.cnblogs.com/iBinary/p/8401469.html
Copyright © 2011-2022 走看看