驱动开发:内核封装TDI网络通信接口

简介: 在上一篇文章`《驱动开发:内核封装WSK网络通信接口》`中,`LyShark`已经带大家看过了如何通过WSK接口实现套接字通信,但WSK实现的通信是内核与内核模块之间的,而如果需要内核与应用层之间通信则使用TDK会更好一些因为它更接近应用层,本章将使用TDK实现,TDI全称传输驱动接口,其主要负责连接`Socket`和协议驱动,用于实现访问传输层的功能,该接口比`NDIS`更接近于应用层,在早期Win系统中常用于实现过滤防火墙,同样经过封装后也可实现通信功能,本章将运用TDI接口实现驱动与应用层之间传输字符串,结构体,多线程收发等技术。

在上一篇文章《驱动开发:内核封装WSK网络通信接口》中,LyShark已经带大家看过了如何通过WSK接口实现套接字通信,但WSK实现的通信是内核与内核模块之间的,而如果需要内核与应用层之间通信则使用TDK会更好一些因为它更接近应用层,本章将使用TDK实现,TDI全称传输驱动接口,其主要负责连接Socket和协议驱动,用于实现访问传输层的功能,该接口比NDIS更接近于应用层,在早期Win系统中常用于实现过滤防火墙,同样经过封装后也可实现通信功能,本章将运用TDI接口实现驱动与应用层之间传输字符串,结构体,多线程收发等技术。

  • TDI传输字符串
  • TDI多线程收发
  • TDI传数结构实现认证

TDI 传输字符串: 服务端在应用层侦听,客户端是驱动程序,驱动程序加载后自动连接应用层并发送消息。

首先来看应用层(服务端)代码,具体我就不说了,来看教程的都是有基础的。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>  
#include <winsock2.h>  

#pragma comment(lib,"ws2_32.lib")
#define PORT 8888 

int main(int argc, char *argv[])
{
  printf("hello lyshark.com \n");
  WSADATA WSAData;
  SOCKET sock, msgsock;
  struct sockaddr_in ServerAddr;

  if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
  {
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(PORT);
    ServerAddr.sin_addr.s_addr = INADDR_ANY;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    int BindRet = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
    int LinsRet = listen(sock, 10);
  }

  while (1)
  {
    char buf[1024] = { 0 };
    msgsock = accept(sock, (LPSOCKADDR)0, (int *)0);
    memset(buf, 0, sizeof(buf));

    recv(msgsock, buf, 1024, 0);
    printf("内核返回: %s \n", buf);

    char send_buffer[1024] = { 0 };
    memset(send_buffer, 0, 1024);
    strcpy(send_buffer, "Hi,R0 !");
    send(msgsock, send_buffer, strlen(send_buffer), 0);
    closesocket(msgsock);
  }
  closesocket(sock);
  WSACleanup();
  return 0;
}

再来是驱动层代码,如下所示;

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#include "MyTDI.hpp"

// 发送接收数据
NTSTATUS SendOnRecv()
{
  NTSTATUS status = STATUS_SUCCESS;
  HANDLE hTdiAddress = NULL;
  HANDLE hTdiEndPoint = NULL;
  PDEVICE_OBJECT pTdiAddressDevObj = NULL;
  PFILE_OBJECT pTdiEndPointFileObject = NULL;
  LONG pServerIp[4] = { 127, 0, 0, 1 };
  LONG lServerPort = 8888;
  UCHAR szSendData[] = "hello lyshark";
  ULONG ulSendDataLength = 1 + strlen(szSendData);
  HANDLE hThread = NULL;

  // TDI初始化
  status = TdiOpen(&pTdiAddressDevObj, &pTdiEndPointFileObject, &hTdiAddress, &hTdiEndPoint);
  if (!NT_SUCCESS(status))
  {
    return STATUS_SUCCESS;
  }

  // TDI TCP连接服务器
  status = TdiConnection(pTdiAddressDevObj, pTdiEndPointFileObject, pServerIp, lServerPort);
  if (!NT_SUCCESS(status))
  {
    return STATUS_SUCCESS;
  }

  // TDI TCP发送信息
  status = TdiSend(pTdiAddressDevObj, pTdiEndPointFileObject, szSendData, ulSendDataLength);
  if (!NT_SUCCESS(status))
  {
    return STATUS_SUCCESS;
  }
  DbgPrint("发送: %s\n", szSendData);

  // 创建接收信息多线程, 循环接收信息

  char szRecvData[1024] = { 0 };
  ULONG ulRecvDataLenngth = 1024;
  RtlZeroMemory(szRecvData, ulRecvDataLenngth);

  // TDI TCP接收信息
  do
  {
    ulRecvDataLenngth = TdiRecv(pTdiAddressDevObj, pTdiEndPointFileObject, szRecvData, ulRecvDataLenngth);
    if (0 < ulRecvDataLenngth)
    {
      DbgPrint("接收数据: %s\n", szRecvData);
      break;;
    }

  } while (TRUE);

  // 释放
  TdiClose(pTdiEndPointFileObject, hTdiAddress, hTdiEndPoint);
  return STATUS_SUCCESS;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
  DbgPrint("驱动卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
  for (int x = 0; x < 10; x++)
  {
    SendOnRecv();
  }

  DbgPrint("驱动加载成功 \n");
  Driver->DriverUnload = UnDriver;
  return STATUS_SUCCESS;
}

首先运行应用层开启服务端侦听,然后运行驱动程序,会输出如下信息;

image.png

TDI 多线程收发包: 实现驱动内部发送数据包后开启一个线程用于等待应用层返回并输出结果,多线程收发在发送数据包后需要创建新的线程等待接收。

首先是服务端代码。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>  
#include <winsock2.h>  

#pragma comment(lib,"ws2_32.lib")
#define PORT 8888 

int main(int argc, char *argv[])
{
    printf("hello lyshark.com \n");
    WSADATA WSAData;
    SOCKET sock, msgsock;
    struct sockaddr_in ServerAddr;

    if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
    {
        ServerAddr.sin_family = AF_INET;
        ServerAddr.sin_port = htons(PORT);
        ServerAddr.sin_addr.s_addr = INADDR_ANY;

        sock = socket(AF_INET, SOCK_STREAM, 0);
        int BindRet = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
        int LinsRet = listen(sock, 10);
    }

    while (1)
    {
        char buf[1024] = { 0 };
        msgsock = accept(sock, (LPSOCKADDR)0, (int *)0);
        memset(buf, 0, sizeof(buf));

        recv(msgsock, buf, 1024, 0);
        printf("内核返回: %s \n", buf);

        char send_buffer[1024] = { 0 };
        memset(send_buffer, 0, 1024);
        strcpy(send_buffer, "Hi,R0 !");
        send(msgsock, send_buffer, strlen(send_buffer), 0);
        closesocket(msgsock);
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}

驱动程序代码如下,RecvThreadProc主要负责数据接收,SendThreadData负责数据发送。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#include "LySocket.hpp"

typedef struct _MY_DATA
{
    PDEVICE_OBJECT pTdiAddressDevObj;
    PFILE_OBJECT pTdiEndPointFileObject;
    HANDLE hTdiAddress;
    HANDLE hTdiEndPoint;
}MY_DATA, *PMY_DATA;

// 接收信息多线程
VOID RecvThreadProc(_In_ PVOID StartContext)
{
    PMY_DATA pMyData = (PMY_DATA)StartContext;
    NTSTATUS status = STATUS_SUCCESS;
    char szRecvData[1024] = { 0 };
    ULONG ulRecvDataLenngth = 1024;
    RtlZeroMemory(szRecvData, ulRecvDataLenngth);

    // TDI TCP接收信息
    do
    {
        ulRecvDataLenngth = TdiRecv(pMyData->pTdiAddressDevObj, pMyData->pTdiEndPointFileObject, szRecvData, ulRecvDataLenngth);
        if (0 < ulRecvDataLenngth)
        {
            DbgPrint("线程句柄:%x --> 接收数据包: %s\n", pMyData->hTdiEndPoint, szRecvData);
            break;;
        }

    } while (TRUE);

    // 释放
    TdiClose(pMyData->pTdiEndPointFileObject, pMyData->hTdiAddress, pMyData->hTdiEndPoint);
    ExFreePool(pMyData);
}

// 多线程发送
NTSTATUS SendThreadData()
{
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE hTdiAddress = NULL;
    HANDLE hTdiEndPoint = NULL;
    PDEVICE_OBJECT pTdiAddressDevObj = NULL;
    PFILE_OBJECT pTdiEndPointFileObject = NULL;
    LONG pServerIp[4] = { 127, 0, 0, 1 };
    LONG lServerPort = 8888;
    UCHAR szSendData[] = "hello lyshark";
    ULONG ulSendDataLength = 1 + strlen(szSendData);
    HANDLE hThread = NULL;

    // TDI初始化
    status = TdiOpen(&pTdiAddressDevObj, &pTdiEndPointFileObject, &hTdiAddress, &hTdiEndPoint);
    if (!NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }

    // TDI TCP连接服务器
    status = TdiConnection(pTdiAddressDevObj, pTdiEndPointFileObject, pServerIp, lServerPort);
    if (!NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }

    // TDI TCP发送信息
    status = TdiSend(pTdiAddressDevObj, pTdiEndPointFileObject, szSendData, ulSendDataLength);
    if (!NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }
    DbgPrint("发送 %s\n", szSendData);

    // 创建接收信息多线程, 循环接收信息
    PMY_DATA pMyData = ExAllocatePool(NonPagedPool, sizeof(MY_DATA));
    pMyData->pTdiAddressDevObj = pTdiAddressDevObj;
    pMyData->pTdiEndPointFileObject = pTdiEndPointFileObject;
    pMyData->hTdiAddress = hTdiAddress;
    pMyData->hTdiEndPoint = hTdiEndPoint;

    PsCreateSystemThread(&hThread, 0, NULL, NtCurrentProcess(), NULL, RecvThreadProc, pMyData);
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
    DbgPrint("hello lyshark.com \n");

    for (int x = 0; x < 10; x++)
    {
        SendThreadData();
    }
    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

运行应用层服务端等待侦听,运行驱动程序输出如下效果;

image.png

TDI 传数结构实现认证: 驱动内部发送结构体给应用层,应用层验证结构体成员,此功能可实现对驱动程序的控制机制,例如是否允许驱动加载卸载等,通常用于驱动辅助认证。

应用层代码

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>  
#include <winsock2.h>  

#pragma comment(lib,"ws2_32.lib")
#define PORT 8888

// 传输结构体
typedef struct
{
    int uuid;
    char username[256];
    char password[256];
}SocketData;

int main(int argc, char *argv[])
{
    printf("hello lyshark.com \n");

    WSADATA WSAData;
    SOCKET sock, msgsock;
    struct sockaddr_in ServerAddr;

    if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
    {
        ServerAddr.sin_family = AF_INET;
        ServerAddr.sin_port = htons(PORT);
        ServerAddr.sin_addr.s_addr = INADDR_ANY;

        sock = socket(AF_INET, SOCK_STREAM, 0);
        int BindRet = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
        int LinsRet = listen(sock, 10);
    }

    while (1)
    {
        char buf[8192] = { 0 };
        msgsock = accept(sock, (LPSOCKADDR)0, (int *)0);
        memset(buf, 0, sizeof(buf));

        // 接收返回数据
        recv(msgsock, buf, sizeof(SocketData), 0);

        // 强转结构体
        SocketData* msg = (SocketData*)buf;

        printf("UUID = %d \n", msg->uuid);
        printf("名字 = %s \n", msg->username);
        printf("密码 = %s \n", msg->password);

        // 验证通过则继续使用
        if ((strcmp(msg->username, "lyshark") == 0) && (strcmp(msg->password, "123") == 0))
        {
            char send_buffer[8192] = { 0 };
            memset(send_buffer, 0, 8192);
            strcpy(send_buffer, "success");
            send(msgsock, send_buffer, strlen(send_buffer), 0);
            closesocket(msgsock);
        }
        // 不通过则禁止驱动加载
        else
        {
            char send_buffer[8192] = { 0 };
            memset(send_buffer, 0, 8192);
            strcpy(send_buffer, "error");
            send(msgsock, send_buffer, strlen(send_buffer), 0);
            closesocket(msgsock);
        }
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}

驱动层代码

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "LySocket.hpp"

// 传输结构体
typedef struct
{
    int uuid;
    char username[256];
    char password[256];
}SocketData;

// 验证账号密码是否正确
BOOLEAN CheckDriver()
{
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE hTdiAddress = NULL;
    HANDLE hTdiEndPoint = NULL;
    PDEVICE_OBJECT pTdiAddressDevObj = NULL;
    PFILE_OBJECT pTdiEndPointFileObject = NULL;
    LONG pServerIp[4] = { 127, 0, 0, 1 };
    LONG lServerPort = 8888;

    // TDI初始化
    status = TdiOpen(&pTdiAddressDevObj, &pTdiEndPointFileObject, &hTdiAddress, &hTdiEndPoint);
    if (!NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }

    // TDI TCP连接服务器
    status = TdiConnection(pTdiAddressDevObj, pTdiEndPointFileObject, pServerIp, lServerPort);
    if (!NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }

    SocketData ptr;

    RtlZeroMemory(&ptr, sizeof(SocketData));

    // 填充结构
    ptr.uuid = 1001;
    RtlCopyMemory(ptr.username, "lyshark", strlen("xxxxxxx"));
    RtlCopyMemory(ptr.password, "123123", strlen("xxxxxx"));

    // TDI TCP发送信息
    status = TdiSend(pTdiAddressDevObj, pTdiEndPointFileObject, &ptr, sizeof(SocketData));
    if (!NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }

    // 创建接收信息多线程, 循环接收信息
    char szRecvData[8192] = { 0 };
    ULONG ulRecvDataLenngth = 8192;
    RtlZeroMemory(szRecvData, ulRecvDataLenngth);

    // TDI TCP接收信息
    do
    {
        ulRecvDataLenngth = TdiRecv(pTdiAddressDevObj, pTdiEndPointFileObject, szRecvData, ulRecvDataLenngth);
        if (0 < ulRecvDataLenngth)
        {
            DbgPrint("接收数据: %s\n", szRecvData);

            if (strncmp(szRecvData, "success", 7) == 0)
            {
                // 释放
                TdiClose(pTdiEndPointFileObject, hTdiAddress, hTdiEndPoint);
                return TRUE;
            }
            else if (strncmp(szRecvData, "error", 5) == 0)
            {
                // 释放
                TdiClose(pTdiEndPointFileObject, hTdiAddress, hTdiEndPoint);
                return FALSE;
            }
            break;;
        }
    } while (TRUE);

    // 释放
    TdiClose(pTdiEndPointFileObject, hTdiAddress, hTdiEndPoint);
    return STATUS_SUCCESS;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
    DbgPrint("hello lyshark.com \n");

    BOOLEAN ref = CheckDriver();

    if (ref == FALSE)
    {
        DbgPrint("[LyShark.com] 驱动已过期,无法加载 \n");
        Driver->DriverUnload = UnDriver;
        return STATUS_SUCCESS;
    }

    DbgPrint("[*] 驱动正常使用 \n");
    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

运行应用层服务端,并运行驱动程序,则会验证该驱动是否合法,如果合法则加载不合法则拒绝;

image.png

相关文章
|
14天前
|
机器学习/深度学习 数据采集 人工智能
未来的守护神:AI驱动的网络安全之盾,如何用智慧的光芒驱散网络黑暗势力?揭秘高科技防御系统背后的惊天秘密!
【10月更文挑战第3天】随着网络技术的发展,网络安全问题日益严峻,传统防御手段已显不足。本文探讨了构建AI驱动的自适应网络安全防御系统的必要性及其关键环节:数据采集、行为分析、威胁识别、响应决策和执行。通过Python库(如scapy、scikit-learn和TensorFlow)的应用实例,展示了如何利用AI技术提升网络安全防护水平。这种系统能够实时监控、智能分析并自动化响应,显著提高防护效率与准确性,为数字世界提供更强大的安全保障。
34 2
|
13天前
|
XML 开发工具 Android开发
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
ExoPlayer最初是为了解决Android早期MediaPlayer控件对网络视频兼容性差的问题而推出的。现在,Android官方已将其升级并纳入Jetpack的Media3库,使其成为音视频操作的统一引擎。新版ExoPlayer支持多种协议,解决了设备和系统碎片化问题,可在整个Android生态中一致运行。通过修改`build.gradle`文件、布局文件及Activity代码,并添加必要的权限,即可集成并使用ExoPlayer进行网络视频播放。具体步骤包括引入依赖库、配置播放界面、编写播放逻辑以及添加互联网访问权限。
64 1
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
|
5天前
|
弹性计算 Kubernetes 网络协议
阿里云弹性网络接口技术的容器网络基础教程
阿里云弹性网络接口技术的容器网络基础教程
阿里云弹性网络接口技术的容器网络基础教程
|
16天前
|
网络协议 Java 程序员
【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用
【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用
20 2
|
12天前
|
网络协议 网络架构
【第三期】计算机网络常识/网络分层模型与数据包封装传输过程
【第三期】计算机网络常识/网络分层模型与数据包封装传输过程
30 0
|
1月前
|
运维 网络协议 搜索推荐
内核网络小白之故障寻踪记
本文记述了一次由 skb(socket buffer)异常导致的内核故障排查过程。
|
2月前
|
小程序 数据安全/隐私保护
Taro@3.x+Vue@3.x+TS开发微信小程序,网络请求封装
在 `src/http` 目录下创建 `request.ts` 文件,并配置 Taro 的网络请求方法 `Taro.request`,支持多种 HTTP 方法并处理数据加密。
Taro@3.x+Vue@3.x+TS开发微信小程序,网络请求封装
|
1月前
|
域名解析 负载均衡 网络协议
Linux网络接口配置不当所带来的影响
总而言之,Linux网络接口的恰当配置是保证网络稳定性、性能和安全性的基础。通过遵循最佳实践和定期维护,可以最大程度地减少配置错误带来的负面影响。
99 0
|
2月前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享安卓与iOS开发中的线程管理比较
【8月更文挑战第30天】本文将探讨网络安全与信息安全的重要性,并分享关于网络安全漏洞、加密技术和安全意识的知识。我们将了解常见的网络攻击类型和防御策略,以及如何通过加密技术和提高安全意识来保护个人和组织的信息安全。
|
8天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:守护数字世界的坚盾
在数字化浪潮中,网络安全已成为维系现代社会正常运转的关键。本文旨在探讨网络安全漏洞的成因、加密技术的应用及安全意识的提升,以期为广大用户和技术人员提供实用的知识分享。通过对这些方面的深入剖析,我们期望能够共同构建一个更加安全可靠的数字环境。

热门文章

最新文章