代码语言:javascript复制
包含的头文件
#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