梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作

代码部分:

实现一个文件C:\\text.txt,并读取写入内容到文件,然后将文件设置为只读,并隐藏文件。代码如下:

  1 //MyCreateFile.c
  2 //2016.07.22
  3 #include <ntddk.h>
  4 
  5 NTSTATUS MyCreateFile()
  6 {
  7     HANDLE hFile;
  8 
  9     NTSTATUS Status = STATUS_SUCCESS;
 10 
 11     UNICODE_STRING usFileName;
 12     OBJECT_ATTRIBUTES FileObjAttr;
 13     IO_STATUS_BLOCK IoStatusBlock;
 14 
 15 
 16     memset (&FileObjAttr, 0, sizeof(OBJECT_ATTRIBUTES));
 17 
 18     RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
 19     InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);    //OBJ_CASE_INSENSITIVE 大小写不敏感
 20 
 21     Status = ZwCreateFile (&hFile,
 22         GENERIC_ALL,
 23         &FileObjAttr,
 24         &IoStatusBlock,
 25         NULL,
 26         FILE_ATTRIBUTE_NORMAL,
 27         FILE_SHARE_READ,            
 28         FILE_OPEN_IF,                //如果没有文件,创建文件。如果有文件,直接打开
 29         FILE_NON_DIRECTORY_FILE,    //不是目录
 30         NULL,
 31         0);
 32     if (!NT_SUCCESS(Status))
 33     {
 34         return Status;
 35     }
 36 
 37     KdPrint(("Create File Success!"));
 38 
 39     ZwClose (hFile);
 40 
 41     return Status;
 42 }
 43 
 44 NTSTATUS MyOpenFile()
 45 {
 46     HANDLE hFile;
 47 
 48     UNICODE_STRING usFileName;
 49     NTSTATUS Status = STATUS_SUCCESS;
 50     OBJECT_ATTRIBUTES FileObjAttr;
 51     IO_STATUS_BLOCK IoStatusBlock;
 52 
 53     RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
 54     memset (&FileObjAttr, 0, sizeof(OBJECT_ATTRIBUTES));
 55 
 56     InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
 57 
 58     Status = ZwOpenFile(&hFile, 
 59         GENERIC_ALL,
 60         &FileObjAttr,
 61         &IoStatusBlock,
 62         FILE_SHARE_READ,
 63         FILE_NON_DIRECTORY_FILE);
 64     if (!NT_SUCCESS(Status))
 65     {
 66         KdPrint(("Open File Failed:0x%X", Status));
 67         return Status;
 68     }
 69 
 70     KdPrint(("Open File Success!"));
 71 
 72     ZwClose(hFile);
 73 
 74     return Status;
 75 }
 76 
 77 NTSTATUS MyZwSetInfomationFile()
 78 {
 79     HANDLE hFile;
 80 
 81     UNICODE_STRING usFileName;
 82     NTSTATUS Status = STATUS_SUCCESS;
 83     OBJECT_ATTRIBUTES FileObjAttr;
 84     IO_STATUS_BLOCK IoStatusBlock;
 85     FILE_BASIC_INFORMATION fbi;
 86 
 87 
 88     RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
 89     memset (&FileObjAttr, 0, sizeof(OBJECT_ATTRIBUTES));
 90 
 91     InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
 92 
 93     Status = ZwOpenFile(&hFile, 
 94         GENERIC_ALL,
 95         &FileObjAttr,
 96         &IoStatusBlock,
 97         FILE_SHARE_READ,
 98         FILE_NON_DIRECTORY_FILE);
 99     if (!NT_SUCCESS(Status))
100     {
101         KdPrint(("Open File Failed:0x%X", Status));
102         return Status;
103     }
104 
105     KdPrint(("Open File Success!"));
106 
107     Status = ZwQueryInformationFile (hFile, &IoStatusBlock, &fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);    //查看FileBasicInformation
108     if (!NT_SUCCESS(Status))
109     {
110         KdPrint(("Query Information Error code: %X", Status));
111         ZwClose (hFile);
112         return Status;
113     }
114 
115     KdPrint(("CreationTime:0x%X    Attributes:0x%X", fbi.CreationTime, fbi.FileAttributes));
116     fbi.FileAttributes |= FILE_ATTRIBUTE_HIDDEN;    //隐藏文件
117     fbi.FileAttributes |= FILE_ATTRIBUTE_READONLY;    //只读属性
118 
119 
120     Status = ZwSetInformationFile (hFile, &IoStatusBlock, &fbi, sizeof(FILE_BASIC_INFORMATION),    FileBasicInformation);
121     if (!NT_SUCCESS(Status))
122     {
123         KdPrint(("Set Information Error:0x%X", Status));
124         ZwClose(hFile);
125         return Status;
126     }
127 
128     ZwClose(hFile);
129 
130     return Status;
131 }
132 
133 NTSTATUS MyReadFile()
134 {
135     HANDLE hFile;
136 
137     UNICODE_STRING usFileName;
138     NTSTATUS Status = STATUS_SUCCESS;
139     OBJECT_ATTRIBUTES FileObjAttr;
140     IO_STATUS_BLOCK IoStatusBlock;
141     LARGE_INTEGER ReadBuffer;
142 
143     char strBuffer[100] = {0};
144 
145     RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
146     memset (&FileObjAttr, 0, sizeof(OBJECT_ATTRIBUTES));
147 
148     InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
149 
150     Status = ZwOpenFile(&hFile, 
151         GENERIC_ALL,
152         &FileObjAttr,
153         &IoStatusBlock,
154         FILE_SHARE_READ,
155         FILE_NON_DIRECTORY_FILE);
156     if (!NT_SUCCESS(Status))
157     {
158         KdPrint(("Open File Failed:0x%X", Status));
159         return Status;
160     }
161 
162     KdPrint(("Open File Success!"));
163     ReadBuffer.QuadPart = 0;
164 
165     Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)strBuffer, 16, &ReadBuffer, NULL);    //从文件的0位置读取16个字节到strBuffer
166     if (!NT_SUCCESS(Status))
167     {
168         KdPrint(("ReadFile Failed, Error Code:0x%X", Status));
169         ZwClose(hFile);
170         return Status;
171     }
172     
173     KdPrint(("strBuffer:<%s>", strBuffer));
174 
175     
176     ZwClose(hFile);
177     return Status;
178 }
179 
180 NTSTATUS MyWriteFile()
181 {
182     HANDLE hFile;
183 
184     UNICODE_STRING usFileName;
185     NTSTATUS Status = STATUS_SUCCESS;
186     OBJECT_ATTRIBUTES FileObjAttr;
187     IO_STATUS_BLOCK IoStatusBlock;
188     LARGE_INTEGER WriteBuffer;
189 
190      char strBuffer[100] = "ahuakndkaj.;'?";
191 
192     RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
193     memset (&FileObjAttr, 0, sizeof(OBJECT_ATTRIBUTES));
194 
195     InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
196 
197     Status = ZwOpenFile(&hFile, 
198         GENERIC_ALL,
199         &FileObjAttr,
200         &IoStatusBlock,
201         FILE_SHARE_READ,
202         FILE_NON_DIRECTORY_FILE);
203     if (!NT_SUCCESS(Status))
204     {
205         KdPrint(("Open File Failed:0x%X", Status));
206         return Status;
207     }
208 
209     KdPrint(("Open File Success!"));
210     
211     WriteBuffer.QuadPart = 0;
212 
213     Status = ZwWriteFile(hFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)strBuffer, 16, &WriteBuffer, NULL);    //将strBuffer中的前16个字节写入文件,从文件的0位置开始写
214     if (!NT_SUCCESS(Status))
215     {
216         KdPrint(("WriteFile Failed, Error Code:0x%X", Status));
217         ZwClose(hFile);
218         return Status;
219     }
220     
221     ZwClose(hFile);
222     return Status;
223 }
224 
225 VOID MyUnload(PDRIVER_OBJECT pDriverObject)
226 {
227     KdPrint(("Unload MyCreateFile.sys Success"));
228 }
229 
230 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
231 {
232     pDriverObject->DriverUnload = MyUnload;
233 
234     MyOpenFile();
235     MyCreateFile();
236     MyOpenFile();
237 
238      MyReadFile();
239     MyWriteFile();
240      MyReadFile();
241     
242     MyZwSetInfomationFile();
243 
244     return STATUS_SUCCESS;
245 }
MyCreateFile.c

 

 

文件的操作函数有:

ZwCreateFile            //创建文件或者打开文件
ZwOpenFile             //打开文件
ZwQueryInformationFile    //查看文件信息
ZwSetInformationFile      //设置文件信息
ZwReadFile           //读取文件
ZwWriteFile          //写入文件

 

 

创建或打开文件ZwCreateFile

 1 NTSTATUS ZwCreateFile(
 2   _Out_    PHANDLE            FileHandle,              //文件句柄
 3   _In_     ACCESS_MASK        DesiredAccess,           //访问权限,一般为GENERIC_ALL,即所有权限
 4   _In_     POBJECT_ATTRIBUTES ObjectAttributes,          //文件对象的属性,需要用InitializeObjectAttributes来初始化
 5   _Out_    PIO_STATUS_BLOCK   IoStatusBlock,           //用于接收返回信息
 6   _In_opt_ PLARGE_INTEGER     AllocationSize,         
7
_In_ ULONG FileAttributes,   //FILE_ATTRIBUTE_NORMAL 8 _In_ ULONG ShareAccess,   //FILE_SHARE_READ 9 _In_ ULONG CreateDisposition,    //FILE_OPEN_IF 如果没有文件,创建文件。如果有文件,直接打开 10 _In_ ULONG CreateOptions,    //FILE_NON_DIRECTORY_FILE 不是目录 11 _In_opt_ PVOID EaBuffer, //NULL 12 _In_ ULONG EaLength   //0 13 );

 

其中的第三个参数ObjectAttributes需要使用函数InitializeObjectAttributes来初始化,函数参数:

1 VOID InitializeObjectAttributes(
2   [out]          POBJECT_ATTRIBUTES   InitializedAttributes,      //文件对象指针
3   [in]           PUNICODE_STRING      ObjectName,                  //文件路径及名称
4   [in]           ULONG                Attributes,                  //flag,一般是OBJ_CASE_INSENSITIVE(大小写不敏感)
5   [in]           HANDLE               RootDirectory,              //根目录,如果ObjectName是绝对路径的话,那么根目录就是NULL
6   [in, optional] PSECURITY_DESCRIPTOR SecurityDescriptor          //默认为NULL
7 );

 

 

打开文件函数ZwOpenFile:

1 NTSTATUS ZwOpenFile(
2   _Out_ PHANDLE            FileHandle,
3   _In_  ACCESS_MASK        DesiredAccess,
4   _In_  POBJECT_ATTRIBUTES ObjectAttributes,
5   _Out_ PIO_STATUS_BLOCK   IoStatusBlock,
6   _In_  ULONG              ShareAccess,
7   _In_  ULONG              OpenOptions        //和ZwCreateFile的CreateOptions参数相同. FILE_NON_DIRECTORY_FILE 不是目录
8 );

 

 

获取文件属性函数ZwQueryInformationFile:

1 NTSTATUS ZwQueryInformationFile(
2   _In_  HANDLE                 FileHandle,
3   _Out_ PIO_STATUS_BLOCK       IoStatusBlock,
4   _Out_ PVOID                  FileInformation,            //接收文件相应FileInformationClass信息的结构
5   _In_  ULONG                  Length,                     //FileInformation的大小
6   _In_  FILE_INFORMATION_CLASS FileInformationClass        //指定获取文件什么信息(FileInformation)的枚举值
7 );

 

 

设置文件属性函数ZwSetInformationFile

1 NTSTATUS ZwSetInformationFile(
2   _In_  HANDLE                 FileHandle,
3   _Out_ PIO_STATUS_BLOCK       IoStatusBlock,
4   _In_  PVOID                  FileInformation,
5   _In_  ULONG                  Length,
6   _In_  FILE_INFORMATION_CLASS FileInformationClass
7 );

 

 

读取文件函数ZwReadFile:

 1 NTSTATUS ZwReadFile(
 2   _In_     HANDLE           FileHandle,
 3   _In_opt_ HANDLE           Event,                
 4   _In_opt_ PIO_APC_ROUTINE  ApcRoutine,            
 5   _In_opt_ PVOID            ApcContext,            
 6   _Out_    PIO_STATUS_BLOCK IoStatusBlock,
 7   _Out_    PVOID            Buffer,                //保存读取到的
 8   _In_     ULONG            Length,                //从文件读取多少个字节
 9   _In_opt_ PLARGE_INTEGER   ByteOffset,            //从文件的哪个位置开始读取,传入一个LARGE_INTEGER的指针
10   _In_opt_ PULONG           Key                    //NULL
11 );

 

 

写入文件函数ZwWriteFile

 1 NTSTATUS ZwWriteFile(
 2   _In_     HANDLE           FileHandle,
 3   _In_opt_ HANDLE           Event,
 4   _In_opt_ PIO_APC_ROUTINE  ApcRoutine,
 5   _In_opt_ PVOID            ApcContext,
 6   _Out_    PIO_STATUS_BLOCK IoStatusBlock,
 7   _In_     PVOID            Buffer,
 8   _In_     ULONG            Length,
 9   _In_opt_ PLARGE_INTEGER   ByteOffset,
10   _In_opt_ PULONG           Key
11 );

 

 

 

有些地方可能现在还不太清楚,以后再回来补吧。

 

操作部分:

启动并按章MyCreateFile.sys驱动后,C盘生成了test.txt的文件

 

这个文件是只读的,并且是隐藏的:

 

test.txt文件中写着“ahuakndkaj.;'?  "

 

DbgView输出:

 

 

0. 没有相应文件时,MyOpenFile里 ZwOpenFile打开文件失败

1. MyCreateFile里 ZwCreateFile创建文件成功

2. MyOpenFile里 ZwOpenFile打开文件成功

3. MyReadFile里 ZwOpenFile打开文件成功

4. MyReadFile里 ZwReadFile读取文件失败 这时文件中还没有数据

5. MyWriteFile里 ZwOpenFile打开文件成功 没输出错误 说明ZwWriteFile也成功了

6. MyReadFile里 ZwReadFile读取文件成功

7. MyReadFile里 读取到了数据

8. MyZwQueryInfomationFile里 打开文件成功

9. 获取文件属性成功 没输出错误 说明MyZwSetInfomationFile也成功了

10. 驱动卸载成功