首页
社区
课程
招聘
[原创]PEB结构----枚举用户模块列表
发表于: 2007-9-27 13:00 30318

[原创]PEB结构----枚举用户模块列表

2007-9-27 13:00
30318

PEB结构----枚举用户模块列表

参考文章:
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是共用的,如下图所示:




--------------------------------------------------------------------------------------------------------------
第四部分:代码实现:
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;
}

我是个菜鸟,以上是我的一点儿愚见,如有错误,希望能善意指出,谅解。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (17)
雪    币: 266
活跃值: (52)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
2
不错,学习了
2007-9-27 13:36
0
雪    币: 224
活跃值: (147)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
3
图片看不到,楼主传为本地吧,
2007-9-27 14:23
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
抱歉,没注意到baidu空间图片的这个问题,请问,怎么转到本地啊?
2007-9-27 14:54
0
雪    币: 47147
活跃值: (20445)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
2007-9-27 14:56
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
谢谢wynney,谢谢kanxue,图片已经本地化了,图片是我自己画的,有些丑,见谅……
2007-9-27 15:06
0
雪    币: 224
活跃值: (147)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=kanxue;364774]http://bbs.pediy.com/showpost.php?postid=292659[/QUOTE]

建议楼主按老大的这个链接把图插到文章中应在位置,这样方面大家收藏~
2007-9-27 15:08
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
在03年绿盟上也看到了相似的方法
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=2002
2007-9-27 15:33
0
雪    币: 191
活跃值: (41)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
9
LDR_MODULE 其实就是这个结构:

lkd> dt nt!_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 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 Void
   +0x04c PatchInformation : Ptr32 Void
2007-9-27 17:19
0
雪    币: 191
活跃值: (41)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
10
另外,如果要读取其它进程的 PEB 地址可以看看 http://www.ztssoft.com/post/PebAddress.html
2007-9-27 17:27
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
11
楼上暴露真身了
2007-9-27 17:32
0
雪    币: 191
活跃值: (41)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
12
呵呵
2007-9-27 17:47
0
雪    币: 1829
活跃值: (1377)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
13
好文,学习之,鼓励之
2007-9-27 18:37
0
雪    币: 280
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
谢谢,收藏了。
2007-9-28 09:50
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
谢谢各位,尤其小喂,呵呵,可不可以把你的blog上的code跟我share一下啊?
answerhyh@hotmail.com,thanks!
2007-9-28 10:21
0
雪    币: 191
活跃值: (41)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
16
把 blog 更新了一下,把代码传上去了。
2007-9-28 19:42
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
谢谢小喂
2007-9-29 09:35
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
18
不错,学习了~~
2007-9-30 23:40
0
游客
登录 | 注册 方可回帖
返回
//