这个问题不是很具体。不知道你是感觉哪里有困难,是windbg+vm这种跟踪方式,还是使用这种方式跟踪NtDeleteFile时有困难?我使用WinDBG+VirtualPC跟踪了一下XP SP3,大致结果如下:
1)对NtDeleteFile设置断点后,在资源管理器(Shift+Delete)和命令行(del)执行删除文件操作,断点都没有命中。
2)观察NtDeleteFile的汇编代码(uf NtDeleteFile),可以看到,其中的主要调用是nt!ObOpenObjectByName,也就是通过这个调用向文件系统发出请求的。
3)Win32 API的DeleteFile是用来删除文件的,使用另一个WinDBG通过用户态调试对其跟踪,以下是DeleteFileW(DeleteFile的宽字符版本,DeleteFileA会调用这个函数)的执行过程:
0:000> wtTracing kernel32!DeleteFileW to return address 7c831e4e 14 0 [ 0] kernel32!DeleteFileW 12 0 [ 1] ntdll!RtlDosPathNameToNtPathName_U 30 1556 [ 1] ntdll!RtlDosPathNameToNtPathName_U 44 1586 [ 0] kernel32!DeleteFileW 3 0 [ 1] ntdll!NtOpenFile 2 0 [ 2] ntdll!KiFastSystemCall 1 0 [ 1] ntdll!NtOpenFile 55 1592 [ 0] kernel32!DeleteFileW 1 0 [ 1] ntdll!NtQueryInformationFile 2 0 [ 1] ntdll!ZwQueryInformationFile 2 0 [ 2] ntdll!KiFastSystemCall 1 0 [ 1] ntdll!ZwQueryInformationFile 69 1598 [ 0] kernel32!DeleteFileW 3 0 [ 1] ntdll!RtlFreeHeap 79 69 [ 1] ntdll!RtlFreeHeap 78 1746 [ 0] kernel32!DeleteFileW 1 0 [ 1] ntdll!ZwSetInformationFile 2 0 [ 1] ntdll!NtSetInformationFile 2 0 [ 2] ntdll!KiFastSystemCall 1 0 [ 1] ntdll!NtSetInformationFile 81 1752 [ 0] kernel32!DeleteFileW 1 0 [ 1] ntdll!NtClose 2 0 [ 1] ntdll!ZwClose 2 0 [ 2] ntdll!KiFastSystemCall 1 0 [ 1] ntdll!ZwClose 90 1758 [ 0] kernel32!DeleteFileW
1848 instructions were executed in 1847 events (0 from other threads)
可以发现,DeleteFile API根本没有调用NtDeleteFile,其主要操作是先打开文件,然后调用内核服务NtSetInformationFile,最后再关闭文件。这印证了API文档中的说法: The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed.
哈哈,岁月无情呀。
对的,!drvobj刚好满足你的需要,我也很喜欢用这个命令。
对于不太熟悉这个命令的朋友,我再罗嗦几句。
这个命令可以跟两个参数,即
!drvobj DriverObject [Flags]
第一个参数可以是_DRIVER_OBJECT结构的地址,也可以是驱动程序的名称。
当不知道驱动对象的地址时,使用名称是很方便的,比如下面的命令就可以得到NTFS驱动程序的对象地址,和它的设备实例:
lkd> !drvobj ntfsDriver object (8a834f38) is for: \FileSystem\NtfsDriver Extension List: (id , addr)
Device Object list:8993b020 8a825020 8a85b900
有了驱动对象的地址8a834f38,那么既可以使用dt命令来观察它的详细信息,也可以使用!drvobj:
lkd> dt _DRIVER_OBJECT 8a834f38ntdll!_DRIVER_OBJECT +0x000 Type : 4 +0x002 Size : 168 +0x004 DeviceObject : 0x8993b020 _DEVICE_OBJECT +0x008 Flags : 0x92 +0x00c DriverStart : 0xba536000 +0x010 DriverSize : 0x8c400 +0x014 DriverSection : 0x8a8e66f8 +0x018 DriverExtension : 0x8a834fe0 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\FileSystem\Ntfs" +0x024 HardwareDatabase : 0x8066f260 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : 0xba5557a0 _FAST_IO_DISPATCH +0x02c DriverInit : 0xba5bb184 long Ntfs!GsDriverEntry+0 +0x030 DriverStartIo : (null) +0x034 DriverUnload : (null) +0x038 MajorFunction : [28] 0x88fd2c00 long +ffffffff88fd2c00
然后用dds命令可以列出MajorFunction数组的内容:
lkd> dds 8a834f38+388a834f70 88fd2c008a834f74 804f3520 nt!IopInvalidDeviceRequest8a834f78 ba55b0ea Ntfs!NtfsFsdClose8a834f7c ba538f3b Ntfs!NtfsFsdRead8a834f80 ba537b57 Ntfs!NtfsFsdWrite8a834f84 ba55c2b9 Ntfs!NtfsFsdDispatchWait8a834f88 88fd2c178a834f8c ba55c2b9 Ntfs!NtfsFsdDispatchWait8a834f90 ba55c2b9 Ntfs!NtfsFsdDispatchWait8a834f94 ba575ec8 Ntfs!NtfsFsdFlushBuffers8a834f98 ba55c404 Ntfs!NtfsFsdDispatch8a834f9c ba55c404 Ntfs!NtfsFsdDispatch8a834fa0 ba55dfbd Ntfs!NtfsFsdDirectoryControl8a834fa4 ba560758 Ntfs!NtfsFsdFileSystemControl8a834fa8 ba55c404 Ntfs!NtfsFsdDispatch8a834fac 804f3520 nt!IopInvalidDeviceRequest8a834fb0 ba54a5af Ntfs!NtfsFsdShutdown8a834fb4 ba5afaa3 Ntfs!NtfsFsdLockControl8a834fb8 ba55bab8 Ntfs!NtfsFsdCleanup8a834fbc 804f3520 nt!IopInvalidDeviceRequest8a834fc0 ba55c404 Ntfs!NtfsFsdDispatch8a834fc4 ba55c404 Ntfs!NtfsFsdDispatch8a834fc8 804f3520 nt!IopInvalidDeviceRequest8a834fcc 804f3520 nt!IopInvalidDeviceRequest8a834fd0 804f3520 nt!IopInvalidDeviceRequest8a834fd4 ba55c2b9 Ntfs!NtfsFsdDispatchWait8a834fd8 ba55c2b9 Ntfs!NtfsFsdDispatchWait8a834fdc ba5787f0 Ntfs!NtfsFsdPnp8a834fe0 8a834f38!drvobj把简化了上面的操作,因此使用一条命令就可以完成,即:lkd> !drvobj ntfs 2 (设置位1以显示分发例程)
为什么我的出现
lkd> !drvobj ntfsDriver object ntfs not found