[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上面均可以.