TDI簡單的UDP網路通訊
阿新 • • 發佈:2019-02-17
#include "ntifs.h" #include "tdi.h" #include "tdikrnl.h" #include "KernelSocket.h" HANDLE g_hSocket = NULL; PFILE_OBJECT g_pSocketUdpObject = NULL; #define RECVBUFF 2048 CHAR Packet[30786] = { 0 }; //建立本地地址 NTSTATUS CreateLocalAddress(); //發生UDP資料 NTSTATUS TdiSendDatagram(char* szIpAddress, unsigned short Port, char* pData, unsigned long bufferLength); //接受UDP資料 unsigned long TdiReceiveDatagram(char* szIpAddress, unsigned short Port, char* pData, unsigned long Length, PLARGE_INTEGER Timeout); void DriverUnload(_In_ PDRIVER_OBJECT pdriverObject) { } NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT pDriverObject, _In_ PUNICODE_STRING registryPath) { //KdBreakPoint(); pDriverObject->DriverUnload = DriverUnload; NTSTATUS status = STATUS_UNSUCCESSFUL; //建立本地地址 status = CreateLocalAddress(); if (!NT_SUCCESS(status)) { KdPrint(("CreateLocalAddress error\n")); return status; } //傳送UDP資料 char szSendMessage[] = "你這個傻瓜真可笑!\n"; status = TdiSendDatagram("192.168.2.223", 1234, szSendMessage, sizeof(szSendMessage)); if (status != STATUS_SUCCESS) { KdPrint(("TdiSendDatagram error\n")); ObDereferenceObject(g_pSocketUdpObject); ZwClose(g_hSocket); return status; } //接受UDP資料 LARGE_INTEGER Timeout; Timeout.QuadPart = 5 * 1000 * (-10000); //5秒 ULONG RecvSize = RECVBUFF; //fx 2016年10月14日20:53:03 //RecvSize這個大小在udp中不能太大 unsigned long uRecvSize = 0; uRecvSize = TdiReceiveDatagram("192.168.2.223", 1234, Packet, RecvSize, &Timeout); if (uRecvSize <= 0) { KdPrint(("TdiReceiveDatagram error\n")); ObDereferenceObject(g_pSocketUdpObject); ZwClose(g_hSocket); return status; } KdPrint(("uRecvSize=%d\n", uRecvSize)); KdPrint(("%s\n", Packet)); ObDereferenceObject(g_pSocketUdpObject); ZwClose(g_hSocket); return STATUS_SUCCESS; } //建立本地地址 NTSTATUS CreateLocalAddress() { UNICODE_STRING Name; OBJECT_ATTRIBUTES Attr; unsigned char LocalAddrBuffer[sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS)] = { 0 }; PFILE_FULL_EA_INFORMATION Ea; PTA_IP_ADDRESS Sin; IO_STATUS_BLOCK IoStatus; NTSTATUS Status; Ea = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(LocalAddrBuffer)); if (Ea == NULL)return STATUS_UNSUCCESSFUL; Ea->NextEntryOffset = 0; Ea->Flags = 0; Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; Ea->EaValueLength = sizeof(TA_IP_ADDRESS); RtlCopyMemory(Ea->EaName, TdiTransportAddress, Ea->EaNameLength + 1); Sin = (PTA_IP_ADDRESS)(Ea->EaName + Ea->EaNameLength + 1); Sin->TAAddressCount = 1; Sin->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; Sin->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; Sin->Address[0].Address[0].sin_port = 0; // Sin->Address[0].Address[0].in_addr = 0; //本地自動 RtlZeroMemory(Sin->Address[0].Address[0].sin_zero, sizeof(Sin->Address[0].Address[0].sin_zero)); RtlInitUnicodeString(&Name, L"\\Device\\Udp"); InitializeObjectAttributes(&Attr, &Name, OBJ_CASE_INSENSITIVE, 0, 0); Status = ZwCreateFile(&g_hSocket, 0, &Attr, &IoStatus, 0, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, 0, Ea, sizeof(LocalAddrBuffer)); ExFreePool((PVOID)Ea); if (!NT_SUCCESS(Status)) { return Status; } Status = ObReferenceObjectByHandle(g_hSocket, GENERIC_READ | GENERIC_WRITE, 0, KernelMode, (PVOID *)&g_pSocketUdpObject, 0); return Status; } //發生UDP資料 NTSTATUS TdiSendDatagram(char* szIpAddress, unsigned short Port, char* pData, unsigned long bufferLength) { PIRP Irp; PMDL Mdl; PDEVICE_OBJECT DeviceObject; PTDI_CONNECTION_INFORMATION ConnectInfo; PTA_IP_ADDRESS TA; PTDI_ADDRESS_IP IpAddress; IO_STATUS_BLOCK Iosb; KEVENT Event; NTSTATUS Status; DeviceObject = IoGetRelatedDeviceObject(g_pSocketUdpObject); ConnectInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); if (ConnectInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES; KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, DeviceObject, g_pSocketUdpObject, &Event, &Iosb); if (Irp == NULL) { ExFreePool(ConnectInfo); return STATUS_INSUFFICIENT_RESOURCES; } //分配MDL Mdl = IoAllocateMdl(pData, bufferLength, FALSE, FALSE, NULL); if (Mdl == NULL) { IoFreeIrp(Irp); ExFreePool(ConnectInfo); return STATUS_INSUFFICIENT_RESOURCES; } __try { MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); } __except (EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl(Mdl); IoFreeIrp(Irp); ExFreePool(ConnectInfo); return STATUS_UNSUCCESSFUL; } RtlZeroMemory(ConnectInfo, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); ConnectInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS); ConnectInfo->RemoteAddress = (PUCHAR)((ULONG_PTR)ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION)); TA = (PTA_IP_ADDRESS)(ConnectInfo->RemoteAddress); TA->TAAddressCount = 1; TA->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP); TA->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; IpAddress = (PTDI_ADDRESS_IP)(TA->Address[0].Address); IpAddress->sin_port = ntohs(Port); IpAddress->in_addr = inet_addr(szIpAddress); TdiBuildSendDatagram(Irp, DeviceObject, g_pSocketUdpObject, NULL, NULL, Mdl, bufferLength, ConnectInfo); Status = IoCallDriver(DeviceObject, Irp); if ((Status == STATUS_PENDING) && (&Event != NULL)) { Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); if (Status == STATUS_TIMEOUT) { IoCancelIrp(Irp); Iosb.Status = STATUS_TIMEOUT; } Status = Iosb.Status; } ExFreePool(ConnectInfo); return Status; } //接受UDP資料 unsigned long TdiReceiveDatagram(char* szIpAddress, unsigned short Port, char* pData, unsigned long Length, PLARGE_INTEGER Timeout) { PTDI_CONNECTION_INFORMATION ReceiveInfo; PTDI_CONNECTION_INFORMATION ReturnInfo; PTA_IP_ADDRESS ReturnAddress; PDEVICE_OBJECT DeviceObject; PTDI_ADDRESS_IP IpAddress; PTA_IP_ADDRESS TA; IO_STATUS_BLOCK Iosb; KEVENT Event; PVOID MdlBuffer; NTSTATUS Status; PIRP Irp; PMDL Mdl; unsigned long uRecvSize = 0; DeviceObject = IoGetRelatedDeviceObject(g_pSocketUdpObject); if (DeviceObject == NULL)return STATUS_INVALID_PARAMETER; ReceiveInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS) + sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); if (ReceiveInfo == NULL)return STATUS_INSUFFICIENT_RESOURCES; MdlBuffer = ExAllocatePool(PagedPool, Length); if (MdlBuffer == NULL)return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(ReceiveInfo, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS) + sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); RtlCopyMemory(MdlBuffer, pData, Length); ReceiveInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS); ReceiveInfo->RemoteAddress = (PUCHAR)((ULONG_PTR)ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION)); TA = (PTA_IP_ADDRESS)(ReceiveInfo->RemoteAddress); TA->TAAddressCount = 1; TA->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP); TA->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; IpAddress = (PTDI_ADDRESS_IP)(TA->Address[0].Address); IpAddress->sin_port = ntohs(Port); IpAddress->in_addr = inet_addr(szIpAddress); ReturnInfo = (PTDI_CONNECTION_INFORMATION)((ULONG_PTR)ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); ReturnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS); ReturnInfo->RemoteAddress = (PUCHAR)((ULONG_PTR)ReturnInfo + sizeof(TDI_CONNECTION_INFORMATION)); ReturnAddress = (PTA_IP_ADDRESS)(ReturnInfo->RemoteAddress); ReturnAddress->TAAddressCount = 1; ReturnAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP); ReturnAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; IpAddress = (PTDI_ADDRESS_IP)(ReturnAddress->Address[0].Address); IpAddress->sin_port = 0; IpAddress->in_addr = 0; KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, DeviceObject, g_pSocketUdpObject, &Event, &Iosb); if (Irp == NULL) { ExFreePool(MdlBuffer); ExFreePool(ReceiveInfo); return STATUS_INSUFFICIENT_RESOURCES; } Mdl = IoAllocateMdl(MdlBuffer, Length, FALSE, FALSE, NULL); if (Mdl == NULL) { IoFreeIrp(Irp); ExFreePool(MdlBuffer); ExFreePool(ReceiveInfo); return STATUS_INSUFFICIENT_RESOURCES; } __try { MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); } __except (EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl(Mdl); IoFreeIrp(Irp); ExFreePool(MdlBuffer); ExFreePool(ReceiveInfo); return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildReceiveDatagram(Irp, DeviceObject, g_pSocketUdpObject, NULL, NULL, Mdl, Length, ReceiveInfo, ReturnInfo, TDI_RECEIVE_NORMAL); Status = IoCallDriver(DeviceObject, Irp); if ((Status == STATUS_PENDING) && (&Event != NULL)) { Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, Timeout); if (Status == STATUS_TIMEOUT) { IoCancelIrp(Irp); Iosb.Status = STATUS_TIMEOUT; } Status = Iosb.Status; } if (NT_SUCCESS(Status)) { uRecvSize = Iosb.Information; if (uRecvSize > 0)RtlCopyMemory(pData, MdlBuffer, Iosb.Information); } ExFreePool(MdlBuffer); ExFreePool(ReceiveInfo); return uRecvSize; }
#include <stdio.h> #include <Winsock2.h> #pragma comment (lib,"ws2_32.lib") int main(void) { WSADATA WsaData = { 0 }; WSAStartup(MAKEWORD(2, 2), &WsaData); SOCKET m_SrvSocker = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); SOCKADDR_IN m_SrvAddr; m_SrvAddr.sin_family = AF_INET; m_SrvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); m_SrvAddr.sin_port = htons(1234); if (bind(m_SrvSocker, (SOCKADDR*)&m_SrvAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) { printf("繫結失敗\n"); getchar(); getchar(); return -1; } char szBuff[MAX_PATH] = { 0 }; SOCKADDR_IN m_ClientAddr; int nlen = sizeof(SOCKADDR); recvfrom(m_SrvSocker, szBuff, sizeof(szBuff), 0, (SOCKADDR*)&m_ClientAddr, &nlen); printf("%s:%s\n", inet_ntoa(m_ClientAddr.sin_addr), szBuff); ZeroMemory(szBuff, sizeof(szBuff)); CopyMemory(szBuff, "這個服務端發的訊息", sizeof("這個服務端發的訊息")); sendto(m_SrvSocker, szBuff, sizeof("這個服務端發的訊息"), 0, (SOCKADDR*)&m_ClientAddr, sizeof(SOCKADDR)); getchar(); getchar(); closesocket(m_SrvSocker); WSACleanup(); return 0; }