zoukankan      html  css  js  c++  java
  • ObCallback回调钩子检测

    ObCallback回调钩子检测

    2013-12-20 Nie.Meining Ring0

    在 PatchGuard 的摧残下,通过 ObRegisterCallbacks 函数注册回调钩子已经成了 RK/ARK 中的主流技术之一。注册回调钩子的具体做法可以参考MSDN上的示例代码:http://code.msdn.microsoft.com/windowshardware/ObCallback-Sample-67a47841

    今天研究了一下检测这类回调钩子的方法,发出来跟大家分享。本人水平有限,错漏之处还请大家指正。

    首先关注的还是注册回调钩子时调用的 ObRegisterCallbacks 函数,MSDN上的函数声明如下:

    1. NTSTATUS ObRegisterCallbacks(
    2. _In_ POB_CALLBACK_REGISTRATION CallBackRegistration,
    3. _Out_ PVOID *RegistrationHandle
    4. );


    也就是说调用该函数后,我们会得到一个神奇的 RegistrationHandle 指针,而该指针指向的数据结构必然用于描述本次注册的回调钩子(否则 ObUnRegisterCallbacks 就摘不掉钩子了)。

    经过一番逆向和调试,发现这个数据结构由三个部分顺序组织在内存中:

    -----------------------------------------------------------------------------------------------------

    Part1:

    钩子数据结构的头部信息,如版本号,CallbackOperator 个数等


    Part2:(这个部分的长度取决于该回调钩子包含多少个CallbackOperator)

    钩子数据结构的CallbackOperator1 相关信息

    钩子数据结构的CallbackOperator2 相关信息

    ……


    Part3:

    钩子数据结构的额外信息,如 Altitude 等

    -----------------------------------------------------------------------------------------------------

    具体来讲,用 C 语言可以描述如下:

    1. struct CALLBACK_NODE {
    2. // 版本号,目前是 0x100, 可通过 ObGetFilterVersion 获取该值
    3. USHORT usVersion;
    4.  
    5. // 本节点上有多少个 CallbackOperator,即多少个 CallbackBodies
    6. USHORT usCallbackBodyCount;
    7.  
    8. // 注册回调时设定的 OB_CALLBACK_REGISTRATION.RegistrationContext
    9. // 即 PreCallbackRoutine 和 PostCallbackRoutine 的参数
    10. PVOID pContext;
    11.  
    12. // 这里似乎是 0x000C000C/0x00080008 一类的值
    13. ULONG ulXXX_000X000X;
    14.  
    15. // 指向 Altitude 字符串
    16. // 注意这个字符串因为最大长度是恒定的,所以不一定以 NULL 结尾
    17. PWCHAR wcsAltitude;
    18.  
    19. // CALLBACK_BODY 数组,其元素个数为 ulCallbackCount
    20. struct CALLBACK_BODY CallbackBodies[1];
    21. //
    22. // CALLBACK_BODY数组后,紧接着 Altitude 字符串和一些其它数据
    23. //
    24. };


    其中的 struct CALLBACK_BODY CallbackBodies[] 数组就是描述该 CallbackNode 上的各个 CallbackOperator 的数据结构:

    1. struct CALLBACK_BODY {
    2.  
    3. // 所有的 CALLBACK_NODE 通过这个链表串在一起
    4. LIST_ENTRY ListEntry;
    5.  
    6. // 注册回调时设定的 OB_OPERATION_REGISTRATION.Operations,
    7. // 即 OB_OPERATION_HANDLE_CREATE 这些东西
    8. ULONG ulOperations;
    9.  
    10. // 这里似乎始终是 1
    11. ULONG ulXXX_1;
    12.  
    13. // 指向该 CallbackBody 对应的 CallbackNode
    14. struct CALLBACK_NODE* pCallbackNode;
    15.  
    16. // 注册回调时设定的 OB_OPERATION_REGISTRATION.pObjectType
    17. // 即 PsProcessType,PsThreadType 这些东西
    18. PVOID pObjectType;
    19.  
    20. // 这就是注册回调时设定的 PreCallbackRoutine 函数地址
    21. PVOID pPreCallbackRoutine;
    22.  
    23. // 这就是注册回调时设定的 PostCallbackRoutine 函数地址
    24. PVOID pPostCallbackRoutine;
    25.  
    26. // 这里似乎是个引用计数
    27. ULONG ulRefCount;
    28.  
    29. };


    注意这里面的 CALLBACK_BODY.ListEntry 链表很有意思,它将系统中的其它 CALLBACK_NODE.CallbackBodies 都链在了一起。因此我们就可以通过遍历这个链表检测系统中的其它回调钩子。

    检测的大致思路是,先自己调用ObRegisterCallbacks注册一个假钩子,这样就得到了一个节点,然后用这个节点开始遍历。

    写了一个测试代码,在64位Win8系统上测试截图如下:

    x64bd360.png

    图中 CallbackDetect.sys 中钩子是我的检测模块注册的假钩子;bd0001.sys 中的钩子是百度卫士注册的钩子;其它是360注册的钩子。


    完整测试代码下载(64位/32位系统通用):CallbackDetect.zip 

    jpg改rar

     

     
  • 相关阅读:
    python2.7学习记录之三
    编程题
    解题的小问题(C++)
    算法入门(C++)
    逻辑回归
    入门级(python)
    python2.7学习记录之二
    sql语句-排序后加入序号再运算判断取想要的项
    linux中c多线程同步方法
    进程间的通讯方式
  • 原文地址:https://www.cnblogs.com/kuangke/p/6155354.html
Copyright © 2011-2022 走看看