aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2023-11-07 17:46:29 +0100
committerGitHub <noreply@github.com>2023-11-07 17:46:29 +0100
commitb539b0d0902bc0fda235d8bbf1bc7f64e9028465 (patch)
treeb4f3e0283cfd2ed757d5721ffb9c6d6862db8597
parent58a9e2d9679f268a64b9082dae70498147bb58a8 (diff)
fuzz: improve coverage and remove dead code (#2135)
We are not able to remove custom rules: remove the empty stubs (which originate from the original OpenDPI code). `ndpi_guess_protocol_id()` is only called on the first packet of the flow, so the bitmask `flow->excluded_protocol_bitmask` is always empty, since we didn't call any dissectors yet. Move another hash function to the dedicated source file.
-rw-r--r--fuzz/fuzz_alg_crc32_md5.c3
-rw-r--r--fuzz/fuzz_ds_hash.cpp2
-rw-r--r--fuzz/fuzz_gcrypt_cipher.cpp42
-rw-r--r--fuzz/fuzz_gcrypt_gcm.cpp10
-rw-r--r--src/lib/ndpi_hash.c27
-rw-r--r--src/lib/ndpi_main.c82
-rw-r--r--src/lib/ndpi_utils.c34
-rw-r--r--tests/cfgs/default/pcap/stun.pcapbin29574 -> 34424 bytes
-rw-r--r--tests/cfgs/default/result/stun.pcap.out18
9 files changed, 84 insertions, 134 deletions
diff --git a/fuzz/fuzz_alg_crc32_md5.c b/fuzz/fuzz_alg_crc32_md5.c
index 1f45e476e..def56566c 100644
--- a/fuzz/fuzz_alg_crc32_md5.c
+++ b/fuzz/fuzz_alg_crc32_md5.c
@@ -15,6 +15,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_murmur_hash((const char *)data, size);
ndpi_quick_hash(data, size);
+ if(size >= 16)
+ ndpi_quick_16_byte_hash(data);
+
str = ndpi_malloc(size + 1);
if(str) {
memcpy(str, data, size);
diff --git a/fuzz/fuzz_ds_hash.cpp b/fuzz/fuzz_ds_hash.cpp
index 5b26d684b..2b7463b49 100644
--- a/fuzz/fuzz_ds_hash.cpp
+++ b/fuzz/fuzz_ds_hash.cpp
@@ -57,6 +57,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_hash_find_entry(h, value_added.data(), value_added.size(), &value);
}
+ if (fuzzed_data.ConsumeBool())
+ ndpi_hash_free(NULL, cleanup_func);
ndpi_hash_free(&h, cleanup_func);
return 0;
diff --git a/fuzz/fuzz_gcrypt_cipher.cpp b/fuzz/fuzz_gcrypt_cipher.cpp
index 7eaffcdc2..270c583ea 100644
--- a/fuzz/fuzz_gcrypt_cipher.cpp
+++ b/fuzz/fuzz_gcrypt_cipher.cpp
@@ -67,28 +67,34 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
rc_e = mbedtls_cipher_setkey(ctx_e, key.data(), key.size() * 8, MBEDTLS_ENCRYPT);
rc_d = mbedtls_cipher_setkey(ctx_d, key.data(), key.size() * 8, MBEDTLS_DECRYPT);
if(rc_e == 0 && rc_d == 0) {
- rc_e = mbedtls_cipher_set_iv(ctx_e, iv.data(), iv.size());
- rc_d = mbedtls_cipher_set_iv(ctx_d, iv.data(), iv.size());
- if(rc_e == 0 && rc_d == 0) {
- mbedtls_cipher_reset(ctx_e);
- mbedtls_cipher_reset(ctx_d);
-
- rc_e = mbedtls_cipher_update(ctx_e, input.data(), input.size(), output, &output_size);
- if(rc_e == 0) {
- rc_e = mbedtls_cipher_finish(ctx_e, NULL, &output_size2);
+
+ if(fuzzed_data.ConsumeBool()) {
+ rc_e = mbedtls_cipher_crypt(ctx_e, iv.data(), iv.size(),
+ input.data(), input.size(), output, &output_size);
+ } else {
+ rc_e = mbedtls_cipher_set_iv(ctx_e, iv.data(), iv.size());
+ rc_d = mbedtls_cipher_set_iv(ctx_d, iv.data(), iv.size());
+ if(rc_e == 0 && rc_d == 0) {
+ mbedtls_cipher_reset(ctx_e);
+ mbedtls_cipher_reset(ctx_d);
+
+ rc_e = mbedtls_cipher_update(ctx_e, input.data(), input.size(), output, &output_size);
if(rc_e == 0) {
+ rc_e = mbedtls_cipher_finish(ctx_e, NULL, &output_size2);
+ if(rc_e == 0) {
- rc_d = mbedtls_cipher_update(ctx_d, output, output_size, decrypted, &decrypted_size);
- if(rc_d == 0) {
- rc_d = mbedtls_cipher_finish(ctx_d, NULL, &output_size2);
- /* TODO: decryption doesn't work with no-aesni data path!
- Note that with MASAN, aesni is always disabled */
+ rc_d = mbedtls_cipher_update(ctx_d, output, output_size, decrypted, &decrypted_size);
+ if(rc_d == 0) {
+ rc_d = mbedtls_cipher_finish(ctx_d, NULL, &output_size2);
+ /* TODO: decryption doesn't work with no-aesni data path!
+ Note that with MASAN, aesni is always disabled */
#if 0
- if(rc_d == 0) {
- assert(input.size() == decrypted_size);
- assert(memcmp(input.data(), decrypted, decrypted_size) == 0);
- }
+ if(rc_d == 0) {
+ assert(input.size() == decrypted_size);
+ assert(memcmp(input.data(), decrypted, decrypted_size) == 0);
+ }
#endif
+ }
}
}
}
diff --git a/fuzz/fuzz_gcrypt_gcm.cpp b/fuzz/fuzz_gcrypt_gcm.cpp
index debead9b4..3e0b85cca 100644
--- a/fuzz/fuzz_gcrypt_gcm.cpp
+++ b/fuzz/fuzz_gcrypt_gcm.cpp
@@ -20,13 +20,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
int key_len, rc_e, rc_d;
mbedtls_cipher_id_t cipher;
unsigned char *tag;
- int iv_len, tag_len, input_length, force_auth_tag_error;
+ int iv_len, tag_len, ad_len, input_length, force_auth_tag_error;
/* No real memory allocations involved */
if(fuzzed_data.remaining_bytes() < 1 + 4 + 512 / 8 +
1 + 64 + /* iv */
1 + /* tag_len */
+ 1 + 17 + /* ad */
1 + 64 + /* input */
1 + /* force_auth_tag_error */
1 /* useless data: to be able to add the check with assert */)
@@ -50,6 +51,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
tag_len = fuzzed_data.ConsumeIntegralInRange(0, 17);
tag = (unsigned char *)malloc(tag_len);
+ ad_len = fuzzed_data.ConsumeIntegralInRange(0, 17);
+ std::vector<u_int8_t>ad = fuzzed_data.ConsumeBytes<uint8_t>(ad_len);
+
input_length = fuzzed_data.ConsumeIntegralInRange(16, 64);
std::vector<unsigned char>input = fuzzed_data.ConsumeBytes<u_int8_t>(input_length);
output = (unsigned char *)malloc(input_length);
@@ -71,7 +75,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
rc_e = mbedtls_gcm_crypt_and_tag(gcm_e_ctx, MBEDTLS_GCM_ENCRYPT,
input.size(),
iv.data(), iv.size(),
- NULL, 0, /* TODO */
+ ad.data(), ad.size(),
input.data(),
output,
tag_len, tag);
@@ -85,7 +89,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
rc_d = mbedtls_gcm_auth_decrypt(gcm_d_ctx,
input.size(),
iv.data(), iv.size(),
- NULL, 0, /* TODO */
+ ad.data(), ad.size(),
tag, tag_len,
output,
decrypted);
diff --git a/src/lib/ndpi_hash.c b/src/lib/ndpi_hash.c
index 567e1d67c..0a3507d76 100644
--- a/src/lib/ndpi_hash.c
+++ b/src/lib/ndpi_hash.c
@@ -125,4 +125,31 @@ u_int32_t ndpi_hash_string_len(const char *str, u_int len) {
return(hash);
}
+/* ******************************************************************** */
+
+#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r))))
+
+/*
+ 'in_16_bytes_long` points to some 16 byte memory data to be hashed;
+ two independent 64-bit linear congruential generators are applied
+ results are mixed, scrambled and cast to 32-bit
+*/
+u_int32_t ndpi_quick_16_byte_hash(u_int8_t *in_16_bytes_long) {
+ u_int64_t a = *(u_int64_t*)(in_16_bytes_long + 0);
+ u_int64_t c = *(u_int64_t*)(in_16_bytes_long + 8);
+ // multipliers are taken from sprng.org, addends are prime
+ a = a * 0x2c6fe96ee78b6955 + 0x9af64480a3486659;
+ c = c * 0x369dea0f31a53f85 + 0xd0c6225445b76b5b;
+
+ // mix results
+ a += c;
+
+ // final scramble
+ a ^= ROR64(a, 13) ^ ROR64(a, 7);
+
+ // down-casting, also taking advantage of upper half
+ a ^= a >> 32;
+
+ return((u_int32_t)a);
+}
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 5cdaa9f2b..eaffe2056 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -224,8 +224,6 @@ static int addDefaultPort(struct ndpi_detection_module_struct *ndpi_str,
ndpi_port_range *range, ndpi_proto_defaults_t *def,
u_int8_t customUserProto, ndpi_default_ports_tree_node_t **root,
const char *_func, int _line);
-static int removeDefaultPort(ndpi_port_range *range, ndpi_proto_defaults_t *def,
- ndpi_default_ports_tree_node_t **root);
static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet);
static void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
@@ -474,7 +472,6 @@ u_int8_t ndpi_is_subprotocol_informative(struct ndpi_detection_module_struct *nd
/* All dissectors that have calls to ndpi_match_host_subprotocol() */
case NDPI_PROTOCOL_DNS:
return(1);
- break;
default:
return(0);
@@ -683,37 +680,6 @@ static int addDefaultPort(struct ndpi_detection_module_struct *ndpi_str,
/* ****************************************************** */
/*
- NOTE
-
- This function must be called with a semaphore set, this in order to avoid
- changing the datastructures while using them
-*/
-static int removeDefaultPort(ndpi_port_range *range, ndpi_proto_defaults_t *def,
- ndpi_default_ports_tree_node_t **root) {
- ndpi_default_ports_tree_node_t node;
- u_int16_t port;
-
- for(port = range->port_low; port <= range->port_high; port++) {
- ndpi_default_ports_tree_node_t *ret;
-
- node.proto = def, node.default_port = port;
-
- ret = (ndpi_default_ports_tree_node_t *)
- ndpi_tdelete(&node, (void *) root,
- ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
-
- if(ret != NULL) {
- ndpi_free((ndpi_default_ports_tree_node_t *) ret);
- return(0);
- }
- }
-
- return(-1);
-}
-
-/* ****************************************************** */
-
-/*
This is a function used to see if we need to
add a trailer $ in case the string is complete
or is a string that can be matched in the
@@ -833,19 +799,6 @@ static int ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct *nd
}
-/* ****************************************************** */
-
-/*
- NOTE
-
- This function must be called with a semaphore set, this in order to avoid
- changing the datastructures while using them
-*/
-static int ndpi_remove_host_url_subprotocol(struct ndpi_detection_module_struct *ndpi_str, char *value, int protocol_id) {
- NDPI_LOG_ERR(ndpi_str, "[NDPI] Missing implementation for proto %s/%d\n", value, protocol_id);
- return(-1);
-}
-
/* ******************************************************************** */
int ndpi_init_empty_app_protocol(ndpi_protocol_match const * const hostname_list,
@@ -4014,15 +3967,8 @@ u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_str,
if(found != NULL) {
u_int16_t guessed_proto = found->proto->protoId;
- /* We need to check if the guessed protocol isn't excluded by nDPI */
- if(flow && (proto == IPPROTO_UDP) &&
- NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, guessed_proto) &&
- is_udp_not_guessable_protocol(guessed_proto))
- return(NDPI_PROTOCOL_UNKNOWN);
- else {
- *user_defined_proto = found->customUserProto;
- return(guessed_proto);
- }
+ *user_defined_proto = found->customUserProto;
+ return(guessed_proto);
}
} else {
/* No TCP/UDP */
@@ -4264,8 +4210,8 @@ int ndpi_add_trusted_issuer_dn(struct ndpi_detection_module_struct *ndpi_str, ch
}
/* ******************************************************************** */
-int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
- char *rule, u_int8_t do_add) {
+static int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
+ char *rule) {
char *at, *proto, *elem;
ndpi_proto_defaults_t *def;
u_int subprotocol_id, i;
@@ -4330,11 +4276,6 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
def = NULL;
if(def == NULL) {
- if(!do_add) {
- /* We need to remove a rule */
- NDPI_LOG_ERR(ndpi_str, "Unable to find protocol '%s': skipping rule '%s'\n", proto, rule);
- return(-3);
- } else {
ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];
char *equal = strchr(proto, '=');
u_int16_t user_proto_id = ndpi_str->ndpi_num_supported_protocols;
@@ -4371,7 +4312,6 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
def = &ndpi_str->proto_defaults[ndpi_str->ndpi_num_supported_protocols];
subprotocol_id = ndpi_str->ndpi_num_supported_protocols;
ndpi_str->ndpi_num_supported_protocols++, ndpi_str->ndpi_num_custom_protocols++;
- }
}
while((elem = strsep(&rule, ",")) != NULL) {
@@ -4445,11 +4385,8 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
else
range.port_low = range.port_high = atoi(&elem[4]);
- if(do_add)
- rc = addDefaultPort(ndpi_str, &range, def, 1 /* Custom user proto */,
+ rc = addDefaultPort(ndpi_str, &range, def, 1 /* Custom user proto */,
is_tcp ? &ndpi_str->tcpRoot : &ndpi_str->udpRoot, __FUNCTION__, __LINE__);
- else
- rc = removeDefaultPort(&range, def, is_tcp ? &ndpi_str->tcpRoot : &ndpi_str->udpRoot);
if(rc != 0) ret = rc;
} else if(is_ip) {
@@ -4458,11 +4395,8 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
if(rc != 0)
return(rc);
} else {
- if(do_add)
- ndpi_add_host_url_subprotocol(ndpi_str, value, subprotocol_id, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED,
- NDPI_PROTOCOL_ACCEPTABLE, 0);
- else
- ndpi_remove_host_url_subprotocol(ndpi_str, value, subprotocol_id);
+ ndpi_add_host_url_subprotocol(ndpi_str, value, subprotocol_id, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED,
+ NDPI_PROTOCOL_ACCEPTABLE, 0);
}
}
@@ -4971,7 +4905,7 @@ int ndpi_load_protocols_file_fd(struct ndpi_detection_module_struct *ndpi_str, F
/* printf("Processing: \"%s\"\n", buffer); */
- if(ndpi_handle_rule(ndpi_str, buffer, 1) != 0)
+ if(ndpi_handle_rule(ndpi_str, buffer) != 0)
NDPI_LOG_INFO(ndpi_str, "Discraded rule '%s'\n", buffer);
}
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index 68c07fa6c..b41ec6706 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -2051,11 +2051,10 @@ const char* ndpi_risk2str(ndpi_risk_enum risk) {
case NDPI_TLS_ALPN_SNI_MISMATCH:
return("ALPN/SNI Mismatch");
-
+
case NDPI_MALWARE_HOST_CONTACTED:
return("Client contacted a malware host");
- break;
-
+
default:
ndpi_snprintf(buf, sizeof(buf), "%d", (int)risk);
return(buf);
@@ -2201,35 +2200,6 @@ ndpi_http_method ndpi_http_str2method(const char* method, u_int16_t method_len)
/* ******************************************************************** */
-#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r))))
-
-/*
- 'in_16_bytes_long` points to some 16 byte memory data to be hashed;
- two independent 64-bit linear congruential generators are applied
- results are mixed, scrambled and cast to 32-bit
-*/
-u_int32_t ndpi_quick_16_byte_hash(u_int8_t *in_16_bytes_long) {
- u_int64_t a = *(u_int64_t*)(in_16_bytes_long + 0);
- u_int64_t c = *(u_int64_t*)(in_16_bytes_long + 8);
-
- // multipliers are taken from sprng.org, addends are prime
- a = a * 0x2c6fe96ee78b6955 + 0x9af64480a3486659;
- c = c * 0x369dea0f31a53f85 + 0xd0c6225445b76b5b;
-
- // mix results
- a += c;
-
- // final scramble
- a ^= ROR64(a, 13) ^ ROR64(a, 7);
-
- // down-casting, also taking advantage of upper half
- a ^= a >> 32;
-
- return((u_int32_t)a);
-}
-
-/* ******************************************************************** */
-
int ndpi_hash_init(ndpi_str_hash **h)
{
if (h == NULL)
diff --git a/tests/cfgs/default/pcap/stun.pcap b/tests/cfgs/default/pcap/stun.pcap
index aceefec22..c7e645eea 100644
--- a/tests/cfgs/default/pcap/stun.pcap
+++ b/tests/cfgs/default/pcap/stun.pcap
Binary files differ
diff --git a/tests/cfgs/default/result/stun.pcap.out b/tests/cfgs/default/result/stun.pcap.out
index a396239ff..4c421c21e 100644
--- a/tests/cfgs/default/result/stun.pcap.out
+++ b/tests/cfgs/default/result/stun.pcap.out
@@ -1,13 +1,14 @@
Guessed flow protos: 0
DPI Packets (TCP): 9 (4.50 pkts/flow)
-DPI Packets (UDP): 8 (2.67 pkts/flow)
-Confidence DPI : 5 (flows)
-Num dissector calls: 20 (4.00 diss/flow)
+DPI Packets (UDP): 12 (3.00 pkts/flow)
+DPI Packets (other): 1 (1.00 pkts/flow)
+Confidence DPI : 7 (flows)
+Num dissector calls: 22 (3.14 diss/flow)
LRU cache ookla: 0/0/0 (insert/search/found)
LRU cache bittorrent: 0/0/0 (insert/search/found)
LRU cache zoom: 0/0/0 (insert/search/found)
-LRU cache stun: 6/22/0 (insert/search/found)
+LRU cache stun: 8/28/0 (insert/search/found)
LRU cache tls_cert: 0/0/0 (insert/search/found)
LRU cache mining: 0/0/0 (insert/search/found)
LRU cache msteams: 0/0/0 (insert/search/found)
@@ -17,16 +18,17 @@ Automa domain: 0/0 (search/found)
Automa tls cert: 0/0 (search/found)
Automa risk mask: 1/0 (search/found)
Automa common alpns: 0/0 (search/found)
-Patricia risk mask: 4/0 (search/found)
+Patricia risk mask: 8/0 (search/found)
Patricia risk mask IPv6: 2/0 (search/found)
Patricia risk: 1/0 (search/found)
Patricia risk IPv6: 1/0 (search/found)
-Patricia protocols: 6/2 (search/found)
+Patricia protocols: 8/4 (search/found)
Patricia protocols IPv6: 2/0 (search/found)
Skype_TeamsCall 15 2124 1
STUN 62 7620 2
-GoogleHangoutDuo 33 6292 1
+ICMP 1 122 1
+GoogleHangoutDuo 41 7228 2
FacebookVoip 75 10554 1
1 UDP 192.168.12.169:38123 <-> 31.13.86.54:40003 [proto: 78.268/STUN.FacebookVoip][IP: 119/Facebook][ClearText][Confidence: DPI][DPI packets: 2][cat: VoIP/10][40 pkts/6134 bytes <-> 35 pkts/4420 bytes][Goodput ratio: 73/67][10.09 sec][Hostname/SNI: turner.facebook][bytes ratio: 0.162 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/0 260/331 6004/5997 1040/1126][Pkt Len c2s/s2c min/avg/max/stddev: 70/68 153/126 190/174 31/39][Risk: ** Known Proto on Non Std Port **][Risk Score: 50][PLAIN TEXT (unauthorized)][Plen Bins: 8,14,9,28,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
@@ -34,3 +36,5 @@ FacebookVoip 75 10554 1
3 UDP [3516:bf0b:fc53:75e7:70af:f67f:8e49:f603]:56880 <-> [2a38:e156:8167:a333:face:b00c::24d9]:3478 [proto: 78/STUN][IP: 0/Unknown][ClearText][Confidence: DPI][DPI packets: 5][cat: Network/14][21 pkts/1722 bytes <-> 21 pkts/2226 bytes][Goodput ratio: 24/41][191.49 sec][bytes ratio: -0.128 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 2/2 9451/9451 10358/10358 2441/2441][Pkt Len c2s/s2c min/avg/max/stddev: 82/106 82/106 82/106 0/0][PLAIN TEXT (WOBTrOXR)][Plen Bins: 50,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
4 TCP 87.47.100.17:3478 <-> 54.1.57.155:37257 [proto: 78/STUN][IP: 0/Unknown][ClearText][Confidence: DPI][DPI packets: 6][cat: Network/14][9 pkts/1494 bytes <-> 11 pkts/2178 bytes][Goodput ratio: 60/67][0.95 sec][Hostname/SNI: apps-host.com][bytes ratio: -0.186 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/0 104/96 267/252 102/93][Pkt Len c2s/s2c min/avg/max/stddev: 74/94 166/198 234/354 41/65][PLAIN TEXT (Unauthorized)][Plen Bins: 10,0,15,21,42,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
5 TCP 10.77.110.51:41588 <-> 10.206.50.239:42000 [VLAN: 1611][proto: 78.38/STUN.Skype_TeamsCall][IP: 0/Unknown][ClearText][Confidence: DPI][DPI packets: 3][cat: VoIP/10][7 pkts/1006 bytes <-> 8 pkts/1118 bytes][Goodput ratio: 58/57][1.05 sec][bytes ratio: -0.053 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/0 189/134 369/399 144/153][Pkt Len c2s/s2c min/avg/max/stddev: 70/64 144/140 164/172 31/43][Plen Bins: 0,0,25,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+ 6 UDP 192.168.12.169:43016 <-> 74.125.247.128:3478 [proto: 78.201/STUN.GoogleHangoutDuo][IP: 126/Google][ClearText][Confidence: DPI][DPI packets: 4][cat: VoIP/10][4 pkts/528 bytes <-> 4 pkts/408 bytes][Goodput ratio: 68/59][1.25 sec][Hostname/SNI: turn.l.google.com][bytes ratio: 0.128 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 9/23 342/409 974/1177 447/543][Pkt Len c2s/s2c min/avg/max/stddev: 62/74 132/102 198/122 61/19][PLAIN TEXT (BSnLfRxS6)][Plen Bins: 12,37,25,0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+ 7 ICMP 192.168.12.169:0 -> 74.125.247.128:0 [proto: 81/ICMP][IP: 126/Google][ClearText][Confidence: DPI][DPI packets: 1][cat: Network/14][1 pkts/122 bytes -> 0 pkts/0 bytes][Goodput ratio: 65/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][PLAIN TEXT (62NfUD5)][Plen Bins: 0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]