Windows内核驱动EPROCESS遍历进程模块

  • 2019 年 11 月 15 日
  • 筆記

包含的头文件  #include <ntifs.h>  #include <ntstrsafe.h>  声明的API函数  NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);  NTKERNELAPI  PPEB_EX  PsGetProcessPeb(PEPROCESS Process);  NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE Id, PEPROCESS *Process);  NTKERNELAPI NTSTATUS PsLookupThreadByThreadId(HANDLE Id, PETHREAD *Thread);  NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);  //NTKERNELAPI VOID NTAPI KeAttachProcess(PEPROCESS Process);  //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:%wZn", &rtl_user_process_param->CommandLine);  DbgPrint("ImagePath=%wZn", &rtl_user_process_param->ImagePathName);  //DbgPrint("Window Title=%wZn", &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=%wZn",  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