逐渐将博客园的文章搬到CSDN来吧。
基于上一篇文章获取peb结构,大概了解了peb的获取方法,但是那个方法只能获得当前进程的PEB,不能获得其他的进程的PEB。根据那个思想,获得其他进程PEB则需要注入,得到进程信息,然后进程间通信,将信息返回来,经过考虑,这个方法太复杂。
下面介绍的方法是 用了一个未公开的函数NtQueryInformationProcess,获得进程信息,然后去读对方进程ReadProcessMemory。
结构体是使用的一个模板,从别处借鉴的。
#pragma once
#include
#include
#include
#include
#define NT_SUCCESS(x) ((x) >= 0)
#define ProcessBasicInformation 0
typedef
NTSTATUS(WINAPI *pfnNtWow64QueryInformationProcess64)
(HANDLE ProcessHandle, UINT32 ProcessInformationClass,
PVOID ProcessInformation, UINT32 ProcessInformationLength,
UINT32* ReturnLength);
typedef
NTSTATUS(WINAPI *pfnNtWow64ReadVirtualMemory64)
(HANDLE ProcessHandle, PVOID64 BaseAddress,
PVOID BufferData, UINT64 BufferLength,
PUINT64 ReturnLength);
typedef
NTSTATUS(WINAPI *pfnNtQueryInformationProcess)
(HANDLE ProcessHandle, ULONG ProcessInformationClass,
PVOID ProcessInformation, UINT32 ProcessInformationLength,
UINT32* ReturnLength);
template
struct _UNICODE_STRING_T
{
WORD Length;
WORD MaximumLength;
T Buffer;
};
template
struct _LIST_ENTRY_T
{
T Flink;
T Blink;
};
template
struct _PEB_T
{
typedef T type;
union
{
struct
{
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE BitField;
};
T dummy01;
};
T Mutant;
T ImageBaseAddress;
T Ldr;
T ProcessParameters;
T SubSystemData;
T ProcessHeap;
T FastPebLock;
T AtlThunkSListPtr;
T IFEOKey;
T CrossProcessFlags;
T UserSharedInfoPtr;
DWORD SystemReserved;
DWORD AtlThunkSListPtr32;
T ApiSetMap;
T TlsExpansionCounter;
T TlsBitmap;
DWORD TlsBitmapBits[2];
T ReadOnlySharedMemoryBase;
T HotpatchInformation;
T ReadOnlyStaticServerData;
T AnsiCodePageData;
T OemCodePageData;
T UnicodeCaseTableData;
DWORD NumberOfProcessors;
union
{
DWORD NtGlobalFlag;
NGF dummy02;
};
LARGE_INTEGER CriticalSectionTimeout;
T HeapSegmentReserve;
T HeapSegmentCommit;
T HeapDeCommitTotalFreeThreshold;
T HeapDeCommitFreeBlockThreshold;
DWORD NumberOfHeaps;
DWORD MaximumNumberOfHeaps;
T ProcessHeaps;
T GdiSharedHandleTable;
T ProcessStarterHelper;
T GdiDCAttributeList;
T LoaderLock;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
DWORD OSPlatformId;
DWORD ImageSubsystem;
DWORD ImageSubsystemMajorVersion;
T ImageSubsystemMinorVersion;
T ActiveProcessAffinityMask;
T GdiHandleBuffer[A];
T PostProcessInitRoutine;
T TlsExpansionBitmap;
DWORD TlsExpansionBitmapBits[32];
T SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
T pShimData;
T AppCompatInfo;
_UNICODE_STRING_T CSDVersion;
T ActivationContextData;
T ProcessAssemblyStorageMap;
T SystemDefaultActivationContextData;
T SystemAssemblyStorageMap;
T MinimumStackCommit;
T FlsCallback;
_LIST_ENTRY_T FlsListHead;
T FlsBitmap;
DWORD FlsBitmapBits[4];
T FlsHighIndex;
T WerRegistrationData;
T WerShipAssertPtr;
T pContextData;
T pImageHeaderHash;
T TracingFlags;
T CsrServerReadOnlySharedMemoryBase;
};
typedef _PEB_T _PEB32;
typedef _PEB_T _PEB64;
typedef struct _STRING_32
{
WORD Length;
WORD MaximumLength;
UINT32 Buffer;
} STRING32, *PSTRING32;
typedef struct _STRING_64
{
WORD Length;
WORD MaximumLength;
UINT64 Buffer;
} STRING64, *PSTRING64;
typedef struct _RTL_DRIVE_LETTER_CURDIR_32
{
WORD Flags;
WORD Length;
ULONG TimeStamp;
STRING32 DosPath;
} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;
typedef struct _RTL_DRIVE_LETTER_CURDIR_64
{
WORD Flags;
WORD Length;
ULONG TimeStamp;
STRING64 DosPath;
} RTL_DRIVE_LETTER_CURDIR64, *PRTL_DRIVE_LETTER_CURDIR64;
typedef struct _UNICODE_STRING_32
{
WORD Length;
WORD MaximumLength;
UINT32 Buffer;
} UNICODE_STRING32, *PUNICODE_STRING32;
typedef struct _UNICODE_STRING_64
{
WORD Length;
WORD MaximumLength;
UINT64 Buffer;
} UNICODE_STRING64, *PUNICODE_STRING64;
typedef struct _CURDIR_32
{
UNICODE_STRING32 DosPath;
UINT32 Handle;
} CURDIR32, *PCURDIR32;
typedef struct _RTL_USER_PROCESS_PARAMETERS_32
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
UINT32 ConsoleHandle;
ULONG ConsoleFlags;
UINT32 StandardInput;
UINT32 StandardOutput;
UINT32 StandardError;
CURDIR32 CurrentDirectory;
UNICODE_STRING32 DllPath;
UNICODE_STRING32 ImagePathName;
UNICODE_STRING32 CommandLine;
UINT32 Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING32 WindowTitle;
UNICODE_STRING32 DesktopInfo;
UNICODE_STRING32 ShellInfo;
UNICODE_STRING32 RuntimeData;
RTL_DRIVE_LETTER_CURDIR32 CurrentDirectores[32];
ULONG EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;
typedef struct _CURDIR_64
{
UNICODE_STRING64 DosPath;
UINT64 Handle;
} CURDIR64, *PCURDIR64;
typedef struct _RTL_USER_PROCESS_PARAMETERS_64
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
UINT64 ConsoleHandle;
ULONG ConsoleFlags;
UINT64 StandardInput;
UINT64 StandardOutput;
UINT64 StandardError;
CURDIR64 CurrentDirectory;
UNICODE_STRING64 DllPath;
UNICODE_STRING64 ImagePathName;
UNICODE_STRING64 CommandLine;
UINT64 Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING64 WindowTitle;
UNICODE_STRING64 DesktopInfo;
UNICODE_STRING64 ShellInfo;
UNICODE_STRING64 RuntimeData;
RTL_DRIVE_LETTER_CURDIR64 CurrentDirectores[32];
ULONG EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS64, *PRTL_USER_PROCESS_PARAMETERS64;
typedef struct _PROCESS_BASIC_INFORMATION64 {
NTSTATUS ExitStatus;
UINT32 Reserved0;
UINT64 PebBaseAddress;
UINT64 AffinityMask;
UINT32 BasePriority;
UINT32 Reserved1;
UINT64 UniqueProcessId;
UINT64 InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION64;
typedef struct _PROCESS_BASIC_INFORMATION32 {
NTSTATUS ExitStatus;
UINT32 PebBaseAddress;
UINT32 AffinityMask;
UINT32 BasePriority;
UINT32 UniqueProcessId;
UINT32 InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION32;
实现方法:
// 枚举PEB.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "PEB.h"
#include
using namespace std;
int main()
{
HANDLE m_ProcessHandle;
int PID;
cout << "输入PID:";
cin >> PID;
m_ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
BOOL bSource = FALSE;
BOOL bTarget = FALSE;
//判断自己的位数
IsWow64Process(GetCurrentProcess(), &bSource);
//判断目标的位数
IsWow64Process(m_ProcessHandle, &bTarget);
if(bTarget == FALSE && bSource == TRUE)
{
HMODULE NtdllModule = GetModuleHandle(L"ntdll.dll");
pfnNtWow64QueryInformationProcess64 NtWow64QueryInformationProcess64 = (pfnNtWow64QueryInformationProcess64)GetProcAddress(NtdllModule, "NtWow64QueryInformationProcess64");
pfnNtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = (pfnNtWow64ReadVirtualMemory64)GetProcAddress(NtdllModule, "NtWow64ReadVirtualMemory64");
PROCESS_BASIC_INFORMATION64 pbi = { 0 };
UINT64 ReturnLength = 0;
NTSTATUS Status = NtWow64QueryInformationProcess64(m_ProcessHandle, ProcessBasicInformation, &pbi, (UINT32)sizeof(pbi), (UINT32*)&ReturnLength);
if (NT_SUCCESS(Status))
{
_PEB64* Peb = (_PEB64*)malloc(sizeof(_PEB64));
RTL_USER_PROCESS_PARAMETERS64* ProcessParameters = (RTL_USER_PROCESS_PARAMETERS64*)malloc(sizeof(RTL_USER_PROCESS_PARAMETERS64));
Status = NtWow64ReadVirtualMemory64(m_ProcessHandle, (PVOID64)pbi.PebBaseAddress,
(_PEB64*)Peb, sizeof(_PEB64), &ReturnLength);
cout << "PebBaseAddress:" << hex << pbi.PebBaseAddress << endl;
cout << "Ldr:" << hex << Peb->Ldr << endl;
cout << "ImageBaseAddress:" << hex << Peb->ImageBaseAddress << endl;
}
}
//自己是32 目标是32
else if (bTarget == TRUE && bSource == TRUE)
{
HMODULE NtdllModule = GetModuleHandle(L"ntdll.dll");
pfnNtQueryInformationProcess NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(NtdllModule,
"NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION32 pbi = { 0 };
UINT32 ReturnLength = 0;
NTSTATUS Status = NtQueryInformationProcess(m_ProcessHandle,
ProcessBasicInformation, &pbi, (UINT32)sizeof(pbi), (UINT32*)&ReturnLength);
if (NT_SUCCESS(Status))
{
_PEB32* Peb = (_PEB32*)malloc(sizeof(_PEB32));
ReadProcessMemory(m_ProcessHandle, (PVOID)pbi.PebBaseAddress, (_PEB32*)Peb, sizeof(_PEB32), NULL);
printf("PEB:%x\r\n", pbi.PebBaseAddress);
printf("LdrAddress:%x\r\n", ((_PEB32*)Peb)->Ldr);
printf("ImageBaseAddress:%x\r\n", ((_PEB32*)Peb)->ImageBaseAddress);
}
}
return 0;
}
有了PEB 则可以获得进程的各种信息,比如:模块、完整路径、命令行、环境变量、默认堆等等,参照结构体可得。
如何对PEB结构体不是很清楚,可以用windeg调试一下,attach到进程,然后使用!peb命令。