发IRP强制删除文件
作者:admin 日期:2011-02-16
学习了下,顺便加点注释。这个程序比较简单,主要练习了两个点:
(1)模拟发送IRP
(2)使用内核事件对象同步IRP的执行
强制删除文件的思路很简单,把SECTION_OBJECT_POINTERS结构的DataSectionObject和ImageSectionObject两个域清空即可删除正在运行的文件。如果不清空就不能删除运行中的文件。正在运行的文件的这两个域值不为0而文件系统正在根据这两个域决定该文件是否可以删除。如果文件系统检测这两个值为0,就理解为文件没有被使用,可以删除。接下去,就是直接发IRP。
测试时,在C盘目录下放一个test.exe并执行,然后加载驱动即可。
强制删除文件功能在ForceDeleteFile中实现,DriverEntry中只需要简单调用即可。具体实现如下
view plaincopy to clipboardprint?
01.NTSTATUS DriverEntry(
02. IN OUT PDRIVER_OBJECT DriverObject,
03. IN PUNICODE_STRING RegistryPath
04. )
05.{
06. // 其他初始化代码
07. // ……
08.
09. DbgPrint ( "Delete File %s", ForceDeleteFile(L"\\DosDevices\\C:\\test.exe") ? "Success!" : "Failed!" ) ;
10. return STATUS_SUCCESS;
11.}
12.
13.NTSTATUS FD_SetFileCompletion(
14. IN PDEVICE_OBJECT DeviceObject,
15. IN PIRP Irp,
16. IN PVOID Context
17. )
18.{
19. Irp->UserIosb->Status = Irp->IoStatus.Status;
20. Irp->UserIosb->Information = Irp->IoStatus.Information;
21.
22. KeSetEvent ( Irp->UserEvent, IO_NO_INCREMENT, FALSE ) ;
23.
24. IoFreeIrp(Irp);
25. return STATUS_MORE_PROCESSING_REQUIRED;
26.}
27.
28.HANDLE FD_OpenFile ( WCHAR szFileName[] )
29.{
30. NTSTATUS ntStatus ;
31. UNICODE_STRING FileName ;
32. OBJECT_ATTRIBUTES objectAttributes;
33. HANDLE hFile ;
34. IO_STATUS_BLOCK ioStatus ;
35.
36. // 确保IRQL在PASSIVE_LEVEL上
37. if (KeGetCurrentIrql() > PASSIVE_LEVEL)
38. return NULL;
39.
40. // 初始化文件名
41. RtlInitUnicodeString ( &FileName, szFileName ) ;
42. DbgPrint ( "%ws", FileName.Buffer ) ;
43.
44. //初始化对象属性
45. InitializeObjectAttributes ( &objectAttributes, &FileName,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE, NULL, NULL ) ;
46.
47. // 打开文件
48. ntStatus = IoCreateFile ( &hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatus, \
49. 0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_Delete,FILE_OPEN,0,NULL,0,CreateFileTypeNone,NULL,IO_NO_PARAMETER_CHECKING);
50. if ( !NT_SUCCESS(ntStatus) )
51. return NULL ;
52.
53. return hFile ;
54.}
55.
56.BOOLEAN FD_StripFileAttributes ( HANDLE FileHandle )
57.{
58. NTSTATUS ntStatus = STATUS_SUCCESS;
59. PFILE_OBJECT fileObject;
60. PDEVICE_OBJECT DeviceObject;
61. PIRP Irp;
62. KEVENT SycEvent;
63. FILE_BASIC_INFORMATION FileInformation;
64. IO_STATUS_BLOCK ioStatus;
65. PIO_STACK_LOCATION irpSp;
66.
67. // 获取文件对象
68. ntStatus = ObReferenceObjectByHandle ( FileHandle, Delete,
69. *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;
70. if ( !NT_SUCCESS(ntStatus) )
71. {
72. DbgPrint ( "ObReferenceObjectByHandle error!" ) ;
73. return FALSE;
74. }
75.
76. // 获取与指定文件对象相关联的设备对象
77. DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;
78.
79. // 创建IRP
80. Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;
81. if ( Irp == NULL )
82. {
83. ObDereferenceObject(fileObject);
84.
85. DbgPrint ( "FD_StripFileAttributes IoAllocateIrp error" ) ;
86. return FALSE;
87. }
88.
89. // 初始化同步事件对象
90. KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;
91.
92. memset ( &FileInformation, 0, 0x28 ) ;
93. FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
94.
95. // 初始化IRP
96. Irp->AssociatedIrp.SystemBuffer = &FileInformation;
97. Irp->UserEvent = &SycEvent;
98. Irp->UserIosb = &ioStatus;
99. Irp->Tail.Overlay.OriginalFileObject = fileObject;
100. Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
101. Irp->RequestorMode = KernelMode;
102.
103. // 设置IRP堆栈信息
104. irpSp = IoGetNextIrpStackLocation(Irp);
105. irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
106. irpSp->DeviceObject = DeviceObject;
107. irpSp->FileObject = fileObject;
108. irpSp->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION) ;
109. irpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
110. irpSp->Parameters.SetFile.FileObject = fileObject ;
111.
112. // 设置完成例程
113. IoSetCompletionRoutine ( Irp, FD_SetFileCompletion ,NULL, TRUE, TRUE, TRUE ) ;
114.
115. // 派发IRP
116. IoCallDriver(DeviceObject, Irp);
117.
118. // 等待IRP的完成
119. KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL ) ;
120.
121. // 递减引用计数
122. ObDereferenceObject(fileObject);
123.
124. return TRUE ;
125.}
126.
127.BOOLEAN FD_DeleteFile ( HANDLE FileHandle )
128.{
129. NTSTATUS ntStatus = STATUS_SUCCESS;
130. PFILE_OBJECT fileObject;
131. PDEVICE_OBJECT DeviceObject;
132. PIRP Irp;
133. KEVENT SycEvent ;
134. FILE_DISPOSITION_INFORMATION FileInformation;
135. IO_STATUS_BLOCK ioStatus;
136. PIO_STACK_LOCATION irpSp;
137. PSECTION_OBJECT_POINTERS pSectionObjectPointer;
138.
139. // 获取文件对象
140. ntStatus = ObReferenceObjectByHandle ( FileHandle, Delete,
141. *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;
142. if ( !NT_SUCCESS(ntStatus) )
143. {
144. DbgPrint ( "ObReferenceObjectByHandle error!" ) ;
145. return FALSE;
146. }
147.
148. // 获取与指定文件对象相关联的设备对象
149. DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;
150.
151. // 创建IRP
152. Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;
153. if (Irp == NULL)
154. {
155. ObDereferenceObject ( fileObject ) ;
156. DbgPrint ( "FD_DeleteFile IoAllocateIrp error" ) ;
157. return FALSE;
158. }
159.
160. // 初始化同步事件对象
161. KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;
162.
163. FileInformation.DeleteFile = TRUE;
164.
165. // 初始化IRP
166. Irp->AssociatedIrp.SystemBuffer = &FileInformation;
167. Irp->UserEvent = &SycEvent;
168. Irp->UserIosb = &ioStatus;
169. Irp->Tail.Overlay.OriginalFileObject = fileObject;
170. Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
171. Irp->RequestorMode = KernelMode;
172.
173. // 设置IRP堆栈
174. irpSp = IoGetNextIrpStackLocation(Irp);
175. irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
176. irpSp->DeviceObject = DeviceObject;
177. irpSp->FileObject = fileObject;
178. irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
179. irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
180. irpSp->Parameters.SetFile.FileObject = fileObject;
181.
182. // 设置完成例程
183. IoSetCompletionRoutine ( Irp, FD_SetFileCompletion, NULL, TRUE, TRUE, TRUE ) ;
184.
185. // 如果没有这3行,就无法删除正在运行的文件
186. pSectionObjectPointer = fileObject->SectionObjectPointer;
187. pSectionObjectPointer->ImageSectionObject = 0;
188. pSectionObjectPointer->DataSectionObject = 0;
189.
190. // 派发IRP
191. IoCallDriver ( DeviceObject, Irp ) ;
192.
193. // 等待IRP完成
194. KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL);
195.
196. // 递减引用计数
197. ObDereferenceObject ( fileObject ) ;
198.
199. return TRUE ;
200.}
201.
202.BOOLEAN ForceDeleteFile ( WCHAR szFileName[] )
203.{
204. HANDLE hFile = NULL ;
205. BOOLEAN status = FALSE ;
206.
207. __try {
208. // 打开文件
209. if ( ( hFile = FD_OpenFile( szFileName ) ) == NULL )
210. {
211. DbgPrint ( "FD_OpenFile error!" ) ;
212. return FALSE ;
213. }
214.
215. // //去掉只读属性,才能删除只读文件
216. if ( FD_StripFileAttributes(hFile) == FALSE )
217. {
218. ZwClose ( hFile ) ;
219. DbgPrint ( "FD_StripFileAttributes error!" ) ;
220. return FALSE ;
221. }
222.
223. // 删除文件
224. status = FD_DeleteFile(hFile) ;
225. ZwClose ( hFile ) ;
226.
227. return status ;
228.
229. } __except ( 1 ) {
230. DbgPrint ( "execption!" ) ;
231. }
232.
233. return FALSE ;
234.}