Windows图形应用:获取特定进程活跃UDP连接的远程IP和端口
Hey there, let's break down how to solve this—since IP Helper can't give you remote UDP addresses (as you figured out, UDP's connectionless nature means there's no persistent "connection" table to query), you need to either capture network packets or hook into Windows' network stack directly. Here are practical implementations for both C++ and C# that fit your Windows app needs:
Option 1: Npcap (Modern WinPcap Replacement)
Npcap is the go-to for Windows packet capture, and it's easy to integrate with C++. Here's a step-by-step approach:
Set Up Dependencies:
- Install the Npcap SDK and add its include/lib paths to your C++ project.
- Link against
wpcap.libandPacket.lib.
Get Target Process's Local UDP Ports:
- Use IP Helper's
GetExtendedUdpTableto fetch all UDP endpoints on the system, then filter entries matching your target process ID. This gives you the local ports the process is using.
- Use IP Helper's
Capture & Filter Packets:
- Enumerate network adapters with
pcap_findalldevs_ex. - Open the relevant adapter with
pcap_open_live. - Set a BPF filter to capture only UDP traffic involving your target ports:
char filter[256]; sprintf(filter, "udp and (src port %d or dst port %d)", localPort, localPort); pcap_compile(handle, &fp, filter, 0, PCAP_NETMASK_UNKNOWN); pcap_setfilter(handle, &fp);
- Enumerate network adapters with
Parse Packets for Remote Addresses:
- Use
pcap_loopto capture packets. For each packet, parse the IP header (IPv4/IPv6) and UDP header:- If the packet's source port matches your local port, the remote address is the IP header's destination address + UDP header's destination port.
- If the packet's destination port matches your local port, the remote address is the IP header's source address + UDP header's source port.
- Use
Simplified Code Snippet
#include <winsock2.h> #include <pcap.h> void packetHandler(u_char* userData, const struct pcap_pkthdr* pkthdr, const u_char* packet) { // Parse IP and UDP headers (handle IPv4/IPv6 differences in production code) // Extract remote IP/port and map to your target process via local port } int main() { pcap_if_t* alldevs; pcap_t* handle; char errbuf[PCAP_ERRBUF_SIZE]; // Enumerate adapters if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr, "Error finding devices: %s\n", errbuf); return 1; } // Open first adapter (replace with your target network adapter) handle = pcap_open_live(alldevs->name, 65536, 1, 1000, errbuf); if (handle == NULL) { fprintf(stderr, "Couldn't open device: %s\n", errbuf); return 1; } // Set filter for target UDP port (replace 1234 with your process's port) struct bpf_program fp; char filter[] = "udp and (src port 1234 or dst port 1234)"; if (pcap_compile(handle, &fp, filter, 0, PCAP_NETMASK_UNKNOWN) == -1) { fprintf(stderr, "Couldn't parse filter: %s\n", pcap_geterr(handle)); return 1; } pcap_setfilter(handle, &fp); // Start capturing packets pcap_loop(handle, 0, packetHandler, NULL); pcap_close(handle); pcap_freealldevs(alldevs); return 0; }
Option 2: Windows Filtering Platform (WFP)
For a more integrated, library-free approach, use WFP to intercept UDP packets at the network stack and directly get the associated process ID. This is more accurate than packet capture, as it ties packets to processes without relying on port matching.
- Key Steps:
- Initialize the WFP filter engine with
FwpmEngineOpen0. - Add a filter that matches UDP traffic and your target process ID (use
FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4/V6for incoming traffic,FWPM_LAYER_ALE_AUTH_CONNECT_V4/V6for outgoing). - Register a callback function that triggers when a matching packet is detected. The callback receives a
FWPS_INCOMING_VALUES0structure containing the remote IP/port and process ID. - Clean up the filter engine when done.
- Initialize the WFP filter engine with
Note: WFP requires admin privileges, and you'll need to handle IPv4/IPv6 traffic separately.
SharpPcap (Npcap C# Wrapper)
SharpPcap is a popular C# wrapper for Npcap, making packet capture straightforward and idiomatic for .NET apps.
Install Dependency:
- Add the
SharpPcapNuGet package to your project.
- Add the
Get Target Process's Local UDP Ports:
- Use P/Invoke to call
GetExtendedUdpTable(since .NET's built-inUdpConnectionInformationdoesn't include process IDs). Alternatively, useSystem.Managementto query WMI for UDP ports tied to your process.
- Use P/Invoke to call
Capture & Parse Packets:
- Enumerate capture devices with
CaptureDeviceList.Instance. - Open the target device, set a BPF filter for your process's UDP ports.
- Subscribe to the
PacketArrivalevent to process incoming packets.
- Enumerate capture devices with
Simplified Code Snippet
using System; using SharpPcap; using PacketDotNet; class UdpRemoteAddressCapture { static void Main(string[] args) { // Replace with your target process's local UDP port int targetLocalPort = 1234; // Get all available capture devices var devices = CaptureDeviceList.Instance; if (devices.Count == 0) { Console.WriteLine("No capture devices found"); return; } // Select the first device (replace with your target network adapter) var device = devices[0]; // Open device for promiscuous capture device.Open(DeviceMode.Promiscuous, 1000); // Set filter to capture only UDP traffic involving the target port device.Filter = $"udp and (src port {targetLocalPort} or dst port {targetLocalPort})"; // Handle incoming packets device.PacketArrival += (sender, e) => { var packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data); var ipPacket = packet.Extract<IpPacket>(); var udpPacket = packet.Extract<UdpPacket>(); if (ipPacket != null && udpPacket != null) { string remoteIp; int remotePort; // Determine remote address based on which side is using the local port if (udpPacket.SourcePort == targetLocalPort) { remoteIp = ipPacket.DestinationAddress.ToString(); remotePort = udpPacket.DestinationPort; } else { remoteIp = ipPacket.SourceAddress.ToString(); remotePort = udpPacket.SourcePort; } Console.WriteLine($"Found active UDP endpoint: Remote IP = {remoteIp}, Port = {remotePort}"); } }; // Start capturing device.StartCapture(); Console.WriteLine("Capturing UDP traffic... Press any key to stop"); Console.ReadKey(); device.StopCapture(); device.Close(); } }
- Admin Privileges: All these methods require admin rights—your app will need to request elevation to work correctly.
- UDP "Active" Definition: Since UDP is connectionless, "active" means recent packet activity. You'll need to track unique remote IP/port pairs and prune stale entries if needed.
- Process Association Accuracy: If multiple processes share the same UDP port (rare, as most apps use exclusive binds), WFP is the most reliable way to tie packets directly to a process ID.
内容的提问来源于stack exchange,提问作者Jonathan

