一、几个重要的数据结构,可以通过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
...
*/

  

通过PEB的Ldr枚举进程内所有已加载的模块的更多相关文章

  1. IE报错:模块"scrrun.dll"已加载,但对DllRegisterServer的调用失败,错误代码为0x80004005

    在我的win10系统上打开某内部网页登录的时候弹出'模块"scrrun.dll"已加载,但对DllRegisterServer的调用失败,错误代码为0x80004005'报错信息, ...

  2. 实现winform DataGridView控件判断滚动条是否滚动到当前已加载的数据行底部

    判断 DataGridView控件滚动条是否滚动到当前已加载的数据行底部,其实方法很简单,就是为DataGridView控件添加Scroll事件,然后写入以下代码就可以了,应用范围:可实现分部加载数据 ...

  3. 模块已加载,但对dllregisterServer的调用失败

    在注册dll或者ocx的时候, 经常会遇到这么一个问题: 模块  已加载,但对dllregisterServer的调用失败,错误代码为0x8004***** 网上有网友回复说需要在管理员的模式下进行注 ...

  4. 模块shimgvw.dll已加载,但找不到入口点DllRegisterServer

    [环境]Windows 7 / Windows Server 2008 [现象]在文件夹浏览器中不能显示图片缩略图. [错误信息]查系统日志,有如下消息:“模块shimgvw.dll已加载,但找不到入 ...

  5. 模块"xxxx.dll"已加载,但对DllRegisterServer的调用失败,错误代码为 XXXXXXXXX

    WIN7.WIN8  注册 卸载dll  报错: 模块"xxxx.dll"已加载,但对DllRegisterServer的调用失败,错误代码为 XXXXXXXXX 解决方法: 若为 ...

  6. winform DataGridView控件判断滚动条是否滚动到当前已加载的数据行底部 z

    http://www.zuowenjun.cn/post/2015/05/20/162.html 判断 DataGridView控件滚动条是否滚动到当前已加载的数据行底部,其实方法很简单,就是为Dat ...

  7. System.Reflection.Assembly.GetEntryAssembly()获取的为当前已加载的程序集

    今天在使用System.Reflection.Assembly.GetEntryAssembly()获取程序集时,发现获取的程序集不全.原来是因为C#的程序集为延迟加载,此方法只获取当前已加载的,未加 ...

  8. 检测js代码是否已加载的判断代码

    该方法不局限于jQuery的检测,对与任何Javascript变量或函数都是通用的. 当前网页加载jQuery后,jQuery()或$()函数将会被定义,所以检测jQuery是否已经加载存在以下2种方 ...

  9. Javascript中只能在 HTML 输出流中使用 document.write,在文档已加载后使用它(比如在函数中),会覆盖整个文档。

    意思就是说,初次加载时如果没有加载document.write,那么再次加载的时候回覆盖掉原来的内容,只显示新加载的内容. <!DOCTYPE html> <html> < ...

随机推荐

  1. Spark—初识spark

    Spark--初识spark 一.Spark背景 1)MapReduce局限性 <1>仅支持Map和Reduce两种操作,提供给用户的只有这两种操作 <2>处理效率低效 Map ...

  2. python基础之文件的读取

    #文件名 txt文件的读取#文件的读取 open("文件","读写方法") with open("文件","读写方法") ...

  3. python3执行.sql文件

    这个脚本主要是遍历执行文件夹下的sql文件,但是没有辨别文件的格式,所以文件夹下只能够放.sql文件,否则会报错哈. 我的sql文件夹与执行的文件平级,所以dir_path就是sql,大家依照自己的路 ...

  4. 二进制方式安装 k8s

    推荐个好用的安装k8s的工具 https://github.com/easzlab/kubeasz 该工具基于二进制方式部署 k8s, 利用 ansible-playbook 实现自动化    1.1 ...

  5. P2015

    二叉苹果树 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include< ...

  6. Mysql 基础用法

    #创建表 CREATE TABLE table_name (column_name int) CREATE TABLE IF NOT EXISTS `runoob_tbl`( `runoob_id` ...

  7. C语言学习之基本数据类型【一】

    近期学习鸿蒙硬件物联网开发,用到的开发语言是C: 一.基础语法:第一个案例: 命令 gcc hello.c #include <stdio.h> //stdio.h 是一个头文件 , #i ...

  8. HTML之单词

    段落 paragraph <a href="https://www.runoob.com">超链接 anchor (锚点,引申为连接,link已经被html占用) Hy ...

  9. jvm源码解读--19 Java的join()方法解读 以及 invokestatic 字节码 执行 流程图

  10. decimal和float的区别

    场景 今天在开发的时候,在mongodb中有个字段保存的数据结构是decimal,然后需要对这个字段的值进行范围的查询.结果却怎么查询值范围都是空. 解决 如图中看到的,利用Navicat,可以明显的 ...