概述
ObQueryNameString这个函数早就臭名远播啦,某文就说
"这个函数的使用,在有些环境下会有问题。它的上层函数是 ZwQueryObject()。在某些情况下会导致系统挂起,或者直接 BSOD。它是从 对象管理器中的 ObpRootDirectoryObject开始遍历,通过 OBJECT_HEADER_TO_NAME_INFO 获得对象名称。今天问了下 PolyMeta好象是在处理 PIPE 时会挂启,这个问题出现在 2000 系统。在 XP 上好象补丁了。"
而百度一下也多是问关于调用失败的问题,而我在使用该函数时看了看一些例子与文章,发现了一个重要的问题,在此我觉得非常必要说一下
首先在首次搜了搜例子源码后,我发现其中有一个比较奇怪的地方(或许是我功力不足、孤听寡闻吧).
NTSTATUS
ObQueryNameString(
IN PVOID Object,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength
);
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
其中的函数的第二个参数牛人是这样构建的:
POBJECT_NAME_INFORMATION pTmpStr;
pTmpStr = ExAllocatePoolWithTag(NonPagedPool,1024,"Reg1");
非常容易就可以看出它并没有初始化该参数的一些数据而仅仅是分配了一块内存区,虽然该参数被标记为OUT,但一般而言还是应该初始化的,毕竟没有源码你没法知道函数究竟有没有使用该参数的一些数据,只要稍有差池,在内核中系统马上就给你个BSOD.而一般的方法(仅对我而言)还是应该这样的:
POBJECT_NAME_INFORMATION pTmpStr;
w_char t[1024];
RtlInitUnicodeString(&(pTmpStr->Name),t);
但其实我的做法是错误的,缓冲区会溢出,系统立刻就BOSD啦,其实错不在我,而是ObQueryNameStringbe本身存在着一些非常严重的缺陷,在我看了另一位CSDN牛人的文章《 ObQueryNameString源码解读》后我算是感受到这函数的牛啦.重点的在这位大牛讲到"ObQueryNameString并没有利用参数ObjectNameInfo.Name.Buffer来指出缓冲区的地址,而是简单地认为名称紧跟着OBJECT_NAME_INFORMATION结构."这样的话,假如像我这样构建参数OBJECT_NAME_INFORMATION后面跟着的只是一个UNICODE_STRING结构,真正的缓冲区指向了别处,这样必定会造成缓冲区溢出,对未知的系统数据进行重写,这时BSOD只是时间问题啦.假如你足够幸运的话,真正的缓冲区刚好跟着UNICODE_STRING结构,还可以免于一死.当然前者的牛人这样构建参数还有一个非常重要的原因,在这篇牛文中还说到"注意了,用户提供的缓冲区的大小是有函数参数Length指定的,而不是由参数ObjectNameInfo.Name.MaximumLength或ObjectNameInfo.Name.Length指定的。",这样看来牛人所写的代码还是考证过的才敢这样写的.至于编这函数恐怕是一MS实习生.另外这牛人怎样弄得源码还公开了就不得而知啦.反正就是提醒大家一句用ObQueryNameString要用牛人所写的形式.
今天写的这篇小文仅是为那些使用ObQueryNameString的人提个醒,也为用ObQueryNameString而错误的人给个参考,大牛们还请直接飘过吧.至于本人的功力还请大家见笑了,有什么错误还请大家留言指出吧.
请大家注意语言文明.
最后
以上就是欢喜冥王星为你收集整理的ObQueryNameString一设计缺陷简述的全部内容,希望文章能够帮你解决ObQueryNameString一设计缺陷简述所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复