Hook集合----SSDTHook(x86 Win7)

      最近在学习Ring0层Hook的一些知识点,很久就写完SSDTHook的代码了,但是一直没有整理成笔记,最近有时间也就整理整理。

介绍:

     SSDTHook 实质是利用Ntoskrnl.exe 中全局导出的SSDT来进行Hook,SSDT(SystemServiceDescriptorTable,系统服务描述表),为什么要去用到SSDT表呢?

     我们看一下ZwOpenProcess实现就明白了。为什么不用Nt系列函数,可以看我之前的文章。

 

kd> u 0x8485acd8
            nt!ZwOpenProcess:
            8485acd8 b8 be000000      mov     eax,0BEh
            8485acdd 8d542404        lea     edx,[esp+4]
            8485ace1 9c              pushfd
            8485ace2 6a08            push    8
            8485ace4 e8d5190000      call    nt!KiSystemService (8485c6be)
            8485ace9 c21000          ret     10h
            nt!ZwOpenProcessToken:
            8485acec b8bf000000      mov     eax,0BFh
            8485acf1 8d542404        lea     edx,[esp+4]

 

    KiSystemService是系统调用的内核入口,也是从Ring3陷入Ring0的关键点。在第一句中mov eax,0BEh 中的BEh在我看来就是一个序号,相当于中断向量表中的中断类型号一样,在SSDT表中通过这序号,才找到真正的NtOpenProcess函数的代码出。很容易就能理解,我们为什么要找这个。原因在于:我们要把SSDT表中相应位置的函数地址替换掉,就实现了Hook。

 (一)

 

     ⚪首先找到全局导出的KeServiceDescriptorTable。

     ⚪然后从MmGetSystemRoutineAddress函数中获取ZwOpenProcess函数地址。

     ⚪从ZwOpenProcess中获取序号。

     ⚪将SSDT表所在页属性改为可读可写的状态。

     ⚪将自己写好的Fake函数地址替换进去即可。

 

Hook之前:                                                                               Hook之后:

 

 

             

 

 

 

 

(二)

 

/*
typedef struct _SYSTEM_SERVICE_DESCRIPTOR_TABLE_     
{
    PVOID ServiceTableBase; //这个指向系统服务函数地址表
    PULONG ServiceCounterTableBase;
    ULONG NumberOfService; //服务函数的个数
    ULONG ParamTableBase;
}SYSTEM_SERVICE_DESCRIPTOR_TABLE, *PSYSTEM_SERVICE_DESCRIPTOR_TABLE;

0x84988b00 struct _SYSTEM_SERVICE_DESCRIPTOR_TABLE_ *
ServiceTableBase         0x8489d43c
ServiceCounterTableBase  0x00000000
NumberOfService          0x191
ParamTableBase           0x8489da84
*/
extern PSYSTEM_SERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
PUCHAR __ZwOpenProcess = NULL;
PMDL __MDL = NULL;
PVOID *__ServiceTableBase = NULL;
LPFN_NTOPENPROCESS __NtOpenProcess = NULL;
BOOLEAN __IsHook = FALSE;


#define SSDT_INDEX(ZwFunctionAddress) * (PULONG)((PUCHAR)ZwFunctionAddress +1)
#define SSDT_HOOK(ZwFunctionAddress,FakeFunctionAddress,OriginalFunctionAddress)\
                 OriginalFunctionAddress = (PVOID) InterlockedExchange((PLONG)&__ServiceTableBase[SSDT_INDEX(ZwFunctionAddress)],(LONG)FakeFunctionAddress)
#define SSDT_UNHOOK(ZwFunctionAddress,OriginalFunctionAddress)\
                   (PVOID) InterlockedExchange((PLONG)&__ServiceTableBase[SSDT_INDEX(ZwFunctionAddress)],(LONG)OriginalFunctionAddress)
NTSTATUS SSDTHook(BOOLEAN IsOk)
{
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    UNICODE_STRING v1;
    RtlInitUnicodeString(&v1, L"ZwOpenProcess");
    
    if (IsOk)
    {
        __ZwOpenProcess = (PUCHAR)MmGetSystemRoutineAddress(&v1);
        /*
        2: kd> u 0x8485acd8
            nt!ZwOpenProcess:
            8485acd8 b8 be000000      mov     eax,0BEh
            8485acdd 8d542404        lea     edx,[esp+4]
            8485ace1 9c              pushfd
            8485ace2 6a08            push    8
            8485ace4 e8d5190000      call    nt!KiSystemService (8485c6be)
            8485ace9 c21000          ret     10h
            nt!ZwOpenProcessToken:
            8485acec b8bf000000      mov     eax,0BFh
            8485acf1 8d542404        lea     edx,[esp+4]

        */
        if (__ZwOpenProcess)
        {
            if (__MDL == NULL)
            {
                __MDL = MmCreateMdl(NULL, KeServiceDescriptorTable->ServiceTableBase,
                    KeServiceDescriptorTable->NumberOfService * sizeof(PVOID));
                if (!__MDL)
                {
                    return Status;
                }
                MmBuildMdlForNonPagedPool(__MDL);
                //设置标志让内存变成读写
                __MDL->MdlFlags = __MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
                __ServiceTableBase = MmMapLockedPages(__MDL, KernelMode);
            }
            

            if (__ServiceTableBase)
            {
                if (!__IsHook)
                {
                    //开始HOOK
                    SSDT_HOOK(__ZwOpenProcess, FakeNtOpenProcess, __NtOpenProcess);
                    Status = STATUS_SUCCESS;
                    /*
                    2: kd> u 0x84a31ba1
                        nt!NtOpenProcess:
                        84a31ba1 8bff            mov     edi,edi
                        84a31ba3 55              push    ebp
                        84a31ba4 8bec            mov     ebp,esp
                        84a31ba6 51              push    ecx
                        84a31ba7 51              push    ecx
                        84a31ba8 64a124010000    mov     eax,dword ptr fs:[00000124h]
                        84a31bae 8a803a010000    mov     al,byte ptr [eax+13Ah]
                        84a31bb4 8b4d14          mov     ecx,dword ptr [ebp+14h]

                    */

                    __IsHook = TRUE;
                }
                
            }
        }
    }
    else
    {
        if (__IsHook)
        {
            SSDT_UNHOOK(__ZwOpenProcess, __NtOpenProcess);
            __IsHook = FALSE;
        }
        if (__MDL)
        {
            MmUnmapLockedPages(__ServiceTableBase, __MDL);
            IoFreeMdl(__MDL);
            __MDL = NULL;
            Status = STATUS_SUCCESS;

        }
        
    
    }
    

    return Status;
}

NTSTATUS FakeNtOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
{
    
    __try
    {
        PEPROCESS EProcess = PsGetCurrentProcess();
        if (EProcess != NULL && IsRealProcess(EProcess))
        {
            char * ProcessName = (ULONG_PTR)EProcess + x86_IMAGEFILENAME_OFFSET;
            if (strcmp(ProcessName, "HookRing3.exe")==0)
            {
                return STATUS_ACCESS_DENIED;
            }
        }
    }
    __except (1)
    {
        return GetExceptionCode();
    }
    return ((LPFN_NTOPENPROCESS)__NtOpenProcess)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);

}

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值