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\n");
}

 

 

通過上面的代碼,我們的計算器則會被保護.那么此時我們編譯之后安裝驅動那么軟件就和剛開始那樣,不能進行關閉進程了.

你如果關閉計算器,重新打開則打開不了了, 

如果你啟動計算器之后,在安驅動,那么計算機就同上圖所示,關閉不了了.

 

 

 四丶去掉保護.

去掉保護,那么我們就要逆向 設置對象回調的這個API了.

那么簡單的演示則是用PChunter去掉.我們的程序就可以關閉了.

如果有時間,則逆向一下,找到數組. 找到表,抹掉即可.

去掉之后則可以退出了. 包括xxx殺毒.

 

代碼下載地址: WDK7600 + Notepad++ +x64Check編譯. 你可以使用Free編譯.我沒用.

鏈接:https://pan.baidu.com/s/1JDBnsznailhCw513pKsbsQ
提取碼:3uhq


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM