From 2e23d937624c732340de4da7ae9c11d88d7b0114 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Sun, 21 Jan 2018 14:35:30 +0300 Subject: [PATCH] New option: --ip-id. Handles additional IP ID numbers of passive DPI. --- README.md | 2 ++ goodbyedpi.c | 57 ++++++++++++++++++++++++++++++--- repl_str.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ repl_str.h | 1 + 4 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 repl_str.c create mode 100644 repl_str.h diff --git a/README.md b/README.md index 9fca8df..7f5ec1c 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Usage: goodbyedpi.exe [OPTION...] -a additional space between Method and Request-URI (enables -s, may break sites) -w try to find and parse HTTP traffic on all processed ports (not only on port 80) --port [value] additional TCP port to perform fragmentation on (and HTTP tricks with -w) + --ip-id [value] handle additional IP ID (decimal, drop redirects and TCP RSTs with this ID). + This option can be supplied multiple times. --dns-addr [value] redirect UDP DNS requests to the supplied IP address (experimental) --dns-port [value] redirect UDP DNS requests to the supplied port (53 by default) --dns-verb print verbose DNS redirection messages diff --git a/goodbyedpi.c b/goodbyedpi.c index f99cb69..f940952 100644 --- a/goodbyedpi.c +++ b/goodbyedpi.c @@ -11,6 +11,7 @@ #include #include "windivert.h" #include "goodbyedpi.h" +#include "repl_str.h" #include "service.h" #include "dnsredir.h" #include "blackwhitelist.h" @@ -35,17 +36,20 @@ "(ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255)" \ ")" +/* #IPID# is a template to find&replace */ +#define IPID_TEMPLATE "#IPID#" #define FILTER_STRING_TEMPLATE "(ip and tcp and " \ "(inbound and ((" \ - "((ip.Id <= 0xF and ip.Id >= 0x0) and tcp.SrcPort == 80 and tcp.Ack) or " \ + "(((ip.Id <= 0xF and ip.Id >= 0x0) " IPID_TEMPLATE \ + ") and tcp.SrcPort == 80 and tcp.Ack) or " \ "((tcp.SrcPort == 80 or tcp.SrcPort == 443) and tcp.Ack and tcp.Syn)" \ ") and " DIVERT_NO_LOCALNETS_SRC ") or " \ "(outbound and " \ "(tcp.DstPort == 80 or tcp.DstPort == 443) and tcp.Ack and " \ DIVERT_NO_LOCALNETS_DST ")" \ "))" -#define FILTER_STRING_PASSIVE "inbound and ip and tcp and " \ - "(ip.Id <= 0xF and ip.Id >= 0x0) and " \ +#define FILTER_PASSIVE_STRING_TEMPLATE "inbound and ip and tcp and " \ + "((ip.Id <= 0xF and ip.Id >= 0x0) " IPID_TEMPLATE ") and " \ "(tcp.SrcPort == 443 or tcp.SrcPort == 80) and tcp.Rst and " \ DIVERT_NO_LOCALNETS_SRC @@ -91,10 +95,12 @@ static struct option long_options[] = { {"dns-port", required_argument, 0, 'g' }, {"dns-verb", no_argument, 0, 'v' }, {"blacklist", required_argument, 0, 'b' }, + {"ip-id", required_argument, 0, 'i' }, {0, 0, 0, 0 } }; static char *filter_string = NULL; +static char *filter_passive_string = NULL; static void add_filter_str(int proto, int port) { const char *udp = " or (ip and udp and (udp.SrcPort == %d or udp.DstPort == %d))"; @@ -115,6 +121,34 @@ static void add_filter_str(int proto, int port) { free(current_filter); } +static void add_ip_id_str(int id) { + char *newstr; + const char *ipid = " or ip.Id == %d"; + char *addfilter = malloc(strlen(ipid) + 16); + + sprintf(addfilter, ipid, id); + + newstr = repl_str(filter_string, IPID_TEMPLATE, addfilter); + free(filter_string); + filter_string = newstr; + + newstr = repl_str(filter_passive_string, IPID_TEMPLATE, addfilter); + free(filter_passive_string); + filter_passive_string = newstr; +} + +static void finalize_filter_strings() { + char *newstr; + + newstr = repl_str(filter_string, IPID_TEMPLATE, ""); + free(filter_string); + filter_string = newstr; + + newstr = repl_str(filter_passive_string, IPID_TEMPLATE, ""); + free(filter_passive_string); + filter_passive_string = newstr; +} + static char* dumb_memmem(const char* haystack, int hlen, const char* needle, int nlen) { // naive implementation if (nlen > hlen) return NULL; @@ -312,6 +346,8 @@ int main(int argc, char *argv[]) { if (filter_string == NULL) filter_string = strdup(FILTER_STRING_TEMPLATE); + if (filter_passive_string == NULL) + filter_passive_string = strdup(FILTER_PASSIVE_STRING_TEMPLATE); printf("GoodbyeDPI: Passive DPI blocker and Active DPI circumvention utility\n"); @@ -395,6 +431,16 @@ int main(int argc, char *argv[]) { add_filter_str(IPPROTO_TCP, i); i = 0; break; + case 'i': + /* i is used as a temporary variable here */ + i = atoi(optarg); + if (i < 0 || i > 65535) { + printf("IP ID parameter error!\n"); + exit(EXIT_FAILURE); + } + add_ip_id_str(i); + i = 0; + break; case 'd': if (!do_dns_redirect) { do_dns_redirect = 1; @@ -447,6 +493,8 @@ int main(int argc, char *argv[]) { " -e [value] set HTTPS fragmentation to value\n" " -w try to find and parse HTTP traffic on all processed ports (not only on port 80)\n" " --port [value] additional TCP port to perform fragmentation on (and HTTP tricks with -w)\n" + " --ip-id [value] handle additional IP ID (decimal, drop redirects and TCP RSTs with this ID).\n" + " This option can be supplied multiple times.\n" " --dns-addr [value] redirect UDP DNS requests to the supplied IP address (experimental)\n" " --dns-port [value] redirect UDP DNS requests to the supplied port (53 by default)\n" " --dns-verb print verbose DNS redirection messages\n" @@ -479,12 +527,13 @@ int main(int argc, char *argv[]) { } printf("\nOpening filter\n"); + finalize_filter_strings(); filter_num = 0; if (do_passivedpi) { /* IPv4 filter for inbound RST packets with ID [0x0; 0xF] */ filters[filter_num] = init( - FILTER_STRING_PASSIVE, + filter_passive_string, WINDIVERT_FLAG_DROP); if (filters[filter_num] == NULL) die(); diff --git a/repl_str.c b/repl_str.c new file mode 100644 index 0000000..5e261bc --- /dev/null +++ b/repl_str.c @@ -0,0 +1,90 @@ +#include +#include +#include + +#if (__STDC_VERSION__ >= 199901L) +#include +#endif + +char *repl_str(const char *str, const char *from, const char *to) { + + /* Adjust each of the below values to suit your needs. */ + + /* Increment positions cache size initially by this number. */ + size_t cache_sz_inc = 16; + /* Thereafter, each time capacity needs to be increased, + * multiply the increment by this factor. */ + const size_t cache_sz_inc_factor = 3; + /* But never increment capacity by more than this number. */ + const size_t cache_sz_inc_max = 1048576; + + char *pret, *ret = NULL; + const char *pstr2, *pstr = str; + size_t i, count = 0; + #if (__STDC_VERSION__ >= 199901L) + uintptr_t *pos_cache_tmp, *pos_cache = NULL; + #else + ptrdiff_t *pos_cache_tmp, *pos_cache = NULL; + #endif + size_t cache_sz = 0; + size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from); + + /* Find all matches and cache their positions. */ + while ((pstr2 = strstr(pstr, from)) != NULL) { + count++; + + /* Increase the cache size when necessary. */ + if (cache_sz < count) { + cache_sz += cache_sz_inc; + pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz); + if (pos_cache_tmp == NULL) { + goto end_repl_str; + } else pos_cache = pos_cache_tmp; + cache_sz_inc *= cache_sz_inc_factor; + if (cache_sz_inc > cache_sz_inc_max) { + cache_sz_inc = cache_sz_inc_max; + } + } + + pos_cache[count-1] = pstr2 - str; + pstr = pstr2 + fromlen; + } + + orglen = pstr - str + strlen(pstr); + + /* Allocate memory for the post-replacement string. */ + if (count > 0) { + tolen = strlen(to); + retlen = orglen + (tolen - fromlen) * count; + } else retlen = orglen; + ret = malloc(retlen + 1); + if (ret == NULL) { + goto end_repl_str; + } + + if (count == 0) { + /* If no matches, then just duplicate the string. */ + strcpy(ret, str); + } else { + /* Otherwise, duplicate the string whilst performing + * the replacements using the position cache. */ + pret = ret; + memcpy(pret, str, pos_cache[0]); + pret += pos_cache[0]; + for (i = 0; i < count; i++) { + memcpy(pret, to, tolen); + pret += tolen; + pstr = str + pos_cache[i] + fromlen; + cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen; + memcpy(pret, pstr, cpylen); + pret += cpylen; + } + ret[retlen] = '\0'; + } + +end_repl_str: + /* Free the cache and return the post-replacement string, + * which will be NULL in the event of an error. */ + free(pos_cache); + return ret; +} diff --git a/repl_str.h b/repl_str.h new file mode 100644 index 0000000..ffd28d8 --- /dev/null +++ b/repl_str.h @@ -0,0 +1 @@ +char *repl_str(const char *str, const char *from, const char *to);