From fd81053d79a83fe78579e64f2672c201be4d133c Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 23 Sep 2025 11:52:46 +0300 Subject: [PATCH] nfqws: --dpi-desync-fake-tls=!+offset --- docs/changes.txt | 1 + nfq/desync.c | 20 +++++++++++++++----- nfq/nfqws.c | 22 ++++++++++++++++++---- nfq/pools.h | 1 + 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index b932b877..825567bf 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -547,5 +547,6 @@ v71.5 winws: --wf-raw-part nfqws: --dpi-desync=hostfakesplit nfqws: --dpi-desync-fake-tcp-mod=seq +nfqws: --dpi-desync-fake-tls=!+offset blockcheck: new strategies blockcheck: curl test simulation : SIMULATE=1 diff --git a/nfq/desync.c b/nfq/desync.c index 5f79f63f..06f62550 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -1897,6 +1897,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { struct blob_item *fake_item; + size_t fake_size; uint8_t *fake_data; uint8_t fake_data_buf[FAKE_MAX_TCP]; int n=0; @@ -1920,25 +1921,28 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint default: fake_data = fake_item->data; } + fake_data += fake_item->offset; + fake_size = fake_item->size - fake_item->offset; + pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, htonl(sequence), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - fake_data, fake_item->size, pkt1, &pkt1_len)) + fake_data, fake_size, pkt1, &pkt1_len)) { reasm_orig_cancel(ctrack); goto send_orig; } DLOG("sending fake[%d] seq=+%u : ", n, sequence-sequence0); - hexdump_limited_dlog(fake_data,fake_item->size,PKTDATA_MAXDUMP); DLOG("\n"); + hexdump_limited_dlog(fake_data,fake_size,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) { reasm_orig_cancel(ctrack); goto send_orig; } ip_id=IP4_IP_ID_NEXT(ip_id); - if (dp->tcp_mod.seq) sequence += fake_item->size; + if (dp->tcp_mod.seq) sequence += fake_size; } } bFake = true; @@ -3065,6 +3069,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint case DESYNC_FAKE: if (!reasm_offset) { + size_t fake_size; + uint8_t *fake_data; struct blob_item *fake_item; int n=0; @@ -3073,16 +3079,20 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint LIST_FOREACH(fake_item, fake, next) { n++; + + fake_data=fake_item->data + fake_item->offset; + fake_size=fake_item->size - fake_item->offset; + pkt1_len = sizeof(pkt1); if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF,ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), dp->desync_fooling_mode, NULL, 0, 0, - fake_item->data, fake_item->size, pkt1, &pkt1_len)) + fake_data, fake_size, pkt1, &pkt1_len)) { goto send_orig; } DLOG("sending fake[%d] : ", n); - hexdump_limited_dlog(fake_item->data,fake_item->size,PKTDATA_MAXDUMP); DLOG("\n"); + hexdump_limited_dlog(fake_data,fake_size,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) goto send_orig; ip_id=IP4_IP_ID_NEXT(ip_id); diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 465ac183..d93ca464 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -1423,6 +1423,11 @@ static bool onetime_tls_mod(struct desync_profile *dp) } if (!onetime_tls_mod_blob(dp->n,n,tls_mod,fake_tls->data,&fake_tls->size,fake_tls->size_buf,(struct fake_tls_mod_cache*)fake_tls->extra)) return false; + if (fake_tls->offset >= fake_tls->size) + { + DLOG("profile %d fake[%d] tls mod shrinked data to %zu and offset %zu is now out of data range\n", dp->n, n, fake_tls->size, fake_tls->offset); + return false; + } } return true; } @@ -1740,7 +1745,7 @@ static void exithelp(void) " --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n" " --dpi-desync-fake-tcp-mod=mod[,mod]\t\t; comma separated list of tcp fake mods. available mods : none,seq\n" " --dpi-desync-fake-http=|0xHEX\t; file containing fake http request\n" - " --dpi-desync-fake-tls=|0xHEX|!\t; file containing fake TLS ClientHello (for https)\n" + " --dpi-desync-fake-tls=|0xHEX|![+offset] ; file containing fake TLS ClientHello (for https)\n" " --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=,dupsid,padencap\n" " --dpi-desync-fake-unknown=|0xHEX\t; file containing unknown protocol fake payload\n" " --dpi-desync-fake-syndata=|0xHEX\t; file containing SYN data payload\n" @@ -2761,9 +2766,18 @@ int main(int argc, char **argv) break; case IDX_DPI_DESYNC_FAKE_TLS: { - dp->tls_fake_last = strcmp(optarg,"!") ? - load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->tls_mod_last.sni)) : - load_const_blob_to_collection(fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),&dp->fake_tls,4+sizeof(dp->tls_mod_last.sni)); + if (optarg[0]=='!' && (optarg[1]==0 || optarg[1]=='+')) + { + dp->tls_fake_last = load_const_blob_to_collection(fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),&dp->fake_tls,4+sizeof(dp->tls_mod_last.sni)); + if (optarg[1]=='+') dp->tls_fake_last->offset=atoi(optarg+1); + } + else + dp->tls_fake_last = load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->tls_mod_last.sni)); + if (dp->tls_fake_last->offset >= dp->tls_fake_last->size) + { + DLOG_ERR("offset %zu is out of data range %zu\n",dp->tls_fake_last->offset,dp->tls_fake_last->size); + exit_clean(1); + } if (!(dp->tls_fake_last->extra2 = malloc(sizeof(struct fake_tls_mod)))) { DLOG_ERR("out of memory\n"); diff --git a/nfq/pools.h b/nfq/pools.h index 0590b4ec..6c19d8f8 100644 --- a/nfq/pools.h +++ b/nfq/pools.h @@ -157,6 +157,7 @@ struct blob_item { uint8_t *data; // main data blob size_t size; // main data blob size size_t size_buf;// main data blob allocated size + size_t offset; // optional offset to useful data void *extra; // any data without size void *extra2; // any data without size LIST_ENTRY(blob_item) next;