最近在看rootkits相关的资料,无意间又翻到了驱动过滤类的知识。分层驱动程序不仅可以截获数据,也可以在传递数据之前对其进行修改。
IRP和堆栈位置
学习windows下的驱动,IRP一定是重中之重,他其实就相当于windows应用层下的消息,传递着各个操作的命令。先来看看IRP的结构:
结合上面的结构图,定义如下:
typedef struct _IRP {
PMDL MdlAddress;//MDL地址,内存描述符表。用来建立一块虚拟地址空间与物理地址页面之间的映射
/*下面是一个共用体,很重要,联合的IRP,里面的SystemBuffer是指向应用层传递来的数据,采用的是DO_BUFFER_IO缓冲区拷贝的方式通信,速度慢,一般在DeviceIoControl小数据使用*/
union {
struct _IRP *MasterIrp;
LONG IrpCount;
PVOID SystemBuffer;
} AssociatedIrp;
/*里面有两个结构,一个Status是IRP完成的状态,一个是Infotmation存放数据传输的个数*/
IO_STATUS_BLOCK IoStatus;
CHAR StackCount;//栈的个数,可以由设备对象中StackSize的值决定
CHAR CurrentLocation;//当前的设备栈位置,很重要,过滤器驱动需要判断是否大于0,否则直接蓝屏处理
PKEVENT UserEvent;//构建IRP时很重要,同步事件,后面会讲到。
} Overlay;
PVOID UserBuffer;//用户缓冲区,第三种方式和应用程序共享数据。这种速度最快,但也是最不安全,内核程序直接读取用户的内存,必
须保证在相同设备上下文中访问才不会出错。
union {
struct {
struct {
union {
struct _IO_STACK_LOCATION *CurrentStackLocation;//IO设备栈指针,他是一个设备栈数组
};
};
} Overlay;
} Tail;
} IRP, *PIRP;
我们可以详细看下IO_STACK_LOCATION结构(截取一部分):
typedef struct _IO_STACK_LOCATION {
UCHAR MajorFunction;//IRP主功能码
UCHAR MinorFunction;//IRP次功能码,尤其是Pnp的IRP尤为重要
UCHAR Flags;
UCHAR Control;//DeviceControl的控制码