Browse Source

Add dupip modifier for inserting destination IP into SNI fake packet

pull/2093/head
Semyon Saprykin 5 months ago
parent
commit
431e430548
  1. 62
      nfq/desync.c
  2. 6
      nfq/nfqws.c
  3. 1
      nfq/params.h

62
nfq/desync.c

@ -880,7 +880,7 @@ static uint16_t IP4_IP_ID_ADD(uint16_t ip_id, uint16_t inc, t_ip_id_mode mode)
// fake_mod buffer must at least sizeof(desync_profile->fake_tls) // fake_mod buffer must at least sizeof(desync_profile->fake_tls)
// return : true - altered, false - not altered // return : true - altered, false - not altered
// fake_data_size_out receives the new size if altered // fake_data_size_out receives the new size if altered
static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcache, const struct fake_tls_mod *tls_mod, const uint8_t *fake_data, size_t fake_data_size, size_t fake_mod_buf_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod, size_t *fake_data_size_out) static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcache, const struct fake_tls_mod *tls_mod, const uint8_t *fake_data, size_t fake_data_size, size_t fake_mod_buf_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod, size_t *fake_data_size_out, const struct sockaddr *dst_addr)
{ {
bool b = false; bool b = false;
*fake_data_size_out = fake_data_size; *fake_data_size_out = fake_data_size;
@ -929,11 +929,20 @@ static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcach
DLOG("fake[%d] applied dupsid tls mod\n", fake_n); DLOG("fake[%d] applied dupsid tls mod\n", fake_n);
} }
} }
// Apply altsni - randomly select domain from pool // Apply altsni and/or dupip - randomly select domain from pool or use destination IP
if (tls_mod->mod & FAKE_TLS_MOD_ALTSNI) if (tls_mod->mod & (FAKE_TLS_MOD_ALTSNI | FAKE_TLS_MOD_DUPIP))
{ {
if (!tls_mod->altsni || !tls_mod->altsni->count) bool has_altsni = (tls_mod->mod & FAKE_TLS_MOD_ALTSNI) && tls_mod->altsni && tls_mod->altsni->count;
DLOG("fake[%d] altsni set but no domains loaded\n", fake_n); bool has_dupip = (tls_mod->mod & FAKE_TLS_MOD_DUPIP) && dst_addr;
if (!has_altsni && !has_dupip)
{
if (tls_mod->mod & FAKE_TLS_MOD_ALTSNI)
DLOG("fake[%d] altsni set but no domains loaded\n", fake_n);
if (tls_mod->mod & FAKE_TLS_MOD_DUPIP)
DLOG("fake[%d] dupip set but no destination address\n", fake_n);
}
else else
{ {
const uint8_t *ext; const uint8_t *ext;
@ -943,26 +952,45 @@ static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcach
if (!TLSFindExt(current_data, current_size, 0, &ext, &extlen, false)) if (!TLSFindExt(current_data, current_size, 0, &ext, &extlen, false))
{ {
DLOG("fake[%d] altsni: cannot find SNI extension\n", fake_n); DLOG("fake[%d] altsni/dupip: cannot find SNI extension\n", fake_n);
} }
else else
{ {
size_t sniext_offset = ext - current_data; size_t sniext_offset = ext - current_data;
if (!TLSAdvanceToHostInSNI(&ext, &extlen, &slen)) if (!TLSAdvanceToHostInSNI(&ext, &extlen, &slen))
{ {
DLOG("fake[%d] altsni: invalid SNI structure\n", fake_n); DLOG("fake[%d] altsni/dupip: invalid SNI structure\n", fake_n);
} }
else else
{ {
const char *random_sni = tls_mod->altsni->domains[random() % tls_mod->altsni->count]; // Note: ip_str must remain in scope until memcpy(sni, selected_sni, ...) is called
size_t slen_new = strlen(random_sni); char ip_str[INET6_ADDRSTRLEN];
const char *selected_sni;
// Calculate total options: altsni domains count + 1 if dupip is enabled
size_t total_options = (has_altsni ? tls_mod->altsni->count : 0) + (has_dupip ? 1 : 0);
size_t choice = random() % total_options;
if (has_altsni && choice < tls_mod->altsni->count)
{
// Select from altsni pool
selected_sni = tls_mod->altsni->domains[choice];
}
else
{
// Use destination IP (dupip)
ntop46(dst_addr, ip_str, sizeof(ip_str));
selected_sni = ip_str;
}
size_t slen_new = strlen(selected_sni);
ssize_t slen_delta = (ssize_t)slen_new - (ssize_t)slen; ssize_t slen_delta = (ssize_t)slen_new - (ssize_t)slen;
size_t sni_offset = ext - current_data; size_t sni_offset = ext - current_data;
size_t new_size = (slen_delta >= 0) ? current_size + (size_t)slen_delta : current_size - (size_t)(-slen_delta); size_t new_size = (slen_delta >= 0) ? current_size + (size_t)slen_delta : current_size - (size_t)(-slen_delta);
if (new_size > fake_mod_buf_size) if (new_size > fake_mod_buf_size)
{ {
DLOG("fake[%d] not enough space for altsni (need %zu, have %zu)\n", fake_n, new_size, fake_mod_buf_size); DLOG("fake[%d] not enough space for altsni/dupip (need %zu, have %zu)\n", fake_n, new_size, fake_mod_buf_size);
} }
else else
{ {
@ -974,24 +1002,20 @@ static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcach
if (slen_delta) if (slen_delta)
{ {
memmove(sni + slen_new, sni + slen, fake_mod + current_size - (sni + slen)); memmove(sni + slen_new, sni + slen, fake_mod + current_size - (sni + slen));
// Update TLS record length
phton16(fake_mod + 3, (uint16_t)(pntoh16(fake_mod + 3) + slen_delta)); phton16(fake_mod + 3, (uint16_t)(pntoh16(fake_mod + 3) + slen_delta));
// Update handshake length
phton24(fake_mod + 6, (uint32_t)(pntoh24(fake_mod + 6) + slen_delta)); phton24(fake_mod + 6, (uint32_t)(pntoh24(fake_mod + 6) + slen_delta));
// Update extensions length
if (modcache->extlen_offset) if (modcache->extlen_offset)
phton16(fake_mod + modcache->extlen_offset, (uint16_t)(pntoh16(fake_mod + modcache->extlen_offset) + slen_delta)); phton16(fake_mod + modcache->extlen_offset, (uint16_t)(pntoh16(fake_mod + modcache->extlen_offset) + slen_delta));
// Update SNI extension length (ext type 2 bytes before data)
phton16(sniext - 2, (uint16_t)(pntoh16(sniext - 2) + slen_delta)); phton16(sniext - 2, (uint16_t)(pntoh16(sniext - 2) + slen_delta));
// Update SNI list length
phton16(sniext, (uint16_t)(pntoh16(sniext) + slen_delta)); phton16(sniext, (uint16_t)(pntoh16(sniext) + slen_delta));
// Update hostname length (2 bytes before hostname)
phton16(sni - 2, (uint16_t)(pntoh16(sni - 2) + slen_delta)); phton16(sni - 2, (uint16_t)(pntoh16(sni - 2) + slen_delta));
*fake_data_size_out = new_size; *fake_data_size_out = new_size;
} }
memcpy(sni, random_sni, slen_new); memcpy(sni, selected_sni, slen_new);
b = true; b = true;
DLOG("fake[%d] applied altsni: %s (size_delta=%zd)\n", fake_n, random_sni, slen_delta); DLOG("fake[%d] applied %s: %s (size_delta=%zd)\n", fake_n,
(has_altsni && has_dupip) ? "altsni+dupip" : (has_dupip ? "dupip" : "altsni"),
selected_sni, slen_delta);
} }
} }
} }
@ -2047,7 +2071,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
{ {
case TLS: case TLS:
if ((fake_item->size <= sizeof(fake_data_buf)) && if ((fake_item->size <= sizeof(fake_data_buf)) &&
runtime_tls_mod(n, (struct fake_tls_mod_cache *)fake_item->extra, (struct fake_tls_mod *)fake_item->extra2, fake_item->data, fake_item->size, sizeof(fake_data_buf), rdata_payload, rlen_payload, fake_data_buf, &fake_size_mod)) runtime_tls_mod(n, (struct fake_tls_mod_cache *)fake_item->extra, (struct fake_tls_mod *)fake_item->extra2, fake_item->data, fake_item->size, sizeof(fake_data_buf), rdata_payload, rlen_payload, fake_data_buf, &fake_size_mod, (struct sockaddr *)&dst))
{ {
fake_data = fake_data_buf; fake_data = fake_data_buf;
break; break;

6
nfq/nfqws.c

@ -1233,6 +1233,8 @@ static bool parse_tlsmod_list(char *opt, struct fake_tls_mod *tls_mod)
} }
else if (!strcmp(p, "altsni")) else if (!strcmp(p, "altsni"))
tls_mod->mod |= FAKE_TLS_MOD_ALTSNI; tls_mod->mod |= FAKE_TLS_MOD_ALTSNI;
else if (!strcmp(p, "dupip"))
tls_mod->mod |= FAKE_TLS_MOD_DUPIP;
else if (!strcmp(p, "padencap")) else if (!strcmp(p, "padencap"))
tls_mod->mod |= FAKE_TLS_MOD_PADENCAP; tls_mod->mod |= FAKE_TLS_MOD_PADENCAP;
else if (!strcmp(p, "dupsid")) else if (!strcmp(p, "dupsid"))
@ -1517,7 +1519,7 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
size_t extlen; size_t extlen;
modcache->extlen_offset = modcache->padlen_offset = 0; modcache->extlen_offset = modcache->padlen_offset = 0;
if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_SNI | FAKE_TLS_MOD_ALTSNI | FAKE_TLS_MOD_PADENCAP)) if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_SNI | FAKE_TLS_MOD_ALTSNI | FAKE_TLS_MOD_DUPIP | FAKE_TLS_MOD_PADENCAP))
{ {
if (!TLSFindExtLen(fake_tls, *fake_tls_size, &modcache->extlen_offset)) if (!TLSFindExtLen(fake_tls, *fake_tls_size, &modcache->extlen_offset))
{ {
@ -1525,7 +1527,7 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
return false; return false;
} }
DLOG("profile %d fake[%d] tls extensions length offset : %zu\n", profile_n, fake_n, modcache->extlen_offset); DLOG("profile %d fake[%d] tls extensions length offset : %zu\n", profile_n, fake_n, modcache->extlen_offset);
if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_SNI | FAKE_TLS_MOD_ALTSNI)) if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_SNI | FAKE_TLS_MOD_ALTSNI | FAKE_TLS_MOD_DUPIP))
{ {
size_t slen; size_t slen;
if (!TLSFindExt(fake_tls, *fake_tls_size, 0, &ext, &extlen, false)) if (!TLSFindExt(fake_tls, *fake_tls_size, 0, &ext, &extlen, false))

1
nfq/params.h

@ -63,6 +63,7 @@
#define FAKE_TLS_MOD_SNI 0x80 #define FAKE_TLS_MOD_SNI 0x80
#define FAKE_TLS_MOD_PADENCAP 0x100 #define FAKE_TLS_MOD_PADENCAP 0x100
#define FAKE_TLS_MOD_ALTSNI 0x200 #define FAKE_TLS_MOD_ALTSNI 0x200
#define FAKE_TLS_MOD_DUPIP 0x400
#define FAKE_MAX_TCP 1460 #define FAKE_MAX_TCP 1460
#define FAKE_MAX_UDP 1472 #define FAKE_MAX_UDP 1472

Loading…
Cancel
Save