12.10
_IO_STACK_LOCATION的
UCHAR MajorFunction;
UCHAR MinorFunction;
UCHAR Flags;
UCHAR Control;
字段作用
MajorFunction:
该字段定义了一个函数功能集,内核模式驱动可以实现其中的每一个函数。每一个函数由一个函数代码对应
当内核模式驱动接收到一个IRP时,驱动首先检查当前StackLocation中的MajorFunction字段,得出驱动将要执行的功能,可能的MajorFunction功能代码如下:
#define IRP_MJ_CREATE 0x00
#define IRP_MJ_CREATE_NAMED_PIPE 0x01
#define IRP_MJ_CLOSE 0x02
#define IRP_MJ_READ 0x03
#define IRP_MJ_WRITE 0x04
#define IRP_MJ_QUERY_INFORMATION 0x05
#define IRP_MJ_SET_INFORMATION 0x06
#define IRP_MJ_QUERY_EA 0x07
#define IRP_MJ_SET_EA 0x08
#define IRP_MJ_FLUSH_BUFFERS 0x09
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
#define IRP_MJ_DIRECTORY_CONTROL 0x0c
#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
#define IRP_MJ_DEVICE_CONTROL 0x0e
#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
#define IRP_MJ_SHUTDOWN 0x10
#define IRP_MJ_LOCK_CONTROL 0x11
#define IRP_MJ_CLEANUP 0x12
#define IRP_MJ_CREATE_MAILSLOT 0x13
#define IRP_MJ_QUERY_SECURITY 0x14
#define IRP_MJ_SET_SECURITY 0x15
#define IRP_MJ_POWER 0x16
#define IRP_MJ_SYSTEM_CONTROL 0x17
#define IRP_MJ_DEVICE_CHANGE 0x18
#define IRP_MJ_QUERY_QUOTA 0x19
#define IRP_MJ_SET_QUOTA 0x1a
#define IRP_MJ_PNP 0x1b
#define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete....
#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
MinorFunction
MinorFunction提供了MajorFunction更详细的信息
Flags
Flags提供了函数期望驱动执行的附加信息
Control
当内核驱动异步处理IRP时,驱动可以通过调用IoMarkIrpPending()将IRP标记为Pending状态,以排队IRP处理。IoMarkIrpPending实际上只是将当前Stack Location的Control字段设定为SL_PENDING_RETURNED。内核驱动可以检查该字段查询是否有该标记。
12.12
1.结构化异常处理例程,对内核态地址读写异常是无法防止BSOD的
2.ProbeForRead无法校验用户态地址是否合法
3.上个模式是内核模式时,ProbeForRead不做任何检查
4.PorbeForWrite是传入长度0时,不做校验
以下转自MJ0011百度空间:
很多安全防御软件在进行用户态内存的校验时,会使用 ProbeForRead函数,这个函数的源代码如下:
if (Length != 0) {
if (((ULONG_PTR)Address & (Alignment - 1)) != 0) {
ExRaiseDatatypeMisalignment();
} else if ((((ULONG_PTR)Address + Length) > (ULONG_PTR)MM_USER_PROBE_ADDRESS) ||
(((ULONG_PTR)Address + Length) < (ULONG_PTR)Address)) {
*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0;
}
}
我们可以看到它实际做了这么两件事:
1.检查缓存长度不为0后,检查内存是否按指定的字节数对其
2.检查整个缓存区是否位于用户态内存范围内
这两个检查任意一个不成功,该函数都会引发一个异常。
12.13
驱动访问用户态无效地址会BSOD,SEH可以防止。
除了ProbeForRead、ProbeForWrite等检查外,还要看看BufferLength是否为0。
MmIsAddressVaild会检查读写这一页内存是否会发生异常。
ProbeForRead不会进行读操作,ProbeForWrite会进行读写操作。
12.20
ms_exc.disabled置为1时,为有效
为-1时,无效
ms_exc.disabled代表被_try\_except包起来的代码