diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 4ea3ba6c..2cd0609d 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -6,7 +6,7 @@ body: attributes: value: | ### Carefully read all the text IN FULL. Take this seriously. - ### Use this form only for software bug reports! The webside does not open? That's likely NOT a bug, do NOT report it here! You have a question regarding the program? That's not a bug either! + ### Use this form only for software bug reports! The website does not open? That's likely NOT a bug, do NOT report it here! You have a question regarding the program? That's not a bug either! #### If in doubt, [use NTC.party forum](https://ntc.party/c/community-software/goodbyedpi). ### Внимательно прочитайте ВЕСЬ текст ниже. Отнеситесь к этому со всей ответственностью. ### Используйте эту форму только для сообщений об ошибках в программе! Неоткрывающиеся сайты таковыми не являются, вопросы по программе к ошибкам не относятся. diff --git a/README.md b/README.md index 14fa59f9..6d536250 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,10 @@ Usage: goodbyedpi.exe [OPTION...] --fake-from-hex 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-with-sni Generate fake packets for Fake Request Mode with given SNI domain name. + The packets mimic Mozilla Firefox 130 TLS ClientHello packet + (with random generated fake SessionID, key shares and ECH grease). + Can be supplied multiple times for multiple fake packets. --fake-gen Generate random-filled fake packets for Fake Request Mode, value of them (up to 30). --fake-resend Send each fake packet value number of times. @@ -149,6 +153,7 @@ Modify them according to your own needs. * Horribly outdated Windows 7 installations are not able to load WinDivert driver due to missing support for SHA256 digital signatures. Install KB3033929 [x86](https://www.microsoft.com/en-us/download/details.aspx?id=46078)/[x64](https://www.microsoft.com/en-us/download/details.aspx?id=46148), or better, update the whole system using Windows Update. * Intel/Qualcomm Killer network cards: `Advanced Stream Detect` in Killer Control Center is incompatible with GoodbyeDPI, [disable it](https://github.com/ValdikSS/GoodbyeDPI/issues/541#issuecomment-2296038239). +* QUIC trading software [may interfere with GoodbyeDPI](https://github.com/ValdikSS/GoodbyeDPI/issues/677#issuecomment-2390595606). First start QUIC, then GoodbyeDPI. * ~~Some SSL/TLS stacks unable to process fragmented ClientHello packets, and HTTPS websites won't open. Bug: [#4](https://github.com/ValdikSS/GoodbyeDPI/issues/4), [#64](https://github.com/ValdikSS/GoodbyeDPI/issues/64).~~ Fragmentation issues are fixed in v0.1.7. * ~~ESET Antivirus is incompatible with WinDivert driver [#91](https://github.com/ValdikSS/GoodbyeDPI/issues/91). This is most probably antivirus bug, not WinDivert.~~ diff --git a/src/fakepackets.c b/src/fakepackets.c index 1cf262e1..d4d22549 100644 --- a/src/fakepackets.c +++ b/src/fakepackets.c @@ -57,6 +57,91 @@ static const unsigned char fake_https_request[] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; +// Captured from Firefox 130.0.1 +static const unsigned char fake_clienthello_part0[] = { // 116 bytes + // TLS 1.2 ClientHello header (DD for length placeholder) + 0x16, 0x03, 0x01, 0xDD, 0xDD, 0x01, 0x00, 0xDD, 0xDD, 0x03, 0x03, + // Random bytes (AA for placeholder) + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + // Random Session ID + 0x20, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + // Cipher Suites + 0x00, 0x22, 0x13, 0x01, 0x13, 0x03, 0x13, 0x02, 0xC0, 0x2B, 0xC0, 0x2F, 0xCC, 0xA9, 0xCC, 0xA8, + 0xC0, 0x2C, 0xC0, 0x30, 0xC0, 0x0A, 0xC0, 0x09, 0xC0, 0x13, 0xC0, 0x14, 0x00, 0x9C, 0x00, 0x9D, + 0x00, 0x2F, 0x00, 0x35, + // Compression Methods + 0x01, 0x00, + // Extensions Length + 0xDD, 0xDD, +}; +// SNI: 00 00 L1 L1 L2 L2 00 L3 L3 (sni) +// L1 = L+5, L2 = L+3, L3 = L // 9 + L bytes +static const unsigned char fake_clienthello_part1[] = { // 523 bytes + // extended_master_secret + 0x00, 0x17, 0x00, 0x00, + // renegotiation_info + 0xFF, 0x01, 0x00, 0x01, 0x00, + // supported_groups + 0x00, 0x0A, 0x00, 0x0E, + 0x00, 0x0C, 0x00, 0x1D, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x01, 0x00, 0x01, 0x01, + // ex_point_formats + 0x00, 0x0B, 0x00, 0x02, 0x01, 0x00, + // session_ticket + 0x00, 0x23, 0x00, 0x00, + // ALPN + 0x00, 0x10, 0x00, 0x0E, + 0x00, 0x0C, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2F, 0x31, 0x2E, 0x31, + // status_request + 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, + // delegated_credentials + 0x00, 0x22, 0x00, 0x0A, 0x00, 0x08, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, + // key_share + 0x00, 0x33, 0x00, 0x6B, 0x00, 0x69, 0x00, 0x1D, 0x00, 0x20, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0x00, 0x17, 0x00, 0x41, 0x04, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + // supported_versions + 0x00, 0x2B, 0x00, 0x05, 0x04, 0x03, 0x04, 0x03, 0x03, + // signature_algorithms + 0x00, 0x0D, 0x00, 0x18, 0x00, 0x16, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x08, 0x04, 0x08, 0x05, + 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x03, 0x02, 0x01, + // psk_key_exchange_modes + 0x00, 0x2D, 0x00, 0x02, 0x01, 0x01, + // record_size_limit + 0x00, 0x1C, 0x00, 0x02, 0x40, 0x01, + // encrypted_client_hello + 0xFE, 0x0D, 0x01, 0x19, 0x00, 0x00, 0x01, 0x00, 0x01, 0xAA, 0x00, 0x20, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0x00, 0xEF, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA +}; +// JA4: t13d1715h2_5b57614c22b0_5c2c66f702b0 +// JA4_r: t13d1715h2_002f,0035,009c,009d,1301,1302,1303,c009,c00a,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0017,001c,0022,0023,002b,002d,0033,fe0d,ff01_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201 +// JA3 Fullstring: 771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-34-51-43-13-45-28-65037,29-23-24-25-256-257,0 +// JA3: b5001237acdf006056b409cc433726b0 + static int send_fake_data(const HANDLE w_filter, const PWINDIVERT_ADDRESS addr, const char *pkt, @@ -311,3 +396,46 @@ int fake_load_random(unsigned int count, unsigned int maxsize) { } return 0; } + +void set_uint16be(unsigned char *buffer, int offset, int value) { + buffer[offset] = (value >> 8) & 0xFF; + buffer[offset + 1] = value & 0xFF; +} + +int fake_load_from_sni(const char *domain_name) { + if (!domain_name) { + return 1; // just extra safeguard against NPE + } + // calculate sizes + const int name_size = strlen(domain_name); + const int part0_size = sizeof(fake_clienthello_part0); + const int part1_size = sizeof(fake_clienthello_part1); + const int sni_head_size = 9; + const int packet_size = part0_size + part1_size + sni_head_size + name_size; + // allocate memory + unsigned char *packet = malloc(packet_size); + // copy major parts of packet + memcpy(packet, fake_clienthello_part0, part0_size); + memcpy(&packet[part0_size + sni_head_size + name_size], fake_clienthello_part1, part1_size); + // replace placeholders with random generated values + unsigned int random = 0; + for (int i = 0; i < packet_size; i++) { + if (packet[i] == 0xAA) { + rand_s(&random); + packet[i] = random & 0xFF; + } + } + // write size fields into packet + set_uint16be(packet, 0x0003, packet_size - 5); + set_uint16be(packet, 0x0007, packet_size - 9); + set_uint16be(packet, 0x0072, packet_size - 116); + // write SNI extension + set_uint16be(packet, part0_size + 0, 0x0000); + set_uint16be(packet, part0_size + 2, name_size + 5); + set_uint16be(packet, part0_size + 4, name_size + 3); + packet[part0_size + 6] = 0x00; + set_uint16be(packet, part0_size + 7, name_size); + memcpy(&packet[part0_size + sni_head_size], domain_name, name_size); + // add packet to fakes + return fake_add(packet, packet_size); +} diff --git a/src/fakepackets.h b/src/fakepackets.h index 60de5acc..3bc6de63 100644 --- a/src/fakepackets.h +++ b/src/fakepackets.h @@ -19,4 +19,5 @@ int send_fake_https_request(const HANDLE w_filter, const BYTE set_seq ); int fake_load_from_hex(const char *data); +int fake_load_from_sni(const char *domain_name); int fake_load_random(unsigned int count, unsigned int maxsize); diff --git a/src/goodbyedpi.c b/src/goodbyedpi.c index 9248eb40..b1f4d330 100644 --- a/src/goodbyedpi.c +++ b/src/goodbyedpi.c @@ -189,6 +189,7 @@ static struct option long_options[] = { {"reverse-frag",no_argument, 0, '(' }, {"max-payload", optional_argument, 0, '|' }, {"fake-from-hex", required_argument, 0, 'u' }, + {"fake-with-sni", required_argument, 0, '}' }, {"fake-gen", required_argument, 0, 'j' }, {"fake-resend", required_argument, 0, 't' }, {"debug-exit", optional_argument, 0, 'x' }, @@ -905,6 +906,11 @@ int main(int argc, char *argv[]) { printf("WARNING: bad fake HEX value %s\n", optarg); } break; + case '}': // --fake-with-sni + if (fake_load_from_sni(optarg)) { + printf("WARNING: bad domain name for SNI: %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!"); @@ -970,6 +976,10 @@ int main(int argc, char *argv[]) { " --fake-from-hex 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-with-sni Generate fake packets for Fake Request Mode with given SNI domain name.\n" + " The packets mimic Mozilla Firefox 130 TLS ClientHello packet\n" + " (with random generated fake SessionID, key shares and ECH grease).\n" + " Can be supplied multiple times for multiple fake packets.\n" " --fake-gen Generate random-filled fake packets for Fake Request Mode, value of them\n" " (up to 30).\n" " --fake-resend Send each fake packet value number of times.\n"