[toc]windows
整理一下windows内核中.经常使用的代码.这里只整理下进程的相关代码.函数
内核中记录进程的结构体是EPROCESS结构.因此只须要遍历这个结构便可.标准方法可使用ZwQuerySystemInformation函数.使用SystemProcessInformation功能号. 另外也有不少种枚举进程的方法好比找到EPROCESS结构进行枚举的.(CPU结构体 KPCR)等等.不过兼容性都是不太好.另外一种方法是枚举句柄表 PspCidTable里面有记录EPROCESS 也能检查出断链等隐藏的进程.不过缺点就是. PspCidTable并非一个公开的变量.要活的它的地址的话.你就须要使用硬编码或者符号了.可是你们知道使用硬编码那么就不会跟着系统走了.若是想要通用那么就最好不要使用. 这里看到网上有更简单的方法.
只用使用几个公开API便可.编码
PsLookUpProcessByProcessId 根据进程Pid返回进程的EPROCESS3d
ObDereferenceObject 返回的EPROCESS会被引用一次,进行解引用.code
另外还须要几个API能够得到进程的名字 进程的父PID等等orm
遍历多大,根据进程PID排列.步进为4, 总工是 2^31 -1便可.blog
具体代码以下:进程
#include <ntifs.h> NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process); //未公开的进行导出便可 NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);//未公开进行导出 void DriverUnLoad(PDRIVER_OBJECT pDriverObj) { KdPrint(("驱动卸载成功")); } /* 1.枚举全部进程. 2^31方 */ PEPROCESS GetEprocessByPid(HANDLE pid) { //根据PID 返回PEPROCESS PEPROCESS pEpro = NULL; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; ntStatus = PsLookupProcessByProcessId(pid, &pEpro); if (NT_SUCCESS(ntStatus)) { return pEpro; } return NULL; } void IteratorProcess() { PEPROCESS pCurrentEprocess = NULL; for (int i = 0; i < 2147483648; i += 4) { pCurrentEprocess = GetEprocessByPid((HANDLE)i); if (pCurrentEprocess != NULL) { DbgPrint("进程名字为: %s 进程PID = %d 进程的父Pid = %d\r\n", PsGetProcessImageFileName(pCurrentEprocess), PsGetProcessId(pCurrentEprocess), PsGetProcessInheritedFromUniqueProcessId(pCurrentEprocess)); ObDereferenceObject(pCurrentEprocess); //解引用 } } } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { ULONG iCount = 0; NTSTATUS ntStatus; pDriverObj->DriverUnload = DriverUnLoad; IteratorProcess(); //遍历进程 return STATUS_SUCCESS; }
结果
内存
在Ring3咱们想暂停与恢复进程通常都是使用NativeApi.动态获取等等.
在内核中同样也有.在VISTA以后,便有导出了.ci
未挂起前
加载驱动进行挂起
#include <ntifs.h> NTKERNELAPI NTSTATUS PsSuspendProcess(PEPROCESS proc); //暂停进程 NTKERNELAPI NTSTATUS PsResumeProcess(PEPROCESS proc); //恢复进程 void DriverUnLoad(PDRIVER_OBJECT pDriverObj) { KdPrint(("驱动卸载成功")); } /* 1.枚举全部进程. 2^31方 */ PEPROCESS GetEprocessByPid(HANDLE pid) { //根据PID 返回PEPROCESS PEPROCESS pEpro = NULL; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; ntStatus = PsLookupProcessByProcessId(pid, &pEpro); if (NT_SUCCESS(ntStatus)) { return pEpro; } return NULL; } void TestSusPendProcess(ULONG pid) { PEPROCESS pCurrentEprocess = NULL; pCurrentEprocess = GetEprocessByPid((HANDLE)pid); if (pCurrentEprocess != NULL) { PsSuspendProcess(pCurrentEprocess); DbgPrint("挂起进程成功\r\n"); ObDereferenceObject(pCurrentEprocess); } } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { ULONG iCount = 0; NTSTATUS ntStatus; pDriverObj->DriverUnload = DriverUnLoad; //IteratorProcess(); //遍历进程 TestSusPendProcess(2728); //挂起进程,传入指定PID return STATUS_SUCCESS; }
恢复进程代码同上.不一一举例.
标准方法结束 就是采用ZwOpenProcess 打开进程获取句柄.而后使用内核函数 ZwTerminateProcess结束. 最后ZwClose关闭句柄.
非标准结束就是Attach进程.而后内存清零来结束这个进程.若是能Attach上.那么就能够用来强杀进程.固然Attach能够. 本身修改页表.(PDE PTE)等.修改指定内存也是同样的.
代码以下
void ZwKillProcess(ULONG pid) { HANDLE ProcessHandle = NULL; OBJECT_ATTRIBUTES obj; CLIENT_ID cid = { 0 }; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; InitializeObjectAttributes(&obj,NULL,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,NULL,NULL); cid.UniqueProcess = (HANDLE)pid; cid.UniqueThread = 0; ntStatus = ZwOpenProcess(&ProcessHandle, GENERIC_ALL, &obj, &cid); if (NT_SUCCESS(ntStatus)) { ZwTerminateProcess(ProcessHandle, 0); ZwClose(ProcessHandle); } ZwClose(ProcessHandle); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { ULONG iCount = 0; NTSTATUS ntStatus; pDriverObj->DriverUnload = DriverUnLoad; //IteratorProcess(); //遍历进程 ZwKillProcess(2728); //挂起进程,传入指定PID return STATUS_SUCCESS; }
非标准的方式就是Attach进进程进行内存清零.这里提供了两种方法.原理是同样
KeAttachProcess方法 与 KeStackAttachProcess方法. 其中第一种属于旧方法了.根据MSDN所说API已经升级为了KeStackAttachProcess
代码以下
#include <ntifs.h> NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process); //未公开的进行导出便可 NTKERNELAPI VOID NTAPI KeAttachProcess(PEPROCESS Process); NTKERNELAPI VOID NTAPI KeDetachProcess(); void DriverUnLoad(PDRIVER_OBJECT pDriverObj) { KdPrint(("驱动卸载成功")); } /* 1.枚举全部进程. 2^31方 */ PEPROCESS GetEprocessByPid(HANDLE pid) { //根据PID 返回PEPROCESS PEPROCESS pEpro = NULL; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; ntStatus = PsLookupProcessByProcessId(pid, &pEpro); if (NT_SUCCESS(ntStatus)) { return pEpro; } return NULL; } //新方法 void MemKillProcess(HANDLE pid) { PEPROCESS proc = NULL; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; PKAPC_STATE pApcState = NULL; PsLookupProcessByProcessId((HANDLE)pid,&proc); if (proc == 0) { return; } //KeAttachProcess(proc); //KeDetachProcess() 等都已通过时.因此使用新的 pApcState = (PKAPC_STATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(PKAPC_STATE), '1111'); if (NULL == pApcState) { ObDereferenceObject(proc); return; } __try{ KeStackAttachProcess(proc, pApcState); //KeAttachProcess(proc); for (int i = 0x10000; i < 0x20000000; i += PAGE_SIZE) { __try { memset((PVOID)i, 0, PAGE_SIZE); } __except (1) { ; //内部处理异常 } } KeUnstackDetachProcess(pApcState); //KeDetachProcess(); ObDereferenceObject(proc); return; } __except (1) { DbgPrint("强杀出错\r\n"); KeUnstackDetachProcess(pApcState); ObDereferenceObject(proc); } return; } HANDLE GetPidByProcessName(char *ProcessName) { PEPROCESS pCurrentEprocess = NULL; HANDLE pid = 0; DbgPrint("寻找名为%s的PID\r\n", ProcessName); for (int i = 0; i < 2147483647; i += 4) { pCurrentEprocess = GetEprocessByPid((HANDLE)i); if (pCurrentEprocess != NULL) { /*DbgPrint("进程名字为: %s 进程PID = %d 进程的父Pid = %d\r\n", PsGetProcessImageFileName(pCurrentEprocess), PsGetProcessId(pCurrentEprocess), PsGetProcessInheritedFromUniqueProcessId(pCurrentEprocess));*/ pid = PsGetProcessId(pCurrentEprocess); if (strstr(PsGetProcessImageFileName(pCurrentEprocess), ProcessName) != NULL) { ObDereferenceObject(pCurrentEprocess); //解引用 DbgPrint("找到了\r\n"); return pid; } ObDereferenceObject(pCurrentEprocess); //解引用 } } DbgPrint("未找到\r\n"); return (HANDLE)-1; } //旧方法 void OldMemKillProcess(HANDLE pid) { SIZE_T i = 0; //依附进程 PEPROCESS proc = 0; PsLookupProcessByProcessId(pid, &proc); if (NULL == proc) { return; } KeAttachProcess((PEPROCESS)proc); //这里改成指定进程的 EPROCESS for (i = 0x10000; i < 0x20000000; i += PAGE_SIZE) { __try { memset((PVOID)i, 0, PAGE_SIZE); //把进程内存所有置零 } _except(1) { ; } } //退出依附进程 KeDetachProcess(); ObDereferenceObject(proc); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { ULONG iCount = 0; NTSTATUS ntStatus; pDriverObj->DriverUnload = DriverUnLoad; MemKillProcess(GetPidByProcessName("calc.exe")); //新方法 OldMemKillProcess(GetPidByProcessName("calc.exe"));//旧方法 return STATUS_SUCCESS; }
两种方法在win7 64上面均可以.