zoukankan      html  css  js  c++  java
  • 通过PEB的Ldr枚举进程内所有已加载的模块

    一、几个重要的数据结构,可以通过windbg的dt命令查看其详细信息

    _PEB、_PEB_LDR_DATA、_LDR_DATA_TABLE_ENTRY

    二、技术原理

    1、通过fs:[30h]获取当前进程的_PEB结构

    2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构

    3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构

    4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构,注意:这里的Flink指向的是_LDR_DATA_TABLE_ENTRY结构中的InMemoryOrderLinks成员,因此需要计算真正的_LDR_DATA_TABLE_ENTRY起始地址,我们可以用CONTAINING_RECORD来计算。

    5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息。

    三、代码实现(基于XP sp2 系统)

    //EnumInLoadModule.c  
    //compile:cl EnumInLoadModule.c
    #include <windows.h>

    #define CONTAINING_RECORD(address, type, field) ((type *)( /
    (PCHAR)(address) - /
    (ULONG_PTR)(&((type *)0)->field)))

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

    typedef struct _PEB_LDR_DATA
    {
    DWORD Length;
    UCHAR Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    PVOID EntryInProgress;
    }PEB_LDR_DATA,*PPEB_LDR_DATA;

    typedef struct _LDR_DATA_TABLE_ENTRY
    {
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    DWORD SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    DWORD Flags;
    WORD LoadCount;
    WORD TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    DWORD CheckSum;
    DWORD TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;
    }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

    typedef struct _PEB
    {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR SpareBool;
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PPEB_LDR_DATA Ldr;
    }PEB,*PPEB;

    int main(void)
    {
    PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
    PLIST_ENTRY pListEntryStart = NULL,pListEntryEnd = NULL;
    PPEB_LDR_DATA pPebLdrData = NULL;
    PPEB pPeb = NULL;

    //故意加载一些DLL,以便测试!
    LoadLibrary("ResLibDemo");
    __asm
    {
    //1、通过fs:[30h]获取当前进程的_PEB结构
    mov eax,dword ptr fs:[30h];
    mov pPeb,eax
    }

    //2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构
    pPebLdrData = pPeb->Ldr;

    //3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构
    pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;

    //查找所有已载入到内存中的模块
    do
    {
    //4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构
    pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks);

    //5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息
    printf("%S/n",pLdrDataEntry->BaseDllName.Buffer);

    pListEntryStart = pListEntryStart->Flink;

    }while(pListEntryStart != pListEntryEnd);
    }

    /*
    output:
    EnumInLoadModule.exe
    ntdll.dll
    kernel32.dll
    ResLibDemo.dll
    ...
    */
  • 相关阅读:
    数字索引分页
    经典语录 cloud
    日常交际技巧经验总结100句(大全) cloud
    成大事必备9种能力、9种手段、9种心态 cloud
    浅谈服务器虚拟化
    使用mysqlard监控mysql服务器性能
    CentOS服务器iptables配置
    如何编写好的应用程序
    电子杂志新出路
    泸州老窖集团有限责任公司电子化职能化和网络化的管理新模式
  • 原文地址:https://www.cnblogs.com/dsky/p/2364503.html
Copyright © 2011-2022 走看看