对象名称来引用文件
内核模式设备驱动程序引用到一个文件及其对象的名称。此名称是与该文件的完整路径一起 /DosDevices。例如对于 C:/Windows/Example.txt 文件的对象名称是 /DosDevices/C:/Windows/Example.txt。然后通过调用 InitializeObjectAttributes 函数的为 OBJECT_ATTRIBUTES 结构封装为对象的名称。
注意如果早期加载的设备驱动程序,不可能还存在 /DosDevices 命名空间。因此,/DosDevices 命名空间是设备驱动程序将无法访问,因为没有驱动器号公开的。仅可保证在文件系统的部分是 /SystemRoot 的命名空间。/SystemRoot 命名空间映射到操作系统安装位置文件夹。例如对于此文件夹可能是 C:/Windows 或 D:/Winnt。
下面的代码示例阐释了如何通过其对象名称来引用到一个文件
UNICODE_STRING uniName;
OBJECT_ATTRIBUTES objAttr;
RtlInitUnicodeString(&uniName, L"//DosDevices//C://WINDOWS//example.txt"); // or L"//SystemRoot//example.txt"
InitializeObjectAttributes(&objAttr, &uniName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);
回到顶端
获取文件句柄
若要获取文件句柄,您可以将一个 OBJECT_ATTRIBUTES 结构传递给 ZwCreateFile 函数。可以 GENERIC_READ、 GENERIC_WRITE,或 GENERIC_ALL,设置 DesiredAccess 参数,具体取决于要执行的内容。如果将 CreateOptions 参数设置为 FILE_SYNCHRONOUS_IO_NONALERT 或 FILE_SYNCHRONOUS_IO_ALERT,文件系统跟踪的当前文件位置偏移量。因此,您可以按顺序读取或写入的文件更高版本。此外,您可以访问随机位置上的文件。
下面的代码示例阐释了如何获取文件句柄
HANDLE handle;
NTSTATUS ntstatus;
IO_STATUS_BLOCK ioStatusBlock;
// Do not try to perform any file operations at higher IRQL levels.
// Instead, you may use a work item or a system worker thread to perform file operations.
if(KeGetCurrentIrql() != PASSIVE_LEVEL)
return STATUS_INVALID_DEVICE_STATE;
ntstatus = ZwCreateFile(&handle,
GENERIC_WRITE,
&objAttr, &ioStatusBlock, NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
回到顶端
读取或写入到文件
您现在可以调用 ZwReadFile 函数或 ZwWriteFile 函数。完成修改文件后,请使用 ZwClose 函数来关闭该句柄。
下面的代码示例阐释了如何向文件写入
#define BUFFER_SIZE 30
CHAR buffer[BUFFER_SIZE];
size_t cb;
if(NT_SUCCESS(ntstatus)) {
ntstatus = RtlStringCbPrintfA(buffer, sizeof(buffer), "This is %d test/r/n", 0x0);
if(NT_SUCCESS(ntstatus)) {
ntstatus = RtlStringCbLengthA(buffer, sizeof(buffer), &cb);
if(NT_SUCCESS(ntstatus)) {
ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, cb, NULL, NULL);
}
}
ZwClose(handle);
}
下面的代码示例阐释了如何从文件中读取
LARGE_INTEGER byteOffset;
ntstatus = ZwCreateFile(&handle,
GENERIC_READ,
&objAttr, &ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
if(NT_SUCCESS(ntstatus)) {
byteOffset.LowPart = byteOffset.HighPart = 0;
ntstatus = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, BUFFER_SIZE, &byteOffset, NULL);
if(NT_SUCCESS(ntstatus)) {
buffer[BUFFER_SIZE-1] = '/0';
DbgPrint("%s/n", buffer);
}
ZwClose(handle);
}