Skip to content

Commit

Permalink
--fake-from-hex option: load Fake Packet from HEX data
Browse files Browse the repository at this point in the history
This option replaces built-in fake packets with the user-supplied
ones, could be used multiple times (up to 30).
Each fake packet loaded with this option is sent in command
line order, every time (on each TLS ClientHello or HTTP GET/POST).
  • Loading branch information
ValdikSS committed Sep 14, 2024
1 parent 83af8cc commit f0d4212
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 10 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ 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.
--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.
Expand Down
109 changes: 99 additions & 10 deletions src/fakepackets.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <unistd.h>
#include <in6addr.h>
#include <ws2tcpip.h>
#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;

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";
Expand Down Expand Up @@ -54,7 +63,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;
Expand All @@ -66,6 +76,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);
Expand Down Expand Up @@ -148,22 +162,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;
}
Expand All @@ -177,9 +195,17 @@ 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++) {
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,
Expand All @@ -191,7 +217,70 @@ 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++) {
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);
}
9 changes: 9 additions & 0 deletions src/goodbyedpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ 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' },
{"debug-exit", optional_argument, 0, 'x' },
{0, 0, 0, 0 }
};
Expand Down Expand Up @@ -940,6 +941,11 @@ 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 'x': // --debug-exit
debug_exit = true;
break;
Expand Down Expand Up @@ -988,6 +994,9 @@ 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"
" --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"
Expand Down

0 comments on commit f0d4212

Please sign in to comment.