@ -606,45 +606,48 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
// size does not change
// return : true - altered, false - not altered
static bool runtime_tls_mod ( const struct desync_profile * dp , uint8_t * fake_mod , const uint8_t * payload , size_t payload_len )
static bool runtime_tls_mod ( int fake_n , const struct fake_tls_mod_cache * modcache , uint8_t fake_tls_mod , const uint8_t * fake_data , size_t fake_data_size , const uint8_t * payload , size_t payload_len , uint8_t * fake_mod )
{
bool b = false ;
if ( dp - > fake_tls_mod & FAKE_TLS_MOD_PADENCAP )
if ( IsTLSClientHello ( fake_data , fake_data_size , false ) )
{
size_t sz_rec = pntoh16 ( dp - > fake_tls + 3 ) + payload_len ;
size_t sz_handshake = pntoh24 ( dp - > fake_tls + 6 ) + payload_len ;
size_t sz_ext = pntoh16 ( dp - > fake_tls + dp - > fake_tls_extlen_offset ) + payload_len ;
size_t sz_pad = pntoh16 ( dp - > fake_tls + dp - > fake_tls_padlen_offset ) + payload_len ;
if ( ( sz_rec & ~ 0xFFFF ) | | ( sz_handshake & ~ 0xFFFFFF ) | | ( sz_ext & ~ 0xFFFF ) | | ( sz_pad & ~ 0xFFFF ) )
DLOG ( " cannot apply padencap tls mod. length overflow. \n " ) ;
else
if ( fake_tls_mod & FAKE_TLS_MOD_PADENCAP )
{
size_t sz_rec = pntoh16 ( fake_data + 3 ) + payload_len ;
size_t sz_handshake = pntoh24 ( fake_data + 6 ) + payload_len ;
size_t sz_ext = pntoh16 ( fake_data + modcache - > extlen_offset ) + payload_len ;
size_t sz_pad = pntoh16 ( fake_data + modcache - > padlen_offset ) + payload_len ;
if ( ( sz_rec & ~ 0xFFFF ) | | ( sz_handshake & ~ 0xFFFFFF ) | | ( sz_ext & ~ 0xFFFF ) | | ( sz_pad & ~ 0xFFFF ) )
DLOG ( " fake[%d] cannot apply padencap tls mod. length overflow. \n " , fake_n ) ;
else
{
memcpy ( fake_mod , fake_data , fake_data_size ) ;
phton16 ( fake_mod + 3 , ( uint16_t ) sz_rec ) ;
phton24 ( fake_mod + 6 , ( uint32_t ) sz_handshake ) ;
phton16 ( fake_mod + modcache - > extlen_offset , ( uint16_t ) sz_ext ) ;
phton16 ( fake_mod + modcache - > padlen_offset , ( uint16_t ) sz_pad ) ;
b = true ;
}
}
if ( fake_tls_mod & FAKE_TLS_MOD_RND )
{
memcpy ( fake_mod , dp - > fake_tls , dp - > fake_tls_size ) ;
phton16 ( fake_mod + 3 , ( uint16_t ) sz_rec ) ;
phton24 ( fake_mod + 6 , ( uint32_t ) sz_handshake ) ;
phton16 ( fake_mod + dp - > fake_tls_extlen_offset , ( uint16_t ) sz_ext ) ;
phton16 ( fake_mod + dp - > fake_tls_padlen_offset , ( uint16_t ) sz_pad ) ;
if ( ! b ) memcpy ( fake_mod , fake_data , fake_data_size ) ;
fill_random_bytes ( fake_mod + 11 , 32 ) ; // random
fill_random_bytes ( fake_mod + 44 , fake_mod [ 43 ] ) ; // session id
b = true ;
}
}
if ( dp - > fake_tls_mod & FAKE_TLS_MOD_RND )
{
if ( ! b ) memcpy ( fake_mod , dp - > fake_tls , dp - > fake_tls_size ) ;
fill_random_bytes ( fake_mod + 11 , 32 ) ; // random
fill_random_bytes ( fake_mod + 44 , fake_mod [ 43 ] ) ; // session id
b = true ;
}
if ( dp - > fake_tls_mod & FAKE_TLS_MOD_DUP_SID )
{
if ( dp - > fake_tls [ 43 ] ! = payload [ 43 ] )
DLOG ( " cannot apply dupsid tls mod. fake and orig session id length mismatch. \n " ) ;
else if ( payload_len < ( 44 + payload [ 43 ] ) )
DLOG ( " cannot apply dupsid tls mod. data payload is not valid. \n " ) ;
else
if ( fake_tls_mod & FAKE_TLS_MOD_DUP_SID )
{
if ( ! b ) memcpy ( fake_mod , dp - > fake_tls , dp - > fake_tls_size ) ;
memcpy ( fake_mod + 44 , payload + 44 , fake_mod [ 43 ] ) ; // session id
b = true ;
if ( fake_data [ 43 ] ! = payload [ 43 ] )
DLOG ( " fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch. \n " , fake_n ) ;
else if ( payload_len < ( 44 + payload [ 43 ] ) )
DLOG ( " fake[%d] cannot apply dupsid tls mod. data payload is not valid. \n " , fake_n ) ;
else
{
if ( ! b ) memcpy ( fake_mod , fake_data , fake_data_size ) ;
memcpy ( fake_mod + 44 , payload + 44 , fake_mod [ 43 ] ) ; // session id
b = true ;
}
}
}
return b ;
@ -880,8 +883,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if ( ! ( dis - > tcp - > th_flags & TH_SYN ) & & dis - > len_payload )
{
const uint8_t * fake ;
size_t fake_size ;
struct blob_collection_head * fake ;
char host [ 256 ] ;
bool bHaveHost = false ;
uint8_t * p , * phost = NULL ;
@ -893,7 +896,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
int i ;
uint16_t ip_id ;
t_l7proto l7proto = UNKNOWN ;
uint8_t fake_mod [ sizeof ( dp - > fake_tls ) ] ;
if ( replay )
{
@ -1183,16 +1185,13 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
switch ( l7proto )
{
case HTTP :
fake = dp - > fake_http ;
fake_size = dp - > fake_http_size ;
fake = & dp - > fake_http ;
break ;
case TLS :
fake = runtime_tls_mod ( dp , fake_mod , rdata_payload , rlen_payload ) ? fake_mod : dp - > fake_tls ;
fake_size = dp - > fake_tls_size ;
fake = & dp - > fake_tls ;
break ;
default :
fake = dp - > fake_unknown ;
fake_size = dp - > fake_unknown_size ;
fake = & dp - > fake_unknown ;
break ;
}
if ( dp - > desync_mode = = DESYNC_MULTISPLIT | | dp - > desync_mode = = DESYNC_MULTIDISORDER | | dp - > desync_mode2 = = DESYNC_MULTISPLIT | | dp - > desync_mode2 = = DESYNC_MULTIDISORDER )
@ -1273,13 +1272,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
else
seqovl_pos = 0 ;
// we do not need reasm buffer anymore
reasm_orig_cancel ( ctrack ) ;
rdata_payload = NULL ;
uint32_t fooling_orig = FOOL_NONE ;
bool bFake = false ;
pkt1_len = sizeof ( pkt1 ) ;
switch ( dp - > desync_mode )
{
case DESYNC_FAKE_KNOWN :
@ -1291,28 +1285,69 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
case DESYNC_FAKE :
if ( reasm_offset ) break ;
if ( ! prepare_tcp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst , flags_orig , dis - > tcp - > th_seq , dis - > tcp - > th_ack , dis - > tcp - > th_win , scale_factor , timestamps ,
ttl_fake , IP4_TOS ( dis - > ip ) , IP4_IP_ID_FIX ( dis - > ip ) , IP6_FLOW ( dis - > ip6 ) ,
dp - > desync_fooling_mode , dp - > desync_badseq_increment , dp - > desync_badseq_ack_increment ,
fake , fake_size , pkt1 , & pkt1_len ) )
{
return verdict ;
struct blob_item * fake_item ;
uint8_t * fake_data ;
uint8_t fake_data_buf [ FAKE_MAX_TCP ] ;
int n = 0 ;
ip_id = IP4_IP_ID_FIX ( dis - > ip ) ;
LIST_FOREACH ( fake_item , fake , next )
{
n + + ;
switch ( l7proto )
{
case TLS :
if ( ( fake_item - > size < = sizeof ( fake_data_buf ) ) & &
runtime_tls_mod ( n , ( struct fake_tls_mod_cache * ) fake_item - > extra , dp - > fake_tls_mod , fake_item - > data , fake_item - > size , rdata_payload , rlen_payload , fake_data_buf ) )
{
fake_data = fake_data_buf ;
break ;
}
default :
fake_data = fake_item - > data ;
}
pkt1_len = sizeof ( pkt1 ) ;
if ( ! prepare_tcp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst , flags_orig , dis - > tcp - > th_seq , dis - > tcp - > th_ack , dis - > tcp - > th_win , scale_factor , timestamps ,
ttl_fake , IP4_TOS ( dis - > ip ) , ip_id , IP6_FLOW ( dis - > ip6 ) ,
dp - > desync_fooling_mode , dp - > desync_badseq_increment , dp - > desync_badseq_ack_increment ,
fake_data , fake_item - > size , pkt1 , & pkt1_len ) )
{
reasm_orig_cancel ( ctrack ) ;
return verdict ;
}
DLOG ( " sending fake[%d] : " , n ) ;
hexdump_limited_dlog ( fake_data , fake_item - > size , PKTDATA_MAXDUMP ) ; DLOG ( " \n " ) ;
if ( ! rawsend_rep ( dp - > desync_repeats , ( struct sockaddr * ) & dst , desync_fwmark , ifout , pkt1 , pkt1_len ) )
{
reasm_orig_cancel ( ctrack ) ;
return verdict ;
}
ip_id = IP4_IP_ID_NEXT ( ip_id ) ;
}
}
DLOG ( " sending fake : " ) ;
hexdump_limited_dlog ( fake , fake_size , PKTDATA_MAXDUMP ) ; DLOG ( " \n " ) ;
bFake = true ;
break ;
case DESYNC_RST :
case DESYNC_RSTACK :
if ( reasm_offset ) break ;
pkt1_len = sizeof ( pkt1 ) ;
if ( ! prepare_tcp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst , TH_RST | ( dp - > desync_mode = = DESYNC_RSTACK ? TH_ACK : 0 ) , dis - > tcp - > th_seq , dis - > tcp - > th_ack , dis - > tcp - > th_win , scale_factor , timestamps ,
ttl_fake , IP4_TOS ( dis - > ip ) , IP4_IP_ID_FIX ( dis - > ip ) , IP6_FLOW ( dis - > ip6 ) ,
dp - > desync_fooling_mode , dp - > desync_badseq_increment , dp - > desync_badseq_ack_increment ,
NULL , 0 , pkt1 , & pkt1_len ) )
{
reasm_orig_cancel ( ctrack ) ;
return verdict ;
}
DLOG ( " sending fake RST/RSTACK \n " ) ;
if ( ! rawsend_rep ( dp - > desync_repeats , ( struct sockaddr * ) & dst , desync_fwmark , ifout , pkt1 , pkt1_len ) )
{
reasm_orig_cancel ( ctrack ) ;
return verdict ;
}
bFake = true ;
break ;
case DESYNC_HOPBYHOP :
@ -1323,8 +1358,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
( ! split_pos & & ( dp - > desync_mode2 = = DESYNC_FAKEDSPLIT | | dp - > desync_mode2 = = DESYNC_FAKEDDISORDER ) ) | |
( ! multisplit_count & & ( dp - > desync_mode2 = = DESYNC_MULTISPLIT | | dp - > desync_mode2 = = DESYNC_MULTIDISORDER ) ) ) )
{
reasm_orig_cancel ( ctrack ) ;
pkt1_len = sizeof ( pkt1 ) ;
if ( ! prepare_tcp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst , flags_orig , dis - > tcp - > th_seq , dis - > tcp - > th_ack , dis - > tcp - > th_win , scale_factor , timestamps ,
ttl_orig , IP4_TOS ( dis - > ip ) , IP4_IP_ID_FIX ( dis - > ip ) , IP6_FLOW ( dis - > ip6 ) ,
ttl_orig , 0 , 0 , IP6_FLOW ( dis - > ip6 ) ,
fooling_orig , 0 , 0 ,
dis - > data_payload , dis - > len_payload , pkt1 , & pkt1_len ) )
{
@ -1341,11 +1379,9 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
break ;
}
if ( bFake )
{
if ( ! rawsend_rep ( dp - > desync_repeats , ( struct sockaddr * ) & dst , desync_fwmark , ifout , pkt1 , pkt1_len ) )
return verdict ;
}
// we do not need reasm buffer anymore
reasm_orig_cancel ( ctrack ) ;
rdata_payload = NULL ;
enum dpi_desync_mode desync_mode = dp - > desync_mode2 = = DESYNC_NONE ? dp - > desync_mode : dp - > desync_mode2 ;
switch ( desync_mode )
@ -1875,8 +1911,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if ( dis - > len_payload )
{
const uint8_t * fake ;
size_t fake_size ;
struct blob_collection_head * fake ;
char host [ 256 ] ;
bool bHaveHost = false ;
uint16_t ip_id ;
@ -2110,20 +2145,16 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
switch ( l7proto )
{
case QUIC :
fake = dp - > fake_quic ;
fake_size = dp - > fake_quic_size ;
fake = & dp - > fake_quic ;
break ;
case WIREGUARD :
fake = dp - > fake_wg ;
fake_size = dp - > fake_wg_size ;
fake = & dp - > fake_wg ;
break ;
case DHT :
fake = dp - > fake_dht ;
fake_size = dp - > fake_dht_size ;
fake = & dp - > fake_dht ;
break ;
default :
fake = dp - > fake_unknown_udp ;
fake_size = dp - > fake_unknown_udp_size ;
fake = & dp - > fake_unknown_udp ;
break ;
}
@ -2140,7 +2171,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
}
bool bFake = false ;
pkt1_len = sizeof ( pkt1 ) ;
switch ( dp - > desync_mode )
{
case DESYNC_FAKE_KNOWN :
@ -2150,12 +2180,30 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
break ;
}
case DESYNC_FAKE :
if ( ! prepare_udp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst , ttl_fake , IP4_TOS ( dis - > ip ) , IP4_IP_ID_FIX ( dis - > ip ) , IP6_FLOW ( dis - > ip6 ) , dp - > desync_fooling_mode , NULL , 0 , 0 , fake , fake_size , pkt1 , & pkt1_len ) )
return verdict ;
DLOG ( " sending fake : " ) ;
hexdump_limited_dlog ( fake , fake_size , PKTDATA_MAXDUMP ) ; DLOG ( " \n " ) ;
if ( ! rawsend_rep ( dp - > desync_repeats , ( struct sockaddr * ) & dst , desync_fwmark , ifout , pkt1 , pkt1_len ) )
return verdict ;
{
struct blob_item * fake_item ;
int n = 0 ;
ip_id = IP4_IP_ID_FIX ( dis - > ip ) ;
LIST_FOREACH ( fake_item , fake , next )
{
n + + ;
pkt1_len = sizeof ( pkt1 ) ;
if ( ! prepare_udp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst ,
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 ) )
{
return verdict ;
}
DLOG ( " sending fake[%d] : " , n ) ;
hexdump_limited_dlog ( fake_item - > data , fake_item - > size , PKTDATA_MAXDUMP ) ; DLOG ( " \n " ) ;
if ( ! rawsend_rep ( dp - > desync_repeats , ( struct sockaddr * ) & dst , desync_fwmark , ifout , pkt1 , pkt1_len ) )
return verdict ;
ip_id = IP4_IP_ID_NEXT ( ip_id ) ;
}
}
bFake = true ;
break ;
case DESYNC_HOPBYHOP :
@ -2164,9 +2212,9 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
fooling_orig = ( dp - > desync_mode = = DESYNC_HOPBYHOP ) ? FOOL_HOPBYHOP : ( dp - > desync_mode = = DESYNC_DESTOPT ) ? FOOL_DESTOPT : FOOL_IPFRAG1 ;
if ( dis - > ip6 & & ( dp - > desync_mode2 = = DESYNC_NONE | | ! desync_valid_second_stage_udp ( dp - > desync_mode2 ) ) )
{
pkt1_len = sizeof ( pkt1 ) ;
if ( ! prepare_udp_segment ( ( struct sockaddr * ) & src , ( struct sockaddr * ) & dst ,
ttl_orig , IP4_TOS ( dis - > ip ) , IP4_IP_ID_FIX ( dis - > ip ) , IP6_FLOW ( dis - > ip6 ) ,
fooling_orig , NULL , 0 , 0 ,
ttl_orig , 0 , 0 , IP6_FLOW ( dis - > ip6 ) , fooling_orig , NULL , 0 , 0 ,
dis - > data_payload , dis - > len_payload , pkt1 , & pkt1_len ) )
{
return verdict ;