-
-
[原创] 关于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的宽字符串且只在类型创建过程中被使用,而这可以作为特征。
所以,定位的顺序:
加载ntoskrnl镜像,搜索你需要的类型的名称,记得在0x0000后边补上0x9090,不能使用字符串比较函数
计算它的RVA,从INIT节开始遍历特征码 4c 8d 15 xx xx xx xx,也就是lea rdx, [xx],找到特征
遍历导出表得到ObCreateObject,搜特征码得到ObCreateObjectEx
从lea rdx, [xx]向下搜索e8 xx xx xx xx,也就是call ObCreateObjectEx
再向上搜索第一个出现的48 8d 53 24 xx,也就是lea edx, [esp+xx],这一步是为了取得init结构在栈上相对于rsp的偏移,也就是xx
根据_OBJECT_TYPE_INITIALIZER结构体的各项Procedure偏移量,分别获得它们在栈上相对于rsp的偏移,比如我要取OpenProcedure的值那么它相对于rsp的偏移量就是init偏移+OpenProcedure在结构体中的偏移
向上搜索足量字节比如0x120直到下一个call ObCreateObjectEx或到达,这是为了避免在取函数地址时收到上一个对象类型的干扰
从这个地址作为基址向下搜索lea 各种寄存器, [xx],因为写入栈时通常是mov qword ptr [rsp+xx], 寄存器,应该尽可能保存多的寄存器状态(可以将RVA也就是xx的值直接当作状态毕竟这也不碍什么事)避免编译器搞幺蛾子。搜索到mov qword ptr [rsp+xx], 寄存器时根据保存寄存器状态写入相对应栈上的Procedure,如果有一些没有搜到可能是寄存器的赋值在很上面,搜索多一点也没事。
注意如果SecurityProcedure为零那么ObCreateObjectTypeEx中会将其设为SeDefaultObjectMethod,特征是48 89 83 98 00 00 00往上搜索lea rax, [xx]即可。