天书夜读笔记——C++写的内核驱动程序

news/2024/11/16 5:46:39/

友链

extern "C" {#include<ntifs.h>
}class MyDriver 
{
public:MyDriver(PDRIVER_OBJECT driver);virtual NTSTATUS OnDispatch(PDEVICE_OBJECT dev, PIRP irp) {return STATUS_UNSUCCESSFUL;};static MyDriver *d_my_driver;private:static NTSTATUS sDispatch(PDEVICE_OBJECT dev, PIRP irp);PDRIVER_OBJECT d_driver;
};MyDriver::MyDriver(PDRIVER_OBJECT driver) : d_driver(driver)
{size_t i;for(i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++) {d_driver->MajorFunction[i] = sDispatch;}d_my_driver = this;
};NTSTATUS MyDriver::sDispatch(PDEVICE_OBJECT dev, PIRP irp) {return d_my_driver->OnDispatch(dev, irp);
}MyDriver* MyDriver::d_my_driver = NULL;void* __cdecl operator new(unsigned int size) {void* pt = ExAllocatePool(NonPagedPool, size);if(NULL != pt) memset(pt, 0, size);return pt;
}extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg
) {MyDriver::d_my_driver = new MyDriver(driver);return STATUS_UNSUCCESSFUL;
}

类中还定义了一个虚函数(OnDispatch)可以让后续继承该类的子类来进行自己的实现

由于driver是一个singleton,所以我们可以用d_my_driver指针来指向this,这样就解决了静态函数的调用问题(静态函数无法引用类的非静态成员)

因为只有静态成员函数才能像C函数一样被使用,但是静态成员函数无法调用虚函数,因此我们需要一个静态成员d_my_drvier,一个指针,让他指向MyDriver,就和this一样,这样我们就能通过d_my_drvier来调用虚函数了

通过反汇编代码,可以看到,new函数只负责分配内存,构造函数是在driver_entry函数体内被调用的,也就是说编译器在看到new之后会自动调用构造函数

在这里插入图片描述

我们来看一下构造函数的实现

.text:000104CC ; void __thiscall MyDriver::MyDriver(MyDriver *this, _DRIVER_OBJECT *driver)
.text:000104CC ??0MyDriver@@QAE@PAU_DRIVER_OBJECT@@@Z proc near
.text:000104CC                                         ; CODE XREF: DriverEntry(x,x)+16p
.text:000104CC
.text:000104CC driver          = dword ptr  8
.text:000104CC
.text:000104CC this = ecx
.text:000104CC                 mov     edi, edi
.text:000104CE                 push    ebp
.text:000104CF                 mov     ebp, esp
.text:000104D1                 mov     eax, this
.text:000104D3                 mov     this, [ebp+driver]
.text:000104D6                 push    38h
.text:000104D8                 mov     [eax+4], this
.text:000104DB                 mov     dword ptr [eax], offset ??_7MyDriver@@6B@ ; const MyDriver::`vftable'
.text:000104E1                 pop     this
.text:000104E2
.text:000104E2 loc_104E2:                              ; CODE XREF: MyDriver::MyDriver(_DRIVER_OBJECT *)+29j
.text:000104E2                 mov     edx, [eax+4]
.text:000104E5                 mov     dword ptr [this+edx], offset ?sDispatch@MyDriver@@CGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; MyDriver::sDispatch(_DEVICE_OBJECT *,_IRP *)
.text:000104EC                 add     this, 4
.text:000104EF                 cmp     this, 0A4h
.text:000104F5                 jbe     short loc_104E2
.text:000104F7                 mov     ?d_my_driver@MyDriver@@2PAV1@A, eax ; MyDriver * MyDriver::d_my_driver
.text:000104FC                 pop     ebp
.text:000104FD                 retn    4
.text:000104FD ??0MyDriver@@QAE@PAU_DRIVER_OBJECT@@@Z endp

可以看到调用约定为thiscall

this指针通过ecx传入函数,ecx是new函数的返回值,也就是新分配的内存地址

this->eax,然后ebp+driver->this, this->eax+4

那么也就是说在内存地址偏移量为0x4的地方存入了driver这个参数,就是我们构造函数的那个列表初始化中的d_driver成员变量

那么前四个字节干嘛去了呢,继续往下看可以看到

.text:000104DB                 mov     dword ptr [eax], offset ??_7MyDriver@@6B@ ; const MyDriver::`vftable'

可以看到,前四个字节存放的是虚函数表

然后就开始对driver结构体的成员MajorFunction数组依次进行赋值
你可能会疑问,这里的[this+edx]是什么东西,仔细看一下代码,你会发现,前面有一对push pop操作,使得this的值变成了0x38h,正好是MajorFunction成员在driver结构体中的偏移量,而edx的值是[eax+4],也就是driver成员变量,所以一切都解释得通

另外,从代码中可以看出MyDriver::d_my_driver是一个全局变量

构造函数返回后,在driverentry中,构造函数的返回值eax->d_my_driver,这里的eax其实还是new函数的返回值,只不过它所指向的地址被构造函数填满了数据

看到这里,你应该就能够意识到,类其实就是一堆变量和函数的集合,没什么复杂的东西

另外需要补充的一点就是,我们必须要生命一个全局变量

MyDriver* MyDriver::d_my_driver = NULL;

因为在构造函数MyDriver::MyDriver中,我们用到了d_my_driver


http://www.ppmy.cn/news/734971.html

相关文章

适用于XP的DDK

友链 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 占位 …

Ubuntu 18.04 安装网卡驱动(有线连接)

之前一直用小米的驱动&#xff0c;但是感觉太慢了&#xff0c;所以还是决定使用有线连接。 但是之前进入Linux系统后&#xff0c;有线连接没有&#xff0c;所以需要安装驱动。 01 查询网卡类型&#xff08;Windows&#xff09; 进入windows系统&#xff0c;进入CMD命令行&am…

linux装完显卡驱动分辨率低,装上显卡驱动后屏幕分辨率变低了,肿么破。。。...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 00:00.0 Host bridge: Intel Corporation 2nd Generation Core Processor Family DRAM Controller (rev 09) Subsystem: Device 1b0a:2099 Kernel driver in use: agpgart-intel 00:01.0 PCI bridge: Intel Corporation Xeon E3-1…

Python 之测试数据驱动

Parameterized 模块 parameterized 第三方包的安装&#xff1a; pip install parameterized $ pip install parameterized Collecting parameterizedDownloading https://files.pythonhosted.org/packages/65/d4/b0b626eb263a4c2aa3ca3cd20ea3db410db837f7f6b5d3fc4a6c4bee363…

华为服务器linux版的网卡驱动下载,华为服务器RH2288H V3 服务器上安装Windows2008 R2 SP1指导书...

1 安装前准备 1.1 硬件环境准备 无 备注: 本指导书以虚拟光驱、虚拟软驱为例,如使用物理光驱、物理软驱安装系统操作则以实际系统光盘、软盘代替。 1.2 软件环境准备 1.2.1 准备操作系统安装文件 到windows 官网下载安装文件,或者采用光盘安装文件。 …

Clover 驱动文件夹_Intel全系利核显驱动教程

关注上方蓝字关注黑果小白 让小白为你排忧解难 1 驱动准备 清理旧驱动 显卡驱动准备工作,请清理以前的驱动→获取 IGPU 的设备路径→填入 ig-platform-id→填入 device-id关于HD4600集显驱动,举个例子:驱动完 HD4600 也就这点东西。仿冒设备id及核显型号就可以了!缩写解释缩…

shumei gpio

2019独角兽企业重金招聘Python工程师标准>>> • 树莓派GPIO介绍 树莓派包含8个通用IO (GPIO) 用于开关控制 (switch control)&#xff0c;配合扩展版可以进行继电器、电机、LED等外设的驱动。该扩展IO的位置如下所示&#xff1a; Figure 1. 树莓派1扩展IO在板上的位…

Ubuntu搭建驱动开发环境

1、使用的是linux-5.0.1 ubuntu1910 2、安装依赖 build-essential kernel-package gcc make libncurses5-dev libssl-dev libelf-dev均可用sudo apt-get install … 3、源文件获取与安装 3.1、获取内核源码 # 查看系统内核版本 uname -r 5.0.0-32-generic # 获取源文件包 …