写在前面

  此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我

  看此教程之前,问个问题, 没有的话就不要继续了,请重新学习前面驱动篇的教程内容继续。


🔒 华丽的分割线 🔒


练习及参考

1️⃣ 编写驱动,申请一块内存,并在内存中存储GDT表的所有数据。然后在DebugView中显示出来,最后释放内存。

2️⃣ 编写驱动,实现如下功能:
<1> 初始化一个字符串;
<2> 拷贝一个字符串;
<3> 比较两个字符串是否相等;
<4> ANSI_STRINGUNICODE_STRING字符串相互转换;

3️⃣ 思考题:为什么DISPATCH_LEVEL不能访问分页内存。

内核空间与内核模块

  在之前的教程里,我们介绍了普通的应用程序的4GB内存只有低2GB可能被自身使用,而高2GB共用。示意图如下所示:

驱动篇——内核空间与内核模块-LMLPHP

  硬件种类繁多,不可能做一个兼容所有硬件的内核,所以,微软提供规定的接口格式,让硬件驱动人员安装规定的格式编写驱动程序 。在内核中,这些驱动程序每一个都是一个模块,称为内核模块,都可以加载到内核中,都遵守PE结构。但本质上讲,任意一个sys文件与内核文件没有区别。每个驱动都是一个模块。就和在3环的程序加载dll一样,加载一个贴上一个。如下图所示:

驱动篇——内核空间与内核模块-LMLPHP

DRIVER_OBJECT

  DRIVER_OBJECT这个东西,在上一篇具有详细的讲解,这次我们再把它给搬过来:

typedef struct _DRIVER_OBJECT {
    CSHORT Type;
    CSHORT Size;

    PDEVICE_OBJECT DeviceObject;
    ULONG Flags;

    PVOID DriverStart;
    ULONG DriverSize;
    PVOID DriverSection;
    PDRIVER_EXTENSION DriverExtension;

    UNICODE_STRING DriverName;
    PUNICODE_STRING HardwareDatabase;
    PFAST_IO_DISPATCH FastIoDispatch;

    PDRIVER_INITIALIZE DriverInit;
    PDRIVER_STARTIO DriverStartIo;
    PDRIVER_UNLOAD DriverUnload;
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

} DRIVER_OBJECT;

  我们如何通过调试信息输出呢,我们如下示例:

DbgPrint("DRIVER_OBJECT 对象地址:%x \r\n",driver);
DbgPrint("驱动名称:%ws \r\n",driver->DriverName.Buffer);
DbgPrint("模块基址:%x \r\n",driver->DriverStart);
DbgPrint("模块大小:%x \r\n",driver->DriverSize);

遍历内核模块与隐藏

  上篇教程我们讲过DriverSection,它是一个存储目前所有已加载的驱动程序信息相关的LDR_DATA_TABLE_ENTRY结构体的双向循环链表。并且我们用WinDbg手动遍历了一下。那么我们用代码遍历也是可以的。这里就留个作业了,具体代码留在下一篇进行讲解。
  如果我们把这个项目从DriverSectionInLoadOrderLinks摘掉后,是不是可以实现隐藏呢?会不会对我加载后的驱动有没有影响?既然驱动已经加载到内存当中,就算你去除了它的存在信息,对它的功能也没有实际影响。可以实现隐藏,不过只是对付一些API,但它还是被揪出来的,如何进一步隐藏将会在后面的教程介绍。

本节练习

  俗话说得好,光说不练假把式,如下是本节相关的练习。如果练习没做好,就不要看下一节教程了,越到后面,不做练习的话容易夹生了,开始还明白,后来就真的一点都不明白了。本节练习不多,请保质保量的完成。

1️⃣ 遍历内核模块,输出模块名称,基址以及大小。
2️⃣ 编写一个函数,找到一个未导出的函数,并调用。(例子:找到PspTerminateProcess,通过调用这个函数结束记事本进程)
3️⃣ 通过断链实现隐藏驱动模块。

下一篇

  驱动篇——常规的0环与3环通信

11-06 15:50