PEB(Process Environment Block,進程環境塊)存放進程信息,每個進程都有自己的PEB信息。位於用戶地址空間。
PEB地址可以通過函數PsGetProcessPeb(EPROCESS)來獲得,也可以通過EPROCESS基地址加偏移0x1b0(x86)來獲得。
PEB結構
typedef struct _PEB { // Size: 0x1D8 /*000*/ UCHAR InheritedAddressSpace; /*001*/ UCHAR ReadImageFileExecOptions; /*002*/ UCHAR BeingDebugged; /*003*/ UCHAR SpareBool; /*004*/ HANDLE Mutant; /*008*/ HINSTANCE ImageBaseAddress; /*00C*/ VOID *DllList; /*010*/ PPROCESS_PARAMETERS *ProcessParameters; //進程參數塊 /*014*/ ULONG SubSystemData; /*018*/ HANDLE DefaultHeap; /*01C*/ KSPIN_LOCK FastPebLock; /*020*/ ULONG FastPebLockRoutine; /*024*/ ULONG FastPebUnlockRoutine; /*028*/ ULONG EnvironmentUpdateCount; /*02C*/ ULONG KernelCallbackTable; /*030*/ LARGE_INTEGER SystemReserved; /*038*/ ULONG FreeList; /*03C*/ ULONG TlsExpansionCounter; /*040*/ ULONG TlsBitmap; /*044*/ LARGE_INTEGER TlsBitmapBits; /*04C*/ ULONG ReadOnlySharedMemoryBase; /*050*/ ULONG ReadOnlySharedMemoryHeap; /*054*/ ULONG ReadOnlyStaticServerData; /*058*/ ULONG AnsiCodePageData; /*05C*/ ULONG OemCodePageData; /*060*/ ULONG UnicodeCaseTableData; /*064*/ ULONG NumberOfProcessors; /*068*/ LARGE_INTEGER NtGlobalFlag; /*070*/ LARGE_INTEGER CriticalSectionTimeout; /*078*/ ULONG HeapSegmentReserve; /*07C*/ ULONG HeapSegmentCommit; /*080*/ ULONG HeapDeCommitTotalFreeThreshold; /*084*/ ULONG HeapDeCommitFreeBlockThreshold; /*088*/ ULONG NumberOfHeaps; /*08C*/ ULONG MaximumNumberOfHeaps; /*090*/ ULONG ProcessHeaps; /*094*/ ULONG GdiSharedHandleTable; /*098*/ ULONG ProcessStarterHelper; /*09C*/ ULONG GdiDCAttributeList; /*0A0*/ KSPIN_LOCK LoaderLock; /*0A4*/ ULONG OSMajorVersion; /*0A8*/ ULONG OSMinorVersion; /*0AC*/ USHORT OSBuildNumber; /*0AE*/ USHORT OSCSDVersion; /*0B0*/ ULONG OSPlatformId; /*0B4*/ ULONG ImageSubsystem; /*0B8*/ ULONG ImageSubsystemMajorVersion; /*0BC*/ ULONG ImageSubsystemMinorVersion; /*0C0*/ ULONG ImageProcessAffinityMask; /*0C4*/ ULONG GdiHandleBuffer[0x22]; /*14C*/ ULONG PostProcessInitRoutine; /*150*/ ULONG TlsExpansionBitmap; /*154*/ UCHAR TlsExpansionBitmapBits[0x80]; /*1D4*/ ULONG SessionId; } PEB, *PPEB;
PEB偏移0x10處還有個指針ProcessParameters,指向一個進程參數塊PPB、即RTL_USER_PROCESS_PARAMETERS數據結構。
這PPB也是在用戶空間的,雖然是個獨立存在的數據結構,邏輯上卻可以看作是PEB的一部分。
進程參數塊RTL_USER_PROCESS_PARAMETERS結構
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]; ULONG EnvironmentSize; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
下面以x86為例,在Windbg中可以具體實驗感受一下:
1.先隨便找個進程
2.注意PEB是在用戶空間,從他的地址也可以看出來,因為7ffdf000<80000000,
所以在查看PEB時要先使用命令 .process 899ac958 切入我們我們所找的SogouExe.exe進程的地址空間中,這個很重要
然后我們查看進程SogouExe.exe的PEB
3.在偏移0x10處看到了結構體RTL_USER_PROCESS_PARAMETERS,從圖中可以看出,它位於地址0x20000處
繼續查看它
4,在偏移0x38處就存放着進程完整路徑。OK,成功找到,這樣就可以進入具體的代碼實現了
1 BOOLEAN GetProcessPathByEProcess(PEPROCESS EProcess,WCHAR* wzProcessPath) 2 { 3 PPEB Peb = NULL; 4 KAPC_STATE ApcState; 5 ULONG_PTR ProcessParameters = NULL; 6 7 8 if (EProcess==NULL||!MmIsAddressValid(EProcess)) 9 { 10 return FALSE; 11 } 12 Peb = PsGetProcessPeb(EProcess); 13 if (Peb==NULL) 14 { 15 return FALSE; 16 } 17 18 KeStackAttachProcess(EProcess, &ApcState); //切入進程地址空間,很重要 19 20 21 ProcessParameters = *(ULONG_PTR*)((ULONG_PTR)Peb+ProcessParametersOfPeb); 22 23 memcpy(wzProcessPath,((PUNICODE_STRING)((ULONG_PTR)ProcessParameters+ImagePathNameOfProcessParameters))->Buffer, 24 ((PUNICODE_STRING)((ULONG_PTR)ProcessParameters+ImagePathNameOfProcessParameters))->Length); 25 26 27 28 KeUnstackDetachProcess(&ApcState); //切出進程,很重要 29 30 31 32 return TRUE; 33 }