您的位置:首页 > 其它

通过PEB->LDR_DATA结构获取模块基址

2017-12-18 20:01 337 查看
peb的0xc处是ldr结构地址
0x0C: PPEB_LDR_data ldr;

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

LIST_ENTRY结构:
typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

_LDR_DATA_TABLE_ENTRY:

lkd> dt -b _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
      +0x000 Flink            : Ptr32
      +0x004 Blink            : Ptr32
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
      +0x000 Flink            : Ptr32
      +0x004 Blink            : Ptr32
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
      +0x000 Flink            : Ptr32
      +0x004 Blink            : Ptr32
   +0x018 DllBase          : Ptr32
   +0x01c EntryPoint       : Ptr32
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
      +0x000 Length           : Uint2B
      +0x002 MaximumLength    : Uint2B
      +0x004 Buffer           : Ptr32       //+0x28
   +0x02c BaseDllName      : _UNICODE_STRING
      +0x000 Length           : Uint2B
      +0x002 MaximumLength    : Uint2B
      +0x004 Buffer           : Ptr32
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
      +0x000 Flink            : Ptr32
      +0x004 Blink            : Ptr32
   +0x03c SectionPointer   : Ptr32
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32
   +0x048 EntryPointActivationContext : Ptr32
   +0x04c PatchInformation : Ptr32

ULONG_STRING:

typedef struct _UNICODE_STRING {  
    USHORT  Length;  
    USHORT  MaximumLength;  
    PWSTR  Buffer;  
} UNICODE_STRING, *PUNICODE_STRING; 

这几个结构体即是pdr链的几个重要结构体。

通过fs:[0x30]来获取PEB地址,再通过PEB+0xC来获取Ldr地址,再通过Ldr的InLoadOrderLinks和InMeoryOrderLinks和InInitializationOrderLinks三个不同的访问模块顺序的双向链表来访问List_Data_Table_Entry来获取模块的基址和名字。



汇编来访问DLL地址:

以InLoadOrderLinks顺序的Dllbase
mov eax,fs:[0x30]      //访问TEB
mov eax,[eax+0xC]      //访问Ldr
mov eax,[eax+0xC]      //访问InLoadOrderLinks顺序的表,同理0x14和0x1c
mov ebx,[eax+0x18]     //访问以InLoadOrderLinks顺序的Dllbase
mov edx,[eax+0x28]     //0x24是fullname,由于是UNICODE_STRING结构,所以这个+0x4才是字符串地址

以InMemoryOrderLinks顺序的Dllbase

mov eax,fs:[0x30]
mov eax,[eax+0xC]
mov eax,[eax+0x14]
mov ebx,[eax+0x10]
mov edx,[eax+0x20]

以InInitializationOrderLinks顺序的Dllbase

mov eax,fs:[0x30]
mov eax,[eax+0xC]
mov eax,[eax+0x1c]
mov ebx,[eax+0x8]
mov edx,[eax+0x14]
mov eax,[eax] /循环链表

 C语言实现循环打印LDR链表以及DllBase:

void *PEB = NULL,
        *Ldr = NULL,
        *Flink = NULL,
        *p = NULL,
        *BaseAddress = NULL,
        *FullDllName = NULL;

    __asm
    {
        mov eax,fs:[0x30]
        mov PEB,eax
    }
    Ldr = (PVOID)*((PDWORD)((DWORD)PEB + 0xC));
    Flink = (PVOID)*((PDWORD)((DWORD)Ldr + 0x14));
    p = Flink;
    do
    {

        BaseAddress = (PVOID)*((PDWORD)((DWORD)p + 0x10));
        FullDllName = (PVOID)*((PDWORD)((DWORD)p + 0x20));
        wprintf(L"FullDllName is %s\n",FullDllName);
        printf("BaseAddress is %x\n",BaseAddress);
        p = (PVOID)*((PDWORD)p);                                                //p的前四字节为Flink,后四字节为Blink

    } while (Flink != (PVOID)*((PDWORD)p));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: