首页
社区
课程
招聘
[原创] 关于Win7下大多数ObjectHook的检测方式
发表于: 7小时前 127

[原创] 关于Win7下大多数ObjectHook的检测方式

7小时前
127

关于ObjectHook我就不多说了,主要就是写入ObjectType中某一个Procedure从而实现hook,而检测也很简单,就是比较内存中Procedure和磁盘映像中的是否一致。

首先ntoskrnl中注册对象类型通常使用的是ObCreateObjectTypeEx,函数需要传入一些参数,包括对象名称、接受对象类型的指针、_OBJECT_TYPE_INITIALIZER结构体等等。而我们可以通过搜索对象名称初始化过程特征码进行搜索,以PsProcessType为例,初始化类型名代码为

RtlInitUnicodeString(Name,u_Process);

对应的汇编

       1405a95d5 48 8d 15        LEA        RDX,[u_Process]                                  = u"Process"
                 94 fd fc ff
       1405a95dc 48 8d 8c        LEA        RCX=>Name,[RSP + 0xc0]
                 24 c0 00 
                 00 00
       ...
       1405a95ef e8 0c 8a        CALL       RtlInitUnicodeString                             undefined RtlInitUnicodeString()
                 ae ff

这个u_Process是何方神圣呢,点进去

                             **************************************************************
                             * Process                                                    *
                             **************************************************************
                             ??_C@_1BA@NMDNJJOO@?$AAP?$AAr?$AAo?$AAc?$AAe?$  XREF[1]:     PspInitPhase0:1405a95d5(*)  
                             u_Process
       140579370 50 00 72        unicode    u"Process"
                 00 6f 00 
                 63 00 65

可见u_Process也就是L"Process",而经过观察,类型名是16字节对齐、补0x90的宽字符串且只在类型创建过程中被使用,而这可以作为特征。

所以,定位的顺序:

  1. 加载ntoskrnl镜像,搜索你需要的类型的名称,记得在0x0000后边补上0x9090,不能使用字符串比较函数

  2. 计算它的RVA,从INIT节开始遍历特征码 4c 8d 15 xx xx xx xx,也就是lea rdx, [xx],找到特征

  3. 遍历导出表得到ObCreateObject,搜特征码得到ObCreateObjectEx

  4. lea rdx, [xx]向下搜索e8 xx xx xx xx,也就是call ObCreateObjectEx

  5. 再向上搜索第一个出现的48 8d 53 24 xx,也就是lea edx, [esp+xx],这一步是为了取得init结构在栈上相对于rsp的偏移,也就是xx

  6. 根据_OBJECT_TYPE_INITIALIZER结构体的各项Procedure偏移量,分别获得它们在栈上相对于rsp的偏移,比如我要取OpenProcedure的值那么它相对于rsp的偏移量就是init偏移+OpenProcedure在结构体中的偏移

  7. 向上搜索足量字节比如0x120直到下一个call ObCreateObjectEx或到达,这是为了避免在取函数地址时收到上一个对象类型的干扰

  8. 从这个地址作为基址向下搜索lea 各种寄存器, [xx],因为写入栈时通常是mov qword ptr [rsp+xx], 寄存器,应该尽可能保存多的寄存器状态(可以将RVA也就是xx的值直接当作状态毕竟这也不碍什么事)避免编译器搞幺蛾子。搜索到mov qword ptr [rsp+xx], 寄存器时根据保存寄存器状态写入相对应栈上的Procedure,如果有一些没有搜到可能是寄存器的赋值在很上面,搜索多一点也没事。

  9. 注意如果SecurityProcedure为零那么ObCreateObjectTypeEx中会将其设为SeDefaultObjectMethod,特征是48 89 83 98 00 00 00往上搜索lea rax, [xx]即可。



[招生]科锐逆向工程师培训(2026年7月3日实地,远程教学同时开班, 第56期)!

收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回