/* * GoodbyeDPI — Passive DPI blocker and Active DPI circumvention utility. */ #include #include #include #include #include #include #include "windivert.h" #define die() do { printf("Something went wrong!\n" \ "Make sure you're running this program with administrator privileges\n"); \ sleep(10); exit(EXIT_FAILURE); } while (0) #define MAX_FILTERS 4 #define MAX_PACKET_SIZE 1516 #define IPV4_HDR_LEN 20 #define TCP_HDR_LEN 20 #define IPV4_TOTALLEN_OFFSET 2 #define TCP_WINDOWSIZE_OFFSET 14 static HANDLE filters[MAX_FILTERS]; static int filter_num = 0; static const char *http_redirect_10 = "HTTP/1.0 30"; static const char *http_redirect_11 = "HTTP/1.1 30"; static const char *http_host_find = "\r\nHost: "; static const char *http_host_replace = "\r\nhoSt: "; static char* dumb_memmem(char* haystack, int hlen, char* needle, int nlen) { // naive implementation if (nlen > hlen) return 0; int i; for (i=0; i 16) { /* If INBOUND packet with DATA (tcp.Ack) */ /* Drop packets from filter with HTTP 30x Redirect */ if (do_passivedpi && find_passivedpi_redirect(packet_data)) { //printf("Dropping HTTP Redirect packet!\n"); should_reinject = 0; } } /* Handle OUTBOUND packet, search for Host header */ else if (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND && packet_dataLen > 16 && ppTcpHdr->DstPort == htons(80)) { if (do_host || do_host_removespace) { data_addr = find_host_header(packet_data, packet_dataLen); } if (do_host && data_addr) { /* Replace "Host: " with "hoSt: " */ memcpy(data_addr, http_host_replace, strlen(http_host_replace)); //printf("Replaced Host header!\n"); } if (do_host_removespace && data_addr) { host_addr = data_addr + strlen(http_host_find); data_addr_rn = dumb_memmem(host_addr, packet_dataLen - ((PVOID)host_addr - packet_data), "\r\n", 2); if (data_addr_rn) { host_len = data_addr_rn - host_addr; fromhost_uptoend_len = packet_dataLen - ((PVOID)host_addr - packet_data); if (host_len <= 64) { /* Move memory left by 1 byte and reduce packet size for 1 byte */ memmove(host_addr - 1, host_addr, fromhost_uptoend_len); /* Reduce "Total Length" in IP header by 1 byte */ *(uint16_t*)(packet + IPV4_TOTALLEN_OFFSET) = ntohs( htons(*(uint16_t*)(packet + IPV4_TOTALLEN_OFFSET)) - 1); /* Reduce packetLen by 1 byte */ packetLen--; //printf("Replaced Host header!\n"); } } } if (do_host || do_host_removespace) { WinDivertHelperCalcChecksums(packet, packetLen, 0); } } } /* Else if we got TCP packet without data */ else if (WinDivertHelperParsePacket(packet, packetLen, &ppIpHdr, NULL, NULL, NULL, &ppTcpHdr, NULL, NULL, NULL)) { /* If we got SYN+ACK packet */ if (addr.Direction == WINDIVERT_DIRECTION_INBOUND && ppTcpHdr->Syn == 1) { if (do_fragment) { //printf("Changing Window Size!\n"); change_window_size(packet); WinDivertHelperCalcChecksums(packet, packetLen, 0); } } } if (should_reinject) { //printf("Re-injecting!\n"); WinDivertSend(w_filter, packet, packetLen, &addr, NULL); } } else { // error, ignore printf("Error receiving packet!\n"); break; } } }