static HANDLE init(char *filter, UINT64 flags) { LPTSTR errormessage = NULL; filter = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, 0, flags); if (filter != INVALID_HANDLE_VALUE) return filter; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR)&errormessage, 0, NULL); printf("%s", errormessage); return NULL; }
int divertStart(const char *filter, char buf[]) { int ix; divertHandle = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, DIVERT_PRIORITY, 0); if (divertHandle == INVALID_HANDLE_VALUE) { DWORD lastError = GetLastError(); if (lastError == ERROR_INVALID_PARAMETER) { strcpy(buf, "Failed to start filtering : filter syntax error."); } else { sprintf(buf, "Failed to start filtering : failed to open device (code:%lu).\n" "Make sure you run clumsy as Administrator.", lastError); } return FALSE; } LOG("Divert opened handle."); WinDivertSetParam(divertHandle, WINDIVERT_PARAM_QUEUE_LEN, QUEUE_LEN); WinDivertSetParam(divertHandle, WINDIVERT_PARAM_QUEUE_TIME, QUEUE_TIME); LOG("WinDivert internal queue Len: %d, queue time: %d", QUEUE_LEN, QUEUE_TIME); // init package link list initPacketNodeList(); // reset module for (ix = 0; ix < MODULE_CNT; ++ix) { modules[ix]->lastEnabled = 0; } // kick off the loop LOG("Creating threads and mutex..."); stopLooping = FALSE; mutex = CreateMutex(NULL, FALSE, NULL); if (mutex == NULL) { sprintf(buf, "Failed to create mutex (%lu)", GetLastError()); return FALSE; } loopThread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)divertReadLoop, NULL, 0, NULL); if (loopThread == NULL) { sprintf(buf, "Failed to create recv loop thread (%lu)", GetLastError()); return FALSE; } clockThread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)divertClockLoop, NULL, 0, NULL); if (clockThread == NULL) { sprintf(buf, "Failed to create clock loop thread (%lu)", GetLastError()); return FALSE; } LOG("Threads created"); return TRUE; }
/* * Entry. */ int __cdecl main(int argc, char **argv) { int num_threads, i; HANDLE handle, thread; if (argc != 3) { fprintf(stderr, "usage: %s filter num-threads\n", argv[0]); exit(EXIT_FAILURE); } num_threads = atoi(argv[2]); if (num_threads < 1 || num_threads > 64) { fprintf(stderr, "error: invalid number of threads\n"); exit(EXIT_FAILURE); } // Divert traffic matching the filter: handle = WinDivertOpen(argv[1], WINDIVERT_LAYER_NETWORK, 0, 0); if (handle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_INVALID_PARAMETER) { fprintf(stderr, "error: filter syntax error\n"); exit(EXIT_FAILURE); } fprintf(stderr, "error: failed to open the WinDivert device (%d)\n", GetLastError()); exit(EXIT_FAILURE); } // Start the threads for (i = 1; i < num_threads; i++) { thread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)passthru, (LPVOID)handle, 0, NULL); if (thread == NULL) { fprintf(stderr, "error: failed to start passthru thread (%u)\n", GetLastError()); exit(EXIT_FAILURE); } } // Main thread: passthru((LPVOID)handle); return 0; }
/* * Entry. */ int __cdecl main(int argc, char **argv) { HANDLE handle, console; UINT i; INT16 priority = 0; unsigned char packet[MAXBUF]; UINT packet_len; WINDIVERT_ADDRESS addr; PWINDIVERT_IPHDR ip_header; PWINDIVERT_IPV6HDR ipv6_header; PWINDIVERT_ICMPHDR icmp_header; PWINDIVERT_ICMPV6HDR icmpv6_header; PWINDIVERT_TCPHDR tcp_header; PWINDIVERT_UDPHDR udp_header; // Check arguments. switch (argc) { case 2: break; case 3: priority = (INT16)atoi(argv[2]); break; default: fprintf(stderr, "usage: %s windivert-filter [priority]\n", argv[0]); fprintf(stderr, "examples:\n"); fprintf(stderr, "\t%s true\n", argv[0]); fprintf(stderr, "\t%s \"outbound and tcp.DstPort == 80\" 1000\n", argv[0]); fprintf(stderr, "\t%s \"inbound and tcp.Syn\" -4000\n", argv[0]); exit(EXIT_FAILURE); } // Get console for pretty colors. console = GetStdHandle(STD_OUTPUT_HANDLE); // Divert traffic matching the filter: handle = WinDivertOpen(argv[1], WINDIVERT_LAYER_NETWORK, priority, WINDIVERT_FLAG_SNIFF); if (handle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_INVALID_PARAMETER) { fprintf(stderr, "error: filter syntax error\n"); exit(EXIT_FAILURE); } fprintf(stderr, "error: failed to open the WinDivert device (%d)\n", GetLastError()); exit(EXIT_FAILURE); } // Max-out the packet queue: if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_LEN, 8192)) { fprintf(stderr, "error: failed to set packet queue length (%d)\n", GetLastError()); exit(EXIT_FAILURE); } if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_TIME, 2048)) { fprintf(stderr, "error: failed to set packet queue time (%d)\n", GetLastError()); exit(EXIT_FAILURE); } // Main loop: while (TRUE) { // Read a matching packet. if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len)) { fprintf(stderr, "warning: failed to read packet (%d)\n", GetLastError()); continue; } // Print info about the matching packet. WinDivertHelperParsePacket(packet, packet_len, &ip_header, &ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, NULL); if (ip_header == NULL && ipv6_header == NULL) { fprintf(stderr, "warning: junk packet\n"); } // Dump packet info: putchar('\n'); SetConsoleTextAttribute(console, FOREGROUND_RED); printf("Packet [Direction=%u IfIdx=%u SubIfIdx=%u]\n", addr.Direction, addr.IfIdx, addr.SubIfIdx); if (ip_header != NULL) { UINT8 *src_addr = (UINT8 *)&ip_header->SrcAddr; UINT8 *dst_addr = (UINT8 *)&ip_header->DstAddr; SetConsoleTextAttribute(console, FOREGROUND_GREEN | FOREGROUND_RED); printf("IPv4 [Version=%u HdrLength=%u TOS=%u Length=%u Id=0x%.4X " "Reserved=%u DF=%u MF=%u FragOff=%u TTL=%u Protocol=%u " "Checksum=0x%.4X SrcAddr=%u.%u.%u.%u DstAddr=%u.%u.%u.%u]\n", ip_header->Version, ip_header->HdrLength, ntohs(ip_header->TOS), ntohs(ip_header->Length), ntohs(ip_header->Id), WINDIVERT_IPHDR_GET_RESERVED(ip_header), WINDIVERT_IPHDR_GET_DF(ip_header), WINDIVERT_IPHDR_GET_MF(ip_header), ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header)), ip_header->TTL, ip_header->Protocol, ntohs(ip_header->Checksum), src_addr[0], src_addr[1], src_addr[2], src_addr[3], dst_addr[0], dst_addr[1], dst_addr[2], dst_addr[3]); } if (ipv6_header != NULL) { UINT16 *src_addr = (UINT16 *)&ipv6_header->SrcAddr; UINT16 *dst_addr = (UINT16 *)&ipv6_header->DstAddr; SetConsoleTextAttribute(console, FOREGROUND_GREEN | FOREGROUND_RED); printf("IPv6 [Version=%u TrafficClass=%u FlowLabel=%u Length=%u " "NextHdr=%u HopLimit=%u SrcAddr=", ipv6_header->Version, WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(ipv6_header), ntohl(WINDIVERT_IPV6HDR_GET_FLOWLABEL(ipv6_header)), ntohs(ipv6_header->Length), ipv6_header->NextHdr, ipv6_header->HopLimit); for (i = 0; i < 8; i++) { printf("%x%c", ntohs(src_addr[i]), (i == 7? ' ': ':')); } fputs("DstAddr=", stdout); for (i = 0; i < 8; i++) { printf("%x", ntohs(dst_addr[i])); if (i != 7) { putchar(':'); } } fputs("]\n", stdout); } if (icmp_header != NULL) { SetConsoleTextAttribute(console, FOREGROUND_RED); printf("ICMP [Type=%u Code=%u Checksum=0x%.4X Body=0x%.8X]\n", icmp_header->Type, icmp_header->Code, ntohs(icmp_header->Checksum), ntohl(icmp_header->Body)); } if (icmpv6_header != NULL) { SetConsoleTextAttribute(console, FOREGROUND_RED); printf("ICMPV6 [Type=%u Code=%u Checksum=0x%.4X Body=0x%.8X]\n", icmpv6_header->Type, icmpv6_header->Code, ntohs(icmpv6_header->Checksum), ntohl(icmpv6_header->Body)); } if (tcp_header != NULL) { SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("TCP [SrcPort=%u DstPort=%u SeqNum=%u AckNum=%u " "HdrLength=%u Reserved1=%u Reserved2=%u Urg=%u Ack=%u " "Psh=%u Rst=%u Syn=%u Fin=%u Window=%u Checksum=0x%.4X " "UrgPtr=%u]\n", ntohs(tcp_header->SrcPort), ntohs(tcp_header->DstPort), ntohl(tcp_header->SeqNum), ntohl(tcp_header->AckNum), tcp_header->HdrLength, tcp_header->Reserved1, tcp_header->Reserved2, tcp_header->Urg, tcp_header->Ack, tcp_header->Psh, tcp_header->Rst, tcp_header->Syn, tcp_header->Fin, ntohs(tcp_header->Window), ntohs(tcp_header->Checksum), ntohs(tcp_header->UrgPtr)); } if (udp_header != NULL) { SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("UDP [SrcPort=%u DstPort=%u Length=%u " "Checksum=0x%.4X]\n", ntohs(udp_header->SrcPort), ntohs(udp_header->DstPort), ntohs(udp_header->Length), ntohs(udp_header->Checksum)); } SetConsoleTextAttribute(console, FOREGROUND_GREEN | FOREGROUND_BLUE); for (i = 0; i < packet_len; i++) { if (i % 20 == 0) { printf("\n\t"); } printf("%.2X", (UINT8)packet[i]); } SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_BLUE); for (i = 0; i < packet_len; i++) { if (i % 40 == 0) { printf("\n\t"); } if (isprint(packet[i])) { putchar(packet[i]); } else { putchar('.'); } } putchar('\n'); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } }
/* * Entry. */ int __cdecl main(int argc, char **argv) { HANDLE handle, console; UINT i; INT16 priority = 0; unsigned char packet[MAXBUF]; UINT packet_len; WINDIVERT_ADDRESS recv_addr, send_addr; PWINDIVERT_IPHDR ip_header; PWINDIVERT_IPV6HDR ipv6_header; PWINDIVERT_ICMPHDR icmp_header; PWINDIVERT_ICMPV6HDR icmpv6_header; PWINDIVERT_TCPHDR tcp_header; PWINDIVERT_UDPHDR udp_header; UINT payload_len; const char *err_str; TCPPACKET reset0; PTCPPACKET reset = &reset0; UINT8 dnr0[sizeof(ICMPPACKET) + 0x0F*sizeof(UINT32) + 8 + 1]; PICMPPACKET dnr = (PICMPPACKET)dnr0; TCPV6PACKET resetv6_0; PTCPV6PACKET resetv6 = &resetv6_0; UINT8 dnrv6_0[sizeof(ICMPV6PACKET) + sizeof(WINDIVERT_IPV6HDR) + sizeof(WINDIVERT_TCPHDR)]; PICMPV6PACKET dnrv6 = (PICMPV6PACKET)dnrv6_0; // Check arguments. switch (argc) { case 2: break; case 3: priority = (INT16)atoi(argv[2]); break; default: fprintf(stderr, "usage: %s windivert-filter [priority]\n", argv[0]); fprintf(stderr, "examples:\n"); fprintf(stderr, "\t%s true\n", argv[0]); fprintf(stderr, "\t%s \"outbound and tcp.DstPort == 80\" 1000\n", argv[0]); fprintf(stderr, "\t%s \"inbound and tcp.Syn\" -400\n", argv[0]); exit(EXIT_FAILURE); } // Initialize all packets. PacketIpTcpInit(reset); reset->tcp.Rst = 1; reset->tcp.Ack = 1; PacketIpIcmpInit(dnr); dnr->icmp.Type = 3; // Destination not reachable. dnr->icmp.Code = 3; // Port not reachable. PacketIpv6TcpInit(resetv6); resetv6->tcp.Rst = 1; resetv6->tcp.Ack = 1; PacketIpv6Icmpv6Init(dnrv6); dnrv6->ipv6.Length = htons(sizeof(WINDIVERT_ICMPV6HDR) + 4 + sizeof(WINDIVERT_IPV6HDR) + sizeof(WINDIVERT_TCPHDR)); dnrv6->icmpv6.Type = 1; // Destination not reachable. dnrv6->icmpv6.Code = 4; // Port not reachable. // Get console for pretty colors. console = GetStdHandle(STD_OUTPUT_HANDLE); // Divert traffic matching the filter: handle = WinDivertOpen(argv[1], WINDIVERT_LAYER_NETWORK, priority, 0); if (handle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_INVALID_PARAMETER && !WinDivertHelperCheckFilter(argv[1], WINDIVERT_LAYER_NETWORK, &err_str, NULL)) { fprintf(stderr, "error: invalid filter \"%s\"\n", err_str); exit(EXIT_FAILURE); } fprintf(stderr, "error: failed to open the WinDivert device (%d)\n", GetLastError()); exit(EXIT_FAILURE); } // Main loop: while (TRUE) { // Read a matching packet. if (!WinDivertRecv(handle, packet, sizeof(packet), &recv_addr, &packet_len)) { fprintf(stderr, "warning: failed to read packet\n"); continue; } // Print info about the matching packet. WinDivertHelperParsePacket(packet, packet_len, &ip_header, &ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, &payload_len); if (ip_header == NULL && ipv6_header == NULL) { continue; } // Dump packet info: SetConsoleTextAttribute(console, FOREGROUND_RED); fputs("BLOCK ", stdout); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); if (ip_header != NULL) { UINT8 *src_addr = (UINT8 *)&ip_header->SrcAddr; UINT8 *dst_addr = (UINT8 *)&ip_header->DstAddr; printf("ip.SrcAddr=%u.%u.%u.%u ip.DstAddr=%u.%u.%u.%u ", src_addr[0], src_addr[1], src_addr[2], src_addr[3], dst_addr[0], dst_addr[1], dst_addr[2], dst_addr[3]); } if (ipv6_header != NULL) { UINT16 *src_addr = (UINT16 *)&ipv6_header->SrcAddr; UINT16 *dst_addr = (UINT16 *)&ipv6_header->DstAddr; fputs("ipv6.SrcAddr=", stdout); for (i = 0; i < 8; i++) { printf("%x%c", ntohs(src_addr[i]), (i == 7? ' ': ':')); } fputs(" ipv6.DstAddr=", stdout); for (i = 0; i < 8; i++) { printf("%x%c", ntohs(dst_addr[i]), (i == 7? ' ': ':')); } putchar(' '); } if (icmp_header != NULL) { printf("icmp.Type=%u icmp.Code=%u ", icmp_header->Type, icmp_header->Code); // Simply drop ICMP } if (icmpv6_header != NULL) { printf("icmpv6.Type=%u icmpv6.Code=%u ", icmpv6_header->Type, icmpv6_header->Code); // Simply drop ICMPv6 } if (tcp_header != NULL) { printf("tcp.SrcPort=%u tcp.DstPort=%u tcp.Flags=", ntohs(tcp_header->SrcPort), ntohs(tcp_header->DstPort)); if (tcp_header->Fin) { fputs("[FIN]", stdout); } if (tcp_header->Rst) { fputs("[RST]", stdout); } if (tcp_header->Urg) { fputs("[URG]", stdout); } if (tcp_header->Syn) { fputs("[SYN]", stdout); } if (tcp_header->Psh) { fputs("[PSH]", stdout); } if (tcp_header->Ack) { fputs("[ACK]", stdout); } putchar(' '); if (ip_header != NULL && !tcp_header->Rst && !tcp_header->Fin) { reset->ip.SrcAddr = ip_header->DstAddr; reset->ip.DstAddr = ip_header->SrcAddr; reset->tcp.SrcPort = tcp_header->DstPort; reset->tcp.DstPort = tcp_header->SrcPort; reset->tcp.SeqNum = (tcp_header->Ack? tcp_header->AckNum: 0); reset->tcp.AckNum = (tcp_header->Syn? htonl(ntohl(tcp_header->SeqNum) + 1): htonl(ntohl(tcp_header->SeqNum) + payload_len)); WinDivertHelperCalcChecksums((PVOID)reset, sizeof(TCPPACKET), 0); memcpy(&send_addr, &recv_addr, sizeof(send_addr)); send_addr.Direction = !recv_addr.Direction; if (!WinDivertSend(handle, (PVOID)reset, sizeof(TCPPACKET), &send_addr, NULL)) { fprintf(stderr, "warning: failed to send TCP reset (%d)\n", GetLastError()); } } if (ipv6_header != NULL && !tcp_header->Rst && !tcp_header->Fin) { memcpy(resetv6->ipv6.SrcAddr, ipv6_header->DstAddr, sizeof(resetv6->ipv6.SrcAddr)); memcpy(resetv6->ipv6.DstAddr, ipv6_header->SrcAddr, sizeof(resetv6->ipv6.DstAddr)); resetv6->tcp.SrcPort = tcp_header->DstPort; resetv6->tcp.DstPort = tcp_header->SrcPort; resetv6->tcp.SeqNum = (tcp_header->Ack? tcp_header->AckNum: 0); resetv6->tcp.AckNum = (tcp_header->Syn? htonl(ntohl(tcp_header->SeqNum) + 1): htonl(ntohl(tcp_header->SeqNum) + payload_len)); WinDivertHelperCalcChecksums((PVOID)resetv6, sizeof(TCPV6PACKET), 0); memcpy(&send_addr, &recv_addr, sizeof(send_addr)); send_addr.Direction = !recv_addr.Direction; if (!WinDivertSend(handle, (PVOID)resetv6, sizeof(TCPV6PACKET), &send_addr, NULL)) { fprintf(stderr, "warning: failed to send TCP (IPV6) " "reset (%d)\n", GetLastError()); } } } if (udp_header != NULL) { printf("udp.SrcPort=%u udp.DstPort=%u ", ntohs(udp_header->SrcPort), ntohs(udp_header->DstPort)); if (ip_header != NULL) { UINT icmp_length = ip_header->HdrLength*sizeof(UINT32) + 8; memcpy(dnr->data, ip_header, icmp_length); icmp_length += sizeof(ICMPPACKET); dnr->ip.Length = htons((UINT16)icmp_length); dnr->ip.SrcAddr = ip_header->DstAddr; dnr->ip.DstAddr = ip_header->SrcAddr; WinDivertHelperCalcChecksums((PVOID)dnr, icmp_length, 0); memcpy(&send_addr, &recv_addr, sizeof(send_addr)); send_addr.Direction = !recv_addr.Direction; if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, &send_addr, NULL)) { fprintf(stderr, "warning: failed to send ICMP message " "(%d)\n", GetLastError()); } } if (ipv6_header != NULL) { UINT icmpv6_length = sizeof(WINDIVERT_IPV6HDR) + sizeof(WINDIVERT_TCPHDR); memcpy(dnrv6->data, ipv6_header, icmpv6_length); icmpv6_length += sizeof(ICMPV6PACKET); memcpy(dnrv6->ipv6.SrcAddr, ipv6_header->DstAddr, sizeof(dnrv6->ipv6.SrcAddr)); memcpy(dnrv6->ipv6.DstAddr, ipv6_header->SrcAddr, sizeof(dnrv6->ipv6.DstAddr)); WinDivertHelperCalcChecksums((PVOID)dnrv6, icmpv6_length, 0); memcpy(&send_addr, &recv_addr, sizeof(send_addr)); send_addr.Direction = !recv_addr.Direction; if (!WinDivertSend(handle, (PVOID)dnrv6, icmpv6_length, &send_addr, NULL)) { fprintf(stderr, "warning: failed to send ICMPv6 message " "(%d)\n", GetLastError()); } } } putchar('\n'); } }
/* * Run a test case. */ static BOOL run_test(HANDLE inject_handle, const char *filter, const char *packet, const size_t packet_len, BOOL match) { char buf[MAX_PACKET]; UINT buf_len, i; DWORD iolen; WINDIVERT_ADDRESS addr; OVERLAPPED overlapped; const char *err_str; UINT err_pos; HANDLE handle = INVALID_HANDLE_VALUE, handle0 = INVALID_HANDLE_VALUE, event = NULL; // (0) Verify the test data: if (!WinDivertHelperCheckFilter(filter, WINDIVERT_LAYER_NETWORK, &err_str, &err_pos)) { fprintf(stderr, "error: filter string \"%s\" is invalid with error " "\"%s\" (position=%u)\n", filter, err_str, err_pos); goto failed; } memset(&addr, 0, sizeof(addr)); addr.Direction = WINDIVERT_DIRECTION_OUTBOUND; if (WinDivertHelperEvalFilter(filter, WINDIVERT_LAYER_NETWORK, (PVOID)packet, packet_len, &addr) != match) { fprintf(stderr, "error: filter \"%s\" does not match the given " "packet\n", filter); goto failed; } // (1) Open a WinDivert handle to the given filter: handle = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, 0, 0); if (handle == INVALID_HANDLE_VALUE) { fprintf(stderr, "error: failed to open WinDivert handle for filter " "\"%s\" (err = %d)\n", filter, GetLastError()); goto failed; } if (!match) { // Catch non-matching packets: handle0 = handle; handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 33, 0); if (handle == INVALID_HANDLE_VALUE) { fprintf(stderr, "error: failed to open WinDivert handle " "(err = %d)\n", GetLastError()); goto failed; } } // (2) Inject the packet: if (!WinDivertSend(inject_handle, (PVOID)packet, packet_len, &addr, NULL)) { fprintf(stderr, "error: failed to inject test packet (err = %d)\n", GetLastError()); goto failed; } // (3) Wait for the packet to arrive. // NOTE: This may fail, so set a generous time-out of 250ms. memset(&overlapped, 0, sizeof(overlapped)); event = CreateEvent(NULL, FALSE, FALSE, NULL); if (event == NULL) { fprintf(stderr, "error: failed to create event (err = %d)\n", GetLastError()); goto failed; } overlapped.hEvent = event; if (!WinDivertRecvEx(handle, buf, sizeof(buf), 0, &addr, &buf_len, &overlapped)) { if (GetLastError() != ERROR_IO_PENDING) { read_failed: fprintf(stderr, "error: failed to read packet from WinDivert " "handle (err = %d)\n", GetLastError()); goto failed; } switch (WaitForSingleObject(event, 250)) { case WAIT_OBJECT_0: break; case WAIT_TIMEOUT: fprintf(stderr, "error: failed to read packet from WinDivert " "handle (timeout)\n", GetLastError()); goto failed; default: goto read_failed; } if (!GetOverlappedResult(handle, &overlapped, &iolen, TRUE)) { fprintf(stderr, "error: failed to get the overlapped result from " "WinDivert handle (err = %d)\n", GetLastError()); goto failed; } buf_len = (UINT)iolen; } if (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND) { WinDivertHelperCalcChecksums(buf, buf_len, 0); } // (4) Verify that the packet is the same. if (buf_len != packet_len) { fprintf(stderr, "error: packet length mis-match, expected (%u), got " "(%u)\n", packet_len, buf_len); goto failed; } for (i = 0; i < packet_len; i++) { if (packet[i] != buf[i]) { fprintf(stderr, "error: packet data mis-match, expected byte #%u " "to be (0x%.2X), got (0x%.2X)\n", i, (unsigned char)packet[i], (unsigned char)buf[i]); for (i = 0; i < packet_len; i++) { printf("%c", (packet[i] == buf[i]? '.': 'X')); } putchar('\n'); goto failed; } } // (5) Clean-up: if (!WinDivertClose(handle)) { handle = INVALID_HANDLE_VALUE; fprintf(stderr, "error: failed to close WinDivert handle (err = %d)\n", GetLastError()); goto failed; } if (handle0 != INVALID_HANDLE_VALUE) { if (!WinDivertClose(handle0)) { handle0 = INVALID_HANDLE_VALUE; fprintf(stderr, "error: failed to close WinDivert handle " "(err = %d)\n", GetLastError()); goto failed; } } CloseHandle(event); return TRUE; failed: if (handle0 != INVALID_HANDLE_VALUE) { WinDivertClose(handle0); } if (handle != INVALID_HANDLE_VALUE) { WinDivertClose(handle); } if (event != NULL) { CloseHandle(event); } return FALSE; }
/* * Main. */ int main(void) { HANDLE upper_handle, lower_handle; HANDLE console; size_t i; // Open handles to: // (1) stop normal traffic from interacting with the tests; and // (2) stop test packets escaping to the Internet or TCP/IP stack. upper_handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, -510, WINDIVERT_FLAG_DROP); lower_handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 510, WINDIVERT_FLAG_DROP); if (upper_handle == INVALID_HANDLE_VALUE || lower_handle == INVALID_HANDLE_VALUE) { fprintf(stderr, "error: failed to open WinDivert handle (err = %d)", GetLastError()); exit(EXIT_FAILURE); } console = GetStdHandle(STD_OUTPUT_HANDLE); // Wait for existing packets to flush: Sleep(100); // Run tests: size_t num_tests = sizeof(tests) / sizeof(struct test); for (i = 0; i < num_tests; i++) { char *filter = tests[i].filter; char *packet = tests[i].packet->packet; size_t packet_len = tests[i].packet->packet_len; char *name = tests[i].packet->name; BOOL match = tests[i].match; // Ensure the correct checksum: WinDivertHelperCalcChecksums(packet, packet_len, 0); // Run the test: BOOL res = run_test(upper_handle, filter, packet, packet_len, match); printf("%.2u ", i); if (res) { SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("PASSED"); } else { SetConsoleTextAttribute(console, FOREGROUND_RED); printf("FAILED"); } SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf(" p=["); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("%s", name); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf("] f=["); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("%s", filter); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf("]\n"); } WinDivertClose(upper_handle); WinDivertClose(lower_handle); return 0; }
/* * Entry. */ int __cdecl main(int argc, char **argv) { HANDLE handle, process, console; INT16 priority = 1121; // Arbitrary. const char *filter = "true", *err_str; char path[MAX_PATH+1]; char local_str[INET6_ADDRSTRLEN+1], remote_str[INET6_ADDRSTRLEN+1]; char *filename; DWORD path_len; WINDIVERT_ADDRESS addr; BOOL block = FALSE; switch (argc) { case 1: break; case 2: if (strcmp(argv[1], "--block") == 0) { block = TRUE; } else { filter = argv[1]; } break; case 3: if (strcmp(argv[1], "--block") == 0) { block = TRUE; filter = argv[2]; break; } // Fallthrough: default: fprintf(stderr, "usage: %s [filter]\n", argv[0]); fprintf(stderr, " %s --block [filter]\n", argv[0]); exit(EXIT_FAILURE); } // Open WinDivert SOCKET handle: handle = WinDivertOpen(filter, WINDIVERT_LAYER_SOCKET, priority, (block? 0: WINDIVERT_FLAG_SNIFF) | WINDIVERT_FLAG_RECV_ONLY); if (handle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_INVALID_PARAMETER && !WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_SOCKET, NULL, 0, &err_str, NULL)) { fprintf(stderr, "error: invalid filter \"%s\"\n", err_str); exit(EXIT_FAILURE); } fprintf(stderr, "error: failed to open the WinDivert device (%d)\n", GetLastError()); return EXIT_FAILURE; } // Main loop: console = GetStdHandle(STD_OUTPUT_HANDLE); while (TRUE) { if (!WinDivertRecv(handle, NULL, 0, NULL, &addr)) { fprintf(stderr, "failed to read packet (%d)\n", GetLastError()); continue; } switch (addr.Event) { case WINDIVERT_EVENT_SOCKET_BIND: SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("BIND"); break; case WINDIVERT_EVENT_SOCKET_LISTEN: SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("LISTEN"); break; case WINDIVERT_EVENT_SOCKET_CONNECT: SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("CONNECT"); break; case WINDIVERT_EVENT_SOCKET_ACCEPT: SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("ACCEPT"); break; case WINDIVERT_EVENT_SOCKET_CLOSE: SetConsoleTextAttribute(console, FOREGROUND_RED); printf("CLOSE"); break; default: SetConsoleTextAttribute(console, FOREGROUND_BLUE); printf("???"); break; } SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf(" pid="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("%u", addr.Socket.ProcessId); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf(" program="); process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, addr.Socket.ProcessId); path_len = 0; if (process != NULL) { path_len = GetProcessImageFileName(process, path, sizeof(path)); CloseHandle(process); } SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); if (path_len != 0) { filename = PathFindFileName(path); printf("%s", filename); } else if (addr.Socket.ProcessId == 4) { printf("Windows"); } else { printf("???"); } SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf(" endpoint="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("%lu", addr.Socket.EndpointId); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf(" parent="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("%lu", addr.Socket.ParentEndpointId); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf(" protocol="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); switch (addr.Socket.Protocol) { case IPPROTO_TCP: printf("TCP"); break; case IPPROTO_UDP: printf("UDP"); break; case IPPROTO_ICMP: printf("ICMP"); break; case IPPROTO_ICMPV6: printf("ICMPV6"); break; default: printf("%u", addr.Socket.Protocol); break; } SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); WinDivertHelperFormatIPv6Address(addr.Socket.LocalAddr, local_str, sizeof(local_str)); if (addr.Socket.LocalPort != 0 || strcmp(local_str, "::") != 0) { printf(" local="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("[%s]:%u", local_str, addr.Socket.LocalPort); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } WinDivertHelperFormatIPv6Address(addr.Socket.RemoteAddr, remote_str, sizeof(remote_str)); if (addr.Socket.RemotePort != 0 || strcmp(remote_str, "::") != 0) { printf(" remote="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); printf("[%s]:%u", remote_str, addr.Socket.RemotePort); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } putchar('\n'); } return 0; }