Joe1sn's Cabinet

windows内核驱动 6-链表与进程

感觉和之前学的bh文章有大量重复

记录进程

1
2
3
4
5
6
typedef struct _Process {
LIST_ENTRY list;
HANDLE pid;
PEPROCESS pEprocessObj;
char ProcessName[0x10];
} MyProcess, *pMyProcess;

两个extern需要声明

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
NTKERNELAPI PUCHAR PsGetProcessImageFileName(PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS* Process);

VOID ProcessNotify(HANDLE pid, HANDLE pid2, BOOLEAN value) {
UNREFERENCED_PARAMETER(pid);
if (value) {
DbgPrint("Process Created %d\n", pid2);
PEPROCESS CurrentProc = NULL;//PsGetCurrentProcess();
PsLookupProcessByProcessId(pid2, &CurrentProc);
if (!CurrentProc) {
return;
}

PUCHAR processname = PsGetProcessImageFileName(CurrentProc);
DbgPrint("Process Name %s\n", processname);

}

return;
}
....//驱动加载
LIST_ENTRY listhead = { 0 };
InitializeListHead(&listhead);
PsSetCreateProcessNotifyRoutine(ProcessNotify, FALSE);
....//驱动卸载
PsSetCreateProcessNotifyRoutine(ProcessNotify, TRUE);

image-20240320101340059

将获取到的链表进行链接

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
VOID ProcessNotify(HANDLE pid, HANDLE pid2, BOOLEAN value) {
UNREFERENCED_PARAMETER(pid);
if (value) {
DbgPrint("Process Created %d\n", pid2);
PEPROCESS CurrentProc = NULL;//PsGetCurrentProcess();
PsLookupProcessByProcessId(pid2, &CurrentProc);
if (!CurrentProc) {
return;
}

pMyProcess PMyProcess = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(MyProcess),'cpym');
if (PMyProcess) {
RtlZeroMemory(PMyProcess, sizeof(MyProcess));

// init value
PMyProcess->pid = pid2;
PMyProcess->pEprocessObj = CurrentProc;
PMyProcess->ProcessName = PsGetProcessImageFileName(CurrentProc);
KIRQL irql = 0;

KeAcquireSpinLock(&kSpinLock, &irql);
InsertTailList(&listhead, &(PMyProcess->list));
KeReleaseSpinLock(&kSpinLock, irql);
}
PUCHAR processname = PsGetProcessImageFileName(CurrentProc);
DbgPrint("Process Name %s\n", processname);

}

return;
}


//....
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
// ....
InitializeListHead(&listhead);
PsSetCreateProcessNotifyRoutine(ProcessNotify, FALSE);

return Status;
}

//...
VOID
DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("Driver Stopping -> %wZ\n", &DriverObject->DriverName);
DbgPrint("Device Stopping\n");
if (DriverObject->DeviceObject) {
IoDeleteDevice(DriverObject->DeviceObject);

UNICODE_STRING symname = { 0 };
RtlInitUnicodeString(&symname, SYM_NAME);
IoDeleteSymbolicLink(&symname);
}
PsSetCreateProcessNotifyRoutine(ProcessNotify, TRUE);

PLIST_ENTRY temp = NULL;
pMyProcess tempMy = NULL;
while (listhead.Blink != &listhead)
{
temp = RemoveTailList(&listhead);
tempMy = CONTAINING_RECORD(temp, MyProcess, list);

DbgPrint("link -- name: %s -- pid: %d -- obj: %p\n", tempMy->ProcessName, tempMy->pid, tempMy->pEprocessObj);
ExFreePool(temp);
}

}

image-20240320104220909

禁止程序执行

关于进程的遍历这里给出第二种方式,使用PsSetCreateProcessNotifyRoutineEx中使用PPS_CREATE_NOTIFY_INFO

这个API有一个很坑的地方就是必须在 链接器 中加上/INTEGRITYCHECK

回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
VOID MyBlockProcessNotify(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo) {
//UNREFERENCED_PARAMETER(Process);
//DbgPrint("ProcessCreated\n");
if (CreateInfo) {
CHAR Targetp[] = "calc.exe";
PCHAR ProcessName = (PCHAR)PsGetProcessImageFileName(Process);
DbgPrint("now running: %s, pid: %d\n", ProcessName, ProcessId);

if (!strcmp(Targetp, ProcessName)) {
CreateInfo->CreationStatus = STATUS_UNSUCCESSFUL;
}
}
}

注册和释放

1
2
3
PsSetCreateProcessNotifyRoutineEx(MyBlockProcessNotify, FALSE);
PsSetCreateProcessNotifyRoutineEx(MyBlockProcessNotify, TRUE);

image-20240320112936409

参考

https://cloud.tencent.com/developer/article/2195942

https://www.bilibili.com/video/BV1QJ411A7kR