发IRP强制删除文件

学习了下,顺便加点注释。这个程序比较简单,主要练习了两个点:
(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.} 



文章来自: 转载
Tags:
评论: 0 | 查看次数: 11271