编程安全学习笔记

概念:

NT, WDM, WDF驱动模型
设备有可能有名称,如串口\Device\Serial0,也有可能没有设备名称(设备名称与符号连接名不一样,前者
是内核程序对设备的一个标识,内核函数中要用到,后者是外部设备访问设备的标识)

WDM驱动模型:
函数简介:

IoGetDeviceObjectPointer 通过名字来获得设备对象指针
ObReferenceObjectByName 通过名字来获得对象指针(为公开的函数,不只是用于设备指针,还包括驱动对象指针或其他内核对象的指针)
IoGetAttachedDevice 得到绑定设备的最顶层设备对象指针,与下面一个函数有稍微不同
IoGetAttachedDeviceReference 到绑定设备的最顶层设备对象指针
IoCreateDevice 生成设备,需要系统权限的用户才能打开(比如管理员)
IoCreateDeviceSecure 生成有名字的设备(普通用户也可以)
IoAttachDeviceToDeviceStack 绑定设备(依靠设备指针)
IoAttachDeviceToDeviceStackSafe  绑定设备(依靠设备指针,版本要求高)
IoAttachDevice 绑定设备(依靠名字)
IoDetachDevice 解除绑定
IoDeleteDevice 删除设备

IoCallDriver 向设备发送Irp,除了power设备以外
PoCallDriver 向power设备发送请求,在调用IoskipCurrentIrpStackLocation之前先调用PoStartNextPowerIrp.
IoSkipCurrentIrpStackLocation 与 IoCopyCurrentIrpStackLocationToNext 区别:

/*
 1.如果对irp完成之后的事情无兴趣,直接忽略当前IO_STACK_LOCATION, (对我们的程序来说,调用IoSkipCurrentIrpStackLocation),然后向下传递请求,返回IoCallDriver所返回的状态.

2.不但对irp完成之后的事情无兴趣,而且我不打算继续传递,打算立刻返回成功或失败.那么我不用忽略或者拷贝当前IO_STACK_LOCATION,填写参数后调用IoCompleteRequest,并返回我想返回的结果.

3.如果对irp完成之后的事情有兴趣,并打算在完成函数中处理,应该首先拷贝当前 IO_STACK_LOCATION(IoCopyCurrentIrpStackLocationToNext),然后指定完成函数,并返回 IoCallDriver()所返回的status.完成函数中,不需要调用IoCompleteRequest!直接返回Irp的当前状态即可.
IoCompleteRequest 返回给I/o管理器处理完Irp后的状态
*/

IoSetCompletionRoutine 设置完成函数例程
IoCreateSymbolicLink 产生符号连接,通过DeviceIoControl与应用程序进行通信

IoEnumerateDeviceObjectList列举该驱动下所有的设备
InterLockedExchangePointer原子操作交换指针
/*
更改中断服务向量相关代码:见ps2intcap.c
//得到中断向量表地址:
void *p2cGetIdt()
{
    P2C_IDTR idtr;
    // 一句汇编读取到IDT的位置。
    _asm sidt idtr
    return (void *)idtr.base;
}


*/
__declspec(naked) 表示裸函数,可用于生成纯汇编代码,例如:
/*
__declspec(naked) p2cInterruptProc()
{
    __asm
    {
        pushad                    // 保存所有的通用寄存器
        pushfd                    // 保存标志寄存器
        call p2cUserFilter    // 调一个我们自己的函数。 这个函数将实现
                                    // 一些我们自己的功能
        popfd                    // 恢复标志寄存器
        popad                    // 恢复通用寄存器
        jmp    g_p2c_old        // 跳到原来的中断服务程序
    }
}
*/

设计方法:
1. 过滤程序可以绑定设备,在自己的驱动中定义分发函数,或者直接替换利用已知驱动的分发函数,利用
InterLockedExchangePointer.
2. 可以修改底层中断服务程序来过滤,或者利用IOAPIC寄存器编程来改变中断服务程序(IOAPIC寄存器初始地址:0xfec00000),
3. 虚拟磁盘:

WDF驱动模型:
函数与数据结构简介:

WDFDEVICE 设备
WDFDRIVER 驱动
WDFREQUEST 请求——相当于Irp
WDFQUEUE 队列

WDF_DRIVER_CONFIG_INIT(
    OUT PWDF_DRIVER_CONFIG  Config,
    IN PFN_WDF_DRIVER_DEVICE_ADD  EvtDriverDeviceAdd
    ) 初始化一个驱动的配置项,第二个参数是一个回调函数
WdfDeviceInitAssignName 给一个设备的设备对象指定一个名字
WdfDeviceInitSetDeviceType 设置设备的类型
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_, _)可以用于设置设备的扩展,或者其它对象的扩展,例如队列的扩展
WdfDeviceCreate 产生设备对象
WdfDriverCreate 产生驱动对象

WDF_OBJECT_ATTRIBUTES 框架的对象属性,里面有回调函数接口,提供销毁对象的回调函数(如)
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE宏用户配置队列对象(分发函数)分发类型
WDF_IO_QUEUE_CONFIG 配置队列(分发函数)的回调函数等, 分发函数中输入参数有队列对象
WdfIoQueueCreate 产生队列对象,需与某个设备关联
WdfDeviceGetDriver 得到设备对应的的驱动
WdfDriverGetRegistryPath 利用驱动对象得到注册的路径
RtlQueryRegistryValues 请求得到很多注册表项的值
WdfDeviceCreateSymbolicLink 产生设备链接符号

你可能感兴趣的:(编程,汇编,object,IO,扩展,attributes)