### Execute NDISAPI Example Applications Source: https://github.com/wiresock/ndisapi/blob/master/cygwin/README.md Instructions for running the compiled example applications from the binary directory. ```bash ./bin/x64/Release/listadapters ``` -------------------------------- ### Build and Clean NDISAPI Library with Make Source: https://github.com/wiresock/ndisapi/blob/master/cygwin/README.md Commands to compile the NDISAPI static library and associated example applications, as well as instructions for removing build artifacts. ```bash make make clean ``` -------------------------------- ### Example socksify.exe Configuration and Output Source: https://github.com/wiresock/ndisapi/blob/master/examples/cpp/socksify/README.md An example demonstrating the interactive prompts and output of the `socksify.exe` tool when redirecting Firefox traffic through a SOCKS5 proxy. It shows the user input for interface, application, proxy details, and the subsequent redirection messages. ```dos Select interface to filter: 12 Application name to socksify: firefox SOCKS5 proxy IP address: 127.0.0.1 SOCKS5 proxy port: 8080 Local port for the transparent TCP proxy server: 9000 SOCKS5 USERNAME[optional]: SOCKS5 PASSWORD[optional]: No suitable username or password specified, using anonymous authentication with SOCKS5 proxy Press any key to stop filtering Redirect entry was found for the port 50946 is 13.32.110.25:443 Redirect entry was found for the port 50948 is 34.160.90.233:443 Redirect entry was found for the port 50949 is 34.160.90.233:443 Redirect entry was found for the port 50950 is 34.160.90.233:443 ... ``` -------------------------------- ### Start SOCKS5 Proxy with SSH Source: https://github.com/wiresock/ndisapi/blob/master/examples/cpp/socksify/README.md Initiates a SOCKS5 proxy on the local machine using an SSH command. This proxy will be used by the Windows Packet Filter to route application traffic. It requires an SSH client and a remote server to connect to. ```bash ssh user@domain.com -D 8080 ``` -------------------------------- ### Run socksify.exe Tool for Traffic Redirection Source: https://github.com/wiresock/ndisapi/blob/master/examples/cpp/socksify/README.md Executes the `socksify.exe` tool to configure the Windows Packet Filter for traffic redirection. The tool prompts for network interface selection, application name, SOCKS5 proxy details, and a local port for the transparent proxy. User input is required to complete the setup. ```dos D:\projects\winpkfilter\ndisapi\tools_bin_x64\tools\amd64>socksify.exe WinpkFilter is loaded Available network interfaces: Select interface to filter: Application name to socksify: SOCKS5 proxy IP address: SOCKS5 proxy port: Local port for the transparent TCP proxy server: SOCKS5 USERNAME[optional]: SOCKS5 PASSWORD[optional]: ``` -------------------------------- ### Install Hyperscan and llhttp dependencies via vcpkg Source: https://github.com/wiresock/ndisapi/blob/master/examples/cpp/hyperscan/README.md Commands to install the necessary Hyperscan and llhttp libraries for Windows using the vcpkg package manager. These commands target both x86 and x64 architectures for static linking. ```bash vcpkg install hyperscan:x86-windows-static hyperscan:x64-windows-static vcpkg install llhttp:x86-windows-static llhttp:x64-windows-static ``` -------------------------------- ### Initialize Driver and Check Status using CNdisApi Source: https://context7.com/wiresock/ndisapi/llms.txt Demonstrates how to instantiate the CNdisApi class and verify that the WinpkFilter driver is correctly loaded. It also retrieves and displays the driver version to confirm successful initialization. ```cpp #include // Create CNdisApi instance - automatically connects to the driver CNdisApi api; // Check if the driver is loaded successfully if (api.IsDriverLoaded()) { std::cout << "Windows Packet Filter driver loaded successfully" << std::endl; // Get driver version ULONG version = api.GetVersion(); std::cout << "Driver version: " << ((version >> 24) & 0xFF) << "." << ((version >> 16) & 0xFF) << "." << ((version >> 8) & 0xFF) << "." << (version & 0xFF) << std::endl; } else { std::cout << "Failed to load Windows Packet Filter driver" << std::endl; return 1; } ``` -------------------------------- ### Initialize and Use NDISAPI Driver in C Source: https://context7.com/wiresock/ndisapi/llms.txt Demonstrates the basic lifecycle of an NDISAPI application, including opening the driver, checking its status, retrieving adapter information, setting adapter modes, and capturing packets. This requires the ndisapi.h header and a valid handle to the filter driver. ```c #include // Open connection to the driver HANDLE hDriver = OpenFilterDriver(NULL); // NULL uses default driver name if (hDriver == INVALID_HANDLE_VALUE) { printf("Failed to open filter driver\n"); return 1; } // Check if driver is loaded if (!IsDriverLoaded(hDriver)) { printf("Driver not loaded\n"); CloseFilterDriver(hDriver); return 1; } // Get driver version DWORD version = GetDriverVersion(hDriver); printf("Driver version: %u.%u.%u.%u\n", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); // Get adapters list TCP_AdapterList adapterList; if (GetTcpipBoundAdaptersInfo(hDriver, &adapterList)) { printf("Found %d adapters\n", adapterList.m_nAdapterCount); } // Set adapter mode ADAPTER_MODE mode; mode.hAdapterHandle = adapterList.m_nAdapterHandle[0]; mode.dwFlags = MSTCP_FLAG_SENT_TUNNEL | MSTCP_FLAG_RECV_TUNNEL; SetAdapterMode(hDriver, &mode); // Read packet INTERMEDIATE_BUFFER buffer; ETH_REQUEST request; request.hAdapterHandle = adapterList.m_nAdapterHandle[0]; request.EthPacket.Buffer = &buffer; if (ReadPacket(hDriver, &request)) { printf("Packet captured: %d bytes\n", buffer.m_Length); } // Close driver CloseFilterDriver(hDriver); ``` -------------------------------- ### Enumerate Network Adapters with CNdisApi Source: https://context7.com/wiresock/ndisapi/llms.txt Retrieves a list of all TCP/IP bound network adapters using GetTcpipBoundAdaptersInfo. The code iterates through the adapters to display their friendly names, MAC addresses, MTU settings, and internal handles. ```cpp #include CNdisApi api; TCP_AdapterList adapterList; char friendlyName[MAX_PATH * 4]; // Get list of all TCP/IP bound adapters if (api.GetTcpipBoundAdaptersInfo(&adapterList)) { std::cout << "Found " << adapterList.m_nAdapterCount << " network adapters:" << std::endl; for (DWORD i = 0; i < adapterList.m_nAdapterCount; ++i) { // Convert internal adapter name to user-friendly name CNdisApi::ConvertWindows2000AdapterName( reinterpret_cast(adapterList.m_szAdapterNameList[i]), friendlyName, sizeof(friendlyName) ); std::cout << (i + 1) << ") " << friendlyName << std::endl; std::cout << " Internal Name: " << adapterList.m_szAdapterNameList[i] << std::endl; std::cout << " MAC Address: "; for (int j = 0; j < ETHER_ADDR_LENGTH; ++j) { printf("%02X%s", adapterList.m_czCurrentAddress[i][j], (j < ETHER_ADDR_LENGTH - 1) ? ":" : ""); } std::cout << std::endl; std::cout << " MTU: " << adapterList.m_usMTU[i] << std::endl; std::cout << " Handle: " << adapterList.m_nAdapterHandle[i] << std::endl; } } ``` -------------------------------- ### Add Single Static Filter using NDIS API Source: https://context7.com/wiresock/ndisapi/llms.txt Demonstrates how to add a single static filter to block traffic to or from a specific IP subnet using the NDIS API. It covers setting filter parameters like direction, action, and network layer details, and shows methods for adding the filter to the front, back, or a specific position in the filter list. ```cpp #include CNdisApi api; TCP_AdapterList adapterList; api.GetTcpipBoundAdaptersInfo(&adapterList); // Create filter to block specific IP address STATIC_FILTER filter; ZeroMemory(&filter, sizeof(STATIC_FILTER)); filter.m_Adapter.QuadPart = 0; // All adapters filter.m_dwDirectionFlags = PACKET_FLAG_ON_SEND | PACKET_FLAG_ON_RECEIVE; filter.m_FilterAction = FILTER_PACKET_DROP; filter.m_ValidFields = NETWORK_LAYER_VALID; // Block traffic to/from 10.0.0.0/8 subnet filter.m_NetworkFilter.m_dwUnionSelector = IPV4; filter.m_NetworkFilter.m_IPv4.m_ValidFields = IP_V4_FILTER_DEST_ADDRESS; filter.m_NetworkFilter.m_IPv4.m_DestAddress.m_AddressType = IP_SUBNET_V4_TYPE; filter.m_NetworkFilter.m_IPv4.m_DestAddress.m_IpSubnet.m_Ip = inet_addr("10.0.0.0"); filter.m_NetworkFilter.m_IPv4.m_DestAddress.m_IpSubnet.m_IpMask = inet_addr("255.0.0.0"); // Add filter to the front of the filter list if (api.AddStaticFilterFront(&filter)) { std::cout << "Filter added successfully" << std::endl; } // Or add to the back api.AddStaticFilterBack(&filter); // Or insert at specific position api.InsertStaticFilter(&filter, 0); // Insert at position 0 ``` -------------------------------- ### Set Static Packet Filter Table (C++) Source: https://context7.com/wiresock/ndisapi/llms.txt Configures static packet filters to pass, drop, or redirect traffic based on defined criteria. Requires adapter handles and filter rules. Outputs success or failure. ```cpp #include #include #include #include // Assuming necessary definitions for STATIC_FILTER_TABLE, STATIC_FILTER, etc. // For demonstration, simplified definitions might be needed if not in ndisapi.h // Simplified definitions for demonstration purposes #ifndef IPV4 #define IPV4 1 #endif #ifndef TCPUDP #define TCPUDP 2 #endif #ifndef IPPROTO_TCP #define IPPROTO_TCP 6 #endif #ifndef PACKET_FLAG_ON_RECEIVE #define PACKET_FLAG_ON_RECEIVE 0x00000001 #endif #ifndef PACKET_FLAG_ON_SEND #define PACKET_FLAG_ON_SEND 0x00000002 #endif #ifndef FILTER_PACKET_DROP #define FILTER_PACKET_DROP 1 #endif #ifndef FILTER_PACKET_PASS #define FILTER_PACKET_PASS 0 #endif #ifndef NETWORK_LAYER_VALID #define NETWORK_LAYER_VALID 0x00000001 #endif #ifndef TRANSPORT_LAYER_VALID #define TRANSPORT_LAYER_VALID 0x00000002 #endif #ifndef IP_V4_FILTER_PROTOCOL #define IP_V4_FILTER_PROTOCOL 0x00000001 #endif #ifndef TCPUDP_DEST_PORT #define TCPUDP_DEST_PORT 0x00000002 #endif // Placeholder for TCP_AdapterList structure if not fully defined in ndisapi.h typedef struct _TCP_AdapterList { ULONG m_nAdapterCount; HANDLE m_nAdapterHandle[16]; // Max 16 adapters for example UCHAR m_czCurrentAddress[16][6]; // MAC addresses } TCP_AdapterList; // Placeholder for CNdisApi class if not fully defined in ndisapi.h class CNdisApi { public: BOOL GetTcpipBoundAdaptersInfo(TCP_AdapterList* pAdapterList) { // Dummy implementation pAdapterList->m_nAdapterCount = 1; pAdapterList->m_nAdapterHandle[0] = (HANDLE)0x12345678; // Dummy handle memset(pAdapterList->m_czCurrentAddress[0], 0xAA, 6); return TRUE; } BOOL SetPacketFilterTable(PSTATIC_FILTER_TABLE pTable) { // Dummy implementation std::cout << "SetPacketFilterTable called with table size: " << pTable->m_TableSize << std::endl; return TRUE; } VOID ResetPacketFilterTable() { // Dummy implementation std::cout << "ResetPacketFilterTable called." << std::endl; } }; // Placeholder for STATIC_FILTER_TABLE and STATIC_FILTER structures // These should match the actual definitions in ndisapi.h struct _IP_NETWORK_FILTER { ULONG m_dwUnionSelector; struct { ULONG m_ValidFields; ULONG m_Protocol; } m_IPv4; // Add other IP versions if needed }; struct _TCPUDP_TRANSPORT_FILTER { ULONG m_dwUnionSelector; struct { ULONG m_ValidFields; struct { USHORT m_StartRange; USHORT m_EndRange; } m_DestPort; // Add other port ranges if needed } m_TcpUdp; // Add other transport protocols if needed }; typedef struct _STATIC_FILTER { LARGE_INTEGER m_Adapter; ULONG m_dwDirectionFlags; ULONG m_FilterAction; ULONG m_ValidFields; _IP_NETWORK_FILTER m_NetworkFilter; _TCPUDP_TRANSPORT_FILTER m_TransportFilter; // Add other filter fields if needed } STATIC_FILTER, *PSTATIC_FILTER; typedef struct _STATIC_FILTER_TABLE { ULONG m_TableSize; STATIC_FILTER m_StaticFilters[1]; // Flexible array member } STATIC_FILTER_TABLE, *PSTATIC_FILTER_TABLE; int main() { CNdisApi api; TCP_AdapterList adapterList; // Initialize Winsock if not already done WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed\n"; return 1; } if (api.GetTcpipBoundAdaptersInfo(&adapterList) == FALSE) { std::cerr << "Failed to get adapter info\n"; WSACleanup(); return 1; } if (adapterList.m_nAdapterCount == 0) { std::cerr << "No adapters found\n"; WSACleanup(); return 1; } // Allocate filter table for 2 filters auto tableSize = sizeof(STATIC_FILTER_TABLE) + sizeof(STATIC_FILTER); auto filterTable = std::make_unique(tableSize); auto* pFilterTable = reinterpret_cast(filterTable.get()); pFilterTable->m_TableSize = 2; // Filter 1: Block all incoming TCP port 80 traffic auto& filter1 = pFilterTable->m_StaticFilters[0]; filter1.m_Adapter.QuadPart = reinterpret_cast(adapterList.m_nAdapterHandle[0]); filter1.m_dwDirectionFlags = PACKET_FLAG_ON_RECEIVE; filter1.m_FilterAction = FILTER_PACKET_DROP; filter1.m_ValidFields = NETWORK_LAYER_VALID | TRANSPORT_LAYER_VALID; // Network layer: IPv4 filter1.m_NetworkFilter.m_dwUnionSelector = IPV4; filter1.m_NetworkFilter.m_IPv4.m_ValidFields = IP_V4_FILTER_PROTOCOL; filter1.m_NetworkFilter.m_IPv4.m_Protocol = IPPROTO_TCP; // Transport layer: Destination port 80 filter1.m_TransportFilter.m_dwUnionSelector = TCPUDP; filter1.m_TransportFilter.m_TcpUdp.m_ValidFields = TCPUDP_DEST_PORT; filter1.m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; filter1.m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80; // Filter 2: Pass all other traffic (default rule) auto& filter2 = pFilterTable->m_StaticFilters[1]; filter2.m_Adapter.QuadPart = 0; // Apply to all adapters filter2.m_dwDirectionFlags = PACKET_FLAG_ON_SEND | PACKET_FLAG_ON_RECEIVE; filter2.m_FilterAction = FILTER_PACKET_PASS; filter2.m_ValidFields = 0; // Match all packets // Apply filter table if (api.SetPacketFilterTable(pFilterTable)) { std::cout << "Static filters applied successfully" << std::endl; } else { std::cerr << "Failed to apply static filters. Error: " << GetLastError() << std::endl; } // To remove filters: // api.ResetPacketFilterTable(); WSACleanup(); return 0; } ``` -------------------------------- ### Send Packets to Adapter (C++) Source: https://context7.com/wiresock/ndisapi/llms.txt Sends raw packets to a network adapter for transmission. Requires adapter handle and packet data. Outputs success or failure status. ```cpp #include #include #include // Assuming necessary definitions for ether_header, iphdr, etc. // For demonstration, simplified definitions might be needed if not in ndisapi.h #pragma pack(push, 1) typedef struct ether_header { UCHAR h_dest[6]; UCHAR h_source[6]; USHORT h_proto; } ether_header; #pragma pack(pop) // Simplified iphdr for example typedef struct iphdr { UCHAR ip_hl:4; UCHAR ip_v:4; UCHAR ip_tos; USHORT ip_len; USHORT ip_id; USHORT ip_off; UCHAR ip_ttl; UCHAR ip_p; USHORT ip_sum; ULONG ip_src.S_un.S_addr; ULONG ip_dst.S_un.S_addr; } iphdr; #define ETHER_ADDR_LENGTH 6 #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 #define IPPROTO_ICMP 1 CNdisApi api; TCP_AdapterList adapterList; // Initialize Winsock if not already done WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed\n"; return 1; } if (api.GetTcpipBoundAdaptersInfo(&adapterList) == FALSE) { std::cerr << "Failed to get adapter info\n"; WSACleanup(); return 1; } if (adapterList.m_nAdapterCount == 0) { std::cerr << "No adapters found\n"; WSACleanup(); return 1; } HANDLE hAdapter = adapterList.m_nAdapterHandle[0]; // Prepare a packet to send INTERMEDIATE_BUFFER packetBuffer; ZeroMemory(&packetBuffer, sizeof(INTERMEDIATE_BUFFER)); // Allocate buffer for Ethernet frame (e.g., 60 bytes minimum) packetBuffer.m_IBuffer = new BYTE[60]; if (!packetBuffer.m_IBuffer) { std::cerr << "Failed to allocate buffer\n"; WSACleanup(); return 1; } // Build Ethernet frame (example: ARP request) auto* ethHeader = reinterpret_cast(packetBuffer.m_IBuffer); memset(ethHeader->h_dest, 0xFF, ETHER_ADDR_LENGTH); // Broadcast memcpy(ethHeader->h_source, adapterList.m_czCurrentAddress[0], ETHER_ADDR_LENGTH); ethHeader->h_proto = htons(0x0806); // ARP packetBuffer.m_Length = 60; // Minimum Ethernet frame size packetBuffer.m_dwDeviceFlags = PACKET_FLAG_ON_SEND; // Prepare send request ETH_REQUEST request; request.hAdapterHandle = hAdapter; request.EthPacket.Buffer = &packetBuffer; // Send packet to the network if (api.SendPacketToAdapter(&request)) { std::cout << "Packet sent to adapter successfully" << std::endl; } else { std::cerr << "Failed to send packet to adapter. Error: " << GetLastError() << std::endl; } // Clean up allocated buffer delete[] packetBuffer.m_IBuffer; WSACleanup(); ``` -------------------------------- ### Initialize Fast I/O Interface using NDIS API Source: https://context7.com/wiresock/ndisapi/llms.txt Initializes the Fast I/O interface for high-performance packet processing by allocating and configuring a shared memory section between user and kernel modes. This avoids traditional DeviceIoControl calls for packet retrieval. ```cpp #include constexpr size_t FAST_IO_PACKETS = 1024; CNdisApi api; // Calculate required buffer size auto fastIoSize = sizeof(FAST_IO_SECTION_HEADER) + sizeof(INTERMEDIATE_BUFFER) * FAST_IO_PACKETS; // Allocate Fast I/O section auto fastIoBuffer = VirtualAlloc(nullptr, fastIoSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); auto* fastIoSection = static_cast(fastIoBuffer); // Initialize Fast I/O with the driver if (api.InitializeFastIo(fastIoSection, static_cast(fastIoSize))) { std::cout << "Fast I/O initialized successfully" << std::endl; // Now you can read packets directly from the shared memory section // without DeviceIoControl calls } // Cleanup VirtualFree(fastIoBuffer, 0, MEM_RELEASE); ``` -------------------------------- ### Simple Packet Filter Wrapper using NDIS API Source: https://context7.com/wiresock/ndisapi/llms.txt Provides a C++ wrapper class `simple_packet_filter` for simplified packet filtering. It allows defining handlers for incoming and outgoing packets, checking driver status, listing interfaces, and starting/stopping filtering on a specified interface. ```cpp #include "ndisapi/simple_packet_filter.h" // Create packet filter with incoming and outgoing packet handlers auto filter = std::make_unique( // Incoming packet handler [](HANDLE adapter, INTERMEDIATE_BUFFER& buffer) -> ndisapi::simple_packet_filter::packet_action { auto* ethHeader = reinterpret_cast(buffer.m_IBuffer); if (ntohs(ethHeader->h_proto) == ETH_P_IP) { auto* ipHeader = reinterpret_cast(ethHeader + 1); std::cout << "Incoming packet from: " << inet_ntoa(ipHeader->ip_src) << std::endl; } return ndisapi::simple_packet_filter::packet_action::pass; // Forward packet }, // Outgoing packet handler [](HANDLE adapter, INTERMEDIATE_BUFFER& buffer) -> ndisapi::simple_packet_filter::packet_action { auto* ethHeader = reinterpret_cast(buffer.m_IBuffer); if (ntohs(ethHeader->h_proto) == ETH_P_IP) { auto* ipHeader = reinterpret_cast(ethHeader + 1); std::cout << "Outgoing packet to: " << inet_ntoa(ipHeader->ip_dst) << std::endl; } return ndisapi::simple_packet_filter::packet_action::pass; // Forward packet } ); // Check if driver is loaded if (!filter->IsDriverLoaded()) { std::cerr << "WinpkFilter driver not loaded!" << std::endl; return 1; } // List available interfaces auto interfaces = filter->get_interface_names_list(); for (size_t i = 0; i < interfaces.size(); ++i) { std::cout << (i + 1) << ") " << interfaces[i] << std::endl; } // Start filtering on interface 0 filter->start_filter(0); std::cout << "Press Enter to stop..." << std::endl; std::cin.get(); filter->stop_filter(); // Packet actions available: // packet_action::pass - Forward packet normally // packet_action::drop - Silently drop the packet // packet_action::revert - Send packet in opposite direction ``` -------------------------------- ### Send Packets to MSTCP (C++) Source: https://context7.com/wiresock/ndisapi/llms.txt Injects packets up to the TCP/IP protocol stack, simulating received packets. Requires adapter handle and packet data. Outputs success or failure. ```cpp #include #include #include // Assuming necessary definitions for INTERMEDIATE_BUFFER, ETH_REQUEST, TCP_AdapterList CNdisApi api; TCP_AdapterList adapterList; // Initialize Winsock if not already done WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed\n"; return 1; } if (api.GetTcpipBoundAdaptersInfo(&adapterList) == FALSE) { std::cerr << "Failed to get adapter info\n"; WSACleanup(); return 1; } if (adapterList.m_nAdapterCount == 0) { std::cerr << "No adapters found\n"; WSACleanup(); return 1; } HANDLE hAdapter = adapterList.m_nAdapterHandle[0]; // After capturing/modifying a packet, forward it to the protocol stack INTERMEDIATE_BUFFER packetBuffer; ZeroMemory(&packetBuffer, sizeof(INTERMEDIATE_BUFFER)); // Allocate buffer for packet data (example size) packetBuffer.m_IBuffer = new BYTE[1500]; if (!packetBuffer.m_IBuffer) { std::cerr << "Failed to allocate buffer\n"; WSACleanup(); return 1; } packetBuffer.m_Length = 1500; // Set actual packet length // ... (packet data filled from capture or constructed) ETH_REQUEST request; request.hAdapterHandle = hAdapter; request.EthPacket.Buffer = &packetBuffer; // Send packet up to TCP/IP stack (as if received from network) if (api.SendPacketToMstcp(&request)) { std::cout << "Packet forwarded to protocol stack" << std::endl; } else { std::cerr << "Failed to forward packet to protocol stack. Error: " << GetLastError() << std::endl; } // Clean up allocated buffer delete[] packetBuffer.m_IBuffer; WSACleanup(); ``` -------------------------------- ### Read Single Packet in C++ Source: https://context7.com/wiresock/ndisapi/llms.txt Captures a single network packet from the driver queue using the ReadPacket method. It demonstrates how to allocate an INTERMEDIATE_BUFFER, set the adapter mode, and parse the raw Ethernet header. ```cpp #include CNdisApi api; TCP_AdapterList adapterList; api.GetTcpipBoundAdaptersInfo(&adapterList); HANDLE hAdapter = adapterList.m_nAdapterHandle[0]; // Allocate intermediate buffer for the packet INTERMEDIATE_BUFFER packetBuffer; ZeroMemory(&packetBuffer, sizeof(INTERMEDIATE_BUFFER)); // Prepare read request ETH_REQUEST request; request.hAdapterHandle = hAdapter; request.EthPacket.Buffer = &packetBuffer; // Set adapter mode ADAPTER_MODE mode = { hAdapter, MSTCP_FLAG_SENT_TUNNEL | MSTCP_FLAG_RECV_TUNNEL }; api.SetAdapterMode(&mode); // Read packet if (api.ReadPacket(&request)) { std::cout << "Packet captured!" << std::endl; std::cout << " Length: " << packetBuffer.m_Length << " bytes" << std::endl; std::cout << " Direction: " << ((packetBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND) ? "Outgoing" : "Incoming") << std::endl; // Access raw packet data in packetBuffer.m_IBuffer // First 14 bytes are Ethernet header auto* ethHeader = reinterpret_cast(packetBuffer.m_IBuffer); std::cout << " EtherType: 0x" << std::hex << ntohs(ethHeader->h_proto) << std::dec << std::endl; } ``` -------------------------------- ### Recalculate Packet Checksums (C++) Source: https://context7.com/wiresock/ndisapi/llms.txt Static helper methods to recalculate IP, TCP, UDP, and ICMP checksums after packet modification. Takes an INTERMEDIATE_BUFFER as input. ```cpp #include #include #include // Assuming necessary definitions for INTERMEDIATE_BUFFER, ether_header, iphdr, etc. // For demonstration, simplified definitions might be needed if not in ndisapi.h #pragma pack(push, 1) typedef struct ether_header { UCHAR h_dest[6]; UCHAR h_source[6]; USHORT h_proto; } ether_header; #pragma pack(pop) // Simplified iphdr for example typedef struct iphdr { UCHAR ip_hl:4; UCHAR ip_v:4; UCHAR ip_tos; USHORT ip_len; USHORT ip_id; USHORT ip_off; UCHAR ip_ttl; UCHAR ip_p; USHORT ip_sum; ULONG ip_src.S_un.S_addr; ULONG ip_dst.S_un.S_addr; } iphdr; #define ETHER_ADDR_LENGTH 6 #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 #define IPPROTO_ICMP 1 // Initialize Winsock if not already done WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed\n"; return 1; } INTERMEDIATE_BUFFER packetBuffer; ZeroMemory(&packetBuffer, sizeof(INTERMEDIATE_BUFFER)); // Allocate buffer for packet data (example size) packetBuffer.m_IBuffer = new BYTE[1500]; if (!packetBuffer.m_IBuffer) { std::cerr << "Failed to allocate buffer\n"; WSACleanup(); return 1; } packetBuffer.m_Length = 1500; // Set actual packet length // ... (packet captured and modified) // Access IP header auto* ethHeader = reinterpret_cast(packetBuffer.m_IBuffer); auto* ipHeader = reinterpret_cast(ethHeader + 1); // Modify packet (e.g., change destination IP) ipHeader->ip_dst.S_un.S_addr = inet_addr("192.168.1.100"); // Recalculate checksums after modification if (CNdisApi::RecalculateIPChecksum(&packetBuffer)) { std::cout << "IP checksum recalculated successfully." << std::endl; } else { std::cerr << "Failed to recalculate IP checksum." << std::endl; } // For TCP packets if (ipHeader->ip_p == IPPROTO_TCP) { if (CNdisApi::RecalculateTCPChecksum(&packetBuffer)) { std::cout << "TCP checksum recalculated successfully." << std::endl; } else { std::cerr << "Failed to recalculate TCP checksum." << std::endl; } } // For UDP packets if (ipHeader->ip_p == IPPROTO_UDP) { if (CNdisApi::RecalculateUDPChecksum(&packetBuffer)) { std::cout << "UDP checksum recalculated successfully." << std::endl; } else { std::cerr << "Failed to recalculate UDP checksum." << std::endl; } } // For ICMP packets if (ipHeader->ip_p == IPPROTO_ICMP) { if (CNdisApi::RecalculateICMPChecksum(&packetBuffer)) { std::cout << "ICMP checksum recalculated successfully." << std::endl; } else { std::cerr << "Failed to recalculate ICMP checksum." << std::endl; } } // Clean up allocated buffer delete[] packetBuffer.m_IBuffer; WSACleanup(); ``` -------------------------------- ### Read Multiple Packets in C++ Source: https://context7.com/wiresock/ndisapi/llms.txt Optimizes packet capture performance by reading multiple packets in a single call using ReadPackets. This requires allocating a variable-sized request structure and an array of intermediate buffers. ```cpp #include constexpr size_t MAX_PACKETS = 512; CNdisApi api; TCP_AdapterList adapterList; api.GetTcpipBoundAdaptersInfo(&adapterList); HANDLE hAdapter = adapterList.m_nAdapterHandle[0]; // Allocate packet buffers auto packetBuffers = std::make_unique(MAX_PACKETS); ZeroMemory(packetBuffers.get(), sizeof(INTERMEDIATE_BUFFER) * MAX_PACKETS); // Allocate request structure (variable size based on packet count) auto requestSize = sizeof(ETH_M_REQUEST) + sizeof(NDISRD_ETH_Packet) * (MAX_PACKETS - 1); auto requestBuffer = std::make_unique(requestSize); auto* request = reinterpret_cast(requestBuffer.get()); request->hAdapterHandle = hAdapter; request->dwPacketsNumber = MAX_PACKETS; // Initialize packet buffer pointers for (size_t i = 0; i < MAX_PACKETS; ++i) { request->EthPacket[i].Buffer = &packetBuffers[i]; } // Set adapter mode ADAPTER_MODE mode = { hAdapter, MSTCP_FLAG_SENT_TUNNEL | MSTCP_FLAG_RECV_TUNNEL }; api.SetAdapterMode(&mode); // Read multiple packets if (api.ReadPackets(request)) { std::cout << "Successfully read " << request->dwPacketsSuccess << " packets" << std::endl; for (unsigned i = 0; i < request->dwPacketsSuccess; ++i) { std::cout << "Packet " << (i + 1) << ": " << packetBuffers[i].m_Length << " bytes, " << ((packetBuffers[i].m_dwDeviceFlags == PACKET_FLAG_ON_SEND) ? "OUT" : "IN") << std::endl; } } ``` -------------------------------- ### Set Packet Event for Asynchronous Notification in C++ Source: https://context7.com/wiresock/ndisapi/llms.txt Associates a Win32 event with a network adapter to enable asynchronous notification when packets are available. It requires configuring the adapter mode for interception and using WaitForSingleObject to block until data arrives. ```cpp #include CNdisApi api; TCP_AdapterList adapterList; api.GetTcpipBoundAdaptersInfo(&adapterList); HANDLE hAdapter = adapterList.m_nAdapterHandle[0]; // Create a Win32 event for packet notification HANDLE hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); // Associate the event with the adapter if (api.SetPacketEvent(hAdapter, hEvent)) { std::cout << "Packet event set successfully" << std::endl; // Configure adapter for packet interception ADAPTER_MODE mode = { hAdapter, MSTCP_FLAG_SENT_TUNNEL | MSTCP_FLAG_RECV_TUNNEL }; api.SetAdapterMode(&mode); // Wait for packets while (true) { DWORD result = WaitForSingleObject(hEvent, INFINITE); if (result == WAIT_OBJECT_0) { ResetEvent(hEvent); // Process packets here std::cout << "Packets available for processing" << std::endl; break; // Exit for demo } } } CloseHandle(hEvent); ``` -------------------------------- ### Set Adapter Mode for Packet Capture Source: https://context7.com/wiresock/ndisapi/llms.txt Configures the driver to intercept network traffic on a specific adapter using the SetAdapterMode method. It demonstrates how to set flags for tunneling sent and received packets. ```cpp #include CNdisApi api; TCP_AdapterList adapterList; api.GetTcpipBoundAdaptersInfo(&adapterList); // Select an adapter (index 0 in this example) HANDLE hAdapter = adapterList.m_nAdapterHandle[0]; // Configure adapter mode to intercept both sent and received packets ADAPTER_MODE mode; mode.hAdapterHandle = hAdapter; mode.dwFlags = MSTCP_FLAG_SENT_TUNNEL | MSTCP_FLAG_RECV_TUNNEL; if (api.SetAdapterMode(&mode)) { std::cout << "Adapter mode set successfully" << std::endl; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.