|
![]() | 作者: yongmin [yongmin]
![]() |
登录 |
原创作者:spirith 转贴自:一蓑烟雨 参考文章: 1. http://blog.csdn.net/ayken/archive/2007/02/13/1509027.aspx 2. http://icwin.net/ShowArtitle.ASP?art_id=6315&cat_id=39 本文在主主要以上述两篇文章为基础,对PEB的结构进行了详细的分析,重点是在揭示PEB结构中的list―entry的应用,并且以C语言Code进行实证。 本文主要分为四个部分,第一部分说明PEB地址如何获得;第二部分说明PEB的框架结构;第三部对PEB中的List-Entry结构进行了详细剖析,第四部分给出了枚举用户模块列表的代码。 -------------------------------------------------------------------------------------------------------------- 第一部分:PEB地址的取得 1.1原理:FS段寄存器指向当前的TEB结构,在TEB偏移0x30处是PEB指针,通过这个指针即可取得PEB的地址。 1.2实现方法: __asm { mov eax,fs:[0x30] mov PEB,eax } -------------------------------------------------------------------------------------------------------------- 第二部分:PEB的框架结构 在PEB中的0x0c处为一指针,指向PEB_LDR_DATA结构, 在PEB_LDR_DATA的0x0c,0x14,0x1c中为三个LIST_ENTRY,在struct _LDR_MODULE的0x00,0x08和0x10处是三个对应的同名称的LIST_ENTRY, PEB_LDR_DATA和struct _LDR_MODULE就是通过这三个LIST_ENTRY对应连接起来的。 2.1 struct _PEB结构: typedef struct _PEB { // Size: 0x1D8 /*000*/ UCHAR InheritedAddressSpace; /*001*/ UCHAR ReadImageFileExecOptions; /*002*/ UCHAR BeingDebugged; /*003*/ UCHAR SpareBool; // Allocation size /*004*/ HANDLE Mutant; /*008*/ HINSTANCE ImageBaseAddress; // Instance /*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; // Address of a local copy /*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; 2.2 PEB_LDR_DATA结构 typedef struct _PEB_LDR_DATA { ULONG Length; // +0x00 BOOLEAN Initialized; // +0x04 PVOID SsHandle; // +0x08 LIST_ENTRY InLoadOrderModuleList; // +0x0c LIST_ENTRY InMemoryOrderModuleList; // +0x14 LIST_ENTRY InInitializationOrderModuleList;// +0x1c } PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24 2.3 struct _LDR_MODULE结构 -typedef struct _LDR_MODULE -{ - LIST_ENTRY InLoadOrderModuleList; +0x00 - LIST_ENTRY InMemoryOrderModuleList; +0x08 - LIST_ENTRY InInitializationOrderModuleList; +0x10 - void* BaseAddress; +0x18 - void* EntryPoint; +0x1c - ULONG SizeOfImage; - UNICODE_STRING FullDllName; - UNICODE_STRING BaseDllName; - ULONG Flags; - SHORT LoadCount; - SHORT TlsIndex; - HANDLE SectionHandle; - ULONG CheckSum; - ULONG TimeDateStamp; -} LDR_MODULE, *PLDR_MODULE; -------------------------------------------------------------------------------------------------------------- 第三部分:List-Entry链接 PEB_LDR_DATA结构的最后三项跟struct _LDR_MODULE结构的前三项是一样的List-Entry链接,InLoadOrderModuleList,InMemoryOrderModuleList,和InInitializationOrderModuleList,但是这两个结构是怎样链接起来的呢? 其实,着两个结果中的三个List-Entry是共用的,如下图所示: ![]() ![]() ![]() PEB1.jpg (26.2 KB) 2007-9-27 15:10 ![]() ![]() ![]() PEB2.jpg (108.59 KB) 2007-9-27 15:10 -------------------------------------------------------------------------------------------------------------- 第四部分:代码实现: 4.1程枚举用户模块列表时,可以通过以下步骤实现: a. 从fs:[30h]获取PEB地址 b. 从PEB[0x0c]获取Ldr地址 c. 从Ldr[0x0c]获取InLoadOrderModuleList.Flink\ InMemoryOrderModuleList\InInitializationOrderModuleList d. 从InLoadOrderModuleList.Flink\ InMemoryOrderModuleList.Flink\InInitializationOrderModuleList.Flink开始前向遍历循环链表 e. 显示LDR_MODULE结构的BaseAddress、FullDllName成员。 4.2以下为取得InLoadOrderModuleList列表的code #include "stdafx.h" #include "windows.h" #include "winsvc.h" int _tmain(int argc, _TCHAR* argv[]) { void *PEB = NULL, *Ldr = NULL, *Flink = NULL, *p = NULL, *BaseAddress = NULL, *FullDllName = NULL; __asm { mov eax,fs:[0x30] mov PEB,eax } Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) ); Flink = *( ( void ** )( ( unsigned char * )Ldr+ 0x0c ) ); p = Flink; do { BaseAddress = *( ( void ** )( ( unsigned char * )p+ 0x18 ) ); FullDllName = *( ( void ** )( ( unsigned char * )p+ 0x28 ) ); wprintf(L"FullDllName is %s\n",FullDllName); printf("BaseAddress is %x\n",BaseAddress); p = *( ( void ** )p); } while ( Flink != p ); return 0; } 4.3以下为取得InMemoryOrderModuleList列表的code #include "stdafx.h" #include "windows.h" #include "winsvc.h" int _tmain(int argc, _TCHAR* argv[]) { void *PEB = NULL, *Ldr = NULL, *Flink = NULL, *p = NULL, *BaseAddress = NULL, *FullDllName = NULL; __asm { mov eax,fs:[0x30] mov PEB,eax } Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) ); Flink = *( ( void ** )( ( unsigned char * )Ldr+ 0x14 ) ); p = Flink; do { BaseAddress = *( ( void ** )( ( unsigned char * )p+ 0x10 ) ); FullDllName = *( ( void ** )( ( unsigned char * )p+ 0x20 ) ); wprintf(L"FullDllName is %s\n",FullDllName); printf("BaseAddress is %x\n",BaseAddress); p = *( ( void ** )p); } while ( Flink != p ); return 0; } 4.4以下为取得InInitializationOrderModuleList列表的code #include "stdafx.h" #include "windows.h" #include "winsvc.h" int _tmain(int argc, _TCHAR* argv[]) { void *PEB = NULL, *Ldr = NULL, *Flink = NULL, *p = NULL, *BaseAddress = NULL, *FullDllName = NULL; __asm { mov eax,fs:[0x30] mov PEB,eax } Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) ); Flink = *( ( void ** )( ( unsigned char * )Ldr+ 0x1c ) ); p = Flink; do { BaseAddress = *( ( void ** )( ( unsigned char * )p+ 0x08 ) ); FullDllName = *( ( void ** )( ( unsigned char * )p+ 0x18) ); wprintf(L"FullDllName is %s\n",FullDllName); printf("BaseAddress is %x\n",BaseAddress); p = *( ( void ** )p); } while ( Flink != p ); return 0; } [此贴被 yongmin(yongmin) 在 10月17日23时21分 编辑过] |
地主 发表时间: 07-10-17 23:19 |
|
20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon
粤ICP备05087286号