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

驱动的测试代码解读

  1. 打开设备对象:
cpp 复制代码
// 1. 打开底层设备对象
    HANDLE hDevice = CreateFile(
        L"\\\\.\\NDISFilter", // 设备名称
        GENERIC_READ | GENERIC_WRITE, // 访问权限
        0, // 不共享
        NULL, // 默认安全属性
        OPEN_EXISTING, // 打开现有设备
        0, // 无特殊标志
        NULL // 无模板句柄
    );

    if (hDevice == INVALID_HANDLE_VALUE)
    {
        std::cerr << "Failed to open NDISFilter device. Error: " << GetLastError() << std::endl;
        return 1;
    }
  1. 获取网卡地址:
cpp 复制代码
// 2. 获取网卡数目
    ULONG ulNetAdapterCount = 0;
    DWORD dwReadSize = 0;
    BOOL  nRet = FALSE;
    CHAR* pData = NULL;
    CHAR Temp[4];

    nRet = DeviceIoControl(
        hDevice,
        IOCTL_FILTER_GET_NUMBER,
        NULL,
        0,
        &ulNetAdapterCount,
        sizeof(ULONG),
        &dwReadSize,
        NULL
    );
    if (!nRet)
    {
        std::cerr << "IOCTL_FILTER_GET_NUMBER DeviceIoControl Faild !" << std::endl;
        goto Exit;
    }

    // 3. 获取网卡的Mac地址
    pData = new CHAR[_BUFFER_SIZE];
    nRet = DeviceIoControl(
        hDevice,
        IOCTL_FILTER_GET_ALL_ADDRESS,
        NULL,
        0,
        pData,
        ulNetAdapterCount * _MAC_LENGTH,
        &dwReadSize,
        NULL
    );
    if (!nRet)
    {
        std::cerr << "IOCTL_FILTER_GET_ALL_ADDRESS DeviceIoControl Faild !" << std::endl;
        goto Exit;
    }

    for (int i = 0; i < ulNetAdapterCount; i++)
    {
        UCHAR* pAddr = (UCHAR*)pData + i * _MAC_LENGTH;
        std::cout << i << ":" << std::hex << *(pAddr + 0) << std::hex << *(pAddr + 1) << std::hex << *(pAddr + 2) << std::hex << *(pAddr + 3) << std::hex << *(pAddr + 4) << std::hex << *(pAddr + 5) << std::endl;
    }
  1. 发送数据包
cpp 复制代码
        // 4. 测试发送ICMP数据包
        PACKET_INFO PacketInfo;
        memset(&PacketInfo, 0, sizeof(PACKET_INFO));

        PacketInfo.SrcMac[0] = 0x00;
        PacketInfo.SrcMac[1] = 0x0C;
        PacketInfo.SrcMac[2] = 0x29;
        PacketInfo.SrcMac[3] = 0xDB;
        PacketInfo.SrcMac[4] = 0x9F;
        PacketInfo.SrcMac[5] = 0x34;

        PacketInfo.DesMac[0] = 0x00;
        PacketInfo.DesMac[1] = 0x0C;
        PacketInfo.DesMac[2] = 0x29;
        PacketInfo.DesMac[3] = 0xDB;
        PacketInfo.DesMac[4] = 0x9F;
        PacketInfo.DesMac[5] = 0x34;

        // 12.17.10.8
        PacketInfo.SrcIPv4 = inet_addr("12.17.10.8");
        PacketInfo.DesIPv4 = inet_addr("12.17.10.8");

        memset(PacketInfo.Data, 8, _DATA_SIZE);

        PacketInfo.Length = ICMP_PACKET_SIZE;

        // 发送数据包
        nRet = DeviceIoControl(
            hDevice,
            IOCTL_FILTER_SEND_DATA,
            &PacketInfo,
            sizeof(PACKET_INFO),
            &PacketInfo,
            sizeof(PACKET_INFO),
            &dwReadSize,
            NULL
        );
        if (!nRet)
        {
            std::cerr << "IOCTL_FILTER_SEND_DATA DeviceIoControl Faild !" << std::endl;
            goto Exit;
        }
        std::cerr << "IOCTL_FILTER_SEND_DATA DeviceIoControl OK ! count = " << nCount << std::endl;

        // 5. 获取数据包
        nRet = DeviceIoControl(
            hDevice,
            IOCTL_FILTER_RECEIVE_DATA,
            &PacketInfo,
            sizeof(PACKET_INFO),
            &PacketInfo,
            sizeof(PACKET_INFO),
            &dwReadSize,
            NULL
        );
        if (!nRet)
        {
            std::cerr << "IOCTL_FILTER_RECEIVE_DATA DeviceIoControl Faild !" << std::endl;
            goto Exit;
        }
        std::cerr << "IOCTL_FILTER_RECEIVE_DATA DeviceIoControl OK ! count = " << nCount++
            << ", dwReadSize = " << dwReadSize << ", struct->length = " << PacketInfo.Length << std::endl;
  1. 打印数据包:
cpp 复制代码
        try
        {
            memset(pData, 0, _BUFFER_SIZE);
            PCHAR pCopy = pData;
            for (int i = 0; i < dwReadSize; i++)
            {
                memset(Temp, 0, 4);
                int n = _itoa_s((UCHAR)PacketInfo.Data[i], Temp, 16);
                Temp[strlen(Temp)] = '\0';
                strcpy_s(pCopy, 4, Temp);
                pCopy += strlen(Temp);
            }

            std::cerr << "IOCTL_FILTER_RECEIVE_DATA DeviceIoControl OK ! Data = " << pData << std::endl;
        }
        catch (const std::exception& ex)
        {
            std::cerr << ex.what();
        }
  1. 关闭设备
cpp 复制代码
Exit:
    if (NULL != pData) delete[]pData;

    std::cerr << " close NDISFilter device. OK!" << std::endl;
    // 关闭设备对象
    CloseHandle(hDevice);

代码在资源中的FilterDemo中。

驱动的安装和测试

NDIS比较特殊,我们需要以下面的方式进行安装:

  1. 打开任意一个网络适配器,定位到属性:
  1. 点击安装后,会有以下界面:

协议驱动也在这里安装,Filter选择服务就行。

  1. 找到安装驱动的路径:
  1. 然后安装即可,中间会提示我们是否需要加载测试签名的驱动,选择是就好。

  2. 测试程序运行界面如下:

此时,我们注意到我们接收到的数据就是我们发送出去的数据,因为我们将缓冲区全部设置为8。

相关推荐
国科安芯1 小时前
模拟DCDC电源芯片ASP3605S引脚功能及控制环路分析
单片机·嵌入式硬件
A懿轩A2 小时前
【2025最新】Flutter 编译开发 鸿蒙HarmonyOS 6 项目教程(Windows)
windows·flutter·华为·openharmony·开源鸿蒙
ACP广源盛139246256733 小时前
GSV5100B@ACP#一种具有音频提取和插入功能的 2 进 2 出 HDMI2.0 中继器 / CAT 延长器
单片机·嵌入式硬件·音视频
藏,捉3 小时前
使用自己绘制的板子通过485与西门子PLC1214C通讯,控制舵机摇摆运动
单片机·工控·485通讯
kaikaile19953 小时前
基于DSP28335与AD7606的采样程序实现
单片机·嵌入式硬件
Joshua-a4 小时前
STM32嵌入式开发核心:volatile与寄存器操作详解
单片机·嵌入式硬件
say_fall5 小时前
WinAPI 极简教程:超简单的 Windows 接口入门
c语言·windows
九鼎创展科技7 小时前
九鼎创展发布X3588SCV4核心板,集成LPDDR5内存,提升RK3588S平台性能边界
android·人工智能·嵌入式硬件·硬件工程
晨枫阳7 小时前
不同语言数组详解
linux·服务器·windows
s***4538 小时前
【RabbitMQ】超详细Windows系统下RabbitMQ的安装配置
windows·分布式·rabbitmq