免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
返回列表 发帖

内核模式下的文件操作

A、文件的创建
B、文件的打开
C、获取和修改文件属性
D、写文件和读文件
课时:19+12+13

一、文件的创建

InitializeObjectAttributes 初始化  POBJECT_ATTRIBUTES 结构
ZwCreateFile

二、文件的打开
   ZwCreateFile,ZwOpenFile
三、获取和修改文件属性
    ZwQueryInformationFile,ZwSetInformationFile
四、写文件和读文件
   ZwWriteFile,ZwReadFile

//#include <ntdef.h>
#pragma INITCODE
VOID CreateFileTest()
{
NTSTATUS ntStatus;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING  SymbolFileName;
  KdPrint(("\n-----------------创建文件测试  --------------------!\n"));
//初始化UNICODE_STRING字符串

   RtlInitUnicodeString(&SymbolFileName,L"\\Device\\HarddiskVolume1\\1.txt");
   //RtlInitUnicodeString( &SymbolFileName,  L"\\??\\C:\\1.txt");//可用此行替换上一行
//初始化objectAttributes
InitializeObjectAttributes(
         &objectAttributes, //指定一个需要OBJECT_ATTRIBUTES结构地址
         &SymbolFileName,//是一个UNICODE_STRING字串地址,指定需要操作对象名(在这里可以是符号链接名,或者设备名)
         OBJ_CASE_INSENSITIVE, //指定此值表示 不区分大小写。
         NULL,
         NULL );
//创建文件
ntStatus = ZwCreateFile(
  &hfile,
//PHANDLE类型指针 用于返回打开文件的句柄
  GENERIC_WRITE,
//ACCESS_MASK类型 此值用于描述打开文件操作(读,写,或者其它)
  &objectAttributes,
//此值是OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名 需要用InitializeObjectAttributes进行初始化
  &iostatus,
//指向一个IO_STATUS_BLOCK结构,返回值之一 用于存放ZwCreateFile操作的结果状态
  NULL,
  //PLARGE_INTEGER 类型(64位整数指针)该数指定文件初始分配时的大小。该参数如果为NULL,那么文件长度将从0开始,随着写入而增长
  FILE_ATTRIBUTE_NORMAL,
  //此参数在驱动下指定为0或者FILE_ATTRIBUTE_NORMAL,如果文件不是被创建和覆盖写入 则此参数将被忽略
  FILE_SHARE_READ,
  //指定共享模式 有共享读FILE_SHARE_READ,写FILE_SHARE_WRITE,删除FILE_SHARE_DELETE这几中模式
  FILE_OPEN_IF,
  //此值表示 文件存在则打开 不存在则创建一个新的文件 FILE_OPEN ZwOpenFile
  FILE_SYNCHRONOUS_IO_NONALERT,
  //指定文件创建或者打开的附加标志 FILE_SYNCHRONOUS_IO_NONALERT表示在文件中的所有操作均同步,并没有警报
  NULL,
  //对于设备和中间驱动程序,此参数必须是NULL
  0 );  
//对于设备和中间驱动程序,此参数必须是0
if ( NT_SUCCESS(ntStatus))
{
  KdPrint(("创建文件成功!\n"));
}else
{
  KdPrint(("创建文件失败!\n"));
}

//文件操作
//.......

//关闭文件句柄
ZwClose(hfile);

}

#pragma INITCODE
VOID OpenFileTest1()
{
        KdPrint(("\n-----------------打开文件测试 ZwCreateFile---------------------!\n"));

OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING SymbolFileName;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString( &SymbolFileName, L"\\Device\\HarddiskVolume1\\1.txt");
//RtlInitUnicodeString( &SymbolFileName,  L"\\??\\C:\\1.txt");

//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
  &SymbolFileName,
  OBJ_CASE_INSENSITIVE,//对大小写敏感
  NULL,
  NULL );

//创建文件
NTSTATUS ntStatus = ZwCreateFile( &hfile,
  GENERIC_READ,
  &objectAttributes,
  &iostatus,
  NULL,
  FILE_ATTRIBUTE_NORMAL,
  FILE_SHARE_WRITE,
  FILE_OPEN,//对文件打开,如果不存在则返回错误
  FILE_SYNCHRONOUS_IO_NONALERT,
  NULL,
  0 );
if ( NT_SUCCESS(ntStatus))
{
  KdPrint(("打开文件测试 ZwCreateFile 成功!\n"));
}else
{
  KdPrint(("打开文件测试 ZwCreateFile 失败!\n"));
}

//文件操作
//.......

//关闭文件句柄
ZwClose(hfile);
}



#pragma INITCODE
VOID OpenFileTest2()
{
        KdPrint(("\n-----------------打开文件测试2 ZwOpenFile---------------------!\n"));

OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING SymbolFileName;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString( &SymbolFileName, L"\\Device\\HarddiskVolume1\\1.txt");
//RtlInitUnicodeString( &SymbolFileName,  L"\\??\\C:\\1.txt");


//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
  &SymbolFileName,
  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(("用ZwOpenFile 打开文件成功!\n"));
}else
{
  KdPrint((" 用ZwOpenFile 打开文件失败!\n"));
}

//文件操作
//.......

//关闭文件句柄
ZwClose(hfile);
}




#pragma INITCODE
VOID FileAttributeTest()
{
        KdPrint(("\n-----------------ZwQueryInformationFile  ZwSetInformationFile 测试 ---------------------!\n"));

OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING SymbolFileName;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString( &SymbolFileName, L"\\Device\\HarddiskVolume1\\1.txt");
//RtlInitUnicodeString( &SymbolFileName,  L"\\??\\C:\\1.txt");

//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
  &SymbolFileName,
  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(("打开文件成功.\n"));
}

FILE_STANDARD_INFORMATION fsi;
//读取文件长度
ntStatus = ZwQueryInformationFile(hfile,
  &iostatus,
  &fsi,
  sizeof(FILE_STANDARD_INFORMATION),
  FileStandardInformation);
if (NT_SUCCESS(ntStatus))
{
  KdPrint(("文件长度 :%u\n",fsi.EndOfFile.QuadPart));
}

//修改文件属性
FILE_BASIC_INFORMATION fbi;

ntStatus = ZwQueryInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION),
                FileBasicInformation);

fbi.FileAttributes=FILE_ATTRIBUTE_READONLY;//FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_NORMAL
ntStatus = ZwSetInformationFile(hfile,
  &iostatus,
  &fbi,
  sizeof(_FILE_BASIC_INFORMATION),
  FileBasicInformation);
if (NT_SUCCESS(ntStatus))
{
  KdPrint(("设置文件 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; 属性成功.\n"));
}

//关闭文件句柄
ZwClose(hfile);
}


#pragma INITCODE
VOID WriteFileTest()
{
KdPrint(("\n---------------------ZwWriteFile写文件测试--------------------\n"));
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING SymbolFileName;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString( &SymbolFileName, L"\\Device\\HarddiskVolume1\\1.txt");
//RtlInitUnicodeString( &SymbolFileName,  L"\\??\\C:\\1.txt");

//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
  &SymbolFileName,
  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 );
#define BUFFER_SIZE 30
PCHAR pBuffer = (PCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);
//构造要填充的数据
RtlFillMemory(pBuffer,BUFFER_SIZE,'s');//www.yjxsoft.comsssssssss..
strcpy(pBuffer,"www.yjxsoft.com ");

KdPrint(("即将写入 %d 字节\n",BUFFER_SIZE));
//写文件ZwQueryInfomationfile
LARGE_INTEGER sl;
sl.QuadPart=0i64;
ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,30,&sl,NULL);
KdPrint(("成功写入 %d 字节\n",iostatus.Information));


//构造要填充的数据
RtlFillMemory(pBuffer,BUFFER_SIZE,'3');

KdPrint(("成功写入 %d 字节\n",BUFFER_SIZE));
//追加数据
LARGE_INTEGER number;
number.QuadPart =30i64;//设置文件指针
//对文件进行附加写
ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,BUFFER_SIZE,&number,NULL);
KdPrint(("追加写入 %d 字节\n",iostatus.Information));

//关闭文件句柄
ZwClose(hfile);

ExFreePool(pBuffer);
}

#pragma INITCODE
VOID ReadFileTest()
{
KdPrint(("\n---------------------ZwReadFile写文件测试--------------------\n"));

OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING SymbolFileName;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString( &SymbolFileName, L"\\Device\\HarddiskVolume1\\1.txt");
//RtlInitUnicodeString( &SymbolFileName,  L"\\??\\C:\\1.txt");

//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
  &SymbolFileName,
  OBJ_CASE_INSENSITIVE,//对大小写敏感
  NULL,
  NULL );

//创建文件
NTSTATUS ntStatus = ZwCreateFile( &hfile,
  GENERIC_READ,
  &objectAttributes,
  &iostatus,
  NULL,
  FILE_ATTRIBUTE_NORMAL, //常规属性
  FILE_SHARE_READ,//共享读
  FILE_OPEN,//即使存在该文件,也创建
  FILE_SYNCHRONOUS_IO_NONALERT,
  NULL,
  0 );

if (!NT_SUCCESS(ntStatus))
{
  KdPrint(("文件不存在!\n"));
  return;
}

FILE_STANDARD_INFORMATION fsi;
//读取文件长度
ntStatus = ZwQueryInformationFile(hfile,
  &iostatus,
  &fsi,
  sizeof(FILE_STANDARD_INFORMATION),
  FileStandardInformation);

KdPrint(("共读取 %d 字节\n",fsi.EndOfFile.QuadPart));

//为读取的文件分配缓冲区
PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,
  (LONG)fsi.EndOfFile.QuadPart);

//读取文件
ZwReadFile(hfile,NULL,
  NULL,NULL,
  &iostatus,
  pBuffer,
  (LONG)fsi.EndOfFile.QuadPart,
  NULL,NULL);
KdPrint(("实际读取 %d 字节\n",iostatus.Information));
//显示实际读取内容
KdPrint(("读取内容为:%s \n",pBuffer));
//关闭文件句柄
ZwClose(hfile);

//释放缓冲区
ExFreePool(pBuffer);
}



#pragma INITCODE
VOID FileTestAll()
{
//创建文件实验
//打开文件实验
//设置文件属性
//写文件、读文件实验


}

=======================================

笔记: 分三部分
A:
中级篇的最后一课了,先讲一下创建文件ZwCreateFile,具体函数在教案中有详细说明,重要的参数已经标记红色了.其中FILE_OPEN_IF是打开或创建FILE_OPEN只打开不创建,创建成功后需要关闭掉句柄.然后在虚拟机里测试一下,创建出了CreateFileTest.txt文件.再测试一下文件的打开 ,将上面代码复制一下,把FILE_OPEN_IF改成FILE_OPEN,测试成功.再用一下ZwOpenFile函数,其中前四项相同,后面省略了几项,再次测试也成功.

B:
NTSTATUS ZwQueryInformationFile(        //获取文件信息函数
  __in   HANDLE FileHandle,                                                //获取的文件句柄
  __out  PIO_STATUS_BLOCK IoStatusBlock,        //状态返回结构
  __out  PVOID FileInformation,                                        //文件信息(属性)
  __in   ULONG Length,                                                        //文件大小
  __in   FILE_INFORMATION_CLASS FileInformationClass        //获取参数类型
);

NTSTATUS ZwSetInformationFile(        //设置文件属性函数.各种参数与上面相同
  __in   HANDLE FileHandle,
  __out  PIO_STATUS_BLOCK IoStatusBlock,
  __in   PVOID FileInformation,
  __in   ULONG Length,
  __in   FILE_INFORMATION_CLASS FileInformationClass
);

必须要先获取文件信息然后才能设置文件属性,否则会提示错误

C:
NTSTATUS ZwWriteFile(                //写文件
  __in      HANDLE FileHandle,                                        //需要操作的句柄
  __in_opt  HANDLE Event,                                                //一般用不到
  __in_opt  PIO_APC_ROUTINE ApcRoutine,        //一般用不到
  __in_opt  PVOID ApcContext,                                        //一般用不到
  __out     PIO_STATUS_BLOCK IoStatusBlock,//保存返回状态值结构
  __in      PVOID Buffer,                                                        //缓冲区
  __in      ULONG Length,                                                //要写入长度
  __in_opt  PLARGE_INTEGER ByteOffset,                //64位整数,联合类型结构,也就是文件的起始地址
  __in_opt  PULONG Key                                                        //一般用不到
);

老师写在1.TXT下写入了一串字符,然后再读取出来.

NTSTATUS ZwReadFile(                //读文件        参数同上面
  __in      HANDLE FileHandle,
  __in_opt  HANDLE Event,
  __in_opt  PIO_APC_ROUTINE ApcRoutine,
  __in_opt  PVOID ApcContext,
  __out     PIO_STATUS_BLOCK IoStatusBlock,
  __out     PVOID Buffer,
  __in      ULONG Length,
  __in_opt  PLARGE_INTEGER ByteOffset,
  __in_opt  PULONG Key
);

前面60个字节读取出来了,当我们更改文件内容后却读出了乱码.我们的ZwClose要加上,否则被读取的文件就不能够被删除了.

随记:
老师写的代码很详细,但是我一下也看不懂,今后用到时再说吧.另外我发现老师是英文真是好啊,因为我在搜索函数时都没找到没有中文帮助,所以我想有可能是老师亲自翻译的.认真的学习了前面章节后,终于要向高级班迈进了,都是些激动人心的内容啊.

返回列表