• SSDT的hook浅析


     ***********关于hook**********************************

      首先我们说下hook,什么是hook?hook的英文已经说明了,hook在英文中是钩的意思,计算机取其意叫钩子,而我的理解叫

      大家应该写过r3下程序,估计也写过一些r3的hook,例如有一个API是OpenProcess,功能是打开进程得到进程句柄,比如我们要结束一个进程,如果调用TerminateProcess这个API来结束进程,就必须知道进程句柄。

      那么结束一个进程的伪代码就是这样

      push PID       

      push 0

      push 2035711 //权限

      call OpenProcess

      push 0

      push eax

      call TerminateProcess

      这段代码执行,如果正常的话,这个PID的进程应该就会被结束了,这里我们来设想一下,假设我们这里call openprocess做一下修改,变成这样,

       push PID       

      push 0

      push 2035711 //权限

      call myopen 

      push 0

      push eax

      call TerminateProcess

     

      myopen这里是我自己写的一个函数,这个函数跟OpenProcess一样,也有三个参数,也有相同的返回值类型。在这个函数里,我把三个参数,传递给真正的OpenProcess,而把OpenProcess的返回值,做为myopen的返回值,那么,这套流程下来,肯定也是可以执行的,myopen函数类似这样:

      有童鞋要问了,这样做执行是可以执行,但是何必费力做一个包装函数,再调用原函数,这样的意义是什么?

       现在这套流程下来非常正常,我们做的这个包装函数没有意义,现在我们假设,如果有一个恶意进程PID=9527,你写这个结束程序来结束这个PID=9527的进程,这个恶意进程却给你安装了这个包装函数。但是,他稍微的修改了下,变成这样:

     

     嘿嘿,这样下来,会怎么样?你还能结束恶意进程吗?

     当然不能

     因为你如果打开PID为9527的进程时候,得不到正确的句柄返回值,返回值为0。

     这个方法,叫hook,我们也可以在OpenProcess的函数头进行hook。

     而我把这种方法,叫截,截获后,可阻止,可改变,可放行!hook,无非是截获流程,根据自己的需要替换,阻止,放行而已!

     r3层的r0层的hook原理一样,大道至简,现在很多驱动hook一上来就说内核,ssdt,弄的大家一头雾水,其实假传万卷书,真传一句话,驱动hook就是截获api在内核的执行流程,然后根据自己的需要替换,阻止,放行。 理论上你会r3的hook,你一定会r0的hook!

    *********关于SSDT**********************************

      明白了HOOK原理后,那么内核hook就很简单了,只要我们在API函数执行流程走到内核后在内核流程中进行截断,处理,就是内核hook了

     我们在内核流程的位置选择了SSDT表,那么,SSDT表是什么?

     SSDT(System Services Descriptor Table),系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。

    现在我们以OpenProcess来说明,看下SSDT表在函数执行流程中起的作用!

    函数的执行流程以OpenProcess是这样.先说明,下面再解释

    *r3 OpenProcess进入ntdll.dll的NtOpenProcess或ZwOpenProcess函数(反正是同一个地址)

    *进入内核

    *进入Ntoskrnl.exe的ZwOpenProcess

    *根据ZwOpenProcess的索引,找到SSDT表对应的地址,再根据SSDT表对应地址的数据(Ntoskrnl.exe的NtOpenProcess),执行函数。

    *也就是Ntoskrnl.exe的NtOpenProcess才是真正的执行主体

      

     根据上面OpenProcess的流程说明,进入内核后,OpenProcess是进入了Ntoskrnl.exe的ZwOpenProcess这个函数,根据这个函数的索引,在SSDT表查找到真正的内核执行体Ntoskrnl.exe的NtOpenProcess函数,然后执行。

     首先,我们先找到SSDT表,下面我们来看一个被内核导出的结构KeServiceDescriptorTable.

    struct KeServiceDescriptorTable       
              SSDT表的指针 //这个指向系统服务函数地址表
              ServiceCounterTableBase;
              NumberOfService; //服务函数的个数
              TableBase
     end KeServiceDescriptorTable

    这里第一个字段就是SSDT表的指针,我们用windbg看一下,先dd KeServiceDescriptorTable

    第一个字段是80502b8c,这个就是SSDT表的地址了

     我们dd 80502b8c看看SSDT表

    里面存放的都是一些NT函数地址。

    之前说了Ntoskrnl.exe的ZwOpenProcess函数有个索引,根据索引在SSDT表里查找真正的内核执行体函数Ntoskrnl.exe的NtOpenProcess函数

    我们看看ZwOpenProcess,用windbg查看,u nt!ZwOpenProcess

    索引号是7Ah

    那么Ntoskrnl.exe的NtOpenProcess函数应该存放的位置就是=80502b8ch(SSDT表的开始地址)+7Ah(索引)*4(每个函数的间隔),得到80502D74h

    80502D74h处存放的地址是805C2296,这个应该是Ntoskrnl.exe的NtOpenProcess函数的地址,我们看下是不是

    果然是的.

    所以函数在由R3进R0后,要通过SSDT表的来选择最终执行的内核函数,假设我们想在内核中HOOKOpenProcess这个函数,只需要修改80502d74处存放的地址,放入我们自己写的newNtOpenProcess函数地址,在我们newNtOpenProcess函数中,进行了修改或替换或阻止或放行后执行真正的NtOpenProcess,这就是所谓的SSDThook

    那么,我简单说下ssdt表中 hook OpenProcess这个函数步骤

    1.先得到Ntoskrnl.exe的NtOpenProcess函数的地址(用MmGetSystemRoutineAddress函数得到内核导出函数地址)

    2.再得到SSDT表中Ntoskrnl.exe的NtOpenProcess函数应该存放的位置

       (SSDT表的开始地址)+(索引)*4(每个函数的间隔)

         SSDT表的开始地址=[KeServiceDescriptorTable->SSDT表的指针]  

         索引=[Ntoskrnl.exe的zwOpenProcess地址+1]

    3.自己建立一个新函数,参数和返回值要和Ntoskrnl.exe的NtOpenProcess函数一模一样

    4.把自己的新函数地址写到SSDT表中我们算出来的存放位置处,(mov [(SSDT表的开始地址)+(索引)*4(每个函数的间隔)],新函数地址)

    下面是部分重要代码:

    执行效果如图:

     

  • 相关阅读:
    SAP函数生成测试数据
    ABAP——编码规范
    展BOM清单——CS_BOM_EXPL_MAT_V2
    Java使用JCO实现调用SAP接口(建立采购单)
    ECN变更单建立——CCAP_ECN_CREATE
    SmartForms——插入复选框
    SmartForms——属性框被拖拽到左边不能复原
    SmartForms——实例
    SmartForms——基础知识
    SAP PP——生产订单的状态
  • 原文地址:https://www.cnblogs.com/qq32175822/p/3517887.html
Copyright © 2020-2023  润新知