内核进程线程和模块是操作系统内核中非常重要的概念。它们是操作系统的核心部分,用于管理系统资源和处理系统请求。在驱动安全开发中,理解内核进程线程和模块的概念对于编写安全的内核驱动程序至关重要。 内核进程是在操作系统内核中运行的程序。每个进程都有一个唯一的进程标识符(PID),它用于在系统中唯一地标识该进程。在内核中,进程被表示为一个进程控制块(PCB),它包含有关进程的信息,如进程状态、优先级、内存使用情况等。枚举进程可以让我们获取当前系统中所有正在运行的进程的PID和其他有用的信息,以便我们可以监视和管理系统中的进程。 线程是在进程内部执行的轻量级执行单元。与进程不同,线程不拥有自己的地址空间和系统资源,它们共享它们所属进程的资源。在内核中,线程被表示为线程控制块(TCB),它包含有关线程的信息,如线程状态、调度信息、执行上下文等。枚举线程可以让我们获取当前系统中所有正在运行的线程的PID、线程ID和其他有用的信息,以便我们可以监视和管理系统中的线程。 内核模块是一种可加载的内核组件,它可以动态地添加到内核中。内核模块通常用于向内核添加新的设备驱动程序或系统功能。在驱动安全开发中,理解内核模块的概念对于编写安全的内核驱动程序非常重要。枚举内核模块可以让我们获取当前系统中加载的所有内核模块的名称、版本号和其他有用的信息,以便我们可以分析和调试内核模块。 在总体上,内核进程线程和模块是操作系统内核中非常重要的概念。通过了解这些概念,我们可以更好地理解操作系统内部的工作原理,从而编写更安全的内核驱动程序。 4.2.1 内核中实现枚举进程进程就是活动起来的程序,每一个进程在内核里,都有一个名为 EPROCESS 的结构记录它的详细信息,其中就包括进程名,PID,PPID,进程路径等,通常在应用层枚举进程只列出所有进程的编号即可,不过在内核层需要把它的 EPROCESS 地址给列举出来。 在内核中枚举进程我们可通过循环语句遍历进程句柄0-100000 以内的值,每次通过PsLookupProcessByProcessId 打开一个进程并得到进程EPROCESS 结构,当获取到该结构体时只需要调用不同的三个内核函数即可获取到当前句柄所对应的进程相关信息。 当我们需要通过EPROCESS 得到进程名 时可使用PsGetProcessImageFileName() 这个内核函数,该函数的具体定义规范如下所示; PCHAR PsGetProcessImageFileName( PEPROCESS Process );
其中,参数Process 是一个PEPROCESS 类型的指针,表示要获取映像文件名的进程的EPROCESS 结构体指针;返回值是一个PCHAR 类型的指针,指向包含指定进程映像文件名的空字符结尾字符串。 与之功能类似,当我们需要通过EPROCESS 获取进程PID 时,则可以调用PsGetProcessId() 来获取到,该函数的具体定义规范如下所示; HANDLE PsGetProcessId( PEPROCESS Process );
其中,参数Process 是一个PEPROCESS 类型的指针,表示要获取进程ID 的进程的EPROCESS 结构体指针;返回值是一个HANDLE 类型的进程ID 值。 而如果当我们想要获取到进程的父进程时,则同样可使用PsGetProcessInheritedFromUniqueProcessId() 来获取,该函数的具体定义规范如下所示; HANDLE PsGetProcessInheritedFromUniqueProcessId( PEPROCESS Process );
其中,参数Process 是一个PEPROCESS 类型的指针,表示要获取父进程ID的进程的EPROCESS 结构体指针;返回值是一个HANDLE 类型的父进程ID值。 有了这三个函数的支持,我们就可以实现遍历当前所有运行的进程啦,具体实现代码如下所示; #include <ntifs.h>
NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process);
NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);
PEPROCESS LookupProcess(HANDLE Pid) { PEPROCESS eprocess = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; Status = PsLookupProcessByProcessId(Pid, &eprocess); if (NT_SUCCESS(Status)) return eprocess; return NULL; }
VOID EnumProcess() { PEPROCESS eproc = NULL; for (int temp = 0; temp < 100000; temp += 4) { eproc = LookupProcess((HANDLE)temp); if (eproc != NULL) { DbgPrint("进程名: %s --> 进程PID = %d --> 父进程PPID = %d\r\n",PsGetProcessImageFileName(eproc),PsGetProcessId(eproc), PsGetProcessInheritedFromUniqueProcessId(eproc)); ObDereferenceObject(eproc); } } }
VOID UnDriver(PDRIVER_OBJECT driver) { DbgPrint(("Uninstall Driver Is OK \n")); }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) { EnumProcess(); Driver->DriverUnload = UnDriver; return STATUS_SUCCESS; }
输出效果图如下所示: |