在上一篇文章`《驅動開發:內核封裝WSK網路通信介面》`中,`LyShark`已經帶大家看過瞭如何通過WSK介面實現套接字通信,但WSK實現的通信是內核與內核模塊之間的,而如果需要內核與應用層之間通信則使用TDK會更好一些因為它更接近應用層,本章將使用TDK實現,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: [email protected]
#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: [email protected]
#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;
}
首先運行應用層開啟服務端偵聽,然後運行驅動程式,會輸出如下信息;
TDI 多線程收發包: 實現驅動內部發送數據包後開啟一個線程用於等待應用層返回並輸出結果,多線程收發在發送數據包後需要創建新的線程等待接收。
首先是服務端代碼。
// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#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: [email protected]
#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;
}
運行應用層服務端等待偵聽,運行驅動程式輸出如下效果;
TDI 傳數結構實現認證: 驅動內部發送結構體給應用層,應用層驗證結構體成員,此功能可實現對驅動程式的控制機制,例如是否允許驅動載入卸載等,通常用於驅動輔助認證。
應用層代碼
// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#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: [email protected]
#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;
}
運行應用層服務端,並運行驅動程式,則會驗證該驅動是否合法,如果合法則載入不合法則拒絕;
文章作者:lyshark (王瑞)文章出處:https://www.cnblogs.com/LyShark/p/16851278.html
版權聲明:本博客文章與代碼均為學習時整理的筆記,文章 [均為原創] 作品,轉載請 [添加出處] ,您添加出處是我創作的動力!
轉載文章請遵守《中華人民共和國著作權法》相關法律規定或遵守《署名CC BY-ND 4.0國際》規範,合理合規攜帶原創出處轉載,如果不攜帶文章出處,並惡意轉載多篇原創文章被本人發現,本人保留起訴權!