方法是基于PsLoadModuleList方式

驱动中遍历模块

一丶简介

简介:

进入内核了.遍历内核中使用的模块该怎么办. 其实在驱动中.我们的DriverEntry入口位置.

提供了两个参数. 一个是DrIverObject另一个则是注册表路径.

其实遍历模块的技巧就在这个DriverObject中.

众所周知在Ring3下遍历模块可以通过TEB PEB遍历. 我们会接触一个结构体叫做LDR_DATA_TABLE_ENTRY的结构体.

内核中也会使用这个结构体. 看下DriverObject对象所代表的含义.


  1. typedef struct _DRIVER_OBJECT {
  2. CSHORT Type;
  3. CSHORT Size;
  4. PDEVICE_OBJECT DeviceObject; //驱动对象
  5. ULONG Flags; //驱动的标志
  6. PVOID DriverStart; //驱动的起始位置
  7. ULONG DriverSize; //驱动的大小
  8. PVOID DriverSection; //指向驱动程序映像的内存区对象
  9. PDRIVER_EXTENSION DriverExtension; //驱动的扩展空间
  10. UNICODE_STRING DriverName; //驱动名字
  11. PUNICODE_STRING HardwareDatabase;
  12. PFAST_IO_DISPATCH FastIoDispatch;
  13. PDRIVER_INITIALIZE DriverInit;
  14. PDRIVER_STARTIO DriverStartIo;
  15. PDRIVER_UNLOAD DriverUnload;
  16. PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
  17. } DRIVER_OBJECT;
  18. typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;

在这里主要使用 DriverSection这个成员 这个成员则可以解释为LDR_DATA_TABLE_ENTRY结构体.

里面存放着我们的所有模块.


  1. typedef struct _LDR_DATA_TABLE_ENTRY {
  2. LIST_ENTRY InLoadOrderLinks; //链表存储,指向下一个LDR_DATA_TABLE_ENTRY结构
  3. LIST_ENTRY InMemoryOrderLinks;
  4. LIST_ENTRY InInitializationOrderLinks;
  5. PVOID DllBase; //基址
  6. PVOID EntryPoint;
  7. ULONG SizeOfImage;
  8. UNICODE_STRING FullDllName;
  9. UNICODE_STRING BaseDllName; //存放着驱动模块名
  10. ULONG Flags;
  11. USHORT LoadCount;
  12. USHORT TlsIndex;
  13. union {
  14. LIST_ENTRY HashLinks;
  15. struct {
  16. PVOID SectionPointer;
  17. ULONG CheckSum;
  18. };
  19. };
  20. union {
  21. struct {
  22. ULONG TimeDateStamp;
  23. };
  24. struct {
  25. PVOID LoadedImports;
  26. };
  27. };
  28. }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

所以代码就很简单了.直接遍历自身结构体的 DriverSection成员即可.解释为(LDR_DATA_TABLE_ENTRY)结构.

二丶代码以及演示.

  1. #include "Driver.h" //这个替换为自己的. 包含Ntddk.h即可.
  2. #include <wdm.h>
  3. //KLDR_DATA_TABLE_ENTRY
  4. typedef struct _LDR_DATA_TABLE_ENTRY {
  5. LIST_ENTRY InLoadOrderLinks;
  6. LIST_ENTRY InMemoryOrderLinks;
  7. LIST_ENTRY InInitializationOrderLinks;
  8. PVOID DllBase;
  9. PVOID EntryPoint;
  10. ULONG SizeOfImage;
  11. UNICODE_STRING FullDllName;
  12. UNICODE_STRING BaseDllName;
  13. ULONG Flags;
  14. USHORT LoadCount;
  15. USHORT TlsIndex;
  16. union {
  17. LIST_ENTRY HashLinks;
  18. struct {
  19. PVOID SectionPointer;
  20. ULONG CheckSum;
  21. };
  22. };
  23. union {
  24. struct {
  25. ULONG TimeDateStamp;
  26. };
  27. struct {
  28. PVOID LoadedImports;
  29. };
  30. };
  31. }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
  32. NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
  33. {
  34. ULONG iCount = 0;
  35. NTSTATUS ntStatus;
  36. pDriverObj->DriverUnload = DriverUnLoad;
  37. KdBreakPoint();
  38. /*
  39. 主要是遍历DriverObject中的 DriverSection 它可以解释为LDR_DATA_TABLE_ENTRY结构体
  40. */
  41. PLDR_DATA_TABLE_ENTRY pLdr = NULL;
  42. PLIST_ENTRY pListEntry = NULL;
  43. PLIST_ENTRY pCurrentListEntry = NULL;
  44. PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
  45. pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
  46. pListEntry = pLdr->InLoadOrderLinks.Flink;
  47. pCurrentListEntry = pListEntry->Flink;
  48. while (pCurrentListEntry != pListEntry) //前后不相等
  49. {
  50. //获取LDR_DATA_TABLE_ENTRY结构
  51. pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  52. if (pCurrentModule->BaseDllName.Buffer != 0)
  53. {
  54. DbgPrint("ModuleName = %wZ ModuleBase = %p \r\n",
  55. pCurrentModule->BaseDllName,
  56. pCurrentModule->DllBase);
  57. }
  58. pCurrentListEntry = pCurrentListEntry->Flink;
  59. }
  60. return STATUS_SUCCESS;
  61. }

结果.

代码简单改一下.还可以获得指定的模块的基址以及结束地址.

代码如下

  1. VOID GetModuleBaseByName(PDRIVER_OBJECT pDriverObj,UNICODE_STRING ModuleName)
  2. {
  3. PLDR_DATA_TABLE_ENTRY pLdr = NULL;
  4. PLIST_ENTRY pListEntry = NULL;
  5. PLIST_ENTRY pCurrentListEntry = NULL;
  6. PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
  7. pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
  8. pListEntry = pLdr->InLoadOrderLinks.Flink;
  9. pCurrentListEntry = pListEntry->Flink;
  10. while (pCurrentListEntry != pListEntry) //前后不相等
  11. {
  12. //获取LDR_DATA_TABLE_ENTRY结构
  13. pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  14. if (pCurrentModule->BaseDllName.Buffer != 0)
  15. {
  16. if (RtlCompareUnicodeString(&pCurrentModule->BaseDllName, &ModuleName, TRUE) == 0)
  17. {
  18. DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p\r\n",
  19. pCurrentModule->BaseDllName,
  20. pCurrentModule->DllBase,
  21. (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);
  22. }
  23. }
  24. pCurrentListEntry = pCurrentListEntry->Flink;
  25. }
  26. }

驱动中遍历模块,以及获取ntoskrnl.exe基址的更多相关文章

  1. kernel 获取ntoskrnl.exe基址

    标题: kernel shellcode之寻找ntoskrnl.exe基址 http://scz.617.cn:8/windows/201704171416.txt 以64-bits为例,这是Eter ...

  2. scala调用java的方法,返回了一个对象链表List<Student>,在scala中遍历该链表获取指定Student的名字name

    假设Student类如下: class Student { private int no; private String name; public int getNo() { return no; } ...

  3. VC中遍历进程并获取进程信息

    代码如下: /***************************************************/ /* 函数: 遍历进程信息 /* 参数:进程名称 例如: aaa.exe /* ...

  4. python 中requests 模块用py2exe生成exe后SSL certificate exception的问题

    [('system library', 'fopen', 'No such process'), ('BIO routines', 'BIO_new_file', 'no such file'), ( ...

  5. 驱动中获取PsActiveProcessHead变量地址的五种方法也可以获取KdpDebuggerDataListHead

    PsActiveProcessHead的定义: 在windows系统中,所有的活动进程都是连在一起的,构成一个双链表,表头是全局变量PsActiveProcessHead,当一个进程被创建时,其Act ...

  6. SOS从内存转储中提取模块(EXE、DLL和其他二进制文件)

    假设有一种情况,您从客户那里得到一个内存转储,需要模块(DLL.EXE.OCX等)来进一步调试..(.NET模块可用于通过反向工程查看源代码.)我们可以使用windbg目录中的clr10\sos.dl ...

  7. VC中遍历目标进程中的模块

    VC中遍历目标进程中的模块 MFC代码win32 也可以用 在下面代码进行修改转换就可以了CString strModule; 可以换成 char* 但是MODULEENTRY32结构中的szModu ...

  8. java中遍历实体类,获取属性名和属性值

    方式一(实体类): //java中遍历实体类,获取属性名和属性值 public static void testReflect(Object model) throws Exception{ for ...

  9. 在弹框中获取foreach中遍历的id值,并传递给地址栏(方法2)

    1.php有时候我们需要再弹框中获取foreach中遍历的数据(例如id),在弹框中点击按钮并传递给地址栏跳转.那么应该怎么做呢.第二种方法. 2. 可以在弹框中给出一个input hidden 点击 ...

随机推荐

  1. 谈谈游戏服务端SDK接入

    “接sdk其实本质上就是一个对着接口文档写adaptor的工作,重复和无味.” 团队减员,身负多职,上一次调SDK已经可以回溯到游戏测试前夕了... 一般SDK只包含验证和支付功能,绝少部分SDK包含 ...

  2. 【转载】华为荣耀V9的手机录屏功能如何开启

    手机录屏有时候对我们的帮助很大,例如可以录制相应的APP使用教程.微信小程序使用流量讲解视频等,针对于软件开发人员等来说,手机录屏功能针对功能演示视频非常的有帮助.在华为荣耀V9手机中,进行手机录屏有 ...

  3. requestAnimationFrame ---- 请求动画帧。

    window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画.该方法需要传入一个回调函数作为参数,该回调函数会 ...

  4. 你可能还不知道的关于JavaScript类型的细节?

    类型 七种类型: Undefined Null Boolean String Number Symbol Object Undefined.Null 阅读问题:为什么有的编程规范要求使用void 0 ...

  5. Workerman启动与停止相关命令

    start.php为入口文件 一.启动 1.以debug(调试)方式启动 php start.php start 2.以daemon(守护进程)方式启动 php start.php start -d ...

  6. ionic创建组件、页面或者过滤器

    ionic可以直接 用命令来创建组件.页面或者过滤器. 在ionic项目根目录打开命令窗口.输入下列命令: ionic g page pageName //创建新页面 ionic g componen ...

  7. Git submodule 子模块的管理和使用

    因为代码分了两个小组管理,一部分代码使用跨平台语言实现,一部分使用原生实现. 所以使用Git submodule 来进行管理. 1,查看/更新 子模块 $ git submodule add ssh: ...

  8. Spring源码阅读总结(Ing)

    一.Spring源码架构 Spring源码地址 二.Spring中的设计模式 1.工厂模式 BeanFactory 2.模板模式 模板的使用者只需设计一个具体的类,集成模板类,然后定制那些具体方法,这 ...

  9. JAVA项目从运维部署到项目开发(四. Tomcat)

    一.关于中文乱码问题 文件目录:/conf/server.xml 将相关语句改为: <Connector port="8008" protocol="HTTP/1. ...

  10. idea导入mybatis源码

    1.最近在学mybatis,想下载源码导入idea结果网上一查没有一篇完整的,结果让我进了个大坑,算了,废话少说 2.两种办法,一个是git客户端克隆,另外一个是下载code压缩包.先说通过git客户 ...