枚舉進程模塊的方法有很多種,常見的有枚舉PEB和內存搜索法,今天,先來看看實現起來最簡單的枚舉PEB實現獲取進程模塊列表。
首先,慣例是各種繁瑣的結構體定義。需要包含 ntifs.h 和 WinDef.h, 此處不再列出,各位看官根據情況自行添加。
- typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);
- typedef ULONG PPS_POST_PROCESS_INIT_ROUTINE;
- typedef struct _PEB_LDR_DATA {
- BYTE Reserved1[8];
- PVOID Reserved2[3];
- LIST_ENTRY InMemoryOrderModuleList;
- } PEB_LDR_DATA, *PPEB_LDR_DATA;
- typedef struct _RTL_USER_PROCESS_PARAMETERS {
- BYTE Reserved1[16];
- PVOID Reserved2[10];
- UNICODE_STRING ImagePathName;
- UNICODE_STRING CommandLine;
- } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
- typedef struct _PEB {
- BYTE Reserved1[2];
- BYTE BeingDebugged;
- BYTE Reserved2[1];
- PVOID Reserved3[2];
- PPEB_LDR_DATA Ldr;
- PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
- BYTE Reserved4[104];
- PVOID Reserved5[52];
- PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
- BYTE Reserved6[128];
- PVOID Reserved7[1];
- ULONG SessionId;
- } PEB, *PPEB;
- typedef struct _LDR_DATA_TABLE_ENTRY
- {
- LIST_ENTRY InLoadOrderLinks;
- LIST_ENTRY InMemoryOrderLinks;
- LIST_ENTRY InInitializationOrderLinks;
- PVOID DllBase;
- PVOID EntryPoint;
- DWORD SizeOfImage;
- UNICODE_STRING FullDllName;
- UNICODE_STRING BaseDllName;
- DWORD Flags;
- WORD LoadCount;
- WORD TlsIndex;
- LIST_ENTRY HashLinks;
- PVOID SectionPointer;
- DWORD CheckSum;
- DWORD TimeDateStamp;
- PVOID LoadedImports;
- PVOID EntryPointActivationContext;
- PVOID PatchInformation;
- }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);
typedef ULONG PPS_POST_PROCESS_INIT_ROUTINE;
typedef struct _PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
DWORD SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
DWORD Flags;
WORD LoadCount;
WORD TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
DWORD CheckSum;
DWORD TimeDateStamp;
PVOID LoadedImports;
PVOID EntryPointActivationContext;
PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
下面進入真正的實現代碼:
- NTSTATUS GetProcessModules(ULONG ulProcessId)
- {
- NTSTATUS nStatus;
- //PEB結構指針
- PPEB pPEB = NULL;
- //EPROCESS結構指針
- PEPROCESS pEProcess = NULL;
- //查找的函數名稱
- UNICODE_STRING uniFunctionName;
- //進程參數信息
- PRTL_USER_PROCESS_PARAMETERS pParam = NULL;
- //LDR數據結構
- PPEB_LDR_DATA pPebLdrData = NULL;
- //LDR鏈表入口
- PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
- //鏈表頭節點、尾節點
- PLIST_ENTRY pListEntryStart = NULL;
- PLIST_ENTRY pListEntryEnd = NULL;
- //函數指針
- PFNPsGetProcessPeb PsGetProcessPeb = NULL;
- //保存APC狀態
- KAPC_STATE KAPC ={0};
- //是否已經附加到進程
- BOOLEAN bIsAttached = FALSE;
- //獲取進程的EPROCESS結構指針
- nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);
- if (!NT_SUCCESS(nStatus))
- {
- return STATUS_UNSUCCESSFUL;
- }
- //查找函數地址
- RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
- PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);
- if (PsGetProcessPeb == NULL)
- {
- KdPrint(("Get PsGetProcessPeb Failed~!\n"));
- return STATUS_UNSUCCESSFUL;
- }
- //獲取PEB指針
- pPEB = PsGetProcessPeb(pEProcess);
- if (pPEB == NULL)
- {
- KdPrint(("Get pPEB Failed~!\n"));
- return STATUS_UNSUCCESSFUL;
- }
- //附加到進程
- KeStackAttachProcess(pEProcess, &KAPC);
- bIsAttached = TRUE;
- //指向LDR
- pPebLdrData = pPEB->Ldr;
- //頭節點、尾節點
- pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;
- //開始遍歷_LDR_DATA_TABLE_ENTRY
- do
- {
- //通過_LIST_ENTRY的Flink成員獲取_LDR_DATA_TABLE_ENTRY結構
- pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
- //輸出DLL全路徑
- KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName));
- pListEntryStart = pListEntryStart->Flink;
- }while(pListEntryStart != pListEntryEnd);
- //Detach進程
- if (bIsAttached != FALSE)
- {
- KeUnstackDetachProcess(&KAPC);
- }
- //減少引用計數
- if (pEProcess != NULL)
- {
- ObDereferenceObject(pEProcess);
- pEProcess = NULL;
- }
- return STATUS_SUCCESS;
- }
NTSTATUS GetProcessModules(ULONG ulProcessId)
{
NTSTATUS nStatus;
//PEB結構指針
PPEB pPEB = NULL;
//EPROCESS結構指針
PEPROCESS pEProcess = NULL;
//查找的函數名稱
UNICODE_STRING uniFunctionName;
//進程參數信息
PRTL_USER_PROCESS_PARAMETERS pParam = NULL;
//LDR數據結構
PPEB_LDR_DATA pPebLdrData = NULL;
//LDR鏈表入口
PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
//鏈表頭節點、尾節點
PLIST_ENTRY pListEntryStart = NULL;
PLIST_ENTRY pListEntryEnd = NULL;
//函數指針
PFNPsGetProcessPeb PsGetProcessPeb = NULL;
//保存APC狀態
KAPC_STATE KAPC ={0};
//是否已經附加到進程
BOOLEAN bIsAttached = FALSE;
//獲取進程的EPROCESS結構指針
nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);
if (!NT_SUCCESS(nStatus))
{
return STATUS_UNSUCCESSFUL;
}
//查找函數地址
RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);
if (PsGetProcessPeb == NULL)
{
KdPrint(("Get PsGetProcessPeb Failed~!\n"));
return STATUS_UNSUCCESSFUL;
}
//獲取PEB指針
pPEB = PsGetProcessPeb(pEProcess);
if (pPEB == NULL)
{
KdPrint(("Get pPEB Failed~!\n"));
return STATUS_UNSUCCESSFUL;
}
//附加到進程
KeStackAttachProcess(pEProcess, &KAPC);
bIsAttached = TRUE;
//指向LDR
pPebLdrData = pPEB->Ldr;
//頭節點、尾節點
pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;
//開始遍歷_LDR_DATA_TABLE_ENTRY
do
{
//通過_LIST_ENTRY的Flink成員獲取_LDR_DATA_TABLE_ENTRY結構
pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
//輸出DLL全路徑
KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName));
pListEntryStart = pListEntryStart->Flink;
}while(pListEntryStart != pListEntryEnd);
//Detach進程
if (bIsAttached != FALSE)
{
KeUnstackDetachProcess(&KAPC);
}
//減少引用計數
if (pEProcess != NULL)
{
ObDereferenceObject(pEProcess);
pEProcess = NULL;
}
return STATUS_SUCCESS;
}
下面是運行截圖:

本帖為原創,轉帖請說明出處,謝謝合作。
本帖地址:http://blog.csdn.net/sonsie007/article/details/22622177

