PEB的深入学习

  1. 前言
  2. PEB是什么
  3. 准备工具
  4. 实验过程
  5. 参考链接

前言

纯属是之前乱弄shellcode编写的时候看见的PEB,然后当时做了笔记。不是很熟悉PEB这个,打算在了解一下。

PEB是什么

进程环境块(PEB)是 Windows NT操作系统内部使用的数据结构,用以存储每个进程的运行时数据。[1] Microsoft的MSDN文档中仅公开了PEB的少数几个域,该结构“在未来的Windows版本中可能会修改”。[2]PEB包含的数据结构适用于整个进程,如全局上下文,启动参数,程序image装载器的数据结构,程序image的基地址,进程级互斥同步访问对象等。[1]
PEB与kernel mode EPROCESS数据结构密切相关。也是逐进程数据结构,在客户-服务器运行时子系统(CSRSS)进程地址空间被管理。但是,类似于CSRSS数据结构,PEB自身并不是内核模式数据结构。它驻留在所关联的进程的用户态内存空间中。这是因为它被设计为被操作系统的用户态的程序所使用,如NTDLL,在内核态之外执行,如程序映象的加载器与堆管理器。[3]
WinDbg中,卸载PEB内容的命令是!peb,命令参数是PEB在进程地址空间的地址,它实际上是通过!process命令获取,将显示来自于EPROCESS数据结构的信息,其中一个域是PEB地址。[3]

准备工具

windbg
od
vs

实验过程

用汇编写一段寻找PEB地址的指令,然后编译逐渐调试。

global _start
section .text
    _start:
        mov eax,[fs:0x30] ;EAX=PEB
        mov eax,[eax+0xc] ;EAX=PEB->Ldr
        mov esi,[eax+0x14] ;ESI=PEB->Ldr.InMemOrder (Ldr.InMemOrder地址赋到ESI寄存器)
        lodsd ;ESI内存地址指向的值写入到EAX EAX=Second module (进入链表:Flink            : Ptr32 _LIST_ENTR)->进入Ldr.InMemOrder链表的的一个元素位地址
        xchg eax,esi ;EAX和ESI交换值 EAX=ESI,ESI=EAX (EAX=Ldr.InMemOrder->链表第一元素位的地址,然后从EAX和ESI互相切换值)
        lodsd ;EAX=Third(Kernel32)
        mov ebx,[eax+0x10] ;EBX=Kernel32基地址
        mov edx,[ebx+0x3c] ;EDX = DOS->e_lfanew (DOS头偏移地址)
        add edx,ebx ;PE头地址获取
        mov edx,[edx+0x78] ;IMAGE_EXPORT_DIRECTORY
        add edx,ebx ;EDX = Export table
        mov esi, [edx + 0x20]    ; ESI = Offset namestable
        add esi, ebx             ; ESI = Names table
        xor ecx, ecx             ; EXC = 0

yasm和golink编译成exe

yasm.win32.exe -f win32 -o test.obj test.asm
Golink /ni /entry _start shell.obj

然后拖入windbg调,自动解析PEB!peb

  • InheritedAddressSpace: 继承的地址空间
  • ReadImageFileExecOptions: 读取文件镜像执行选项
  • BeingDebugged: 是否在被调试
  • ImageBaseAddress: 镜像基本的地址
  • Ldr: (到PEB_LDR_DATA结构的指针,提供被加载模块的信息。)包含kernel32 与ntdll的基地址
  • SubSystemData: 子系统数据
  • ProcessHeap: 进程堆栈首地址
  • ProcessParameters: 进程参数地址
  • CurrentDirectory: 当前目录
  • WindowTitle: 窗口标题
  • ImageFile: 镜像我呢见
  • CommandLine: 命令行
  • DllPath: DLL路径
  • Environment: 环境

手动解析PEBdt _PEB @$peb

ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 BitField         : 0 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y0
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 IsPackagedProcess : 0y0
   +0x003 IsAppContainer   : 0y0
   +0x003 IsProtectedProcessLight : 0y0
   +0x003 IsLongPathAwareProcess : 0y0
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x00400000 Void
   +0x00c Ldr              : 0x7750dca0 _PEB_LDR_DATA
   +0x010 ProcessParameters : 0x004b1d38 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : (null) 
   +0x018 ProcessHeap      : 0x004b0000 Void
   +0x01c FastPebLock      : 0x7750da60 _RTL_CRITICAL_SECTION
   +0x020 AtlThunkSListPtr : (null) 
   +0x024 IFEOKey          : (null) 
   +0x028 CrossProcessFlags : 3
   +0x028 ProcessInJob     : 0y1
   +0x028 ProcessInitializing : 0y1
   +0x028 ProcessUsingVEH  : 0y0
   +0x028 ProcessUsingVCH  : 0y0
   +0x028 ProcessUsingFTH  : 0y0
   +0x028 ProcessPreviouslyThrottled : 0y0
   +0x028 ProcessCurrentlyThrottled : 0y0
   +0x028 ProcessImagesHotPatched : 0y0
   +0x028 ReservedBits0    : 0y000000000000000000000000 (0)
   +0x02c KernelCallbackTable : (null) 
   +0x02c UserSharedInfoPtr : (null) 
   +0x030 SystemReserved   : 0
   +0x034 AtlThunkSListPtr32 : (null) 
   +0x038 ApiSetMap        : 0x00040000 Void
   +0x03c TlsExpansionCounter : 0
   +0x040 TlsBitmap        : 0x7750dc50 Void
   +0x044 TlsBitmapBits    : [2] 0x10001
   +0x04c ReadOnlySharedMemoryBase : 0x7fe40000 Void
   +0x050 SharedData       : (null) 
   +0x054 ReadOnlyStaticServerData : 0x7fe40750  -> (null) 
   +0x058 AnsiCodePageData : 0x7ffa0000 Void
   +0x05c OemCodePageData  : 0x7ffa0000 Void
   +0x060 UnicodeCaseTableData : 0x7ffd0028 Void
   +0x064 NumberOfProcessors : 0xc
   +0x068 NtGlobalFlag     : 0x70
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER 0xffffe86d`079b8000
   +0x078 HeapSegmentReserve : 0x100000
   +0x07c HeapSegmentCommit : 0x2000
   +0x080 HeapDeCommitTotalFreeThreshold : 0x10000
   +0x084 HeapDeCommitFreeBlockThreshold : 0x1000
   +0x088 NumberOfHeaps    : 1
   +0x08c MaximumNumberOfHeaps : 0x10
   +0x090 ProcessHeaps     : 0x7750c760  -> 0x004b0000 Void
   +0x094 GdiSharedHandleTable : (null) 
   +0x098 ProcessStarterHelper : (null) 
   +0x09c GdiDCAttributeList : 0
   +0x0a0 LoaderLock       : 0x7750b3d0 _RTL_CRITICAL_SECTION
   +0x0a4 OSMajorVersion   : 0xa
   +0x0a8 OSMinorVersion   : 0
   +0x0ac OSBuildNumber    : 0x47bb
   +0x0ae OSCSDVersion     : 0
   +0x0b0 OSPlatformId     : 2
   +0x0b4 ImageSubsystem   : 2
   +0x0b8 ImageSubsystemMajorVersion : 4
   +0x0bc ImageSubsystemMinorVersion : 0
   +0x0c0 ActiveProcessAffinityMask : 0xfff
   +0x0c4 GdiHandleBuffer  : [34] 0
   +0x14c PostProcessInitRoutine : (null) 
   +0x150 TlsExpansionBitmap : 0x7750dc38 Void
   +0x154 TlsExpansionBitmapBits : [32] 1
   +0x1d4 SessionId        : 1
   +0x1d8 AppCompatFlags   : _ULARGE_INTEGER 0x0
   +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER 0x0
   +0x1e8 pShimData        : 0x001b0000 Void
   +0x1ec AppCompatInfo    : (null) 
   +0x1f0 CSDVersion       : _UNICODE_STRING ""
   +0x1f8 ActivationContextData : (null) 
   +0x1fc ProcessAssemblyStorageMap : (null) 
   +0x200 SystemDefaultActivationContextData : 0x001a0000 _ACTIVATION_CONTEXT_DATA
   +0x204 SystemAssemblyStorageMap : (null) 
   +0x208 MinimumStackCommit : 0
   +0x20c SparePointers    : [4] (null) 
   +0x21c SpareUlongs      : [5] 0
   +0x230 WerRegistrationData : (null) 
   +0x234 WerShipAssertPtr : (null) 
   +0x238 pUnused          : (null) 
   +0x23c pImageHeaderHash : (null) 
   +0x240 TracingFlags     : 0
   +0x240 HeapTracingEnabled : 0y0
   +0x240 CritSecTracingEnabled : 0y0
   +0x240 LibLoaderTracingEnabled : 0y0
   +0x240 SpareTracingBits : 0y00000000000000000000000000000 (0)
   +0x248 CsrServerReadOnlySharedMemoryBase : 0x00007df4`2f970000
   +0x250 TppWorkerpListLock : 0
   +0x254 TppWorkerpList   : _LIST_ENTRY [ 0x276254 - 0x276254 ]
   +0x25c WaitOnAddressHashTable : [128] (null) 
   +0x45c TelemetryCoverageHeader : (null) 
   +0x460 CloudFileFlags   : 0x60
   +0x464 CloudFileDiagFlags : 0
   +0x468 PlaceholderCompatibilityMode : 1 ''
   +0x469 PlaceholderCompatibilityModeReserved : [7]  ""
   +0x470 LeapSecondData   : 0x7ff90000 _LEAP_SECOND_DATA
   +0x474 LeapSecondFlags  : 0
   +0x474 SixtySecondEnabled : 0y0
   +0x474 Reserved         : 0y0000000000000000000000000000000 (0)
   +0x478 NtGlobalFlag2    : 0

这里比较重要的是Ldr,(PEB_LDR_DATA结构的指针,提供被加载模块的信息。)

Ldr分析

   +0x000 Length           : 0x30
   +0x004 Initialized      : 0x1 ''
   +0x008 SsHandle         : (null) 
   +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x4b3720 - 0x4b3d30 ]  //按加载顺序
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x4b3728 - 0x4b3d38 ] //按内存顺序
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x4b3628 - 0x4b3d40 ] //按初始化顺序
   +0x024 EntryInProgress  : (null) 
   +0x028 ShutdownInProgress : 0 ''
   +0x02c ShutdownThreadId : (null) 

InLoadOrderModuleList、InMemoryOrderModuleList、InMemoryOrderModuleList这三个是双向链表
(其实三个都一样,顺序不同而已)
对应的格式为 LIST_ENTRY

0:000> dt _LIST_ENTRY
ntdll!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

LDR_DATA_TABLE_ENTRY structure,双向循环链表吧,从一个方向开始,不停的循环,就回到初始位了,就相当于遍历了一次

结构如下

0:000> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING
   +0x034 FlagGroup        : [4] UChar
   +0x034 Flags            : Uint4B
   +0x034 PackagedBinary   : Pos 0, 1 Bit
   +0x034 MarkedForRemoval : Pos 1, 1 Bit
   +0x034 ImageDll         : Pos 2, 1 Bit
   +0x034 LoadNotificationsSent : Pos 3, 1 Bit
   +0x034 TelemetryEntryProcessed : Pos 4, 1 Bit
   +0x034 ProcessStaticImport : Pos 5, 1 Bit
   +0x034 InLegacyLists    : Pos 6, 1 Bit
   +0x034 InIndexes        : Pos 7, 1 Bit
   +0x034 ShimDll          : Pos 8, 1 Bit
   +0x034 InExceptionTable : Pos 9, 1 Bit
   +0x034 ReservedFlags1   : Pos 10, 2 Bits
   +0x034 LoadInProgress   : Pos 12, 1 Bit
   +0x034 LoadConfigProcessed : Pos 13, 1 Bit
   +0x034 EntryProcessed   : Pos 14, 1 Bit
   +0x034 ProtectDelayLoad : Pos 15, 1 Bit
   +0x034 ReservedFlags3   : Pos 16, 2 Bits
   +0x034 DontCallForThreads : Pos 18, 1 Bit
   +0x034 ProcessAttachCalled : Pos 19, 1 Bit
   +0x034 ProcessAttachFailed : Pos 20, 1 Bit
   +0x034 CorDeferredValidate : Pos 21, 1 Bit
   +0x034 CorImage         : Pos 22, 1 Bit
   +0x034 DontRelocate     : Pos 23, 1 Bit
   +0x034 CorILOnly        : Pos 24, 1 Bit
   +0x034 ChpeImage        : Pos 25, 1 Bit
   +0x034 ReservedFlags5   : Pos 26, 2 Bits
   +0x034 Redirected       : Pos 28, 1 Bit
   +0x034 ReservedFlags6   : Pos 29, 2 Bits
   +0x034 CompatDatabaseProcessed : Pos 31, 1 Bit
   +0x038 ObsoleteLoadCount : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x044 TimeDateStamp    : Uint4B
   +0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT
   +0x04c Lock             : Ptr32 Void
   +0x050 DdagNode         : Ptr32 _LDR_DDAG_NODE
   +0x054 NodeModuleLink   : _LIST_ENTRY
   +0x05c LoadContext      : Ptr32 _LDRP_LOAD_CONTEXT
   +0x060 ParentDllBase    : Ptr32 Void
   +0x064 SwitchBackContext : Ptr32 Void
   +0x068 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x074 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x080 OriginalBase     : Uint4B
   +0x088 LoadTime         : _LARGE_INTEGER
   +0x090 BaseNameHashValue : Uint4B
   +0x094 LoadReason       : _LDR_DLL_LOAD_REASON
   +0x098 ImplicitPathOptions : Uint4B
   +0x09c ReferenceCount   : Uint4B
   +0x0a0 DependentLoadFlags : Uint4B
   +0x0a4 SigningLevel     : UChar

跟上面的汇编一样找InMemoryOrderModuleList来遍历0x4b3728 - 0x4b3d38这个地址范围里存着对应的内存顺序载入过程

0:000> dt 0x4b3728 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4b3620 - 0x7750dcb4 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x400000 - 0x401000 ]
   +0x018 DllBase          : 0x00002000 Void
   +0x01c EntryPoint       : 0x00620060 Void
   +0x020 SizeOfImage      : 0x4b21fc
   +0x024 FullDllName      : _UNICODE_STRING "test.exe"
   +0x02c BaseDllName      : _UNICODE_STRING "--- memory read error at address 0x0000ffff ---"
   +0x034 FlagGroup        : [4]  "P???"
   +0x034 Flags            : 0x7750db50
   +0x034 PackagedBinary   : 0y0
   +0x034 MarkedForRemoval : 0y0
   +0x034 ImageDll         : 0y0
   +0x034 LoadNotificationsSent : 0y0
   +0x034 TelemetryEntryProcessed : 0y1
   +0x034 ProcessStaticImport : 0y0
   +0x034 InLegacyLists    : 0y1
   +0x034 InIndexes        : 0y0
   +0x034 ShimDll          : 0y1
   +0x034 InExceptionTable : 0y1
   +0x034 ReservedFlags1   : 0y10
   +0x034 LoadInProgress   : 0y1
   +0x034 LoadConfigProcessed : 0y0
   +0x034 EntryProcessed   : 0y1
   +0x034 ProtectDelayLoad : 0y1
   +0x034 ReservedFlags3   : 0y00
   +0x034 DontCallForThreads : 0y0
   +0x034 ProcessAttachCalled : 0y0
   +0x034 ProcessAttachFailed : 0y1
   +0x034 CorDeferredValidate : 0y0
   +0x034 CorImage         : 0y1
   +0x034 DontRelocate     : 0y0
   +0x034 CorILOnly        : 0y1
   +0x034 ChpeImage        : 0y1
   +0x034 ReservedFlags5   : 0y01
   +0x034 Redirected       : 0y1
   +0x034 ReservedFlags6   : 0y11
   +0x034 CompatDatabaseProcessed : 0y0
   +0x038 ObsoleteLoadCount : 0xdb50
   +0x03a TlsIndex         : 0x7750
   +0x03c HashLinks        : _LIST_ENTRY [ 0x6032501a - 0x0 ]
   +0x044 TimeDateStamp    : 0
   +0x048 EntryPointActivationContext : 0x004b37e0 _ACTIVATION_CONTEXT
   +0x04c Lock             : 0x004b37e0 Void
   +0x050 DdagNode         : 0x004b37e0 _LDR_DDAG_NODE
   +0x054 NodeModuleLink   : _LIST_ENTRY [ 0x19fa64 - 0x0 ]
   +0x05c LoadContext      : 0x773f1124 _LDRP_LOAD_CONTEXT
   +0x060 ParentDllBase    : (null) 
   +0x064 SwitchBackContext : 0x004b3d98 Void
   +0x068 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x074 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x080 OriginalBase     : 0xf9727ce2
   +0x088 LoadTime         : _LARGE_INTEGER 0x00000004`33df1536
   +0x090 BaseNameHashValue : 0
   +0x094 LoadReason       : 2 ( LoadReasonDynamicForwarderDependency )
   +0x098 ImplicitPathOptions : 0
   +0x09c ReferenceCount   : 0
   +0x0a0 DependentLoadFlags : 0xabababab
   +0x0a4 SigningLevel     : 0xab ''

然后通过不断遍历链表元素里的InLoadOrderLinks,最后找到kernel32.dll

0:000> dt 0x4b3728 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4b3620 - 0x7750dcb4 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x400000 - 0x401000 ]
   +0x018 DllBase          : 0x00002000 Void
   +0x01c EntryPoint       : 0x00620060 Void
   +0x020 SizeOfImage      : 0x4b21fc
   +0x024 FullDllName      : _UNICODE_STRING "test.exe"
   +0x02c BaseDllName      : _UNICODE_STRING "--- memory read error at address 0x0000ffff ---"
   +0x034 FlagGroup        : [4]  "P???"
   +0x034 Flags            : 0x7750db50
   +0x034 PackagedBinary   : 0y0
   +0x034 MarkedForRemoval : 0y0
   +0x034 ImageDll         : 0y0
   +0x034 LoadNotificationsSent : 0y0
   +0x034 TelemetryEntryProcessed : 0y1
   +0x034 ProcessStaticImport : 0y0
   +0x034 InLegacyLists    : 0y1
   +0x034 InIndexes        : 0y0
   +0x034 ShimDll          : 0y1
   +0x034 InExceptionTable : 0y1
   +0x034 ReservedFlags1   : 0y10
   +0x034 LoadInProgress   : 0y1
   +0x034 LoadConfigProcessed : 0y0
   +0x034 EntryProcessed   : 0y1
   +0x034 ProtectDelayLoad : 0y1
   +0x034 ReservedFlags3   : 0y00
   +0x034 DontCallForThreads : 0y0
   +0x034 ProcessAttachCalled : 0y0
   +0x034 ProcessAttachFailed : 0y1
   +0x034 CorDeferredValidate : 0y0
   +0x034 CorImage         : 0y1
   +0x034 DontRelocate     : 0y0
   +0x034 CorILOnly        : 0y1
   +0x034 ChpeImage        : 0y1
   +0x034 ReservedFlags5   : 0y01
   +0x034 Redirected       : 0y1
   +0x034 ReservedFlags6   : 0y11
   +0x034 CompatDatabaseProcessed : 0y0
   +0x038 ObsoleteLoadCount : 0xdb50
   +0x03a TlsIndex         : 0x7750
   +0x03c HashLinks        : _LIST_ENTRY [ 0x6032501a - 0x0 ]
   +0x044 TimeDateStamp    : 0
   +0x048 EntryPointActivationContext : 0x004b37e0 _ACTIVATION_CONTEXT
   +0x04c Lock             : 0x004b37e0 Void
   +0x050 DdagNode         : 0x004b37e0 _LDR_DDAG_NODE
   +0x054 NodeModuleLink   : _LIST_ENTRY [ 0x19fa64 - 0x0 ]
   +0x05c LoadContext      : 0x773f1124 _LDRP_LOAD_CONTEXT
   +0x060 ParentDllBase    : (null) 
   +0x064 SwitchBackContext : 0x004b3d98 Void
   +0x068 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x074 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x080 OriginalBase     : 0xf9727ce2
   +0x088 LoadTime         : _LARGE_INTEGER 0x00000004`33df1536
   +0x090 BaseNameHashValue : 0
   +0x094 LoadReason       : 2 ( LoadReasonDynamicForwarderDependency )
   +0x098 ImplicitPathOptions : 0
   +0x09c ReferenceCount   : 0
   +0x0a0 DependentLoadFlags : 0xabababab
   +0x0a4 SigningLevel     : 0xab ''
0:000> dt 0x4b3620 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4b3b08 - 0x4b3728 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x4b3ed0 - 0x7750dcbc ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x773f0000 - 0x0 ]
   +0x018 DllBase          : 0x0019a000 Void
   +0x01c EntryPoint       : 0x003c003a Void
   +0x020 SizeOfImage      : 0x4b34f8
   +0x024 FullDllName      : _UNICODE_STRING "ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "--- memory read error at address 0x0000ffff ---"
   +0x034 FlagGroup        : [4]  "@???"
   +0x034 Flags            : 0x7750db40
   +0x034 PackagedBinary   : 0y0
   +0x034 MarkedForRemoval : 0y0
   +0x034 ImageDll         : 0y0
   +0x034 LoadNotificationsSent : 0y0
   +0x034 TelemetryEntryProcessed : 0y0
   +0x034 ProcessStaticImport : 0y0
   +0x034 InLegacyLists    : 0y1
   +0x034 InIndexes        : 0y0
   +0x034 ShimDll          : 0y1
   +0x034 InExceptionTable : 0y1
   +0x034 ReservedFlags1   : 0y10
   +0x034 LoadInProgress   : 0y1
   +0x034 LoadConfigProcessed : 0y0
   +0x034 EntryProcessed   : 0y1
   +0x034 ProtectDelayLoad : 0y1
   +0x034 ReservedFlags3   : 0y00
   +0x034 DontCallForThreads : 0y0
   +0x034 ProcessAttachCalled : 0y0
   +0x034 ProcessAttachFailed : 0y1
   +0x034 CorDeferredValidate : 0y0
   +0x034 CorImage         : 0y1
   +0x034 DontRelocate     : 0y0
   +0x034 CorILOnly        : 0y1
   +0x034 ChpeImage        : 0y1
   +0x034 ReservedFlags5   : 0y01
   +0x034 Redirected       : 0y1
   +0x034 ReservedFlags6   : 0y11
   +0x034 CompatDatabaseProcessed : 0y0
   +0x038 ObsoleteLoadCount : 0xdb40
   +0x03a TlsIndex         : 0x7750
   +0x03c HashLinks        : _LIST_ENTRY [ 0x1e699fab - 0x0 ]
   +0x044 TimeDateStamp    : 0
   +0x048 EntryPointActivationContext : 0x004b36d8 _ACTIVATION_CONTEXT
   +0x04c Lock             : 0x004b36d8 Void
   +0x050 DdagNode         : 0x004b36d8 _LDR_DDAG_NODE
   +0x054 NodeModuleLink   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x05c LoadContext      : (null) 
   +0x060 ParentDllBase    : 0x004b3f28 Void
   +0x064 SwitchBackContext : (null) 
   +0x068 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x074 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x080 OriginalBase     : 0xf9727ce2
   +0x088 LoadTime         : _LARGE_INTEGER 0xf46857d4
   +0x090 BaseNameHashValue : 0
   +0x094 LoadReason       : 2 ( LoadReasonDynamicForwarderDependency )
   +0x098 ImplicitPathOptions : 0x800
   +0x09c ReferenceCount   : 0
   +0x0a0 DependentLoadFlags : 0xabababab
   +0x0a4 SigningLevel     : 0xab ''
0:000> dt 0x4b3b08 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4b3ec8 - 0x4b3620 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x4b3d40 - 0x4b3ed0 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x75f50000 - 0x75f65f70 ]
   +0x018 DllBase          : 0x000e0000 Void
   +0x01c EntryPoint       : 0x00420040 Void
   +0x020 SizeOfImage      : 0x4b3c08
   +0x024 FullDllName      : _UNICODE_STRING "KERNEL32.DLL"
   +0x02c BaseDllName      : _UNICODE_STRING "--- memory read error at address 0x0000ffff ---"
   +0x034 FlagGroup        : [4]  "0???"
   +0x034 Flags            : 0x7750db30
   +0x034 PackagedBinary   : 0y0
   +0x034 MarkedForRemoval : 0y0
   +0x034 ImageDll         : 0y0
   +0x034 LoadNotificationsSent : 0y0
   +0x034 TelemetryEntryProcessed : 0y1
   +0x034 ProcessStaticImport : 0y1
   +0x034 InLegacyLists    : 0y0
   +0x034 InIndexes        : 0y0
   +0x034 ShimDll          : 0y1
   +0x034 InExceptionTable : 0y1
   +0x034 ReservedFlags1   : 0y10
   +0x034 LoadInProgress   : 0y1
   +0x034 LoadConfigProcessed : 0y0
   +0x034 EntryProcessed   : 0y1
   +0x034 ProtectDelayLoad : 0y1
   +0x034 ReservedFlags3   : 0y00
   +0x034 DontCallForThreads : 0y0
   +0x034 ProcessAttachCalled : 0y0
   +0x034 ProcessAttachFailed : 0y1
   +0x034 CorDeferredValidate : 0y0
   +0x034 CorImage         : 0y1
   +0x034 DontRelocate     : 0y0
   +0x034 CorILOnly        : 0y1
   +0x034 ChpeImage        : 0y1
   +0x034 ReservedFlags5   : 0y01
   +0x034 Redirected       : 0y1
   +0x034 ReservedFlags6   : 0y11
   +0x034 CompatDatabaseProcessed : 0y0
   +0x038 ObsoleteLoadCount : 0xdb30
   +0x03a TlsIndex         : 0x7750
   +0x03c HashLinks        : _LIST_ENTRY [ 0x59b71f87 - 0x0 ]
   +0x044 TimeDateStamp    : 0
   +0x048 EntryPointActivationContext : 0x004b3bc0 _ACTIVATION_CONTEXT
   +0x04c Lock             : 0x004b3bc0 Void
   +0x050 DdagNode         : 0x004b3bc0 _LDR_DDAG_NODE
   +0x054 NodeModuleLink   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x05c LoadContext      : 0x773f1194 _LDRP_LOAD_CONTEXT
   +0x060 ParentDllBase    : 0x004b3788 Void
   +0x064 SwitchBackContext : 0x004b3680 Void
   +0x068 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x074 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x080 OriginalBase     : 0xf9727ce2
   +0x088 LoadTime         : _LARGE_INTEGER 0x00000004`536cd652
   +0x090 BaseNameHashValue : 0x4000
   +0x094 LoadReason       : 2 ( LoadReasonDynamicForwarderDependency )
   +0x098 ImplicitPathOptions : 0
   +0x09c ReferenceCount   : 0
   +0x0a0 DependentLoadFlags : 0xabababab
   +0x0a4 SigningLevel     : 0xab ''

对面上面的汇编

mov eax,[fs:0x30] ;EAX=PEB
mov eax,[eax+0xc] ;EAX=PEB->Ldr
mov esi,[eax+0x14] ;ESI=PEB->Ldr.InMemOrder (Ldr.InMemOrder地址赋到ESI寄存器)
lodsd ;ESI内存地址指向的值写入到EAX EAX=Second module (进入链表:Flink            : Ptr32 _LIST_ENTR)->进入Ldr.InMemOrder链表的的一个元素位地址
xchg eax,esi ;EAX和ESI交换值 EAX=ESI,ESI=EAX (EAX=Ldr.InMemOrder->链表第一元素位的地址,然后从EAX和ESI互相切换值)
lodsd ;EAX=Third(Kernel32)
mov ebx,[eax+0x10] ;EBX=Kernel32基地址

最后对应的0x10链表首地址放的即为kernel32.dll的基址

 +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x75f50000 - 0x75f65f70 ]

其实可以简写成别的(lodsd看起来容易把人搞混)

mov eax, fs:[0x30]   //得到PEB地址,其实这里还有个TEB的概念,但是只用到这一次,为了防止混乱,就不再解释了
mov eax, [eax + 0xc]//指向PEB_LDR_DATA结构的首地址
mov eax, [eax + 0x1c]//一个双向链表的地址
mov eax, [eax]//得到第二个条目kernelBase的链表
mov eax, [eax]//得到第三个条目kernel32链表(win10)
mov eax, [eax + 0x8] //kernel32.dll地址

对应0x8链表里的kernel32.dll基址

在内存里的过程
可以使用OD进行验证,od拖入test.exe。然后在堆栈窗口ctrl+G输入fs:[0]跳到所在位置
执行mov eax,fs[0x30]

执行mov eax, [eax + 0xc]得到LDR地址
(得到PEB地址后,在内存窗口ctrl+G输入PEB的地址,选择”长型”->”地址”)

执行lodsd ;ESI内存地址指向的值写入到EAX EAX=Second module (进入链表:Flink : Ptr32 _LIST_ENTR)->进入Ldr.InMemOrder链表的的一个元素位地址得到链表里的第一个Flink的地址
(数据窗口选择刚刚的InMemoryOrderModuleList地址,选择”数据窗口跟随”)

继续执行

xchg eax,esi ;EAX和ESI交换值 EAX=ESI,ESI=EAX (EAX=Ldr.InMemOrder->链表第一元素位的地址,然后从EAX和ESI互相切换值)
lodsd ;EAX=Third(Kernel32)

如何用C实现?
1.直接用汇编返回对PEB地址然后根据微软给的数据结构解析即可
2.直接用给出的数据结构来解析 (好像可以这么写)

第一种方法

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
int main()
{
    DWORD PPEB;
    DWORD LLDR;
    DWORD dllbase;
    DWORD initlist;
    DWORD virtualaddress;
    PCHAR dllname;
    char *kernel32dllname = "KERNEL32.dll";
    PIMAGE_DOS_HEADER dosheader;
    PIMAGE_NT_HEADERS ntheader;
    PIMAGE_EXPORT_DIRECTORY exportdirectory;
    __asm {
        mov eax, fs:[0x30];EAX = PEB
        mov PPEB,eax
    }
    LLDR = *(PDWORD)(PPEB + 0xc); //LDR
    printf("PEB Address:0x%x\n", PPEB);
    initlist=*(PDWORD)(LLDR+0x1c); //LDR->InInitializationOrderModuleList
    CHAR szGetProcAddr[]="GetProcAddress";
    CHAR szLoadLib[]="LoadLibraryA";

    for (;dllbase = *(PDWORD)(initlist + 0x8);initlist = *(PDWORD)initlist) { //遍历InMemoryOrderLinks链表
        dosheader = (PIMAGE_DOS_HEADER)dllbase; //DOS头部
        ntheader = (PIMAGE_NT_HEADERS)(dllbase+dosheader->e_lfanew); //PE头部
        virtualaddress = ntheader->OptionalHeader.DataDirectory[0].VirtualAddress; //EXPORT_DIRECTORY
        exportdirectory = (PIMAGE_EXPORT_DIRECTORY)(dllbase + virtualaddress); //导出表
        dllname = (PCHAR)(dllbase + exportdirectory->Name); //DLL Name
        if (!strcmp(dllname, kernel32dllname)) {
            printf("%s Address:0x%x\n", kernel32dllname, dllbase);
        }
    }
    system("pause");
    return 0;
}

之后就是从kernel32.dll的PE里导出loadlibraryA和GetProcAddress函数的地址。
(下次在写)

参考链接

https://www.jb51.net/article/171962.htm
https://zhuanlan.zhihu.com/p/109079902
https://www.cnblogs.com/lsgxeva/p/10794735.html
https://xz.aliyun.com/t/2108
https://zh.wikipedia.org/wiki/%E8%BF%9B%E7%A8%8B%E7%8E%AF%E5%A2%83%E5%9D%97


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:PEB的深入学习

本文作者:九世

发布时间:2021-02-22, 14:26:52

最后更新:2021-02-22, 20:04:03

原始链接:http://jiushill.github.io/posts/165f8274.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录