我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函数,问题是文件名在哪里啊。。。
驱动大牛显个身,谢谢啦。。。
上个帖子你无视我的回复,如果你是在“倒分”,麻烦请快点结帖,别浪费其他人的时间。
cnzdgs这位兄台,你在上次帖子中说:
----------------------------------
注意,内核的ZwCreateFile函数是给驱动程序调用的,应用程序调用内核功能不会经过这个函数,而是指定调用NtCreateFile。
----------------------------------
我不太清楚你为啥确定应用程序不会调用ZwCreateFile。现在实际情况是调用了ZwCreateFile,并且我能够阻止文件的创建。
还有
----------------------------------
上个帖子你无视我的回复,如果你是在“倒分”,麻烦请快点结帖,别浪费其他人的时间
----------------------------------
呵呵,明显你说的不对嘛(见上面的解释)。还有我创建这个帐号已经超过5年了,在其他的板块也算头顶红星了,完全没有必要再来这儿“倒分”了。 8-)
如果你认为我说的不对而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标志才做处理,就会发生这种情况。
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
);
}
在上述代码中每次使用Windows的资源管理器创建新的文件都能够在日志中看到
FakedZwCreateFile FilePath Is \??\C:\ABC\
等字样。。。
并且如果return STATUS_OBJECT_NAME_NOT_FOUND的话,在C:\ABC目录下的文件将不会创建成功。
对了,我Hook了NtCreateFile函数,问题似乎与Hook了ZwCreateFile的现象一样。。。难道是我Hook得有问题?
还有上一帖给分,我确实是在某个时候通过RootDirectory获取到了文件名称(是否象cnzdgs兄所说的“如果是相对路径,RootDirectory是缺省路径的句柄”)。但是重新启动机器后,发现RootDirectory一直为空。。。唉。。。
请cnzdgs兄不吝赐教。。。
代码没有问题,这样Hook的就是NtCreateFile。
在资源管理器中操作时经常需要用NtCreateFile打开目录,所以输出了目录的信息是正常的。你试试创建打开一个文件,写些内容然后保存文件,看看输出的信息都有哪些。
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还是起作用的。
问题是我想判断特定文件名。。。
代码是没有问题的,文件名就在ObjectAttributes->ObjectName里面,可能是DbgPrint不支持中文或者有其它问题。你换个全英文的文件名,或者调试设置断点来看,应该至少会有一次是打开文件。
唉,多谢cnzdgs兄。。。
确实是中文文件名称的问题。。。让我郁闷了这么长的时间。
DbgPrint是可以支持中文输出的。但是是不是不支持unicode的中文输出?
再次表达我的感谢。
我一般不用调试输出,所以对DbgPrint不是很了解。