首页 > 系统相关 >windows 驱动实例分析系列: NDIS 6.0的Filter 驱动改造(一)

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

时间:2024-11-01 19:48:00浏览次数:5  
标签:INFORMATION windows NdisRequest OID Filter 驱动 DATA NDIS

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;
}

标签:INFORMATION,windows,NdisRequest,OID,Filter,驱动,DATA,NDIS
From: https://blog.csdn.net/m0_72813396/article/details/142833163

相关文章

  • Windows部署rabbitmq
    本次安装环境:系统:Windows11软件建议版本:erlangOPT26.0.2rabbitmq3.12.4一、下载1.1下载erlang官网下载地址:1.2下载rabbitmq官网下载地址:建议使用解压版,安装版可能会在安装软件时出现查不到erlang环境的报错,导致安装失败。二、部署2.1部署erlang2.1.1安装http复制代码右键管......
  • 内置RC振荡器/抗干扰能力强VK1668 SOP24数码管驱动控制器/LED驱动器原厂技术支持
    产品品牌:永嘉微电/VINKA产品型号:VK1668封装形式:SOP24概述VK1668是一种带键盘扫描接口的数码管或点阵LED驱动控制专用芯片,内部集成有3线串行接口、数据锁存器、LED驱动、键盘扫描等电路。SEG脚接LED阳极,GRID脚接LED阴极,可支持13SEGx4GRID、12SEGx5GRID、11SEGx6GRID、10S......
  • 利用Msfvenom对Windows进行远程控制
    一、准备工作先在kali安装Apache2,下载代码如下sudoaptinstallapache2 启动Apache2服务serviceapache2start 在kali浏览器中输入你的kaliIP,得到该页面说明启动成功二、开始1.msf远控生成(1)在kali运行msf生成exemsfvenom-pwindows/meterpreter/reverse_t......
  • Nothing Phone(2)的灯带驱动研究笔记
    最近整了部NothingPhone(2),bl秒解的设定是真的舒服,所以买来第一时间就透了一遍(指root了)。然后半夜睡不着,就打算研究一下这个灯带是怎么调用的。然后就开始了,一段孤独的旅程充满烦恼~内核源码:很不幸,除了知道了灯带型号是aw20036之外没啥收获,原因无他,单纯看不懂代码,注释都不怎......
  • 渗透测试常用windows命令
    渗透测试是一种评估计算机系统、网络或Web应用安全性的实践,它通过模拟恶意黑客的攻击手段来识别潜在的安全漏洞。在渗透测试过程中,使用Windows命令行工具可以帮助测试者进行信息收集、系统分析等操作。以下是一些渗透测试中常用的Windows命令:1.**系统信息收集**  -`syst......
  • 机器人技术革新:人工智能的强力驱动
    内容概要在当今世界,机器人技术与人工智能的结合正如星星与大海,彼此辉映。随着科技的不断进步,人工智能不仅仅是为机器人赋予了“聪明的大脑”,更是推动了整个行业的快速发展。回顾机器人技术的发展历程,我们会发现,从简单的机械臂到如今高效的自主机器人,这一过程充满了创新与挑战......
  • Windows内核驱动-进程回调
    一、核心代码一共三部分:定义回调函数注册回调移除回调#include<ntddk.h>//定义回调函数,在后续实现VOIDProcessNotifyRoutine( _Inout_PEPROCESSProcess,//进程对象,这是个不透明结构,不建议强行使用其中的字段 _In_HANDLEProcessId,//进程ID _In_......
  • Mac和Windows最全快捷键 - Photoshop2024
    在数字化图像处理的世界里,Photoshop一直是专业设计师和摄影师的首选工具。无论是在图像编辑、图层处理还是各种效果应用上,Photoshop的功能都令人称赞。然而,Photoshop功能繁多,如果一一通过菜单查找,不仅耗时而且不够高效。熟练掌握快捷键可以极大地提高工作效率,让操作更加流畅。......
  • 利用 AWS 的事件驱动数据网格架构应对现代数据挑战
    背景   在当今数据驱动的世界中,企业必须适应数据管理、分析和利用方式的快速变化。传统的集中式系统和单片式架构虽然在历史上已经足够,但已无法满足企业日益增长的需求,因为企业需要更快地实时获取数据见解。事件驱动数据网格架构是这一领域的革命性框架,与AWS服务结合后,它将......
  • Windows Active Directory技术介绍和应用——删除计算机对象
    大纲问题描述操作方案题外参考资料问题描述当我们配置ActiveDirectory时,往往会遇到部分机器需要重新加入域的场景。而这种情况下,可能会收到如下的报错。Thejoinoperationwasnotsuccessful.Thiscouldbebecauseanexistingcomputeraccounthavingname......