一:文件的创建
/************************************************************************ * 函数名称:ZwCreateFile * 功能描述:文件的创建 * 参数列表: FileHandle:返回打开文件的句柄 DesiredAccess:对打开文件操作的描述,读,写或是其他。一般指定为GENERIC_READ 或 GENERIC_WRITE ObjectAttributes:是OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名 IoStatusBlock:指向一个IO_STATUS_BLOCK结构,该结构接收ZwCreateFile操作的结果状态 AllocationSize:是一个指针,指向一个64位整数,该数指定文件初始分配时的大小 该参数仅关系到创建或重写文件操作,如果忽略它,那么文件长度从0开始 病随着写入而增长 FileAttributes:0或FILE_ATTRIBUTE_NORMAL,指定新创建文件的属性 ShareAccess:FILE_SHARE_READ或0,指定文件的共享方式。 如果为写数据而打开文件,可能不希望其他线程访问该文件 CreateDisposition:FILE_OPEN或FILE_OVERWRITE_IF,表明当指定文件存在或不存在时应如何处理 CreateOptions:FILE_SYNCHARONOUS_IO_NONALERT,指定控制打开操作和句柄使用的附加标志位 EaBuffer:一个指针,指向可选的扩展属性区 EaLength:扩展属性区的长度 * 返回 值: NTSTATUS *************************************************************************/ NTSTATUS ZwCreateFile( 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); /* *备注: * 1、CreateDisposition参数。 * 如果想打开文件,CreateDisposition参数设置成FILE_OPEN. * 如果想创建文件,CreateDisposition参数设置成FILE_OVERWRITE_IF * 此时,无论文件是否存在,都会创建新文件 * 2、文件名是通过第三个参数ObjectAttributes * 这个参数是一个OBJECT_ATTRIBUTES结构体 * 通过InitializeObjectAttributes初始化 */
/************************************************************************ * 函数名称:InitializeObjectAttributes * 功能描述:初始化OBJECT_ATTRIBUTES结构体 * 参数列表: InitializedAttributes:返回的OBJECT_ATTRIBUTES结构体 ObjectName:对象名称,用UNICODE_STRING描述,这里设置的是文件名 Attributes:一般设置为OBJ_CASE_INSENSITIVE,对大小写敏感 RootDirectory:一般设置为NULL SecurityDescriptor:一般设置为NULL * 返回 值:相等的字节数 不一致返回零 *************************************************************************/ VOID InitializeObjectAttributes( OUT POBJECT_ATTRIBUTES InitializedAttributes, IN PUNICODE_STRING ObjectName, IN ULONG Attributes, IN HANDLE RootDirectory, IN PSECURITY_DESCRIPTOR SecurityDescriptor); /* *备注: * 1、文件名[必须]是符号链接或者是设备名 * 2、例如:盘符 "c:",就是一个符号链接 * 这里应该用 "\??\c:" 代替 * "c:\1.log" 要写成 "\??\c:\1.log" * 3、其中 "\??\c:" 是符号链接,内核会将它转换成设备名 "\Device\HarddiskColume1" */
(1)创建文件
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iostatus; HANDLE hfile; UNICODE_STRING logFileUnicodeString; //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.log"); //或者改写成 "\\Device\\HarddiskVolume1\\1.log" //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile, //打开文件的句柄 GENERIC_WRITE, //读,写 &objectAttributes, //OBJECT_ATTRIBUTES结构的地址 包含文件名 &iostatus, //接收ZwCreateFile操作的结果状态 NULL, //初始分配时的大小 FILE_ATTRIBUTE_NORMAL, //新创建文件的属性 FILE_SHARE_READ, //共享方式 FILE_OPEN_IF, //当指定文件存在或不存在时应如何处理 FILE_SYNCHRONOUS_IO_NONALERT, //指定控制打开操作和句柄使用的附加标志位 NULL, //指向可选的扩展属性区 0); //扩展属性区的长度 if( NT_SUCCESS(ntStatus) ) { KdPrint(("Create file successfully!\n")); } else { KdPrint(("Create file unsuccessfully!\n")); } //文件操作 //...... //关闭文件句柄 ZwClose(hfile);
(2)打开文件
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iostatus; HANDLE hfile; UNICODE_STRING logFileUnicodeString; //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.log"); //或者改写成 "\\Device\\HarddiskVolume1\\1.log" //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE, //对大小写敏感 NULL, NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile, //打开文件的句柄 GENERIC_READ, //读 &objectAttributes, //OBJECT_ATTRIBUTES结构的地址 包含文件名 &iostatus, //接收ZwCreateFile操作的结果状态 NULL, //初始分配时的大小 FILE_ATTRIBUTE_NORMAL, //新创建文件的属性 FILE_SHARE_READ, //共享方式 FILE_OPEN, //打开文件,如果不存在,则返回错误 FILE_SYNCHRONOUS_IO_NONALERT, //指定控制打开操作和句柄使用的附加标志位 NULL, //指向可选的扩展属性区 0); //扩展属性区的长度 if( NT_SUCCESS(ntStatus) ) { KdPrint(("Open file successfully!\n")); } else { KdPrint(("Open file unsuccessfully!\n")); } //文件操作 //...... //关闭文件句柄 ZwClose(hfile);
二:文件的打开
/************************************************************************ * 函数名称:ZwOpenFile * 功能描述:打开文件 * 参数列表: FileHandle:返回打开的文件句柄 DesiredAccess:打开的权限,一般设为GENERIC_ALL ObjectAttributes:objectAttributes结构 IoStatusBlock:指向一个结构体的指针。该结构体指明打开文件的状态 ShareAccess:共享的权限。可以是FILE_SHARE_READ或者FILE_SHARE_WRITE OpenOptions:打开选项,一般设为FILE_SYNCHRONOUS_IO_NONALERT * 返回 值:指明文件是否被成功打开 *************************************************************************/ NTSTATUS ZwOpenFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions);
如何使用ZwOpenFile打开文件
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iostatus; HANDLE hfile; UNICODE_STRING logFileUnicodeString; //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.log"); //或者写成 \\Device\\HarddiskVolume1\\1.log //初始化objectAttributes InitializeObjectAttributes( &objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); //创建文件 NTSTATUS ntStatus = ZwOpenFile(&hfile, GENERIC_ALL, &objectAttributes, &iostatus, FILE_SHARE_READ || FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); if( NT_SUCCESS(ntStatus) ) { KdPrint(("Create FILE successfully!\n")); } else { KdPrint(("Create FILE unsuccessfully!\n")); } //文件操作 //.......... //关闭文件句柄 ZwClose(hfile);
三:获取或修改文件属性
/************************************************************************ * 函数名称:ZwSetInformationFile * 功能描述:设置文件属性 * 参数列表: FileHandle:文件句柄 IoStatusBlock:返回设置的状态 FileInformation:依据FileInformationClass不同而不同。作为输入信息 Length:FileInformation数据的长度 FileInformationClass:描述修改属性的类型 * 返回 值:设置属性是否成功 *************************************************************************/ NTSTATUS ZwSetInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass);
/************************************************************************ * 函数名称:ZwQueryInformationFile * 功能描述:获取文件属性 * 参数列表: FileHandle:文件句柄 IoStatusBlock:返回设置的状态 FileInformation:依据FileInformationClass不同而不同。作为输出信息 Length:FileInformation数据的长度 FileInformationClass:描述修改属性的类型 * 返回 值:设置属性查询 *************************************************************************/ NTSTATUS ZwQueryInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass);
(1)当FileInformationClass是FileStandardInformation时,
输入和输出的数据时FILE_STANDARD_INFORMATION结构体,描述文件的基本信息
typedef struct FILE_STANDARD_INFORMATION( LARGE_INTEGER AllocationSize;//为文件分配的大小[注意:不是文件大小,而是占用蔟所需要的大小] LARGE_INTEGER EndOfFile; //距离文件结尾还有多少字节 ULONG NumberOfLinks; //有多少个链接文件 BOOLEAN DeletePending; //是否准备删除 BOOLEAN Directory; //是否为目录 )FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
(2)当FileInformationClass是FileBasicInformation时,
输入和输出的数据时FILE_BASIC_INFORMATION结构体,描述文件的基本信息
typedef struct FILE_BASIC_INFORMATION( LARGE_INTEGER CreationTime, //文件创建时间 LARGE_INTEGER LastAccessTime, //最后访问时间 LARGE_INTEGER LastWriteTime, //最后写时间 LARGE_INTEGER ChangeTime, //修改修改时间 ULONG FileAttributes; //文件属性 )FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; //其中,时间参数是从一个LARGE_INTEGER的整数,该整数代表从1601年经过多少个100ns(纳秒) //FileAttributes描述文件属性。 //FILE_ATTRIBUTE_NORMAL描述一般文件 //FILE_ATTRIBUTE_DIRECTORY描述是目录 //FILE_ATTRIBUTE_READONLY描述是只读 //FILE_ATTRIBUTE_SYSTEM代表系统文件
(3)当FileInformationClass是FileNameInformation时,
输入和输出的数据时FILE_NAME_INFORMATION结构体,描述文件的基本信息
typedef struct _FILE_NAME_INFORMATION( ULONG FileNameLength; //文件名长度 WCHAR Filename; //文件名 )FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; //注意:文件名的字符串是宽字符集字符串
(4)当FileInformationClass是FilePositionInformation时,
输入和输出的数据时FILE_POSITION_INFORMATION结构体,描述文件的基本信息
typedef struct FILE_POSITION_INFORMATION( LARGE_INTEGER CurrentByteOffset; //代表当前文件指针位置 )FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
使用ZwQueryInformationFile函数查询、修改文件属性
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iostatus; HANDLE hfile; UNICODE_STRING logFileUnicodeString; //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.log"); //或者写成 "\\Device\\HarddisVolume1\\1.log" //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE, //对大小写敏感 NULL, NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile, GENERIC_READ, &objectAttributes, &iostatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, //打开文件,如果不存在则返回错误 FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( NT_SUCCESS(ntStatus) ) { KdPrint(("Open FILE successFully!\n")); } else { KdPrint(("Open FILE unsuccessFully!\n")); } FILE_STANDARD_INFORMATION fsi; //读取文件长度 ntStatus = ZwQueryInformationFile(hfile, &iostatus, &fsi, sizeof(FILE_STANDARD_INFORMATION). FileStandardInformation); if( NT_SUCCESS(ntStatus) ) { KdPrint(("FILE length:%u\n", fsi.EndOfFile.QuadPart)); } //修改当前文件指针 FILE_POSITION_INFORMATION fpi; fpi.CurrentByteOffset.QuadPart = 100i64; ntStatus = ZwSetInformationFile(hfile, &iostatus, &fpi, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation); if( NT_SUCCESS(ntStatus) ) { KdPrint(("update the FILE pointer successfully.\n")); } //关闭文件句柄 ZwClose(hfile);
四:文件的写操作
/************************************************************************ * 函数名称:ZwWriteFile * 功能描述:文件的写操作 * 参数列表: FileHandle:文件打开的句柄 Event:很少用到,一般设为NULL ApcRoutine:很少用到,一般设为NULL ApcContext:很少用到,一般设为NULL IoStatusBlock:记录些操作的状态。其中,IoStatusBlock.Infomation记录实际写了多少字节 Buffer:从这个缓冲区开始往文件里写 Length:准备写多少字节 Byteoffset:从文件的多少便宜地址开始写 Key:很少用到,一般设为NULL * 返回 值: *************************************************************************/ NTSTATUS ZwWriteFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER Byteoffset OPTIONAL, IN PULONG Key OPTIONAL);
演示如何对文件进行写操作
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iostatus; HANDLE hfile; UNICODE_STRING logFileUnicodeString; //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.log"); //或者写成 "\\Device\\HarddiskVolume1\\1.LOG" //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile, GENERIC_WRITE, &objectAttributes, &iostatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OPEN_IF, //即使存在该文件, 也创建 FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( NT_SUCCESS(ntStatus) ) { KdPrint(("Create file successfully!\n")); } else { KdPrint(("Create file unsuccessfully!\n")); } #define BUFFER_SIZE 1024 PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE); //构造要填充的数据 RtlFillMemory(pBuffer, BUFFER_SIZE, 0xAA); KdPrint(("Thr program will write %d bytes\n", BUFFER_SIZE)); //写文件 NTSTATUS ntStatus = ZwWriteFile(hfile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, NULL, NULL); if( NT_SUCCESS(ntStatus) ) { KdPrint(("Write file successfully!\n")); } else { KdPrint(("Write file unsuccessfully!\n")); } //构造要填充的数据 RtlFillMemory(pBuffer, BUFFER_SIZE, 0xBB); KdPrint(("The program will append %d bytes\n", BUFFER_SIZE)); //追加数据 LARGE_INTEGER number; number.QuadPart = 1024i64; //设置文件指针 //对文件进行附加写 NTSTATUS ntStatus = ZwWriteFile(hfile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, &number, NULL); if( NT_SUCCESS(ntStatus) ) { KdPrint(("Write file successfully!\n")); } else { KdPrint(("Write file unsuccessfully!\n")); } KdPrint(("The program really appended %d bytes\n", iostatus.Information)); //关闭文件句柄 ZwClose(hfile); ExFreePool(pBuffer);
五:文件的读操作
/************************************************************************ * 函数名称:ZwReadFile * 功能描述:文件的读操作 * 参数列表: FileHandle:文件打开的句柄 Event:很少用到,一般设为NULL ApcRoutine:很少用到,一般设为NULL ApcContext:很少用到,一般设为NULL IoStatusBlock:记录些操作的状态。其中,IoStatusBlock.Infomation记录实际写了多少字节 Buffer:从这个缓冲区开始开始从文件里读 Length:准备读多少字节 Byteoffset:从文件的多少偏移地址开始读 Key:很少用到,一般设为NULL * 返回 值: *************************************************************************/ NTSTATUS ZwReadFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER Byteoffset OPTIONAL, IN PULONG Key OPTIONAL);
演示如何对文件进行读操作
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iostatus; HANDLE hfile; UNICODE_STRING logFileUnicodeString; //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.log"); //或者写成 "\\Device\\HarddiskVolume1\\1.LOG" //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile, GENERIC_WRITE, &objectAttributes, &iostatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS(ntStatus) ) { KdPrint(("The file is nor exist!\n")); return; } FILE_STANDARD_INFORMATION fsi; //读取文件长度 ntStatus = ZwQueryInformationFile(hfile, &iostatus, &fsi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); KdPrint(("Thr program want to read %d bytes\n", fsi.EndOfFile.QuadPart)); //为读取的文件分配缓冲区 PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, (LONG)fsi.EndOfFile.QuadPart); //读文件 NTSTATUS ntStatus = ZwReadFile(hfile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, (LONG)fsi.EndOfFile.QuadPart, NULL); if( NT_SUCCESS(ntStatus) ) { KdPrint(("Read file successfully!\n")); } else { KdPrint(("Read file unsuccessfully!\n")); } KdPrint(("The program really read %d bytes\n", iostatus.Information)); //关闭文件句柄 ZwClose(hfile); //释放缓冲区 ExFreePool(pBuffer);