探索黑客技术攻防,实战研究与安全创新

导航菜单

简单驱动开发及逆向之应用程序与驱动程序的通信

虽然应用程序处在操作系统的用户态,而驱动程序处在操作系统的内核态,但是他们之间是必须通信的,应用成的执行都是依赖于操作系统内核的。

创建设备

在编写驱动程序的时候,主函数的入口函数是DRiventey()函数,该函数有一个参数为PDRIVER_OBJECT类型,是指向驱动对象的指针的,为了能够使驱动程序被卸载掉,我们为DRIVER_OBJECT结构体中的DRIVEUNLOAD成员进行了赋值,DRIVEUNLOAD是驱动对象中的一个程序,其保存了驱动卸载例程的指针,起始保存的就是一个函数指针,在DRIVER_OBJECT中,除了DRIVERUNLIAD以外,还有一个数组也存放了函数指针,这个数组名师MAJORFUNCTION,该数组的大小为IRP_MJ_MAXIMUM_FUNCTION+1,IRP_MI_MAXIMMUM_FUNCTION,该数组的大小为IRP_MJ_MAXIMUM_FUNCTION+1,,RP_MJ_MAXIMUM_FUNCTIONSHI是一个宏,该宏的定语为:

在Majorfunction中可以指定非常多的例程指针,比如IRP_MJ_CREATE,irp_mj_read、irp_mj_write、irp_mj_close.........这些例程都有一个相似的定义,定义如下:

这些是摘自WDK提供的文件中的定义,函数名可以随意修改,但是函数的定义是不能修改的,也就是说函数的返回值和参数是已经被确定的。在这些函数的定义中,第一个参数是PDEⅥCE_OBJECT的类型,是一个指向设备对象的指针。第二个参数是一个指向LRP结构体的指针,IRP是I/O请求包。应用程序与驱动程序的通信就是依靠IRP进行的。因此,要在DriverEntry0下指定MajorFunction数组中的各种例程。在没有指定MajorFunction的情况下,有默认的例程来执行。

既然在所有的例程-中都需要设备对象指针,那么自然要创建一个设备,创建设备的函数为.IoCreateDevice0,其定义如下:

该函数用来创建一个设备,参数说明如下:

(1)DRIVEROBJECT:该参数是一个指向驱动对象的指针,指定设备所属的驱动,使用DRIVERENTRY()的第一个参数即可。

(2)deviceextensionsize:指定设备扩展的大小,如果没有设备扩展的话该参数为0

(3)devicename:指定设备名称,设备名通常是\Device\xxx

(4)devicetype:指定设备的类型,由于创建的设备没有具体对应的设备类型,因此此处指定File_DEVICE_UNKNOWN

(5)deicecharacteristics:设置设备对象的特征,这里赋值为0即可。

(6)Exclusive:该参数是一个指向设备对象的指针

(7)deviceobject:该参数是一个指向设备对象的指针

为了能与设备对象进行通信,必须为设备对象指定一个符号链接,用来在应用程序中打开,创建符号链接的函数为IOCREATESYMBOLICLINK(),其定义如下:

该函数的第一个参数用来指定符号链接的名称,该名称通常的格式为\??’\xxx,第二个参数为设备名称。

应用程序与驱动程序的通信方式

应用程序与驱动程序的通信方式通常有打开、关闭、读、写、控制这5种,这5种对应的是Win32API函数分别createfile()、closehandle()、readfile()、writefile()和devicelocontrol(),而这5个win32api函数分别对应着5个派遣例程,分别是IRP_MJ_CREATE、IRP_MJ_CLOSE、IRP_MJWRITE和IRP_MJ_READ、IRP_MJWRITE和IRP_MJDEVICE_CONTROL。下面主要介绍一下DeviceioControl()函数与IRP_MJ_DEVICE_CONTROL派遣例程。deviceloControl()函数是用来向指定设备发送控制码的,当指定的设备接收到deviceloControl()发来的控制码后悔调用IRP_MJ_DEVICE_CONTROL对应的派遣例程,针对不同的控制码进行不同的处理,DeviceloControl()函数的定义如下:

(1) hDevice;该参数指明设备句柄。

(2)  dwIoControICode:该参数是控制码,该值由CTL CODE生成。

(3) lplnBuffer:该参数是输入的缓冲区。

(4) nlnBufferSize;该参数是输入缓冲区大小。

(5) lpOutBuffef:该参数是输出的缓冲区。

(6) nOutBufferSize:该参数是输出缓冲区大小。

(7)  lpBytesReturned:该参数是返回字节的个数。

(8) lpOverlapped:该寥数针对重叠方式使用,通常为O即可。

应用程序与驱动程序的通信实例

应用程序与驱动程序之间的通信实例以前面写的HOOK NtCreateProcessEx()来进行介绍。在应用程序中通过发送控制码来启动和关闭HOOK.对NtCreateProcessEx()的HOOK进行有效地控制。下面直接给出完整的源代码,代码如下:下面来看一下应用层的代码,在于驱动进行通信时候,首先要打开驱动程序:

在使用CREATEFILE()函数时,该函数的第一个参数为驱动程序的符号链接,定义驱动的符号链接为:L”\\??HookNtCreaterProcessEx”,当在应用层中使用的时候应该改为:

打开驱动程序后,通过DEVICELOCONTROL()来对驱动程序发送控制码,使驱动程序开启或者关闭HOOK,代码如下:

在应用程序中使用CTL_CODE宏时应包含头文件Winidoctl.h,运行看一下效果,当开启HOOK时NTCREATEEPROCESSEX()会直接返回,也就是不进行进程的创建,当关闭HOOK后,NtCreaprocessEx()又会正常的创建进程,用KMDMANAGER加载驱动,然后用我们编写的应用程序开启HOOK后运行的任意程序,创建进程都会失败,如图7-12所示。

图片64.png

关于驱动的开发有非常多的东西需要学习,驱动开发时下也非常流行,很多安全厂商都对驱动开发人员有着大量的需求.

本文内容所提及均为本地测试或经过目标授权同意,旨在提供教育和研究信息,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,作者不鼓励或支持任何形式的非法行为。