2009-10-7编辑
PEB (进程环境块)是进程中几个数据结构中唯一在用户地址空间的一个结构。它保存着很多信息,但是我们比较感兴趣的是在此进程中加载的模块信息。在以前都是使用 TOOLHELP32 中的函数取得,其实这些过程最终也是从这个结构中取出响应得信息的。
每个进程的 PEB 结构地址保存在 FS:[0x30] 处,而 MODULE 的信息是在一堆双向链表和其它数据结构中间。要顺利地取出 MODULENAME 信息,必须涉及到下面的这些结构:
typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING;
typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; USHORT Length; ULONG TimeStamp; UNICODE_STRING DosPath; } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LDR_MODULE { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp; } LDR_MODULE, *PLDR_MODULE, LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; ULONG Length; ULONG Flags; ULONG DebugFlags; PVOID ConsoleHandle; ULONG ConsoleFlags; HANDLE StdInputHandle; HANDLE StdOutputHandle; HANDLE StdErrorHandle; UNICODE_STRING CurrentDirectoryPath; HANDLE CurrentDirectoryHandle; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; PVOID Environment; ULONG StartingPositionLeft; ULONG StartingPositionTop; ULONG Width; ULONG Height; ULONG CharWidth; ULONG CharHeight; ULONG ConsoleTextAttributes; ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopName; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB_FREE_BLOCK { struct _PEB_FREE_BLOCK *Next; ULONG Size; } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
typedef void (*PPEBLOCKROUTINE)(PVOID PebLock);
typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA LoaderData; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PVOID FastPebLock; PPEBLOCKROUTINE FastPebLockRoutine; PPEBLOCKROUTINE FastPebUnlockRoutine; ULONG EnvironmentUpdateCount; PVOID *KernelCallbackTable; PVOID EventLogSection; PVOID EventLog; PPEB_FREE_BLOCK FreeList; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[0x2]; PVOID ReadOnlySharedMemoryBase; PVOID ReadOnlySharedMemoryHeap; PVOID *ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; ULONG NumberOfProcessors; ULONG NtGlobalFlag; BYTE Spare2[0x4]; LARGE_INTEGER CriticalSectionTimeout; ULONG HeapSegmentReserve; ULONG HeapSegmentCommit; ULONG HeapDeCommitTotalFreeThreshold; ULONG HeapDeCommitFreeBlockThreshold; ULONG NumberOfHeaps; ULONG MaximumNumberOfHeaps; PVOID **ProcessHeaps; PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; PVOID GdiDCAttributeList; PVOID LoaderLock; ULONG OSMajorVersion; ULONG OSMinorVersion; ULONG OSBuildNumber; ULONG OSPlatformId; ULONG ImageSubSystem; ULONG ImageSubSystemMajorVersion; ULONG ImageSubSystemMinorVersion; ULONG GdiHandleBuffer[0x22]; ULONG PostProcessInitRoutine; ULONG TlsExpansionBitmap; BYTE TlsExpansionBitmapBits[0x80]; ULONG SessionId; } PEB, *PPEB; |
在这些结构丛中,我将进程加载的模块的信息图描述如下:
下面是根据这个示意图,写个一个程序,程序将输出值放到一个对话框中的 LIST 控件中。
…. { PPEB pPEB; char Str[200]; HWND hLog; PPEB_LDR_DATA pLdr; PLIST_ENTRY pListEntry; PLDR_MODULE pModule; char DllName[300];
_asm{ push eax mov eax,fs:[30h] mov pPEB, eax pop eax }
hLog = GetDlgItem(hDlg, IDC_LIST1);
pLdr = pPEB->LoaderData;
if (pLdr->InMemoryOrderModuleList.Flink) { pListEntry = pLdr->InMemoryOrderModuleList.Flink;
while(pListEntry != &pLdr->InMemoryOrderModuleList) { pModule = (PLDR_MODULE)(pListEntry - 1);
WideCharToMultiByte(CP_ACP, 0, pModule->FullDllName.Buffer, pModule->FullDllName.Length, DllName, 300, NULL, FALSE); SendMessage(hLog, LB_ADDSTRING, 0, (LPARAM)DllName);
sprintf(Str, "BaseAddress: 0x%08X sizeofImage: 0x%08X", pModule->BaseAddress, pModule->SizeOfImage); SendMessage(hLog, LB_ADDSTRING, 0, (LPARAM)Str);
pListEntry = pListEntry->Flink; }
} |
好了,大功告成, PEB 里面 LIST_ENTRY 结构用的比较好。值得细细品味 J