天啊,我Hook的ZwCreateFile的文件名到底在哪里啊。。。

jackhui   2008-8-26 14:41 楼主
我Hook了ZwCreateFile,通过
DbgPrint("HookZwCreateFile:%wZ\n",ObjectAttributes->ObjectName);
可以打印目录名称,后来发贴请问如何得到文件名:
http://topic.eeworld.net/u/20080821/15/36e51142-4e57-4735-b51f-8b2fee796b63.html
得知文件名称是在ObjectAttrubutes->RootDirectory中,问题是ObjectAttrubutes->RootDirectory == NULL,使用ObReferenceObjectByHandle得到的结果是STATUS_INVALID_HANDLE。。。

唉,这两天快被驱动弄疯了。。。

我如果在ZwCreateFile中直接返回STATUS_OBJECT_NAME_NOT_FOUND,文件管理器创建文件是不能成功的,说明创建文件还是经过了我的Hook函数,问题是文件名在哪里啊。。。

驱动大牛显个身,谢谢啦。。。

回复评论 (11)

上个帖子你无视我的回复,如果你是在“倒分”,麻烦请快点结帖,别浪费其他人的时间。
点赞  2008-8-26 15:58
cnzdgs这位兄台,你在上次帖子中说:

----------------------------------
注意,内核的ZwCreateFile函数是给驱动程序调用的,应用程序调用内核功能不会经过这个函数,而是指定调用NtCreateFile。
----------------------------------

我不太清楚你为啥确定应用程序不会调用ZwCreateFile。现在实际情况是调用了ZwCreateFile,并且我能够阻止文件的创建。

还有
----------------------------------
上个帖子你无视我的回复,如果你是在“倒分”,麻烦请快点结帖,别浪费其他人的时间
----------------------------------
呵呵,明显你说的不对嘛(见上面的解释)。还有我创建这个帐号已经超过5年了,在其他的板块也算头顶红星了,完全没有必要再来这儿“倒分”了。 8-)
点赞  2008-8-26 16:43
如果你认为我说的不对而1楼说的对的话,说明你对内核服务的了解还不够。我经常遇到别人看不懂我的回复的情况,既然不是“倒分”,我就再详细说说,你自己验证一下看看对不对。

ObjectName是目标文件(目录也是文件)路径及名称,可以是绝对路径也可以是相对路径,如果是相对路径,RootDirectory是缺省路径的句柄,如果是绝对路径,RootDirectory为0,多数情况是用绝对路径的。上帖1楼的回复刚好说反,因为没处理RootDirectory一样可以取得文件名,不会导致你描述的问题,所以我没有提这个地方。你把所有分就这样给了1楼,难免有倒分的嫌疑。

ZwCreateFile与NtCreateFile的接口是相同的,在驱动程序中通常是调用ZwCreateFile,ZwCreateFile函数会再调用NtCreateFile。在用户态下也存在这两个函数,都是通过切入内核后调用内核的NtCreateFile来实现的,不会调用内核的ZwCreateFile函数。如果用户级的操作通过了你的Hook函数,说明你Hook的是NtCreateFile而不是ZwCreateFile,SSDT中是NtCreateFile的地址,通过SSDT来Hook的就是NtCreateFile。我在上帖中提到的只是让你注意一下,不要Hook错了函数,如果Hook的是内核的ZwCreateFile,就只能Hook驱动程序的调用。

凡是对文件(包括目录)的各种访问,都要经过NtCreateFile,所以你Hook到打开目录是正常的。在Hook期间如果没有访问文件的操作,自然不会Hook到打开文件,所以需要先确认是否有文件操作。此外根据你描述的情况(全是目录没有文件),很像是程序中做了判断,把文件都滤掉了,如果程序中判断CreateOptions具有FILE_DIRECTORY_FILE标志才做处理,就会发生这种情况。
点赞  2008-8-26 17:28
cnzdgs兄,你好。
我还是上代码吧
RtlInitUnicodeString(&dllName, L"\\SystemRoot\\System32\\ntdll.dll");
functionAddress = GetDllFunctionAddress("ZwCreateFile", &dllName);
if(functionAddress != 0)
{
                ZwCreateFilePosition = *((WORD*)(functionAddress+1));
                RealZwCreateFile = (ZWCREATEFILE)(*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + ZwCreateFilePosition));
                DbgPrint("Find ZwCreateFile Success\n");
}

....
// 关中断,并且设置CR0的wp位
(ZWCREATEFILE)(*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + ZwCreateFilePosition)) = FakedZwCreateFile ;
// 开中断,并且恢复CR0的wp位
...

NTSTATUS FakedZwCreateFile(
        OUT PHANDLE FileHandle,
        IN ACCESS_MASK DesiredAccess,
        IN POBJECT_ATTRIBUTES ObjectAttributes,
        OUT PIO_STATUS_BLOCK IoStatusBlock,
        IN PLARGE_INTEGER AllocationSize OPTIONAL,
        IN ULONG FileAttributes,
        IN ULONG ShareAccess,
        IN ULONG CreateDisposition,
        IN ULONG CreateOptions,
        IN PVOID EaBuffer OPTIONAL,
        IN ULONG EaLength
)
{
    DbgPrint("FakedZwCreateFile FilePath Is %wZ\n",ObjectAttributes->ObjectName);
    return RealZwCreateFile(
                 FileHandle,
                 DesiredAccess,
                 ObjectAttributes,
                 IoStatusBlock,
                 AllocationSize ,
                 FileAttributes,
                 ShareAccess,
                 CreateDisposition,
                 CreateOptions,
                 EaBuffer ,
                 EaLength
                        );
}
点赞  2008-8-26 18:25
在上述代码中每次使用Windows的资源管理器创建新的文件都能够在日志中看到
FakedZwCreateFile FilePath Is \??\C:\ABC\
等字样。。。

并且如果return STATUS_OBJECT_NAME_NOT_FOUND的话,在C:\ABC目录下的文件将不会创建成功。
点赞  2008-8-26 18:30
对了,我Hook了NtCreateFile函数,问题似乎与Hook了ZwCreateFile的现象一样。。。难道是我Hook得有问题?

还有上一帖给分,我确实是在某个时候通过RootDirectory获取到了文件名称(是否象cnzdgs兄所说的“如果是相对路径,RootDirectory是缺省路径的句柄”)。但是重新启动机器后,发现RootDirectory一直为空。。。唉。。。

请cnzdgs兄不吝赐教。。。
点赞  2008-8-26 19:02
代码没有问题,这样Hook的就是NtCreateFile。
在资源管理器中操作时经常需要用NtCreateFile打开目录,所以输出了目录的信息是正常的。你试试创建打开一个文件,写些内容然后保存文件,看看输出的信息都有哪些。
点赞  2008-8-26 19:21
cnzdgs兄,我如果在C:\ABC目录下创建一个文本文件“新建 文件文档.txt”,这个Hook会输出11次下列日志
FakedZwCreateFile FilePath Is \??\C:\ABC\
此时文件创建成功

如果打开这个文件,会输出一次
FakedZwCreateFile FilePath Is \??\C:\ABC\

如果在FakedZwCreateFile函数中判断是C盘的ABC目录下创建文件(CreateDisposition == FILE_CREATE),并且return STATUS_OBJECT_NAME_NOT_FOUND,那么文件不会创建成功。说明Hook还是起作用的。

问题是我想判断特定文件名。。。
点赞  2008-8-26 20:23
代码是没有问题的,文件名就在ObjectAttributes->ObjectName里面,可能是DbgPrint不支持中文或者有其它问题。你换个全英文的文件名,或者调试设置断点来看,应该至少会有一次是打开文件。
点赞  2008-8-27 01:05
唉,多谢cnzdgs兄。。。
确实是中文文件名称的问题。。。让我郁闷了这么长的时间。
DbgPrint是可以支持中文输出的。但是是不是不支持unicode的中文输出?
再次表达我的感谢。
点赞  2008-8-27 09:44
我一般不用调试输出,所以对DbgPrint不是很了解。
点赞  2008-8-27 11:06
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复