WindowsAPI编程核心技术-强制性功能

强制结束进程

基本原理

用未导出函数PspTerminateThreadByPointer结束一个进程的所有线程,这个进程也随之消亡了。该函数声明:

1
2
3
4
5
NTSTATUS PspTerminateThreadByPointer(
PETHREAD pEThread,
NTSTATUS ntExitCode,
BOOLEAN bDirectTerminate
)

但要注意函数指针的声明的调用约定:

1
2
3
4
5
6
7
#ifdef _WIN64
// 64 位
typedef NTSTATUS(__fastcall *PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
#else
// 32 位
typedef NTSTATUS(*PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
#endif

通过导出函数PsTerminateSystemThread获取PspTerminateThreadByPointer未导出函数地址:

1
2
3
4
5
6
7
8
9
nt!PsTerminateSystemThread:
8B D1 mov edx, ecx
65 48 8B 0C 25 88 01 00 00 mov rcx, qword ptr gs:[188h]
F7 41 74 00 08 00 00 test dword ptr[rcx+74h], 800h
74 08 je nt!PsTerminateSystemThread+0x1C
41 B0 01 mov r8b, 1
E9 78 D9 FC FF jmp nt!PspTerminateThreadByPointer
B8 0D 00 00 C0 mov eax, 0C000000Dh
C3 ret

总结特征码:

Windows 7 Windows 8.1 Windows 10
x86 E8 E8 E8
x64 E8 E9 E9

获取PspTerminateThreadByPointer函数地址具体实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 根据特征码获取 PspTerminateThreadByPointer 数组地址
PVOID SearchPspTerminateThreadByPointer(PUCHAR pSpecialData, ULONG ulSpecialDataSize) {
UNICODE_STRING ustrFuncName;
PVOID pAddress = NULL;
LONG lOffset = 0;
PVOID pPsTerminateSystemThread = NULL;
PVOID pPspTerminateThreadByPointer = NULL;
// 先获取 PsTerminateSystemThread 函数地址
RtlInitUnicodeString(&ustrFuncName, L"PsTerminateSystemThread");
pPsTerminateSystemThread = MmGetSystemRoutineAddress(&ustrFuncName);
if (NULL == pPsTerminateSystemThread) {
ShowError("MmGetSystemRoutineAddress", 0);
return pPspTerminateThreadByPointer;
};
// 然后, 查找 PspTerminateThreadByPointer 函数地址
pAddress = SearchMemory(pPsTerminateSystemThread, (PVOID)((PUCHAR)pPsTerminateSystemThread + 0xFF), pSpecialData, ulSpecialDataSize);
if (NULL == pAddress) {
ShowError("SearchMemory", 0);
return pPspTerminateThreadByPointer;
};
// 先获取偏移, 再计算地址
lOffset = *(PLONG)pAddress;
pPspTerminateThreadByPointer = (PVOID)((PUCHAR)pAddress + sizeof(LONG) + lOffset);
return pPspTerminateThreadByPointer;
};

强制结束指定进程具体实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 强制结束指定进程
NTSTATUS ForceKillProcess(HANDLE hProcessId) {
PVOID pPspTerminateThreadByPointerAddress = NULL;
PEPROCESS pEProcess = NULL;
PETHREAD pEThread = NULL;
PEPROCESS pThreadEProcess = NULL;
NTSTATUS status = STATUS_SUCCESS;
ULONG i = 0;
#ifdef _WIN64
// 64 位
typedef NTSTATUS(__fastcall* PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
#else
// 32 位
typedef NTSTATUS(*PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
#endif
// 获取 PspTerminateThreadByPointer 函数地址
pPspTerminateThreadByPointerAddress = GetPspLoadImageNotifyRoutine();
if (NULL == pPspTerminateThreadByPointerAddress) {
ShowError("GetPspLoadImageNotifyRoutine", 0);
return FALSE;
};
// 获取结束进程的进程结构对象EPROCESS
status = PsLookupProcessByProcessId(hProcessId, &pEProcess);
if (!NT_SUCCESS(status)) {
ShowError("PsLookupProcessByProcessId", status);
return status;
};
// 遍历所有线程, 并结束所有指定进程的线程
for (i = 4; i < 0x80000; i = i + 4) {
status = PsLookupThreadByThreadId((HANDLE)i, &pEThread);
if (NT_SUCCESS(status)) {
// 获取线程对应的进程结构对象
pThreadEProcess = PsGetThreadProcess(pEThread);
// 结束指定进程的线程
if (pEProcess == pThreadEProcess) {
((PSPTERMINATETHREADBYPOINTER)pPspTerminateThreadByPointerAddress)(pEThread, 0, 1);
DbgPrint("PspTerminateThreadByPointer Thread:%d\n", i);
};
// 凡是Lookup...,必需Dereference,否则在某些时候会造成蓝屏
ObDereferenceObject(pEThread);
};
};
// 凡是Lookup...,必需Dereference,否则在某些时候会造成蓝屏
ObDereferenceObject(pEProcess);
return status;
};

源代码

Driver.h:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _DRIVER_H_
#define _DRIVER_H_


#include <ntddk.h>


VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);


#endif

ForceKillProcess.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef _FORCE_KILL_PROCESS_H_
#define _FORCE_KILL_PROCESS_H_


#include <ntifs.h>


// 强制结束指定进程
NTSTATUS ForceKillProcess(HANDLE hProcessId);

// 获取 PspTerminateThreadByPointer 函数地址
PVOID GetPspLoadImageNotifyRoutine();

// 根据特征码获取 PspTerminateThreadByPointer 数组地址
PVOID SearchPspTerminateThreadByPointer(PUCHAR pSpecialData, ULONG ulSpecialDataSize);

// 指定内存区域的特征码扫描
PVOID SearchMemory(PVOID pStartAddress, PVOID pEndAddress, PUCHAR pMemoryData, ULONG ulMemoryDataSize);


#endif

Driver.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "ForceKillProcess.h"
#include "Driver.h"



NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("Enter DriverEntry\n");

NTSTATUS status = STATUS_SUCCESS;
pDriverObject->DriverUnload = DriverUnload;
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = DriverDefaultHandle;
}

// 强制结束指定进程
ForceKillProcess((HANDLE)2848);

DbgPrint("Leave DriverEntry\n");
return status;
}



VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
}


NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return status;
}

ForceKillProcess.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include "ForceKillProcess.h"


VOID ShowError(PCHAR lpszText, NTSTATUS ntStatus)
{
DbgPrint("%s Error[0x%X]\n", lpszText, ntStatus);
}


// 强制结束指定进程
NTSTATUS ForceKillProcess(HANDLE hProcessId)
{
PVOID pPspTerminateThreadByPointerAddress = NULL;
PEPROCESS pEProcess = NULL;
PETHREAD pEThread = NULL;
PEPROCESS pThreadEProcess = NULL;
NTSTATUS status = STATUS_SUCCESS;
ULONG i = 0;

#ifdef _WIN64
// 64 位
typedef NTSTATUS(__fastcall *PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
#else
// 32 位
typedef NTSTATUS(*PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
#endif

// 获取 PspTerminateThreadByPointer 函数地址
pPspTerminateThreadByPointerAddress = GetPspLoadImageNotifyRoutine();
if (NULL == pPspTerminateThreadByPointerAddress)
{
ShowError("GetPspLoadImageNotifyRoutine", 0);
return FALSE;
}
// 获取结束进程的进程结构对象EPROCESS
status = PsLookupProcessByProcessId(hProcessId, &pEProcess);
if (!NT_SUCCESS(status))
{
ShowError("PsLookupProcessByProcessId", status);
return status;
}
// 遍历所有线程, 并结束所有指定进程的线程
for (i = 4; i < 0x80000; i = i + 4)
{
status = PsLookupThreadByThreadId((HANDLE)i, &pEThread);
if (NT_SUCCESS(status))
{
// 获取线程对应的进程结构对象
pThreadEProcess = PsGetThreadProcess(pEThread);
// 结束指定进程的线程
if (pEProcess == pThreadEProcess)
{
((PSPTERMINATETHREADBYPOINTER)pPspTerminateThreadByPointerAddress)(pEThread, 0, 1);
DbgPrint("PspTerminateThreadByPointer Thread:%d\n", i);
}
// 凡是Lookup...,必需Dereference,否则在某些时候会造成蓝屏
ObDereferenceObject(pEThread);
}
}
// 凡是Lookup...,必需Dereference,否则在某些时候会造成蓝屏
ObDereferenceObject(pEProcess);

return status;
}


// 获取 PspTerminateThreadByPointer 函数地址
PVOID GetPspLoadImageNotifyRoutine()
{
PVOID pPspTerminateThreadByPointerAddress = NULL;
RTL_OSVERSIONINFOW osInfo = { 0 };
UCHAR pSpecialData[50] = { 0 };
ULONG ulSpecialDataSize = 0;

// 获取系统版本信息, 判断系统版本
RtlGetVersion(&osInfo);
if (6 == osInfo.dwMajorVersion)
{
if (1 == osInfo.dwMinorVersion)
{
// Win7
#ifdef _WIN64
// 64 位
// E8
pSpecialData[0] = 0xE8;
ulSpecialDataSize = 1;
#else
// 32 位
// E8
pSpecialData[0] = 0xE8;
ulSpecialDataSize = 1;
#endif
}
else if (2 == osInfo.dwMinorVersion)
{
// Win8
#ifdef _WIN64
// 64 位

#else
// 32 位

#endif
}
else if (3 == osInfo.dwMinorVersion)
{
// Win8.1
#ifdef _WIN64
// 64 位
// E9
pSpecialData[0] = 0xE9;
ulSpecialDataSize = 1;
#else
// 32 位
// E8
pSpecialData[0] = 0xE8;
ulSpecialDataSize = 1;
#endif
}
}
else if (10 == osInfo.dwMajorVersion)
{
// Win10
#ifdef _WIN64
// 64 位
// E9
pSpecialData[0] = 0xE9;
ulSpecialDataSize = 1;
#else
// 32 位
// E8
pSpecialData[0] = 0xE8;
ulSpecialDataSize = 1;
#endif
}

// 根据特征码获取地址
pPspTerminateThreadByPointerAddress = SearchPspTerminateThreadByPointer(pSpecialData, ulSpecialDataSize);
return pPspTerminateThreadByPointerAddress;
}


// 根据特征码获取 PspTerminateThreadByPointer 数组地址
PVOID SearchPspTerminateThreadByPointer(PUCHAR pSpecialData, ULONG ulSpecialDataSize)
{
UNICODE_STRING ustrFuncName;
PVOID pAddress = NULL;
LONG lOffset = 0;
PVOID pPsTerminateSystemThread = NULL;
PVOID pPspTerminateThreadByPointer = NULL;

// 先获取 PsTerminateSystemThread 函数地址
RtlInitUnicodeString(&ustrFuncName, L"PsTerminateSystemThread");
pPsTerminateSystemThread = MmGetSystemRoutineAddress(&ustrFuncName);
if (NULL == pPsTerminateSystemThread)
{
ShowError("MmGetSystemRoutineAddress", 0);
return pPspTerminateThreadByPointer;
}

// 然后, 查找 PspTerminateThreadByPointer 函数地址
pAddress = SearchMemory(pPsTerminateSystemThread,
(PVOID)((PUCHAR)pPsTerminateSystemThread + 0xFF),
pSpecialData, ulSpecialDataSize);
if (NULL == pAddress)
{
ShowError("SearchMemory", 0);
return pPspTerminateThreadByPointer;
}

// 先获取偏移, 再计算地址
lOffset = *(PLONG)pAddress;
pPspTerminateThreadByPointer = (PVOID)((PUCHAR)pAddress + sizeof(LONG) + lOffset);

return pPspTerminateThreadByPointer;
}


// 指定内存区域的特征码扫描
PVOID SearchMemory(PVOID pStartAddress, PVOID pEndAddress, PUCHAR pMemoryData, ULONG ulMemoryDataSize)
{
PVOID pAddress = NULL;
PUCHAR i = NULL;
ULONG m = 0;

// 扫描内存
for (i = (PUCHAR)pStartAddress; i < (PUCHAR)pEndAddress; i++)
{
// 判断特征码
for (m = 0; m < ulMemoryDataSize; m++)
{
if (*(PUCHAR)(i + m) != pMemoryData[m])
{
break;
}
}
// 判断是否找到符合特征码的地址
if (m >= ulMemoryDataSize)
{
// 找到特征码位置, 获取紧接着特征码的下一地址
pAddress = (PVOID)(i + ulMemoryDataSize);
break;
}
}

return pAddress;
}

文件保护

基本原理

原理就是直接发送IRP对文件进行操作。

发送IRP打开文件前要先打开文件所在驱动器,并获取其文件系统驱动设备对象以及物理磁盘设备对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 打开磁盘根目录并获取句柄
wcscpy(wszName, L"\\??\\A:\\");
wszName[4] = pustrFilePath->Buffer[0];
RtlInitUnicodeString(&ustrRootPath, wszName);
DbgPrint("RootPath:%wZ\n", &ustrRootPath);
InitializeObjectAttributes(&objectAttributes, &ustrRootPath, OBJ_KERNEL_HANDLE, NULL, NULL);
status = IoCreateFile(&hRootFile, GENERIC_READ | SYNCHRONIZE,&objectAttributes, IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);
if (!NT_SUCCESS(status)) {
DbgPrint("IoCreateFile Error[0x%X]", status);
return status;
};
// 获取磁盘根目录文件对象
status = ObReferenceObjectByHandle(hRootFile, FILE_READ_ACCESS, *IoFileObjectType, KernelMode, &pRootFileObject, NULL);
if (!NT_SUCCESS(status)) {
ZwClose(hRootFile);
DbgPrint("ObReferenceObjectByHandle Error[0x%X]\n", status);
return status;
};
// 获取磁盘根目录设备对象
RootDeviceObject = pRootFileObject->Vpb->DeviceObject;
RootRealDevice = pRootFileObject->Vpb->RealDevice;
// 关闭磁盘根目录句柄和对象
ObDereferenceObject(pRootFileObject);
ZwClose(hRootFile);

创建IRP_MJ_CREATE消息,发送到系统中打开相应文件。用IoAllocateIrp根据文件系统驱动设备对象栈大小DeviceObject->StackSize申请一块IRP数据空间。用KeInitializeEvent初始化一个内核同步事件,并构造一个IRP:设置文件对象数据结构FILE_OBEJCT;用SeCreateAccessState创建访问状态;设置安全上下文IO_SECURITY_CONTEXT数组,用IoGetNextIrpStackLocation获取IRP堆栈空间数据并设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 创建IRP
pIrp = IoAllocateIrp(RootDeviceObject->StackSize, FALSE);
if (NULL == pIrp) {
ObDereferenceObject(pFileObject);
DbgPrint("IoAllocateIrp Error!\n");
return STATUS_UNSUCCESSFUL;
};
// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);
// 创建空文件对象
InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ObCreateObject(KernelMode, *IoFileObjectType, &objectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, &pFileObject);
if (!NT_SUCCESS(status)) {
DbgPrint("ObCreateObject Error[0x%X]\n", status);
return status;
};
// 设置创建的文件对象 FILE_OBJECT
RtlZeroMemory(pFileObject, sizeof(FILE_OBJECT));
pFileObject->Type = IO_TYPE_FILE;
pFileObject->Size = sizeof(FILE_OBJECT);
pFileObject->DeviceObject = RootRealDevice;
pFileObject->Flags = FO_SYNCHRONOUS_IO;
// FILE_OBJECT中的FileName最好动态创建, 否则ObDereferenceObject文件句柄的时候会蓝屏
pFileObject->FileName.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, ulFileNameMaxSize);
pFileObject->FileName.MaximumLength = (USHORT)ulFileNameMaxSize;
pFileObject->FileName.Length = pustrFilePath->Length - 4;
RtlZeroMemory(pFileObject->FileName.Buffer, ulFileNameMaxSize);
RtlCopyMemory(pFileObject->FileName.Buffer, &pustrFilePath->Buffer[2], pFileObject->FileName.Length);
DbgPrint("pFileObject->FileName:%wZ\n", &pFileObject->FileName);
KeInitializeEvent(&pFileObject->Lock, SynchronizationEvent, FALSE);
KeInitializeEvent(&pFileObject->Event, NotificationEvent, FALSE);
// 创建权限状态
RtlZeroMemory(&auxAccessData, sizeof(auxAccessData));
status = SeCreateAccessState(&accessData, &auxAccessData, DesiredAccess, IoGetFileObjectGenericMapping());
if (!NT_SUCCESS(status)) {
IoFreeIrp(pIrp);
ObDereferenceObject(pFileObject);
DbgPrint("SeCreateAccessState Error[0x%X]\n", status);
return status;
};
// 设置安全内容 IO_SECURITY_CONTEXT
ioSecurityContext.SecurityQos = NULL;
ioSecurityContext.AccessState = &accessData;
ioSecurityContext.DesiredAccess = DesiredAccess;
ioSecurityContext.FullCreateOptions = 0;
// 设置IRP
RtlZeroMemory(IoStatusBlock, sizeof(IO_STATUS_BLOCK));
pIrp->MdlAddress = NULL;
pIrp->AssociatedIrp.SystemBuffer = EaBuffer;
pIrp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
pIrp->RequestorMode = KernelMode;
pIrp->UserIosb = IoStatusBlock;
pIrp->UserEvent = &kEvent;
pIrp->PendingReturned = FALSE;
pIrp->Cancel = FALSE;
pIrp->CancelRoutine = NULL;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;
// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_CREATE;
pIoStackLocation->DeviceObject = RootDeviceObject;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Create.SecurityContext = &ioSecurityContext;
pIoStackLocation->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions;
pIoStackLocation->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
pIoStackLocation->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
pIoStackLocation->Parameters.Create.EaLength = EaLength;

IoSetCompletionRoutine为IRP设置一个完成回调函数用于IRP清理工作,再用IoCallDriver将IRP发送到系统中处理并打开文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);
// 发送IRP
status = IoCallDriver(RootDeviceObject, pIrp);
// 等待IRP的处理
if (STATUS_PENDING == status)
KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);
// 判断IRP处理结果
status = IoStatusBlock->Status;
if (!NT_SUCCESS(status)) {
ObDereferenceObject(pFileObject);
DbgPrint("IRP FAILED!\n");
return status;
};
InterlockedIncrement(&pFileObject->DeviceObject->ReferenceCount);
if (pFileObject->Vpb)
InterlockedIncrement(&pFileObject->Vpb->ReferenceCount);
// 返回文件对象
*ppFileObject = pFileObject;
return status;

打开文件并获得文件对象后,没有调用ObDereferenceObject释放文件对象前,文件一直处于打开状态,不能被删除,从而实现文件保护。

1
2
3
4
5
6
7
8
9
10
PFILE_OBJECT ProtectFile(UNICODE_STRING ustrFileName) {
PFILE_OBJECT pFileObject = NULL;
IO_STATUS_BLOCK iosb = { 0 };
NTSTATUS status = STATUS_SUCCESS;
// 创建或者打开文件
status = IrpCreateFile(&pFileObject, DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ustrFileName, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
return pFileObject;
return pFileObject;
};

关闭文件保护:

1
2
3
4
5
BOOLEAN UnprotectFile(PFILE_OBJECT pFileObject) {
if (pFileObject)
ObDereferenceObject(pFileObject);
return TRUE;
};

源代码

Driver.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef _DRIVER_H_
#define _DRIVER_H_


#include <ntddk.h>


#define DEV_NAME L"\\Device\\IRP_FILE_DEV_NAME"
#define SYM_NAME L"\\DosDevices\\IRP_FILE_SYM_NAME"
#define IOCTL_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)


VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS DriverControlHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject);


#endif

FileProtect.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef _FILE_PROTECT_H_
#define _FILE_PROTECT_H_


#include "IrpFile.h"


PFILE_OBJECT ProtectFile(UNICODE_STRING ustrFileName);
BOOLEAN UnprotectFile(PFILE_OBJECT pFileObject);



#endif

IrpFile.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#ifndef _IRP_FILE_H_
#define _IRP_FILE_H_


#include <ntifs.h>


typedef struct _AUX_ACCESS_DATA {
PPRIVILEGE_SET PrivilegesUsed;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessesToAudit;
ACCESS_MASK MaximumAuditMask;
ULONG Unknown[256];
} AUX_ACCESS_DATA, *PAUX_ACCESS_DATA;


NTSTATUS SeCreateAccessState(
PACCESS_STATE AccessState,
PVOID AuxData,
ACCESS_MASK DesiredAccess,
PGENERIC_MAPPING GenericMapping
);

NTSTATUS ObCreateObject(
__in KPROCESSOR_MODE ProbeMode, // 决定是否要验证参数
__in POBJECT_TYPE ObjectType, // 对象类型指针
__in POBJECT_ATTRIBUTES ObjectAttributes, // 对象的属性, 最终会转化成ObAllocateObject需要的OBJECT_CREATE_INFORMATION结构
__in KPROCESSOR_MODE OwnershipMode, // 内核对象?用户对象? 同上
__inout_opt PVOID ParseContext, // 这参数没用
__in ULONG ObjectBodySize, // 对象体大小
__in ULONG PagedPoolCharge, // ...
__in ULONG NonPagedPoolCharge, // ...
__out PVOID *Object // 接收对象体的指针
);




// 完成实例, 设置事件信号量, 并释放IRP
NTSTATUS MyCompleteRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PVOID Context);


// 创建或者打开文件
// ZwCreateFile
NTSTATUS IrpCreateFile(
OUT PFILE_OBJECT *ppFileObject,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING pustrFilePath,
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);

// 文件遍历
// ZwQueryDirectoryFile
NTSTATUS IrpQueryDirectoryFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PUNICODE_STRING FileName OPTIONAL);

// 获取文件的信息
// ZwQueryInformationFile
NTSTATUS IrpQueryInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);


// 设置文件信息
// ZwSetInformationFile
NTSTATUS IrpSetInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);

// 读文件
// ZwReadFile
NTSTATUS IrpReadFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
);

// 写文件
// ZwWriteFile
NTSTATUS IrpWriteFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
);


#endif

Driver.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "FileProtect.h"
#include "Driver.h"


PFILE_OBJECT g_pFileObject = NULL;


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("Enter DriverEntry\n");
NTSTATUS status = STATUS_SUCCESS;

pDriverObject->DriverUnload = DriverUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DriverDefaultHandle;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverDefaultHandle;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverControlHandle;

status = CreateDevice(pDriverObject);

// 保护文件
UNICODE_STRING ustrFileName;
RtlInitUnicodeString(&ustrFileName, L"C:\\520.exe");
g_pFileObject = ProtectFile(ustrFileName);

DbgPrint("Leave DriverEntry\n");
return status;
}


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Enter DriverUnload\n");

// 关闭保护文件
if (g_pFileObject)
{
UnprotectFile(g_pFileObject);
}

if (pDriverObject->DeviceObject)
{
IoDeleteDevice(pDriverObject->DeviceObject);
}
UNICODE_STRING ustrSymName;
RtlInitUnicodeString(&ustrSymName, SYM_NAME);
IoDeleteSymbolicLink(&ustrSymName);

DbgPrint("Leave DriverUnload\n");
}


NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
DbgPrint("Enter DriverDefaultHandle\n");
NTSTATUS status = STATUS_SUCCESS;

pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

DbgPrint("Leave DriverDefaultHandle\n");
return status;
}


NTSTATUS DriverControlHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
DbgPrint("Enter DriverControlHandle\n");
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);
ULONG ulInputLen = pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
ULONG ulOutputLen = pIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
ULONG ulControlCode = pIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
PVOID pBuffer = pIrp->AssociatedIrp.SystemBuffer;
ULONG ulInfo = 0;

switch (ulControlCode)
{
case IOCTL_TEST:
{
break;
}
default:
break;
}

pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = ulInfo;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

DbgPrint("Leave DriverControlHandle\n");
return status;
}


NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Enter CreateDevice\n");
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL;
UNICODE_STRING ustrDevName, ustrSymName;
RtlInitUnicodeString(&ustrDevName, DEV_NAME);
RtlInitUnicodeString(&ustrSymName, SYM_NAME);

status = IoCreateDevice(pDriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateDevice Error[0x%X]\n", status);
return status;
}

status = IoCreateSymbolicLink(&ustrSymName, &ustrDevName);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateSymbolicLink Error[0x%X]\n", status);
return status;
}

DbgPrint("Leave CreateDevice\n");
return status;
}

FileProtect.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "FileProtect.h"


PFILE_OBJECT ProtectFile(UNICODE_STRING ustrFileName)
{
PFILE_OBJECT pFileObject = NULL;
IO_STATUS_BLOCK iosb = { 0 };
NTSTATUS status = STATUS_SUCCESS;

// 创建或者打开文件
status = IrpCreateFile(&pFileObject, DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&ustrFileName, &iosb, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
{
return pFileObject;
}

return pFileObject;
}


BOOLEAN UnprotectFile(PFILE_OBJECT pFileObject)
{
if (pFileObject)
{
ObDereferenceObject(pFileObject);
}
return TRUE;
}

IrpFile.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
#include "IrpFile.h"


// 完成实例, 设置事件信号量, 并释放IRP
NTSTATUS MyCompleteRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PVOID Context)
{
*pIrp->UserIosb = pIrp->IoStatus;

// 设置事件信号
if (pIrp->UserEvent)
{
KeSetEvent(pIrp->UserEvent, IO_NO_INCREMENT, FALSE);
}

// 释放MDL
if (pIrp->MdlAddress)
{
IoFreeMdl(pIrp->MdlAddress);
pIrp->MdlAddress = NULL;
}

// 释放IRP
IoFreeIrp(pIrp);
pIrp = NULL;

return STATUS_MORE_PROCESSING_REQUIRED;
}


// 创建或者打开文件
// ZwCreateFile
NTSTATUS IrpCreateFile(
OUT PFILE_OBJECT *ppFileObject,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING pustrFilePath,
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)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG ulFileNameMaxSize = 512;
WCHAR wszName[100] = { 0 };
UNICODE_STRING ustrRootPath;
OBJECT_ATTRIBUTES objectAttributes = { 0 };
HANDLE hRootFile = NULL;
PFILE_OBJECT pRootFileObject = NULL, pFileObject = NULL;
PDEVICE_OBJECT RootDeviceObject = NULL, RootRealDevice = NULL;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
ACCESS_STATE accessData = { 0 };
AUX_ACCESS_DATA auxAccessData = { 0 };
IO_SECURITY_CONTEXT ioSecurityContext = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;

// 打开磁盘根目录并获取句柄
wcscpy(wszName, L"\\??\\A:\\");
wszName[4] = pustrFilePath->Buffer[0];
RtlInitUnicodeString(&ustrRootPath, wszName);
DbgPrint("RootPath:%wZ\n", &ustrRootPath);
InitializeObjectAttributes(&objectAttributes, &ustrRootPath, OBJ_KERNEL_HANDLE, NULL, NULL);
status = IoCreateFile(&hRootFile, GENERIC_READ | SYNCHRONIZE,
&objectAttributes, IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone,
NULL, IO_NO_PARAMETER_CHECKING);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateFile Error[0x%X]", status);
return status;
}

// 获取磁盘根目录文件对象
status = ObReferenceObjectByHandle(hRootFile, FILE_READ_ACCESS, *IoFileObjectType, KernelMode, &pRootFileObject, NULL);
if (!NT_SUCCESS(status))
{
ZwClose(hRootFile);
DbgPrint("ObReferenceObjectByHandle Error[0x%X]\n", status);
return status;
}

// 获取磁盘根目录设备对象
RootDeviceObject = pRootFileObject->Vpb->DeviceObject;
RootRealDevice = pRootFileObject->Vpb->RealDevice;

// 关闭磁盘根目录句柄和对象
ObDereferenceObject(pRootFileObject);
ZwClose(hRootFile);

// 创建IRP
pIrp = IoAllocateIrp(RootDeviceObject->StackSize, FALSE);
if (NULL == pIrp)
{
ObDereferenceObject(pFileObject);
DbgPrint("IoAllocateIrp Error!\n");
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 创建空文件对象
InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ObCreateObject(KernelMode, *IoFileObjectType, &objectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, &pFileObject);
if (!NT_SUCCESS(status))
{
DbgPrint("ObCreateObject Error[0x%X]\n", status);
return status;
}

// 设置创建的文件对象 FILE_OBJECT
RtlZeroMemory(pFileObject, sizeof(FILE_OBJECT));
pFileObject->Type = IO_TYPE_FILE;
pFileObject->Size = sizeof(FILE_OBJECT);
pFileObject->DeviceObject = RootRealDevice;
pFileObject->Flags = FO_SYNCHRONOUS_IO;

// FILE_OBJECT中的FileName最好动态创建, 否则ObDereferenceObject文件句柄的时候会蓝屏
pFileObject->FileName.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, ulFileNameMaxSize);
pFileObject->FileName.MaximumLength = (USHORT)ulFileNameMaxSize;
pFileObject->FileName.Length = pustrFilePath->Length - 4;
RtlZeroMemory(pFileObject->FileName.Buffer, ulFileNameMaxSize);
RtlCopyMemory(pFileObject->FileName.Buffer, &pustrFilePath->Buffer[2], pFileObject->FileName.Length);
DbgPrint("pFileObject->FileName:%wZ\n", &pFileObject->FileName);
KeInitializeEvent(&pFileObject->Lock, SynchronizationEvent, FALSE);
KeInitializeEvent(&pFileObject->Event, NotificationEvent, FALSE);

// 创建权限状态
RtlZeroMemory(&auxAccessData, sizeof(auxAccessData));
status = SeCreateAccessState(&accessData, &auxAccessData, DesiredAccess, IoGetFileObjectGenericMapping());
if (!NT_SUCCESS(status))
{
IoFreeIrp(pIrp);
ObDereferenceObject(pFileObject);
DbgPrint("SeCreateAccessState Error[0x%X]\n", status);
return status;
}

// 设置安全内容 IO_SECURITY_CONTEXT
ioSecurityContext.SecurityQos = NULL;
ioSecurityContext.AccessState = &accessData;
ioSecurityContext.DesiredAccess = DesiredAccess;
ioSecurityContext.FullCreateOptions = 0;

// 设置IRP
RtlZeroMemory(IoStatusBlock, sizeof(IO_STATUS_BLOCK));
pIrp->MdlAddress = NULL;
pIrp->AssociatedIrp.SystemBuffer = EaBuffer;
pIrp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
pIrp->RequestorMode = KernelMode;
pIrp->UserIosb = IoStatusBlock;
pIrp->UserEvent = &kEvent;
pIrp->PendingReturned = FALSE;
pIrp->Cancel = FALSE;
pIrp->CancelRoutine = NULL;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_CREATE;
pIoStackLocation->DeviceObject = RootDeviceObject;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Create.SecurityContext = &ioSecurityContext;
pIoStackLocation->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions;
pIoStackLocation->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
pIoStackLocation->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
pIoStackLocation->Parameters.Create.EaLength = EaLength;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(RootDeviceObject, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);
}

// 判断IRP处理结果
status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
ObDereferenceObject(pFileObject);
DbgPrint("IRP FAILED!\n");
return status;
}

InterlockedIncrement(&pFileObject->DeviceObject->ReferenceCount);
if (pFileObject->Vpb)
{
InterlockedIncrement(&pFileObject->Vpb->ReferenceCount);
}

// 返回文件对象
*ppFileObject = pFileObject;

return status;
}


// 文件遍历
// ZwQueryDirectoryFile
NTSTATUS IrpQueryDirectoryFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PUNICODE_STRING FileName OPTIONAL)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
RtlZeroMemory(FileInformation, Length);
pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->UserBuffer = FileInformation;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;
pIrp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
pIoStackLocation->MinorFunction = IRP_MN_QUERY_DIRECTORY;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Flags = SL_RESTART_SCAN;
pIoStackLocation->Parameters.QueryDirectory.Length = Length;
pIoStackLocation->Parameters.QueryDirectory.FileName = FileName;
pIoStackLocation->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}


// 获取文件的信息
// ZwQueryInformationFile
NTSTATUS IrpQueryInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
RtlZeroMemory(FileInformation, Length);
pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->AssociatedIrp.SystemBuffer = FileInformation;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.QueryFile.Length = Length;
pIoStackLocation->Parameters.QueryFile.FileInformationClass = FileInformationClass;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}



// 设置文件信息
// ZwSetInformationFile
NTSTATUS IrpSetInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->AssociatedIrp.SystemBuffer = FileInformation;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_SET_INFORMATION;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.SetFile.Length = Length;
pIoStackLocation->Parameters.SetFile.FileInformationClass = FileInformationClass;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}


// 读文件
// ZwReadFile
NTSTATUS IrpReadFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 调整参数
if (NULL == ByteOffset)
{
if (0 == (FO_SYNCHRONOUS_IO & pFileObject->Flags))
{
return STATUS_INVALID_PARAMETER;
}
ByteOffset = &pFileObject->CurrentByteOffset;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
RtlZeroMemory(Buffer, Length);
pIrp->MdlAddress = MmCreateMdl(NULL, Buffer, Length);
if (NULL == pIrp->MdlAddress)
{
IoFreeIrp(pIrp);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(pIrp->MdlAddress);

pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->Flags = IRP_READ_OPERATION;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_READ;
pIoStackLocation->MinorFunction = IRP_MN_NORMAL;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Read.Length = Length;
pIoStackLocation->Parameters.Read.ByteOffset = *ByteOffset;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}


// 写文件
// ZwWriteFile
NTSTATUS IrpWriteFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 调整参数
if (NULL == ByteOffset)
{
if (0 == (FO_SYNCHRONOUS_IO & pFileObject->Flags))
{
return STATUS_INVALID_PARAMETER;
}
ByteOffset = &pFileObject->CurrentByteOffset;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
pIrp->MdlAddress = MmCreateMdl(NULL, Buffer, Length);
if (NULL == pIrp->MdlAddress)
{
IoFreeIrp(pIrp);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(pIrp->MdlAddress);

pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->Flags = IRP_WRITE_OPERATION;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_WRITE;
pIoStackLocation->MinorFunction = IRP_MN_NORMAL;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Write.Length = Length;
pIoStackLocation->Parameters.Write.ByteOffset = *ByteOffset;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}

文件强删

基本原理

在删除运行的文件或加载的DLL文件时,系统调用MmFlushImageSection检测文件是否处于运行状态,若是则拒绝删除操作。这主要是检查文件对象中PSECTION_OBJECT_POINTERS结构数据来判断该文件是否处于运行状态、是否可以删除。

先发送IRP打开删除文件并获取文件对象。发送IRP设置文件属性类型为FileBasicInformation,文件属性为FILE_ATTRIBUTE_NORMAL,以防原来属性为只读。保存并清空PSECTION_OBJECT_POINTERS结构。发送IRP设置文件属性类型为FileDispositionInformation删除文件,这样即使文件运行中也能被强删。

最后还原文件对象的PSECTION_OBJECT_POINTERS结构并用ObDereferenceObject释放文件对象完成清理工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 强制删除文件
NTSTATUS ForceDeleteFile(UNICODE_STRING ustrFileName) {
NTSTATUS status = STATUS_SUCCESS;
PFILE_OBJECT pFileObject = NULL;
IO_STATUS_BLOCK iosb = { 0 };
FILE_BASIC_INFORMATION fileBaseInfo = { 0 };
FILE_DISPOSITION_INFORMATION fileDispositionInfo = { 0 };
PVOID pImageSectionObject = NULL;
PVOID pDataSectionObject = NULL;
PVOID pSharedCacheMap = NULL;
// 发送IRP打开文件
status = IrpCreateFile(&pFileObject, GENERIC_READ | GENERIC_WRITE, &ustrFileName, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status)) {
DbgPrint("IrpCreateFile Error[0x%X]\n", status);
return FALSE;
};
// 发送IRP设置文件属性, 去掉只读属性, 修改为 FILE_ATTRIBUTE_NORMAL
RtlZeroMemory(&fileBaseInfo, sizeof(fileBaseInfo));
fileBaseInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
status = IrpSetInformationFile(pFileObject, &iosb, &fileBaseInfo, sizeof(fileBaseInfo), FileBasicInformation);
if (!NT_SUCCESS(status)) {
DbgPrint("IrpSetInformationFile[SetInformation] Error[0x%X]\n", status);
return status;
};
// 清空PSECTION_OBJECT_POINTERS结构
if (pFileObject->SectionObjectPointer) {
// 保存旧值
pImageSectionObject = pFileObject->SectionObjectPointer->ImageSectionObject;
pDataSectionObject = pFileObject->SectionObjectPointer->DataSectionObject;
pSharedCacheMap = pFileObject->SectionObjectPointer->SharedCacheMap;
// 置为空
pFileObject->SectionObjectPointer->ImageSectionObject = NULL;
pFileObject->SectionObjectPointer->DataSectionObject = NULL;
pFileObject->SectionObjectPointer->SharedCacheMap = NULL;
};
// 发送IRP设置文件属性, 设置删除文件操作
RtlZeroMemory(&fileDispositionInfo, sizeof(fileDispositionInfo));
fileDispositionInfo.DeleteFile = TRUE;
status = IrpSetInformationFile(pFileObject, &iosb, &fileDispositionInfo, sizeof(fileDispositionInfo), FileDispositionInformation);
if (!NT_SUCCESS(status)) {
DbgPrint("IrpSetInformationFile[DeleteFile] Error[0x%X]\n", status);
return status;
};
//还原旧值
if (pFileObject->SectionObjectPointer) {
pFileObject->SectionObjectPointer->ImageSectionObject = pImageSectionObject;
pFileObject->SectionObjectPointer->DataSectionObject = pDataSectionObject;
pFileObject->SectionObjectPointer->SharedCacheMap = pSharedCacheMap;
};
// 关闭文件对象
ObDereferenceObject(pFileObject);
return status;
};

源代码

Driver.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef _DRIVER_H_
#define _DRIVER_H_


#include <ntddk.h>


#define DEV_NAME L"\\Device\\IRP_FILE_DEV_NAME"
#define SYM_NAME L"\\DosDevices\\IRP_FILE_SYM_NAME"
#define IOCTL_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)


VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS DriverControlHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject);


#endif

ForceDelete.h:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _FORCE_DELETE_H_
#define _FORCE_DELETE_H_


#include "IrpFile.h"


// 强制删除文件
NTSTATUS ForceDeleteFile(UNICODE_STRING ustrFileName);


#endif

IrpFile.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#ifndef _IRP_FILE_H_
#define _IRP_FILE_H_


#include <ntifs.h>


typedef struct _AUX_ACCESS_DATA {
PPRIVILEGE_SET PrivilegesUsed;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessesToAudit;
ACCESS_MASK MaximumAuditMask;
ULONG Unknown[256];
} AUX_ACCESS_DATA, *PAUX_ACCESS_DATA;


NTSTATUS SeCreateAccessState(
PACCESS_STATE AccessState,
PVOID AuxData,
ACCESS_MASK DesiredAccess,
PGENERIC_MAPPING GenericMapping
);

NTSTATUS ObCreateObject(
__in KPROCESSOR_MODE ProbeMode, // 决定是否要验证参数
__in POBJECT_TYPE ObjectType, // 对象类型指针
__in POBJECT_ATTRIBUTES ObjectAttributes, // 对象的属性, 最终会转化成ObAllocateObject需要的OBJECT_CREATE_INFORMATION结构
__in KPROCESSOR_MODE OwnershipMode, // 内核对象?用户对象? 同上
__inout_opt PVOID ParseContext, // 这参数没用
__in ULONG ObjectBodySize, // 对象体大小
__in ULONG PagedPoolCharge, // ...
__in ULONG NonPagedPoolCharge, // ...
__out PVOID *Object // 接收对象体的指针
);




// 完成实例, 设置事件信号量, 并释放IRP
NTSTATUS MyCompleteRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PVOID Context);


// 创建或者打开文件
// ZwCreateFile
NTSTATUS IrpCreateFile(
OUT PFILE_OBJECT *ppFileObject,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING pustrFilePath,
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);

// 文件遍历
// ZwQueryDirectoryFile
NTSTATUS IrpQueryDirectoryFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PUNICODE_STRING FileName OPTIONAL);

// 获取文件的信息
// ZwQueryInformationFile
NTSTATUS IrpQueryInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);


// 设置文件信息
// ZwSetInformationFile
NTSTATUS IrpSetInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);

// 读文件
// ZwReadFile
NTSTATUS IrpReadFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
);

// 写文件
// ZwWriteFile
NTSTATUS IrpWriteFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
);


#endif

Driver.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "ForceDelete.h"
#include "Driver.h"


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("Enter DriverEntry\n");
NTSTATUS status = STATUS_SUCCESS;

pDriverObject->DriverUnload = DriverUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DriverDefaultHandle;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverDefaultHandle;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverControlHandle;

status = CreateDevice(pDriverObject);

// 强制删除文件
UNICODE_STRING ustrFileName;
RtlInitUnicodeString(&ustrFileName, L"C:\\520.exe");
status = ForceDeleteFile(ustrFileName);

DbgPrint("Leave DriverEntry\n");
return status;
}


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Enter DriverUnload\n");

if (pDriverObject->DeviceObject)
{
IoDeleteDevice(pDriverObject->DeviceObject);
}
UNICODE_STRING ustrSymName;
RtlInitUnicodeString(&ustrSymName, SYM_NAME);
IoDeleteSymbolicLink(&ustrSymName);

DbgPrint("Leave DriverUnload\n");
}


NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
DbgPrint("Enter DriverDefaultHandle\n");
NTSTATUS status = STATUS_SUCCESS;

pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

DbgPrint("Leave DriverDefaultHandle\n");
return status;
}


NTSTATUS DriverControlHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
DbgPrint("Enter DriverControlHandle\n");
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);
ULONG ulInputLen = pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
ULONG ulOutputLen = pIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
ULONG ulControlCode = pIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
PVOID pBuffer = pIrp->AssociatedIrp.SystemBuffer;
ULONG ulInfo = 0;

switch (ulControlCode)
{
case IOCTL_TEST:
{
break;
}
default:
break;
}

pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = ulInfo;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

DbgPrint("Leave DriverControlHandle\n");
return status;
}


NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Enter CreateDevice\n");
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL;
UNICODE_STRING ustrDevName, ustrSymName;
RtlInitUnicodeString(&ustrDevName, DEV_NAME);
RtlInitUnicodeString(&ustrSymName, SYM_NAME);

status = IoCreateDevice(pDriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateDevice Error[0x%X]\n", status);
return status;
}

status = IoCreateSymbolicLink(&ustrSymName, &ustrDevName);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateSymbolicLink Error[0x%X]\n", status);
return status;
}

DbgPrint("Leave CreateDevice\n");
return status;
}

ForceDelete.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "ForceDelete.h"


// 强制删除文件
NTSTATUS ForceDeleteFile(UNICODE_STRING ustrFileName)
{
NTSTATUS status = STATUS_SUCCESS;
PFILE_OBJECT pFileObject = NULL;
IO_STATUS_BLOCK iosb = { 0 };
FILE_BASIC_INFORMATION fileBaseInfo = { 0 };
FILE_DISPOSITION_INFORMATION fileDispositionInfo = { 0 };
PVOID pImageSectionObject = NULL;
PVOID pDataSectionObject = NULL;
PVOID pSharedCacheMap = NULL;

// 发送IRP打开文件
status = IrpCreateFile(&pFileObject, GENERIC_READ | GENERIC_WRITE, &ustrFileName,
&iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
{
DbgPrint("IrpCreateFile Error[0x%X]\n", status);
return FALSE;
}

// 发送IRP设置文件属性, 去掉只读属性, 修改为 FILE_ATTRIBUTE_NORMAL
RtlZeroMemory(&fileBaseInfo, sizeof(fileBaseInfo));
fileBaseInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
status = IrpSetInformationFile(pFileObject, &iosb, &fileBaseInfo, sizeof(fileBaseInfo), FileBasicInformation);
if (!NT_SUCCESS(status))
{
DbgPrint("IrpSetInformationFile[SetInformation] Error[0x%X]\n", status);
return status;
}

// 清空PSECTION_OBJECT_POINTERS结构
if (pFileObject->SectionObjectPointer)
{
// 保存旧值
pImageSectionObject = pFileObject->SectionObjectPointer->ImageSectionObject;
pDataSectionObject = pFileObject->SectionObjectPointer->DataSectionObject;
pSharedCacheMap = pFileObject->SectionObjectPointer->SharedCacheMap;
// 置为空
pFileObject->SectionObjectPointer->ImageSectionObject = NULL;
pFileObject->SectionObjectPointer->DataSectionObject = NULL;
pFileObject->SectionObjectPointer->SharedCacheMap = NULL;
}

// 发送IRP设置文件属性, 设置删除文件操作
RtlZeroMemory(&fileDispositionInfo, sizeof(fileDispositionInfo));
fileDispositionInfo.DeleteFile = TRUE;
status = IrpSetInformationFile(pFileObject, &iosb, &fileDispositionInfo, sizeof(fileDispositionInfo), FileDispositionInformation);
if (!NT_SUCCESS(status))
{
DbgPrint("IrpSetInformationFile[DeleteFile] Error[0x%X]\n", status);
return status;
}

//还原旧值
if (pFileObject->SectionObjectPointer)
{
pFileObject->SectionObjectPointer->ImageSectionObject = pImageSectionObject;
pFileObject->SectionObjectPointer->DataSectionObject = pDataSectionObject;
pFileObject->SectionObjectPointer->SharedCacheMap = pSharedCacheMap;
}

// 关闭文件对象
ObDereferenceObject(pFileObject);

return status;
}

IrpFile.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
#include "IrpFile.h"


// 完成实例, 设置事件信号量, 并释放IRP
NTSTATUS MyCompleteRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PVOID Context)
{
*pIrp->UserIosb = pIrp->IoStatus;

// 设置事件信号
if (pIrp->UserEvent)
{
KeSetEvent(pIrp->UserEvent, IO_NO_INCREMENT, FALSE);
}

// 释放MDL
if (pIrp->MdlAddress)
{
IoFreeMdl(pIrp->MdlAddress);
pIrp->MdlAddress = NULL;
}

// 释放IRP
IoFreeIrp(pIrp);
pIrp = NULL;

return STATUS_MORE_PROCESSING_REQUIRED;
}


// 创建或者打开文件
// ZwCreateFile
NTSTATUS IrpCreateFile(
OUT PFILE_OBJECT *ppFileObject,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING pustrFilePath,
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)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG ulFileNameMaxSize = 512;
WCHAR wszName[100] = { 0 };
UNICODE_STRING ustrRootPath;
OBJECT_ATTRIBUTES objectAttributes = { 0 };
HANDLE hRootFile = NULL;
PFILE_OBJECT pRootFileObject = NULL, pFileObject = NULL;
PDEVICE_OBJECT RootDeviceObject = NULL, RootRealDevice = NULL;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
ACCESS_STATE accessData = { 0 };
AUX_ACCESS_DATA auxAccessData = { 0 };
IO_SECURITY_CONTEXT ioSecurityContext = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;

// 打开磁盘根目录并获取句柄
wcscpy(wszName, L"\\??\\A:\\");
wszName[4] = pustrFilePath->Buffer[0];
RtlInitUnicodeString(&ustrRootPath, wszName);
DbgPrint("RootPath:%wZ\n", &ustrRootPath);
InitializeObjectAttributes(&objectAttributes, &ustrRootPath, OBJ_KERNEL_HANDLE, NULL, NULL);
status = IoCreateFile(&hRootFile, GENERIC_READ | SYNCHRONIZE,
&objectAttributes, IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone,
NULL, IO_NO_PARAMETER_CHECKING);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateFile Error[0x%X]", status);
return status;
}

// 获取磁盘根目录文件对象
status = ObReferenceObjectByHandle(hRootFile, FILE_READ_ACCESS, *IoFileObjectType, KernelMode, &pRootFileObject, NULL);
if (!NT_SUCCESS(status))
{
ZwClose(hRootFile);
DbgPrint("ObReferenceObjectByHandle Error[0x%X]\n", status);
return status;
}

// 获取磁盘根目录设备对象
RootDeviceObject = pRootFileObject->Vpb->DeviceObject;
RootRealDevice = pRootFileObject->Vpb->RealDevice;

// 关闭磁盘根目录句柄和对象
ObDereferenceObject(pRootFileObject);
ZwClose(hRootFile);

// 创建IRP
pIrp = IoAllocateIrp(RootDeviceObject->StackSize, FALSE);
if (NULL == pIrp)
{
ObDereferenceObject(pFileObject);
DbgPrint("IoAllocateIrp Error!\n");
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 创建空文件对象
InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ObCreateObject(KernelMode, *IoFileObjectType, &objectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, &pFileObject);
if (!NT_SUCCESS(status))
{
DbgPrint("ObCreateObject Error[0x%X]\n", status);
return status;
}

// 设置创建的文件对象 FILE_OBJECT
RtlZeroMemory(pFileObject, sizeof(FILE_OBJECT));
pFileObject->Type = IO_TYPE_FILE;
pFileObject->Size = sizeof(FILE_OBJECT);
pFileObject->DeviceObject = RootRealDevice;
pFileObject->Flags = FO_SYNCHRONOUS_IO;

// FILE_OBJECT中的FileName最好动态创建, 否则ObDereferenceObject文件句柄的时候会蓝屏
pFileObject->FileName.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, ulFileNameMaxSize);
pFileObject->FileName.MaximumLength = (USHORT)ulFileNameMaxSize;
pFileObject->FileName.Length = pustrFilePath->Length - 4;
RtlZeroMemory(pFileObject->FileName.Buffer, ulFileNameMaxSize);
RtlCopyMemory(pFileObject->FileName.Buffer, &pustrFilePath->Buffer[2], pFileObject->FileName.Length);
DbgPrint("pFileObject->FileName:%wZ\n", &pFileObject->FileName);
KeInitializeEvent(&pFileObject->Lock, SynchronizationEvent, FALSE);
KeInitializeEvent(&pFileObject->Event, NotificationEvent, FALSE);

// 创建权限状态
RtlZeroMemory(&auxAccessData, sizeof(auxAccessData));
status = SeCreateAccessState(&accessData, &auxAccessData, DesiredAccess, IoGetFileObjectGenericMapping());
if (!NT_SUCCESS(status))
{
IoFreeIrp(pIrp);
ObDereferenceObject(pFileObject);
DbgPrint("SeCreateAccessState Error[0x%X]\n", status);
return status;
}

// 设置安全内容 IO_SECURITY_CONTEXT
ioSecurityContext.SecurityQos = NULL;
ioSecurityContext.AccessState = &accessData;
ioSecurityContext.DesiredAccess = DesiredAccess;
ioSecurityContext.FullCreateOptions = 0;

// 设置IRP
RtlZeroMemory(IoStatusBlock, sizeof(IO_STATUS_BLOCK));
pIrp->MdlAddress = NULL;
pIrp->AssociatedIrp.SystemBuffer = EaBuffer;
pIrp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
pIrp->RequestorMode = KernelMode;
pIrp->UserIosb = IoStatusBlock;
pIrp->UserEvent = &kEvent;
pIrp->PendingReturned = FALSE;
pIrp->Cancel = FALSE;
pIrp->CancelRoutine = NULL;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_CREATE;
pIoStackLocation->DeviceObject = RootDeviceObject;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Create.SecurityContext = &ioSecurityContext;
pIoStackLocation->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions;
pIoStackLocation->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
pIoStackLocation->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
pIoStackLocation->Parameters.Create.EaLength = EaLength;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(RootDeviceObject, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);
}

// 判断IRP处理结果
status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
ObDereferenceObject(pFileObject);
DbgPrint("IRP FAILED!\n");
return status;
}

InterlockedIncrement(&pFileObject->DeviceObject->ReferenceCount);
if (pFileObject->Vpb)
{
InterlockedIncrement(&pFileObject->Vpb->ReferenceCount);
}

// 返回文件对象
*ppFileObject = pFileObject;

return status;
}


// 文件遍历
// ZwQueryDirectoryFile
NTSTATUS IrpQueryDirectoryFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PUNICODE_STRING FileName OPTIONAL)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
RtlZeroMemory(FileInformation, Length);
pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->UserBuffer = FileInformation;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;
pIrp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
pIoStackLocation->MinorFunction = IRP_MN_QUERY_DIRECTORY;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Flags = SL_RESTART_SCAN;
pIoStackLocation->Parameters.QueryDirectory.Length = Length;
pIoStackLocation->Parameters.QueryDirectory.FileName = FileName;
pIoStackLocation->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}


// 获取文件的信息
// ZwQueryInformationFile
NTSTATUS IrpQueryInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
RtlZeroMemory(FileInformation, Length);
pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->AssociatedIrp.SystemBuffer = FileInformation;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.QueryFile.Length = Length;
pIoStackLocation->Parameters.QueryFile.FileInformationClass = FileInformationClass;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}



// 设置文件信息
// ZwSetInformationFile
NTSTATUS IrpSetInformationFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->AssociatedIrp.SystemBuffer = FileInformation;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_SET_INFORMATION;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.SetFile.Length = Length;
pIoStackLocation->Parameters.SetFile.FileInformationClass = FileInformationClass;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}


// 读文件
// ZwReadFile
NTSTATUS IrpReadFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 调整参数
if (NULL == ByteOffset)
{
if (0 == (FO_SYNCHRONOUS_IO & pFileObject->Flags))
{
return STATUS_INVALID_PARAMETER;
}
ByteOffset = &pFileObject->CurrentByteOffset;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
RtlZeroMemory(Buffer, Length);
pIrp->MdlAddress = MmCreateMdl(NULL, Buffer, Length);
if (NULL == pIrp->MdlAddress)
{
IoFreeIrp(pIrp);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(pIrp->MdlAddress);

pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->Flags = IRP_READ_OPERATION;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_READ;
pIoStackLocation->MinorFunction = IRP_MN_NORMAL;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Read.Length = Length;
pIoStackLocation->Parameters.Read.ByteOffset = *ByteOffset;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}


// 写文件
// ZwWriteFile
NTSTATUS IrpWriteFile(
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL
)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIrp = NULL;
KEVENT kEvent = { 0 };
PIO_STACK_LOCATION pIoStackLocation = NULL;
PDEVICE_OBJECT pDevObj = NULL;

// 判断参数是否有效
if ((NULL == pFileObject) ||
(NULL == pFileObject->Vpb) ||
(NULL == pFileObject->Vpb->DeviceObject))
{
return STATUS_UNSUCCESSFUL;
}

// 调整参数
if (NULL == ByteOffset)
{
if (0 == (FO_SYNCHRONOUS_IO & pFileObject->Flags))
{
return STATUS_INVALID_PARAMETER;
}
ByteOffset = &pFileObject->CurrentByteOffset;
}

// 获取设备对象
pDevObj = pFileObject->Vpb->DeviceObject;

// 创建IRP
pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
if (NULL == pIrp)
{
return STATUS_UNSUCCESSFUL;
}

// 创建事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

// 设置IRP
pIrp->MdlAddress = MmCreateMdl(NULL, Buffer, Length);
if (NULL == pIrp->MdlAddress)
{
IoFreeIrp(pIrp);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(pIrp->MdlAddress);

pIrp->UserEvent = &kEvent;
pIrp->UserIosb = IoStatusBlock;
pIrp->Flags = IRP_WRITE_OPERATION;
pIrp->RequestorMode = KernelMode;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

// 获取下一个IRP的IO_STACK_LOCATION并设置
pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
pIoStackLocation->MajorFunction = IRP_MJ_WRITE;
pIoStackLocation->MinorFunction = IRP_MN_NORMAL;
pIoStackLocation->DeviceObject = pDevObj;
pIoStackLocation->FileObject = pFileObject;
pIoStackLocation->Parameters.Write.Length = Length;
pIoStackLocation->Parameters.Write.ByteOffset = *ByteOffset;

// 设置完成实例, 以便通知IRP处理完成, 释放资源
IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

// 发送IRP
status = IoCallDriver(pDevObj, pIrp);

// 等待IRP的处理
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
}

status = IoStatusBlock->Status;
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}