当前位置: 首页 > news >正文

windows 驱动实例分析系列: NDIS 6.0的Filter 驱动改造(一)

NDIS生成的Filter例程已经非常完善,但根据需要还是要对它进行改造,以适应实际的需求,在这一类的改造中,主要涉及的三个方面: 处理OID、发送数据包、接收数据包。

需求和定义

一般来说,Filter 驱动要么需要对某些数据包进行处理、要么是需要对某些网络适配器的行为进行修改,所以需求最终是处理OID请求、发送和接收数据包。

为了便于演示,将会提供下面3个最基本的功能:

  • 发起OID请求;
  • 发送ICMP数据包;
  • 接收的数据包; 

案例将会创建4个IOCTL来演示:

#define _NDIS_CONTROL_CODE(request,method) \CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)// 获取当前存在的网卡个数
// 输出缓冲区是一个ULONG的值,这个值指出当前系统上有 N 个网络适配器
#define IOCTL_FILTER_GET_NUMBER  _NDIS_CONTROL_CODE(14, METHOD_BUFFERED)// 获取所有网卡的地址
// 输出缓冲区是一个 N*6 大小的缓冲区,根据加载顺序记录 Mac 地址
#define IOCTL_FILTER_GET_ALL_ADDRESS  _NDIS_CONTROL_CODE(15, METHOD_BUFFERED)// 发送一个UDP广播包
// IOCTL_FILTER_SEND_DATA  输入/输出缓冲区
typedef struct _tagPACKET_INFO
{UCHAR   SrcMac[_MAC_LENGTH];// Mac地址UCHAR   DesMac[_MAC_LENGTH];// Mac地址ULONG   SrcIPv4;            // 源IP地址,源地址ULONG   DesIPv4;            // 目的IP地址,源地址// USHORT  SrcPort;            // 源端口      注意ICMP数据包没有使用这两个值// USHORT  DesPort;            // 目的端口    注意ICMP数据包没有使用这两个值USHORT  Length;             // 数据长度CHAR    Data[_DATA_SIZE];   // 数据内容
}PACKET_INFO, * PPACKET_INFO;
#define IOCTL_FILTER_SEND_DATA  _NDIS_CONTROL_CODE(16, METHOD_BUFFERED)// 接收最近的数据包
// 输入/输出缓冲区
#define IOCTL_FILTER_RECEIVE_DATA  _NDIS_CONTROL_CODE(17, METHOD_BUFFERED)

这里的宏定义比较普通,只是NDIS自行封装了_NDIS_CONTROL_CODE(request,method) 。

设备对象和网络适配器

Filter层抽象了网络架构,无论是什么类型的网络适配器,它们对于Filter都是一样的接口,这也是为什么Filter驱动被用于网络数据包过滤的原因之一:

无论 以太网、Wifi、1394、蓝牙这些网络适配器都会在同一时间挂载Filter驱动,Filter驱动将作为所有的网络适配器过滤驱动来实现和设计的。

这里有一个概念上的区别,当Filter驱动被加载到内核中时,它作为一个模块,可能会实例化为多个Filter对象,每个Filter对象依附在一个网络适配器之上,这带来了两面性:

Filter驱动的通讯是针对Filter而不是每个网络适配器;

每个网络适配器都会有自己的上下文;

 这两个点带来的直观影响是NDISFilterDeviceIoControl函数和具体的网络适配器不直接相关。

发送OID

NDIS 定义对象标识符 (OID) 值来标识适配器参数,其中包括操作参数,例如设备特征、可配置的设置和统计信息。这里使用获取网卡Mac地址来演示;

Mac地址涉及的OID包括:

1. OID_802_3_CURRENT_ADDRESS:NIC 当前使用的地址。网络管理软件无法使用 NDIS 接口库设置当前工作站地址。 它必须将此地址设置为配置参数。2. OID_802_3_PERMANENT_ADDRESS:硬件中编码的 NIC 的地址。

代码看起来如下:

NDIS_STATUS FilterGetMacAddress(_In_ NDIS_HANDLE FilterModuleContext)
{PMS_FILTER  pFilter = (PMS_FILTER)FilterModuleContext;UCHAR       Mac[_MAC_LENGTH];ULONG       BytesProcessed = 0;NDIS_STATUS Status = 0;NdisZeroMemory(&Mac[0], _MAC_LENGTH);Status = filterDoInternalRequest(pFilter, NdisRequestQueryInformation, OID_802_3_PERMANENT_ADDRESS,(PVOID)&Mac[0], _MAC_LENGTH, 0, 0, &BytesProcessed);if (Status == NDIS_STATUS_SUCCESS){RtlCopyMemory(&pFilter->Mac[0], &Mac[0], _MAC_LENGTH);}return Status;
}NDIS_STATUS
filterDoInternalRequest(_In_ PMS_FILTER                   FilterModuleContext,_In_ NDIS_REQUEST_TYPE            RequestType,_In_ NDIS_OID                     Oid,_Inout_updates_bytes_to_(InformationBufferLength, *pBytesProcessed)PVOID                        InformationBuffer,_In_ ULONG                        InformationBufferLength,_In_opt_ ULONG                    OutputBufferLength,_In_ ULONG                        MethodId,_Out_ PULONG                      pBytesProcessed)
{FILTER_REQUEST              FilterRequest;PNDIS_OID_REQUEST           NdisRequest = &FilterRequest.Request;NDIS_STATUS                 Status;ASSERT(pBytesProcessed != NULL);*pBytesProcessed = 0;NdisZeroMemory(NdisRequest, sizeof(NDIS_OID_REQUEST));NdisInitializeEvent(&FilterRequest.ReqEvent);NdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;NdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;NdisRequest->Header.Size = sizeof(NDIS_OID_REQUEST);NdisRequest->RequestType = RequestType;switch (RequestType){case NdisRequestQueryInformation:NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =InformationBuffer;NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =InformationBufferLength;break;case NdisRequestSetInformation:NdisRequest->DATA.SET_INFORMATION.Oid = Oid;NdisRequest->DATA.SET_INFORMATION.InformationBuffer =InformationBuffer;NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =InformationBufferLength;break;case NdisRequestMethod:NdisRequest->DATA.METHOD_INFORMATION.Oid = Oid;NdisRequest->DATA.METHOD_INFORMATION.MethodId = MethodId;NdisRequest->DATA.METHOD_INFORMATION.InformationBuffer =InformationBuffer;NdisRequest->DATA.METHOD_INFORMATION.InputBufferLength =InformationBufferLength;NdisRequest->DATA.METHOD_INFORMATION.OutputBufferLength = OutputBufferLength;break;default:ASSERTMSG("Invalid request type in filterDoInternalRequest",FALSE);break;}NdisRequest->RequestId = (PVOID)FILTER_REQUEST_ID;Status = NdisFOidRequest(FilterModuleContext->FilterHandle,NdisRequest);if (Status == NDIS_STATUS_PENDING){NdisWaitEvent(&FilterRequest.ReqEvent, 0);Status = FilterRequest.Status;}if (Status == NDIS_STATUS_SUCCESS){if (RequestType == NdisRequestSetInformation){*pBytesProcessed = NdisRequest->DATA.SET_INFORMATION.BytesRead;}if (RequestType == NdisRequestQueryInformation){*pBytesProcessed = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;}if (RequestType == NdisRequestMethod){*pBytesProcessed = NdisRequest->DATA.METHOD_INFORMATION.BytesWritten;}//// The driver below should set the correct value to BytesWritten// or BytesRead. But now, we just truncate the value to InformationBufferLength//if (RequestType == NdisRequestMethod){if (*pBytesProcessed > OutputBufferLength){*pBytesProcessed = OutputBufferLength;}}else{if (*pBytesProcessed > InformationBufferLength){*pBytesProcessed = InformationBufferLength;}}}return Status;
}

http://www.mrgr.cn/news/61519.html

相关文章:

  • 爬虫基础之爬取歌曲宝歌曲批量下载
  • 李宏毅机器学习课程笔记03 | 类神经网络优化技巧
  • 【计算机网络】lab7 TCP协议
  • 微信小程序mp3音频播放组件,仅需传入url即可
  • 基于单片机的智能家居排气扇系统设计
  • 服务器与机顶盒
  • Ubuntu下搭建自己的Docker镜像仓库
  • svg + canvas + 烟花 + 0.0
  • 记录一次更新idea
  • 记录工作上一次计算的优化
  • 基于JSP的篮球系列网上商城系统【附源码】
  • 图的最短路径算法-迪杰斯特拉(Dijkstra)算法与弗洛伊德(Frolyd)算法(更新中)
  • Git提交代码完整流程
  • 基于SSM+小程序的购物管理系统1
  • Redis-README官方入门文档
  • 深度学习数学基础之链式法则
  • 基于spootboot学生选课系统设计与实现
  • C++17 折叠表达式
  • 【数据结构】排序代码分享
  • WPF+MVVM案例实战(十一)- 环形进度条实现
  • 4. STM32之TIM实验--输出比较(PWM输出,电机,四轴飞行器,智能车,机器人)--(实验2:PWM驱动舵机)
  • 使用 Python 理解置信区间
  • 组合总和
  • 深度学习:梯度下降算法简介
  • 算法练习:LCR 179. 查找总价格为目标值的两个商品
  • “格格不入”的星瑞东方曜,燃油市场有麻烦了