BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / security / #5093同步于 2006/11/25
Security机器人发帖

[原创]深入分析ObReferenceObjectByName有时无法得到指定对象地

flyingkisser
2006/11/25镜像同步0 回复
欢迎拍砖... ------------------------ 深入分析ObReferenceObjectByName有时无法得到指定对象地址的原因 by flyingkisser 06.11.25 有时,我们需要得到像"\Device\XXX"或"\Driver\XXX"这种对象的地址,一般想到的最方便的方法是就是用 ObReferenceObjectByName.这个函数没有公开,但是被导出了。其参数也比较简单,没什么多说的。 比如我们想得到"\Driver\KbdClass"对象的地址,调用这个函数可以轻易获得。然而,当我们用这个API 去获得"\Device\KeyboardClass0"对象的地址时,总是返回0xC0000024,即STATUS_OBJECT_TYPE_MIMATCH 对象的类型不匹配,这是哪门子错误,虽然,此路不通时,还有别的方法可以获得这个对象的地址, 但是,我总想把这个问题搞清楚,于是在xp下面逆向了一个这个函数,并结合win2k源代码,最后终于找到了 问题所在。 ObReferenceObjectByName是ObpLookupObjectName的包裹函数,对于给定的"\X1\X2"这样的名称, ObpLookupObjectName会通过ObpLookupDirectoryEntry得到"\X1"对象的地址,再定位到对象头,由对象头再 找到对象类型的对象的地址,然后再判断一下类型对象->TypeInfo->ParseProcedure有没有值,如果不为空, 则调用。如果为空,则不调用(嗯,的确是费话...).对于"\Device"或是"\Driver",他们的类型对象的 ParseProcdedure都是空,所以代码继续往下走,再通过ObpLookupDirectoryEntry得到"\X1\X2"对象的地址, 然后,和上面是同样的过程,先定位到对象头,再找到对象类型对象的地址,再判断 类型对象->TypeInfo->ParseProcedure是不是为空. 如果是Driver类型的对象,它的Type对象,名称为Driver,其ParseProcedure为空,没有被调用,成功返回 如果是Device类型的对象,它的Type对象,名称为Device,其ParseProcedure不为空,指向IopParseDevice, 而在IopParseDevice内部,会对传入的一个参数进行检测,这个参数就是我们调用 ObReferenceObjectByName()时给定的第7个参数:ParseContext.先把这个指针转换成指向OPEN_PACKET类型的指针 如果这个指针为空,或是这个结构体的Type成员不等于IO_TYPE_OPEN_PACKET或者Size成员不等于sizeof(OPEN_PACKET) 就返回0xC0000024错误,即STATUS_OBJECT_TYPE_MIMATCH.而这个参数一般我们给定的都是空。 所以,ObReferenceObjectByName最终返回了STATUS_OBJECT_TYPE_MIMATCH 其实这里win2k源代码中是有一段注释的,意思是保证这个Routine的调用是从NtCreateFile()发起的,而不是 其实任意的对象打开或创建操作发起的,尽是这个参数被标记为"可选的". 所以,看到这里大家应该清楚了吧,说到底,还是我们被M$玩弄了。 那么,如何解决这个问题呢? 我本想搞清楚这个ParseContext指向的OPEN_PACKET类型的结构体如何初始化的, 不过在IopParseDevice里面会看到大量使用了这个结构体的成员,所以,我觉得分析下去挺没意思了,体力活, 实在不想干。 其实解决这个问题也很简单,调用IoGetDeviceObjectPointer()就是了,当然,从它的名称也能看出,它只能 得到Device类型的对象的地址。 其实比较稳妥的方法是调用ZwCreateFile()得到给定名称的对象的句柄,再用ObReferenceObjectByHandle就能 得到对象的地址了,然后句柄就可以ZwClose掉了,最后对象用完以后可别忘了ObDereferenceObject一下。
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。