mirror of
https://github.com/ValdikSS/GoodbyeDPI.git
synced 2025-12-17 21:04:36 +03:00
Compare commits
7 Commits
EgorWeders
...
0.2.3rc3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a0bef08bf | ||
|
|
cb9cc82fde | ||
|
|
c2784dd79e | ||
|
|
bc95b6f598 | ||
|
|
985a09c73d | ||
|
|
15793fb84f | ||
|
|
f0d42129aa |
@@ -64,6 +64,13 @@ Usage: goodbyedpi.exe [OPTION...]
|
||||
--reverse-frag fragment (split) the packets just as --native-frag, but send them in the
|
||||
reversed order. Works with the websites which could not handle segmented
|
||||
HTTPS TLS ClientHello (because they receive the TCP flow "combined").
|
||||
--fake-from-hex <value> Load fake packets for Fake Request Mode from HEX values (like 1234abcDEF).
|
||||
This option can be supplied multiple times, in this case each fake packet
|
||||
would be sent on every request in the command line argument order.
|
||||
--fake-gen <value> Generate random-filled fake packets for Fake Request Mode, value of them
|
||||
(up to 30).
|
||||
--fake-resend <value> Send each fake packet value number of times.
|
||||
Default: 1 (send each packet once).
|
||||
--max-payload [value] packets with TCP payload data more than [value] won't be processed.
|
||||
Use this option to reduce CPU usage by skipping huge amount of data
|
||||
(like file transfers) in already established sessions.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#define _CRT_RAND_S
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <in6addr.h>
|
||||
@@ -7,6 +9,15 @@
|
||||
#include "windivert.h"
|
||||
#include "goodbyedpi.h"
|
||||
|
||||
struct fake_t {
|
||||
const unsigned char* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static struct fake_t *fakes[30] = {0};
|
||||
int fakes_count = 0;
|
||||
int fakes_resend = 1;
|
||||
|
||||
static const unsigned char fake_http_request[] = "GET / HTTP/1.1\r\nHost: www.w3.org\r\n"
|
||||
"User-Agent: curl/7.65.3\r\nAccept: */*\r\n"
|
||||
"Accept-Encoding: deflate, gzip, br\r\n\r\n";
|
||||
@@ -54,7 +65,8 @@ static int send_fake_data(const HANDLE w_filter,
|
||||
const BOOL is_https,
|
||||
const BYTE set_ttl,
|
||||
const BYTE set_checksum,
|
||||
const BYTE set_seq
|
||||
const BYTE set_seq,
|
||||
const struct fake_t *fake_data
|
||||
) {
|
||||
char packet_fake[MAX_PACKET_SIZE];
|
||||
WINDIVERT_ADDRESS addr_new;
|
||||
@@ -66,6 +78,10 @@ static int send_fake_data(const HANDLE w_filter,
|
||||
PWINDIVERT_TCPHDR ppTcpHdr;
|
||||
unsigned const char *fake_request_data = is_https ? fake_https_request : fake_http_request;
|
||||
UINT fake_request_size = is_https ? sizeof(fake_https_request) : sizeof(fake_http_request) - 1;
|
||||
if (fake_data) {
|
||||
fake_request_data = fake_data->data;
|
||||
fake_request_size = fake_data->size;
|
||||
}
|
||||
|
||||
memcpy(&addr_new, addr, sizeof(WINDIVERT_ADDRESS));
|
||||
memcpy(packet_fake, pkt, packetLen);
|
||||
@@ -148,22 +164,26 @@ static int send_fake_request(const HANDLE w_filter,
|
||||
const BOOL is_https,
|
||||
const BYTE set_ttl,
|
||||
const BYTE set_checksum,
|
||||
const BYTE set_seq
|
||||
const BYTE set_seq,
|
||||
const struct fake_t *fake_data
|
||||
) {
|
||||
if (set_ttl) {
|
||||
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||
is_ipv6, is_https,
|
||||
set_ttl, FALSE, FALSE);
|
||||
set_ttl, FALSE, FALSE,
|
||||
fake_data);
|
||||
}
|
||||
if (set_checksum) {
|
||||
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||
is_ipv6, is_https,
|
||||
FALSE, set_checksum, FALSE);
|
||||
FALSE, set_checksum, FALSE,
|
||||
fake_data);
|
||||
}
|
||||
if (set_seq) {
|
||||
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||
is_ipv6, is_https,
|
||||
FALSE, FALSE, set_seq);
|
||||
FALSE, FALSE, set_seq,
|
||||
fake_data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -177,9 +197,18 @@ int send_fake_http_request(const HANDLE w_filter,
|
||||
const BYTE set_checksum,
|
||||
const BYTE set_seq
|
||||
) {
|
||||
return send_fake_request(w_filter, addr, pkt, packetLen,
|
||||
is_ipv6, FALSE,
|
||||
set_ttl, set_checksum, set_seq);
|
||||
int ret = 0;
|
||||
for (int i=0; i<fakes_count || i == 0; i++) {
|
||||
for (int j=0; j<fakes_resend; j++)
|
||||
if (send_fake_request(w_filter, addr, pkt, packetLen,
|
||||
is_ipv6, FALSE,
|
||||
set_ttl, set_checksum, set_seq,
|
||||
fakes[i]))
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int send_fake_https_request(const HANDLE w_filter,
|
||||
@@ -191,7 +220,94 @@ int send_fake_https_request(const HANDLE w_filter,
|
||||
const BYTE set_checksum,
|
||||
const BYTE set_seq
|
||||
) {
|
||||
return send_fake_request(w_filter, addr, pkt, packetLen,
|
||||
int ret = 0;
|
||||
for (int i=0; i<fakes_count || i == 0; i++) {
|
||||
for (int j=0; j<fakes_resend; j++)
|
||||
if (send_fake_request(w_filter, addr, pkt, packetLen,
|
||||
is_ipv6, TRUE,
|
||||
set_ttl, set_checksum, set_seq);
|
||||
set_ttl, set_checksum, set_seq,
|
||||
fakes[i]))
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fake_add(const unsigned char *data, size_t size) {
|
||||
struct fake_t *fake = malloc(sizeof(struct fake_t));
|
||||
fake->size = size;
|
||||
fake->data = data;
|
||||
|
||||
for (size_t k = 0; k <= sizeof(fakes) / sizeof(*fakes); k++) {
|
||||
if (!fakes[k]) {
|
||||
fakes[k] = fake;
|
||||
fakes_count++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
int fake_load_from_hex(const char *data) {
|
||||
size_t len = strlen(data);
|
||||
if (len < 2 || len % 2 || len > 1420)
|
||||
return 1;
|
||||
|
||||
unsigned char *finaldata = calloc((len + 2) / 2, 1);
|
||||
|
||||
for (size_t i = 0; i<len - 1; i+=2) {
|
||||
char num1 = data[i];
|
||||
char num2 = data[i+1];
|
||||
debug("Current num1: %X, num2: %X\n", num1, num2);
|
||||
unsigned char finalchar = 0;
|
||||
char curchar = num1;
|
||||
|
||||
for (int j=0; j<=1; j++) {
|
||||
if (curchar >= '0' && curchar <= '9')
|
||||
curchar -= '0';
|
||||
else if (curchar >= 'a' && curchar <= 'f')
|
||||
curchar -= 'a' - 0xA;
|
||||
else if (curchar >= 'A' && curchar <= 'F')
|
||||
curchar -= 'A' - 0xA;
|
||||
else
|
||||
return 2; // incorrect character, not a hex data
|
||||
|
||||
if (!j) {
|
||||
num1 = curchar;
|
||||
curchar = num2;
|
||||
continue;
|
||||
}
|
||||
num2 = curchar;
|
||||
}
|
||||
debug("Processed num1: %X, num2: %X\n", num1, num2);
|
||||
finalchar = (num1 << 4) | num2;
|
||||
debug("Final char: %X\n", finalchar);
|
||||
finaldata[i/2] = finalchar;
|
||||
}
|
||||
|
||||
return fake_add(finaldata, len / 2);
|
||||
}
|
||||
|
||||
int fake_load_random(unsigned int count, unsigned int maxsize) {
|
||||
if (count < 1 || count > sizeof(fakes) / sizeof(*fakes))
|
||||
return 1;
|
||||
|
||||
unsigned int random = 0;
|
||||
|
||||
for (unsigned int i=0; i<count; i++) {
|
||||
unsigned int len = 0;
|
||||
if (rand_s(&len))
|
||||
return 1;
|
||||
len = 8 + (len % maxsize);
|
||||
|
||||
unsigned char *data = calloc(len, 1);
|
||||
for (unsigned int j=0; j<len; j++) {
|
||||
rand_s(&random);
|
||||
data[j] = random % 0xFF;
|
||||
}
|
||||
if (fake_add(data, len))
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
extern int fakes_count;
|
||||
extern int fakes_resend;
|
||||
int send_fake_http_request(const HANDLE w_filter,
|
||||
const PWINDIVERT_ADDRESS addr,
|
||||
const char *pkt,
|
||||
@@ -16,3 +18,5 @@ int send_fake_https_request(const HANDLE w_filter,
|
||||
const BYTE set_checksum,
|
||||
const BYTE set_seq
|
||||
);
|
||||
int fake_load_from_hex(const char *data);
|
||||
int fake_load_random(unsigned int count, unsigned int maxsize);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// My mingw installation does not load inet_pton definition for some reason
|
||||
WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, LPCSTR pStringBuf, PVOID pAddr);
|
||||
|
||||
#define GOODBYEDPI_VERSION "v0.2.3"
|
||||
#define GOODBYEDPI_VERSION "v0.2.3rc3"
|
||||
|
||||
#define die() do { sleep(20); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
@@ -188,6 +188,9 @@ static struct option long_options[] = {
|
||||
{"native-frag", no_argument, 0, '*' },
|
||||
{"reverse-frag",no_argument, 0, '(' },
|
||||
{"max-payload", optional_argument, 0, '|' },
|
||||
{"fake-from-hex", required_argument, 0, 'u' },
|
||||
{"fake-gen", required_argument, 0, 'j' },
|
||||
{"fake-resend", required_argument, 0, 't' },
|
||||
{"debug-exit", optional_argument, 0, 'x' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
@@ -940,6 +943,25 @@ int main(int argc, char *argv[]) {
|
||||
else
|
||||
max_payload_size = 1200;
|
||||
break;
|
||||
case 'u': // --fake-from-hex
|
||||
if (fake_load_from_hex(optarg)) {
|
||||
printf("WARNING: bad fake HEX value %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case 'j': // --fake-gen
|
||||
if (fake_load_random(atoub(optarg, "Fake generator parameter error!"), 200)) {
|
||||
puts("WARNING: fake generator has failed!");
|
||||
}
|
||||
break;
|
||||
case 't': // --fake-resend
|
||||
fakes_resend = atoub(optarg, "Fake resend parameter error!");
|
||||
if (fakes_resend == 1)
|
||||
puts("WARNING: fake-resend is 1, no resending is in place!");
|
||||
else if (!fakes_resend)
|
||||
puts("WARNING: fake-resend is 0, fake packet mode is disabled!");
|
||||
else if (fakes_resend > 100)
|
||||
puts("WARNING: fake-resend value is a little too high, don't you think?");
|
||||
break;
|
||||
case 'x': // --debug-exit
|
||||
debug_exit = true;
|
||||
break;
|
||||
@@ -988,6 +1010,13 @@ int main(int argc, char *argv[]) {
|
||||
" --reverse-frag fragment (split) the packets just as --native-frag, but send them in the\n"
|
||||
" reversed order. Works with the websites which could not handle segmented\n"
|
||||
" HTTPS TLS ClientHello (because they receive the TCP flow \"combined\").\n"
|
||||
" --fake-from-hex <value> Load fake packets for Fake Request Mode from HEX values (like 1234abcDEF).\n"
|
||||
" This option can be supplied multiple times, in this case each fake packet\n"
|
||||
" would be sent on every request in the command line argument order.\n"
|
||||
" --fake-gen <value> Generate random-filled fake packets for Fake Request Mode, value of them\n"
|
||||
" (up to 30).\n"
|
||||
" --fake-resend <value> Send each fake packet value number of times.\n"
|
||||
" Default: 1 (send each packet once).\n"
|
||||
" --max-payload [value] packets with TCP payload data more than [value] won't be processed.\n"
|
||||
" Use this option to reduce CPU usage by skipping huge amount of data\n"
|
||||
" (like file transfers) in already established sessions.\n"
|
||||
@@ -1047,7 +1076,9 @@ int main(int argc, char *argv[]) {
|
||||
"Fake requests, TTL: %s (fixed: %hu, auto: %hu-%hu-%hu, min distance: %hu)\n" /* 17 */
|
||||
"Fake requests, wrong checksum: %d\n" /* 18 */
|
||||
"Fake requests, wrong SEQ/ACK: %d\n" /* 19 */
|
||||
"Max payload size: %hu\n", /* 20 */
|
||||
"Fake requests, custom payloads: %d\n" /* 20 */
|
||||
"Fake requests, resend: %d\n" /* 21 */
|
||||
"Max payload size: %hu\n", /* 22 */
|
||||
do_passivedpi, do_block_quic, /* 1 */
|
||||
(do_fragment_http ? http_fragment_size : 0), /* 2 */
|
||||
(do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */
|
||||
@@ -1069,7 +1100,9 @@ int main(int argc, char *argv[]) {
|
||||
do_auto_ttl ? auto_ttl_max : 0, ttl_min_nhops,
|
||||
do_wrong_chksum, /* 18 */
|
||||
do_wrong_seq, /* 19 */
|
||||
max_payload_size /* 20 */
|
||||
fakes_count, /* 20 */
|
||||
fakes_resend, /* 21 */
|
||||
max_payload_size /* 22 */
|
||||
);
|
||||
|
||||
if (do_fragment_http && http_fragment_size > 2 && !do_native_frag) {
|
||||
|
||||
Reference in New Issue
Block a user