TDI 过滤框架:

wdm.h

定义了PDRIVER_OBJECT结构体类型

tdi_fw.c

  1. c_n_a_device: 驱动生成设备
  2. d_n_d_device:删除设备
  3. Devicepatch:唯一的设备分发函数 ,如果能get_original_devobj找到old_devobj就调用IoSkipCurrentIrpStackLocation栈中得到请求,再IoCallDriver将二者发到下层(实际:对请求(IRP)的主功能号(irps->MajorFunction)进行处理。
    (ps:次功能号:irps->MiniorFunction)
    对于特定请求:如IRP_MJ_CREATE ,先tdi_create 进行过滤得到结果,tdi_dispatch_complete 为完成函数,通过result来进行处理
  4. get_origin_devobj tcp/ip/udp 三对设备及其指针匹配

框架

  1. Onload 删除+解绑所有已生成和绑定的设备
  2. DriverEntry 驱动入口+分发函数+生成过滤设备并绑定三种设备(c_n_a_device)

过滤生成请求

disp_obj.c:

  1. tdi_create: 对于 IRP_MJ_CREATE 请求的过滤 ,生成一个文件对象有两种可能:

    • TdiTransportAddress:表明生成传输层地址
    • TdiConnectionContext: 表明生成连接终端

    TDI先生成1,再2,再用控制请求将二者连接起来

    1.1 生成传输层地址时。询问被打开的文件对象来获得ip地址和端口,调用TdiBuildInternalDeviceControlIrp分配空的请求,此请求需要在Passive Level 进行调用
    Ps: 完成函数一般在DisPatch level

    2.1 连接终端的结构:CONNECTION_CONTEXT, 可以从ea中得到

    为了将 文件对象 与 连接上下文 对应起来,可以使用hash表存储(ot_add_fileobj)
    同理存储 文件对象 与 生成地址 对应起来

  2. tdi_create_addrobj_complete/2 从上面的生成的传输层地址得到生成的IP地址(32位长整数即4字节)和端口(16字节整数)

控制请求

disp_obj.c

  1. 两种控制请求(起相同的作用):

    • IRP_MJ_DEVICE_CONTROL:应用层向驱动层发送设备
    • IRP_MJ_INTERNAL_DEVICE_CONTROL:内核内部发送设备控制命令

      次功能号有:

      1. TDI_ASSOCIATE_ADDRESS:将传输层地址对象(IP)和连接对象(FileObj)连接起来,即与连接终端中使用hash表存储的文件对象与连接上下文这个组合连接。
        使得:得到连接上下文对象时,能够立刻知道使用的本地地址。
        方法:从栈空间参数中得到上面传入的传输层地址的文件的句柄并将其转化(ObReferenceObjectByHandle)为文件对象指针(addrobj),ot_find_fileobj找到保存过这个连接上下文所对应的表单元ote_conn,使用
        ote_conn->associated_fileobj= addrobj 将其连接
        使得:将 连接上下文指针 与 地址文件对象指针 连接起来。 //??上面?
        方法:使用另一个表:ot_add_conn_ctx

      三者互联: 连接上下文指针–地址文件对象指针–传输层地址

      1. TDI_DISASSOCIATE_ADDRESS
        上面功能的反向

      2. TDI_CONNECT
        本地试图连接外界时会发生的请求
        a. @1. 用户进程使用的本机地址:获取当前请求的当前栈空间,判断请求类型然后得到以前保存的连接对象和传输层地址等等。
        b. @2. 用户试图连接的远程地址:从irps的参数中得到。

      3. TDI_SEND/TDI_RECEIVE
        流式传输,对应TCP
        使得:得到连接及相关信息
        方法:irps->FileObject 就是连接的文件对象,信息保存在ote_conn中,可以得到连接上下文的指针,地址端口等
        使得:得到要发送或接收的数据
        方法:irp->MdlAddress就是含有数据的MDL的指针

      4. TDI_SEND_DATAGRAM/TDI_RECEIVE_DATAGRAM
        报式传输,对应UDP
        使得:获取地址
        方法:因为没有连接的概念,所以查询到的直接就是ote_addr
        其他与tcp一致

      5. TDI_SET_EVENT_HANDLER
        设置事件回调请求,即侦听,当外部连接我方端口时回调函数被调用
        EventType 事件种类,EventHandler 回调函数

      直接获取发送函数的过滤

      Netbt(基于TCP/IP的NetBios协议),在IRP_MJ_DEVICE_CONTROL的功能码为IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER时,直接获取TCP协议驱动的内部函数TCPSenddata的指针来进行数据发送,即不通过TDI_SEND请求
      处理:tcpsenddata在调用后会返回在DeviceIoControl.Type3InputBuffer
      可以因此获得指针之后调用tdi_dispatch_complete让真实设备完成请求,之后将结果进行转换

      1. 清理请求的过滤IRP_MJ_CLEANUP
        将IRP_MJ_DEVICE_CONTROL尝试转换为IRP_MJ_INTERNAL_CONTROL,转换不成功直接下发,成功则视为internal来进行过滤