包含的頭文件函數
#include <ntifs.h>測試
#include <ntstrsafe.h>orm
聲明的API函數blog
NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);進程
NTKERNELAPI PPEB_EX PsGetProcessPeb(PEPROCESS Process);it
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE Id, PEPROCESS *Process);io
NTKERNELAPI NTSTATUS PsLookupThreadByThreadId(HANDLE Id, PETHREAD *Thread);table
NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);form
//NTKERNELAPI VOID NTAPI KeAttachProcess(PEPROCESS Process);List
//NTKERNELAPI VOID NTAPI KeDetachProcess();
//NTKERNELAPI VOID NTAPI KeStackAttachProcess(PEPROCESS Process, PKAPC_STATE ApcState);
//NTKERNELAPI VOID NTAPI KeUnstackDetachProcess(PKAPC_STATE ApcState);
由於要經過PEPROCESS 來獲取進程和模塊,因此還要用到幾個結構體要,在WinDbg 可看到。
這裏新建一個頭文件,包含了PEB等信息
#include "peb.h"
以下:
#pragma once
#include <ntifs.h>
typedef struct _PEB_LDR_DATA_EX
{
ULONG Length; // +0x00
BOOLEAN Initialized; // +0x04
PVOID SsHandle; // +0x08
LIST_ENTRY InLoadOrderModuleList; // +0x0c
LIST_ENTRY InMemoryOrderModuleList; // +0x14
LIST_ENTRY InInitializationOrderModuleList;// +0x1c
}PEB_LDR_DATA_EX, *PPEB_LDR_DATA_EX;
typedef struct _LDR_DATA_TABLE_ENTRY_EX {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union {
LIST_ENTRY HashLinks;
struct {
PVOID SectionPointer;
ULONG CheckSum;
};
};
union {
ULONG TimeDateStamp;
PVOID LoadedImports;
};
PVOID EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
PVOID ContextInformation;
PVOID OriginalBase;
LARGE_INTEGER LoadTime;
} LDR_DATA_TABLE_ENTRY_EX, *PLDR_DATA_TABLE_ENTRY_EX;
typedef struct _CURDIR {
UNICODE_STRING DosPath;
PVOID Handle;
}CURDIR, *PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
STRING DosPath;
}RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
//進程參數
typedef struct _RTL_USER_PROCESS_PARAMETERS{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
PVOID StandardInput;
PVOID StandardOutput;
PVOID StandardError;
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32];
}RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS;
//進程環境塊(由於Windows內核有一個機構PEB,爲了避免重定義,因此就另起一個名字)
typedef struct _PEB_EX {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR SpareBool;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA_EX Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
UCHAR Reserved4[104];
PVOID Reserved5[52];
PVOID PostProcessInitRoutine;
PVOID Reserved7;
UCHAR Reserved6[128];
ULONG SessionId;
} PEB_EX, *PPEB_EX;
用於遍歷進程函數
void EnumProcess(PEPROCESS eprocess)
{
KAPC_STATE ks;
if (!MmIsAddressValid(eprocess))
return;
//獲取 PEB信息
PPEB_EX peb = PsGetProcessPeb(eprocess);
if (!peb)
return;
//依附進程!!!!!!!!!!!!!!
KeStackAttachProcess(eprocess, &ks);
__try
{
if (PsGetProcessId(eprocess)!=0)
{
//獲取 進程參數
PRTL_USER_PROCESS_PARAMETERS rtl_user_process_param =
(PRTL_USER_PROCESS_PARAMETERS)peb->ProcessParameters;
DbgPrint("CommandLine:%wZ\n", &rtl_user_process_param->CommandLine);
DbgPrint("ImagePath=%wZ\n", &rtl_user_process_param->ImagePathName);
//DbgPrint("Window Title=%wZ\n", &rtl_user_process_param->WindowTitle);
DbgPrint("——————————————————————————————");
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//DbgPrint("Can not Process...");
}
//取消依附進程
KeUnstackDetachProcess(&ks);
}
//遍歷模塊,大致上和遍歷進程同樣,但也要注意
void EnumModules(PEPROCESS eprocess)
{
KAPC_STATE ks;
if (!MmIsAddressValid(eprocess))
return;
//獲取 PEB信息
PPEB_EX peb = PsGetProcessPeb(eprocess);
if (!peb)
return;
//依附進程!!!!!!!!!!!!!!
KeStackAttachProcess(eprocess, &ks);
__try
{
PPEB_LDR_DATA_EX peb_LDR_data = (PPEB_LDR_DATA_EX)peb->Ldr;
PLIST_ENTRY list_entry = &peb_LDR_data->InLoadOrderModuleList;
//先獲取第一個
PLIST_ENTRY currentList = list_entry->Flink;
while (currentList!=list_entry)
{
PLDR_DATA_TABLE_ENTRY_EX ldr_data_table_entry =
(PLDR_DATA_TABLE_ENTRY_EX)currentList;
DbgPrint("Module Base=%p DllPath=%wZ\n",
ldr_data_table_entry->DllBase,
&ldr_data_table_entry->FullDllName);
//指向下一個
currentList = currentList->Flink;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//DbgPrint("Can not Modules...");
}
//取消依附進程
KeUnstackDetachProcess(&ks);
}
//這個函數把上面兩個函數整合在一塊兒了
VOID EnumProcessModuleInformations()
{
//第一個進程環境塊
PEPROCESS eprocess=PsGetCurrentProcess();
PEPROCESS eprocess_first = eprocess;
while (1)
{
//獲取進程
EnumProcess(eprocess);
//下一個進程,我獲取的是WinXP的 EPROCESS !
eprocess = (PEPROCESS)(*(ULONG*)((ULONG)eprocess + 0x88) - 0x88);
if (eprocess == eprocess_first)
{
break;
}
}
eprocess= eprocess_first;
while (1)
{
//獲取模塊
EnumModules(eprocess);
//下一個進程
eprocess = (PEPROCESS)(*(ULONG*)((ULONG)eprocess + 0x88) - 0x88);
if (eprocess == eprocess_first)
{
break;
}
}
}
7
//卸載函數很簡單
VOID unload(PDRIVER_OBJECT p)
{
DbgPrint("UnloadDriver...");
}
8
//驅動入口函數
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver_Obj, PUNICODE_STRING pRegisterPath)
{
DbgPrint("DriverEntry...");
pDriver_Obj->DriverUnload = unload;
DbgPrint("DriverName:%wZ RegisterPath:%wZ \n ",
&pDriver_Obj->DriverName,
pRegisterPath);
//這裏調用
EnumProcessModuleInformations();
return STATUS_SUCCESS;
}
9
最後,基本上OK了,附上一張測試圖:
Windows內核驅動EPROCESS遍歷進程模塊 END