static inline #else __forceinline static #endif u_int8_t check_edk_len(const u_int8_t * payload, u_int16_t payload_packet_len) { u_int32_t edk_len_parsed = 0; // we use a do / while loop here, because we have checked the byte 0 for 0xe3 or 0xc5 already before this call do { u_int32_t edk_len; edk_len = get_l32(payload, 1 + edk_len_parsed); /* if bigger, return here directly with an error... */ if (edk_len > payload_packet_len) return 0; /* this is critical here: * if (edk_len + 5) provokes an overflow to zero, we will have an infinite loop... * the check above does prevent this, bcause the edk_len must be ((u_int32_t)-5), which is always bigger than the packet size */ edk_len_parsed += 5 + edk_len; if (edk_len_parsed == payload_packet_len) return 1; if (edk_len_parsed > payload_packet_len) return 0; } while (payload[edk_len_parsed] == 0xe3 || payload[edk_len_parsed] == 0xc5 || payload[edk_len_parsed] == 0xd4); return 0; }
void ipoque_search_imesh_tcp_udp(struct ipoque_detection_module_struct *ipoque_struct) { struct ipoque_packet_struct *packet = &ipoque_struct->packet; struct ipoque_flow_struct *flow = ipoque_struct->flow; struct ipoque_id_struct *src = ipoque_struct->src; struct ipoque_id_struct *dst = ipoque_struct->dst; if (packet->detected_protocol == IPOQUE_PROTOCOL_IMESH) { if (src != NULL) { src->imesh_timer = packet->tick_timestamp; } if (dst != NULL) { dst->imesh_timer = packet->tick_timestamp; } return; } /* skip marked packets */ if (packet->detected_protocol != IPOQUE_PROTOCOL_UNKNOWN) goto imesh_not_found_end; if (packet->udp != NULL) { IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "UDP FOUND\n"); // this is the login packet if ( //&& ((IPOQUE_TIMESTAMP_COUNTER_SIZE)(packet->tick_timestamp - src->imesh_timer)) < ipoque_struct->imesh_connection_timeout packet->payload_packet_len == 28 && (get_l32(packet->payload, 0)) == 0x00000002 // PATTERN : 02 00 00 00 && (get_l32(packet->payload, 24)) == 0x00000000 // PATTERN : 00 00 00 00 && (packet->udp->dest == htons(1864) || packet->udp->source == htons(1864))) { IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "iMesh Login detected\n"); if (src != NULL) { src->imesh_timer = packet->tick_timestamp; } if (dst != NULL) { dst->imesh_timer = packet->tick_timestamp; } ipoque_int_imesh_add_connection(ipoque_struct); return; } else if ( //&& ((IPOQUE_TIMESTAMP_COUNTER_SIZE)(packet->tick_timestamp - src->imesh_timer)) < ipoque_struct->imesh_connection_timeout packet->payload_packet_len == 36 && (get_l32(packet->payload, 0)) == 0x00000002 // PATTERN : 02 00 00 00 //&& packet->payload[35]==0x0f ) { IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "iMesh detected, %u\n", ipoque_struct->imesh_connection_timeout); if (src != NULL) { IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "iMesh: src < %u, %u, %u\n", (packet->tick_timestamp - src->imesh_timer), packet->tick_timestamp, src->imesh_timer); if (((IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - src->imesh_timer)) < ipoque_struct->imesh_connection_timeout) { src->imesh_timer = packet->tick_timestamp; ipoque_int_imesh_add_connection(ipoque_struct); } } if (dst != NULL) { IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "iMesh: dst < %u, %u, %u\n", (packet->tick_timestamp - dst->imesh_timer), packet->tick_timestamp, dst->imesh_timer); if (((IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - dst->imesh_timer)) < ipoque_struct->imesh_connection_timeout) { dst->imesh_timer = packet->tick_timestamp; ipoque_int_imesh_add_connection(ipoque_struct); } } return; } IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "iMesh UDP packetlen: %d\n", packet->payload_packet_len); } else if (packet->tcp != NULL) { IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "TCP FOUND :: Payload %u\n", packet->payload_packet_len); if (packet->actual_payload_len == 0) { return; } else if ((packet->actual_payload_len == 8 || packet->payload_packet_len == 10) /* PATTERN:: 04 00 00 00 00 00 00 00 [00 00] */ &&packet->payload[0] == 0x04 && packet->payload[1] == 0x00 && packet->payload[2] == 0x00 && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00 && packet->payload[6] == 0x00 && packet->payload[7] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 10 /* PATTERN:: ?? ?? 04|00 00 64|00 00 */ && (packet->payload[2] == 0x04 || packet->payload[2] == 0x00) && packet->payload[3] == 0x00 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x64) && packet->payload[5] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 2 && packet->payload[0] == 0x06 && packet->payload[1] == 0x00) { flow->imesh_stage++; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 10 /* PATTERN:: 06 00 04|00 00 01|00 00 01|00 00 ?? 00 */ && packet->payload[0] == 0x06 && packet->payload[1] == 0x00 && (packet->payload[2] == 0x04 || packet->payload[2] == 0x00) && packet->payload[3] == 0x00 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01) && packet->payload[5] == 0x00 && (packet->payload[6] == 0x01 || packet->payload[6] == 0x00) && packet->payload[7] == 0x00 && packet->payload[9] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 24 && packet->payload[0] == 0x06 // PATTERN :: 06 00 12 00 00 00 34 00 00 && packet->payload[1] == 0x00 && packet->payload[2] == 0x12 && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00 && packet->payload[6] == 0x34 && packet->payload[7] == 0x00 && packet->payload[8] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 8 /* PATTERN:: 06|00 00 02 00 00 00 33 00 */ && (packet->payload[0] == 0x06 || packet->payload[0] == 0x00) && packet->payload[1] == 0x00 && packet->payload[2] == 0x02 && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00 && packet->payload[6] == 0x33 && packet->payload[7] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->payload_packet_len == 6 /* PATTERN:: 02 00 00 00 33 00 */ && packet->payload[0] == 0x02 && packet->payload[1] == 0x00 && packet->payload[2] == 0x00 && packet->payload[3] == 0x00 && packet->payload[4] == 0x33 && packet->payload[5] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 12 && packet->payload[0] == 0x06 // PATTERN : 06 00 06 00 00 00 64 00 && packet->payload[1] == 0x00 && packet->payload[2] == 0x06 && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00 && packet->payload[6] == 0x64 && packet->payload[7] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 10 /* PATTERN:: 06 00 04|01 00 00 00 01|00 00 ?? 00 */ && packet->payload[0] == 0x06 && packet->payload[1] == 0x00 && (packet->payload[2] == 0x04 || packet->payload[2] == 0x01) && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00 && (packet->payload[6] == 0x01 || packet->payload[6] == 0x00) && packet->payload[7] == 0x00 /* && packet->payload[8]==0x00 */ && packet->payload[9] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if ((packet->actual_payload_len == 64 || packet->actual_payload_len == 52 /* PATTERN:: [len] 00 00 00 00 */ || packet->actual_payload_len == 95) && get_u16(packet->payload, 0) == (packet->actual_payload_len) && packet->payload[1] == 0x00 && packet->payload[2] == 0x00 && packet->payload[3] == 0x00 && packet->payload[4] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 6 && packet->payload[0] == 0x06 // PATTERN : 06 00 04|6c 00|01 00 00 && packet->payload[1] == 0x00 && (packet->payload[2] == 0x04 || packet->payload[2] == 0x6c) && (packet->payload[3] == 0x00 || packet->payload[3] == 0x01) && packet->payload[4] == 0x00 && packet->payload[5] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 6 /* PATTERN:: [len] ?? ee 00 00 00 */ && get_u16(packet->payload, 0) == (packet->actual_payload_len) && packet->payload[2] == 0xee && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } else if (packet->actual_payload_len == 10 /* PATTERN:: 06 00 00 00 00 00 00 00 */ && packet->payload[0] == 0x06 && packet->payload[1] == 0x00 && packet->payload[2] == 0x00 && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00 && packet->payload[6] == 0x00 && packet->payload[7] == 0x00) { flow->imesh_stage += 2; IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "IMESH FOUND :: Payload %u\n", packet->actual_payload_len); } } /*give one packet tolerance for detection */ if (flow->imesh_stage >= 4) ipoque_int_imesh_add_connection(ipoque_struct); else if ((flow->packet_counter < 5) || packet->actual_payload_len == 0) { return; } else { goto imesh_not_found_end; } imesh_not_found_end: IPOQUE_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, IPOQUE_PROTOCOL_IMESH); IPQ_LOG(IPOQUE_PROTOCOL_IMESH, ipoque_struct, IPQ_LOG_DEBUG, "iMesh excluded at stage %d\n", flow->imesh_stage); }
static void ndpi_int_edonkey_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; int edk_stage2_len; /*len range increase if safe mode and also only once */ if (ndpi_struct->edonkey_safe_mode == 0) edk_stage2_len = 140; else if (!flow->l4.tcp.edk_ext || packet->payload_packet_len == 212) { edk_stage2_len = 300; } else edk_stage2_len = 140; /* skip excluded connections */ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_EDONKEY) != 0) return; /* source and dst port must be 80 443 or > 1024 */ if (ndpi_struct->edonkey_upper_ports_only != 0) { u_int16_t port; port = ntohs(packet->tcp->source); /* source and dst port must be 80 443 or > 1024 */ if (port < 1024 && port != 80 && port != 443) goto exclude_edk_tcp; port = ntohs(packet->tcp->dest); if (port < 1024 && port != 80 && port != 443) goto exclude_edk_tcp; } /* return here for empty packets, we needed them only for bt port detection */ if (packet->payload_packet_len == 0) return; /* skip marked packets */ if (flow->edk_stage == 0 && packet->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) return; /* first: check for unencrypted traffic */ if (flow->edk_stage == 0) { /* check for client hello */ if (packet->payload_packet_len >= 32 && get_l32(packet->payload, 1) <= (packet->payload_packet_len - 5) && (packet->payload[0] == 0xe3 || packet->payload[0] == 0xc5)) { if (packet->payload[5] == 0x01 && ((packet->payload[6] == 0x10 && get_l32(packet->payload, 29) < 0x0F) || (get_l32(packet->payload, 28) > 0x00 && get_l32(packet->payload, 28) < 0x0F))) { NDPI_LOG_EDONKEY(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "edk hello meta tag recognized\n"); flow->edk_stage = 16 + packet->packet_direction; return; } } } if ((17 - packet->packet_direction) == flow->edk_stage) { if ((packet->payload_packet_len >= 32 && get_l32(packet->payload, 1) == 9 && (packet->payload[0] == 0xe3) && packet->payload[5] == 0x40) || (packet->payload_packet_len >= 32 && (packet->payload[0] == 0xe3) && packet->payload[5] == 0x40 && check_edk_len(packet->payload, packet->payload_packet_len)) || (packet->payload_packet_len >= 32 && packet->payload[0] == 0xe3 && packet->payload[5] == 0x4c && (get_l32(packet->payload, 1) == (packet->payload_packet_len - 5) || check_edk_len(packet->payload, packet->payload_packet_len))) || (packet->payload_packet_len >= 32 && get_l32(packet->payload, 1) == (packet->payload_packet_len - 5) && packet->payload[0] == 0xe3 && packet->payload[5] == 0x38) || (packet->payload_packet_len >= 20 && get_l32(packet->payload, 1) == (packet->payload_packet_len - 5) && packet->payload[0] == 0xc5 && packet->payload[5] == 0x92) || (packet->payload_packet_len >= 20 && get_l32(packet->payload, 1) <= (packet->payload_packet_len - 5) && packet->payload[0] == 0xe3 && packet->payload[5] == 0x58) || (packet->payload_packet_len >= 20 && get_l32(packet->payload, 1) <= (packet->payload_packet_len - 5) && (packet->payload[0] == 0xe3 || packet->payload[0] == 0xc5) && packet->payload[5] == 0x01)) { NDPI_LOG_EDONKEY(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "edk 17: detected plain detection\n"); ndpi_add_connection_as_edonkey(ndpi_struct, flow, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return; } NDPI_LOG_EDONKEY(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "edk 17: id: %u, %u, %u not detected\n", packet->payload[0], get_l32(packet->payload, 1), packet->payload[5]); } exclude_edk_tcp: NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_EDONKEY); return; }
void ndpi_search_soulseek_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; struct ndpi_id_struct *src = flow->src; struct ndpi_id_struct *dst = flow->dst; NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek: search soulseec tcp \n"); if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SOULSEEK) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "packet marked as Soulseek\n"); if (src != NULL) NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, " SRC bitmask: %u, packet tick %llu , last safe access timestamp: %llu\n", NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_SOULSEEK) != 0 ? 1 : 0, (u_int64_t) packet->tick_timestamp, (u_int64_t) src->soulseek_last_safe_access_time); if (dst != NULL) NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, " DST bitmask: %u, packet tick %llu , last safe ts: %llu\n", NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_SOULSEEK) != 0 ? 1 : 0, (u_int64_t) packet->tick_timestamp, (u_int64_t) dst->soulseek_last_safe_access_time); if (packet->payload_packet_len == 431) { if (dst != NULL) { dst->soulseek_last_safe_access_time = packet->tick_timestamp; } return; } if (packet->payload_packet_len == 12 && get_l32(packet->payload, 4) == 0x02) { if (src != NULL) { src->soulseek_last_safe_access_time = packet->tick_timestamp; if (packet->tcp != NULL && src->soulseek_listen_port == 0) { src->soulseek_listen_port = get_l32(packet->payload, 8); return; } } } if (src != NULL && ((u_int32_t) (packet->tick_timestamp - src->soulseek_last_safe_access_time) < ndpi_struct->soulseek_connection_ip_tick_timeout)) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek: SRC update last safe access time and SKIP_FOR_TIME \n"); src->soulseek_last_safe_access_time = packet->tick_timestamp; } if (dst != NULL && ((u_int32_t) (packet->tick_timestamp - dst->soulseek_last_safe_access_time) < ndpi_struct->soulseek_connection_ip_tick_timeout)) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek: DST update last safe access time and SKIP_FOR_TIME \n"); dst->soulseek_last_safe_access_time = packet->tick_timestamp; } } if (dst != NULL && dst->soulseek_listen_port != 0 && dst->soulseek_listen_port == ntohs(packet->tcp->dest) && ((u_int32_t) (packet->tick_timestamp - dst->soulseek_last_safe_access_time) < ndpi_struct->soulseek_connection_ip_tick_timeout)) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek: Plain detection on Port : %u packet_tick_timestamp: %u soulseeek_last_safe_access_time: %u soulseek_connection_ip_ticktimeout: %u\n", dst->soulseek_listen_port, packet->tick_timestamp, dst->soulseek_last_safe_access_time, ndpi_struct->soulseek_connection_ip_tick_timeout); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } if (flow->l4.tcp.soulseek_stage == 0) { u_int32_t index = 0; if (packet->payload_packet_len >= 12 && packet->payload_packet_len < 300 && get_l32(packet->payload, 4) == 1) { while (!get_u_int16_t(packet->payload, index + 2) && (index + get_l32(packet->payload, index)) < packet->payload_packet_len - 4) { if (get_l32(packet->payload, index) < 8) /*Minimum soulsek login msg is 8B */ break; if (index + get_l32(packet->payload, index) + 4 <= index) { /* avoid overflow */ break; } index += get_l32(packet->payload, index) + 4; } if (index + get_l32(packet->payload, index) == packet->payload_packet_len - 4 && !get_u_int16_t(packet->payload, 10)) { /*This structure seems to be soulseek proto */ index = get_l32(packet->payload, 8) + 12; // end of "user name" if ((index + 4) <= packet->payload_packet_len && !get_u_int16_t(packet->payload, index + 2)) // for passwd len { index += get_l32(packet->payload, index) + 4; //end of "Passwd" if ((index + 4 + 4) <= packet->payload_packet_len && !get_u_int16_t(packet->payload, index + 6)) // to read version,hashlen { index += get_l32(packet->payload, index + 4) + 8; // enf of "hash value" if (index == get_l32(packet->payload, 0)) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek Login Detected\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } } } } } if (packet->payload_packet_len > 8 && packet->payload_packet_len < 200 && get_l32(packet->payload, 0) == packet->payload_packet_len - 4) { //Server Messages: const u_int32_t msgcode = get_l32(packet->payload, 4); if (msgcode == 0x7d) { flow->l4.tcp.soulseek_stage = 1 + packet->packet_direction; NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek Messages Search\n"); return; } else if (msgcode == 0x02 && packet->payload_packet_len == 12) { const u_int32_t soulseek_listen_port = get_l32(packet->payload, 8); if (src != NULL) { src->soulseek_last_safe_access_time = packet->tick_timestamp; if (packet->tcp != NULL && src->soulseek_listen_port == 0) { src->soulseek_listen_port = soulseek_listen_port; NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "\n Listen Port Saved : %u", src->soulseek_listen_port); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } } } //Peer Messages : Peer Init Message Detection if (get_l32(packet->payload, 0) == packet->payload_packet_len - 4) { const u_int32_t typelen = get_l32(packet->payload, packet->payload_packet_len - 9); const u_int8_t type = packet->payload[packet->payload_packet_len - 5]; const u_int32_t namelen = get_l32(packet->payload, 5); if (packet->payload[4] == 0x01 && typelen == 1 && namelen <= packet->payload_packet_len && (4 + 1 + 4 + namelen + 4 + 1 + 4) == packet->payload_packet_len && (type == 'F' || type == 'P' || type == 'D')) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "1\n"); } NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "3\n"); //Peer Message : Pierce Firewall if (packet->payload_packet_len == 9 && get_l32(packet->payload, 0) == 5 && packet->payload[4] <= 0x10 && get_u_int32_t(packet->payload, 5) != 0x00000000) { flow->l4.tcp.soulseek_stage = 1 + packet->packet_direction; NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_TRACE, "Soulseek Size 9 Pierce Firewall\n"); return; } } if (packet->payload_packet_len > 25 && packet->payload[4] == 0x01 && !get_u_int16_t(packet->payload, 7) && !get_u_int16_t(packet->payload, 2)) { const u_int32_t usrlen = get_l32(packet->payload, 5); if (usrlen <= packet->payload_packet_len - 4 + 1 + 4 + 4 + 1 + 4) { const u_int32_t typelen = get_l32(packet->payload, 4 + 1 + 4 + usrlen); const u_int8_t type = packet->payload[4 + 1 + 4 + usrlen + 4]; if (typelen == 1 && (type == 'F' || type == 'P' || type == 'D')) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected Pattern command(D|P|F).\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } } } } else if (flow->l4.tcp.soulseek_stage == 2 - packet->packet_direction) { if (packet->payload_packet_len > 8) { if ((packet->payload[0] || packet->payload[1]) && get_l32(packet->payload, 4) == 9) { /* 9 is search result */ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected Second Pkt\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } if (get_l32(packet->payload, 0) == packet->payload_packet_len - 4) { const u_int32_t msgcode = get_l32(packet->payload, 4); if (msgcode == 0x03 && packet->payload_packet_len >= 12) //Server Message : Get Peer Address { const u_int32_t usrlen = get_l32(packet->payload, 8); if (usrlen <= packet->payload_packet_len && 4 + 4 + 4 + usrlen == packet->payload_packet_len) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek Request Get Peer Address Detected\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } } } } if (packet->payload_packet_len == 8 && get_l32(packet->payload, 4) == 0x00000004) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } if (packet->payload_packet_len == 4 && get_u_int16_t(packet->payload, 2) == 0x00 && get_u_int16_t(packet->payload, 0) != 0x00) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } else if (packet->payload_packet_len == 4) { flow->l4.tcp.soulseek_stage = 3; return; } } else if (flow->l4.tcp.soulseek_stage == 1 + packet->packet_direction) { if (packet->payload_packet_len > 8) { if (packet->payload[4] == 0x03 && get_l32(packet->payload, 5) == 0x00000031) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected Second Pkt with SIGNATURE :: 0x0331000000 \n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } } } if (flow->l4.tcp.soulseek_stage == 3 && packet->payload_packet_len == 8 && !get_u_int32_t(packet->payload, 4)) { NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected bcz of 8B pkt\n"); ndpi_int_soulseek_add_connection(ndpi_struct, flow); return; } if (flow->l4.tcp.soulseek_stage && flow->packet_counter < 11) { } else { NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOULSEEK); } }
void ipoque_search_pplive_tcp_udp(struct ipoque_detection_module_struct *ipoque_struct) { struct ipoque_packet_struct *packet = &ipoque_struct->packet; struct ipoque_flow_struct *flow = ipoque_struct->flow; struct ipoque_id_struct *src = ipoque_struct->src; struct ipoque_id_struct *dst = ipoque_struct->dst; u16 a; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "search pplive.\n"); if (packet->udp != NULL) { if (src != NULL && src->pplive_vod_cli_port == packet->udp->source && IPOQUE_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, IPOQUE_PROTOCOL_PPLIVE)) { if (src->pplive_last_packet_time_set == 1 && (IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - src->pplive_last_packet_time) < ipoque_struct->pplive_connection_timeout) { ipoque_int_pplive_add_connection(ipoque_struct); src->pplive_last_packet_time_set = 1; src->pplive_last_packet_time = packet->tick_timestamp; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "timestamp src.\n"); return; } else { src->pplive_vod_cli_port = 0; src->pplive_last_packet_time = 0; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: VOD port timer reset.\n"); } } if (dst != NULL && dst->pplive_vod_cli_port == packet->udp->dest && IPOQUE_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, IPOQUE_PROTOCOL_PPLIVE)) { if (dst->pplive_last_packet_time_set == 1 && (IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - dst->pplive_last_packet_time) < ipoque_struct->pplive_connection_timeout) { ipoque_int_pplive_add_connection(ipoque_struct); dst->pplive_last_packet_time_set = 1; dst->pplive_last_packet_time = packet->tick_timestamp; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "timestamp dst.\n"); return; } else { dst->pplive_last_packet_time_set = 0; dst->pplive_vod_cli_port = 0; dst->pplive_last_packet_time = 0; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: VOD port timer reset.\n"); } } if ((packet->payload_packet_len >= 76) && ((packet->payload[0] == 0x01) || (packet->payload[0] == 0x18) || (packet->payload[0] == 0x05)) && (packet->payload[1] == 0x00) && get_l32(packet->payload, 12) == 0 && (packet->payload[16] == 0 || packet->payload[16] == 1) && (packet->payload[17] == 0) && (packet->payload[24] == 0xac)) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } if (packet->payload_packet_len > 50 && packet->payload[0] == 0xe9 && packet->payload[1] == 0x03 && (packet->payload[3] == 0x00 || packet->payload[3] == 0x01) && packet->payload[4] == 0x98 && packet->payload[5] == 0xab && packet->payload[6] == 0x01 && packet->payload[7] == 0x02) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } if (packet->payload_packet_len == 94 && packet->payload[8] == 0x00 && get_u32(packet->payload, 9) == ntohl(0x02010000) && get_u32(packet->payload, 58) == ntohl(0xb1130000)) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } if ((packet->payload_packet_len >= 90 && packet->payload_packet_len <= 110) && (packet->payload[0] >= 0x0a && packet->payload[0] <= 0x0f) && get_u32(packet->payload, 86) == 0) { int i; for (i = 56; i < 68; i += 2) { if ((get_u32(packet->payload, i) == ntohl(0x4fde7e7f)) && (get_u16(packet->payload, i + 4) == 0)) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive through " "bitpattern 4f de 7e 7f 00 00.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } } if (flow->packet_counter < 5 && !flow->pplive_stage) { /* With in 1st 4 packets */ if (((packet->payload_packet_len >= 90 && packet->payload_packet_len <= 110) && (!get_u32(packet->payload, packet->payload_packet_len - 16) || !get_u32(packet->payload, packet->payload_packet_len - 4))) ) { flow->pplive_stage = 2; /* Now start looking for size(28 | 30) */ IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "Maybe found pplive packet. Now start looking for size(28 | 30).\n"); } if (68 == packet->payload_packet_len && get_l16(packet->payload, 0) == 0x21 && packet->payload[19] == packet->payload[20] && packet->payload[20] == packet->payload[21] && packet->payload[12] == packet->payload[13] && packet->payload[14] == packet->payload[15]) { flow->pplive_stage = 3 + packet->packet_direction; } IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "need next packet I.\n"); return; } if (flow->pplive_stage == 3 + packet->packet_direction) { /* Because we are expecting packet in reverese direction.. */ IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "need next packet II.\n"); return; } if (flow->pplive_stage == (4 - packet->packet_direction) && packet->payload_packet_len > 67 && (get_l16(packet->payload, 0) == 0x21 || (get_l16(packet->payload, 0) == 0x22 && !get_l16(packet->payload, 28)))) { if (dst != NULL) { dst->pplive_vod_cli_port = packet->udp->dest; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: VOD Port marked %u.\n", ntohs(packet->udp->dest)); dst->pplive_last_packet_time = packet->tick_timestamp; dst->pplive_last_packet_time_set = 1; } IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } if (flow->pplive_stage == 2) { if ((packet->payload_packet_len == 30 && (packet->payload[0] == 0x02 || packet->payload[0] == 0x03) && get_u32(packet->payload, 21) == ntohl(0x00000001)) || (packet->payload_packet_len == 28 && (packet->payload[0] == 0x01 || packet->payload[0] == 0x00) && (get_u32(packet->payload, 19) == ntohl(0x00000001)))) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } if (flow->packet_counter < 45) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "need next packet III.\n"); return; } } } else if (packet->tcp != NULL) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: TCP found, plen = %d, stage = %d, payload[0] = %x, payload[1] = %x, payload[2] = %x, payload[3] = %x \n", packet->payload_packet_len, flow->pplive_stage, packet->payload[0], packet->payload[1], packet->payload[2], packet->payload[3]); if (src != NULL && src->pplive_vod_cli_port == packet->tcp->source && IPOQUE_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, IPOQUE_PROTOCOL_PPLIVE)) { if (src->pplive_last_packet_time_set == 1 && (IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - src->pplive_last_packet_time) < ipoque_struct->pplive_connection_timeout) { ipoque_int_pplive_add_connection(ipoque_struct); src->pplive_last_packet_time_set = 1; src->pplive_last_packet_time = packet->tick_timestamp; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "timestamp src.\n"); return; } else { src->pplive_vod_cli_port = 0; src->pplive_last_packet_time = 0; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: VOD port timer reset.\n"); } } if (dst != NULL && dst->pplive_vod_cli_port == packet->tcp->dest && IPOQUE_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, IPOQUE_PROTOCOL_PPLIVE)) { if (dst->pplive_last_packet_time_set == 1 && (IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - dst->pplive_last_packet_time) < ipoque_struct->pplive_connection_timeout) { flow->detected_protocol = IPOQUE_PROTOCOL_PPLIVE; packet->detected_protocol = IPOQUE_PROTOCOL_PPLIVE; dst->pplive_last_packet_time_set = 1; dst->pplive_last_packet_time = packet->tick_timestamp; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "timestamp dst.\n"); return; } else { dst->pplive_last_packet_time_set = 0; dst->pplive_vod_cli_port = 0; dst->pplive_last_packet_time = 0; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: VOD port timer reset.\n"); } } if (packet->payload_packet_len > 4 && memcmp(packet->payload, "GET /", 5) == 0) { ipq_parse_packet_line_info(ipoque_struct); if (packet->parsed_lines == 8 && packet->line[0].ptr != NULL && packet->line[0].len >= 8 && memcmp(&packet->payload[packet->line[0].len - 8], "HTTP/1.", 7) == 0 && packet->line[2].ptr != NULL && packet->line[2].len >= 16 && memcmp(packet->line[2].ptr, "x-flash-version:", 16) == 0 && packet->user_agent_line.ptr != NULL && packet->user_agent_line.len >= 11 && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0", 11) == 0 && packet->line[6].ptr != NULL && packet->line[6].len >= 21 && memcmp(packet->line[6].ptr, "Pragma: Client=PPLive", 21) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: found HTTP request.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } else if (packet->parsed_lines == 6 && packet->line[0].ptr != NULL && packet->line[0].len >= 8 && memcmp(&packet->payload[packet->line[0].len - 8], "HTTP/1.", 7) == 0 && packet->user_agent_line.ptr != NULL && packet->user_agent_line.len >= 10 && memcmp(packet->user_agent_line.ptr, "PPLive DAC", 10) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: found HTTP request.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } // searches for packets > 20 byte that begin with a hex number == packet->payload_packet_len - 4 // and with the same number at position 16, 17, 18, 19 if (packet->payload_packet_len > 20 && ntohl(get_u32(packet->payload, 0)) == packet->payload_packet_len - 4) { if (packet->payload[4] == 0x21 && packet->payload[5] == 0x00) { if ((packet->payload[9] == packet->payload[10]) && (packet->payload[9] == packet->payload[11])) { if ((packet->payload[16] == packet->payload[17]) && (packet->payload[16] == packet->payload[18]) && (packet->payload[16] == packet->payload[19])) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: direct server request or response found\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } } } // stage > 0, packet begins with 21 00, bytes at positions 5, 6, 7 are equal, bytes at positions 12, 13, 14, 15 are equal, if (packet->payload_packet_len > 20 && flow->pplive_stage) { if (packet->payload[0] == 0x21 && packet->payload[1] == 0x00) { if (packet->payload[5] == packet->payload[6] && packet->payload[5] == packet->payload[7]) { if (packet->payload[12] == packet->payload[13] && packet->payload[14] == packet->payload[15] && packet->payload[12] == packet->payload[14]) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: direct server request or response found\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } } } // packet (len>11) begins with a hex number == packet->payload_packet_len - 4 and matches certain bitmuster if (packet->payload_packet_len > 11 && ntohl(get_u32(packet->payload, 0)) == packet->payload_packet_len - 4) { if (packet->payload[4] == 0xe9 && packet->payload[5] == 0x03 && ((packet->payload[7] == packet->payload[10]) || (packet->payload[7] == packet->payload[11]))) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: direct server request or response found\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } // stage > 0, len>10, begins with e9 03, matches certain pattern if (packet->payload_packet_len > 10 && flow->pplive_stage) { if (packet->payload[0] == 0xe9 && packet->payload[1] == 0x03 && ((packet->payload[3] == packet->payload[6]) || (packet->payload[3] == packet->payload[7]))) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: direct server request or response found\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } /* Adware in the PPLive Client -> first TCP Packet has length of 4 Bytes -> 2nd TCP Packet has length of 96 Bytes */ /* or */ /* Peer-List Requests over TCP -> first Packet has length of 4 Bytes -> 2nd TCP Packet has length of 71 Bytes */ /* there are different possibilities of the order of the packets */ IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: TCP found, plen = %d, stage = %d, payload[0] = %x, payload[1] = %x, payload[2] = %x, payload[3] = %x \n", packet->payload_packet_len, flow->pplive_stage, packet->payload[0], packet->payload[1], packet->payload[2], packet->payload[3]); /* generic pplive detection (independent of the stage) !!! */ // len > 11, packet begins with a hex number == packet->payload_packet_len - 4, pattern: ?? ?? ?? ?? 21 00 ?? ?? 98 ab 01 02 if (packet->payload_packet_len > 11 && ntohl(get_u32(packet->payload, 0)) == packet->payload_packet_len - 4) { if (packet->payload[4] == 0x21 && packet->payload[5] == 0x00 && ((packet->payload[8] == 0x98 && packet->payload[9] == 0xab && packet->payload[10] == 0x01 && packet->payload[11] == 0x02) )) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: direct server request or response found\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } // packet 4 to 19 have a hex representation from 0x30 to 0x39 if (packet->payload_packet_len > 20) { a = 4; while (a < 20) { if (packet->payload[a] >= '0' && packet->payload[a] <= '9') { if (a == 19) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: direct new header format found\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } else { a++; } } else { break; } } } } /* 1st and 2nd (KD: ??????? )Packet of Client is 4 Byte */ // stage == 0, p_len == 4, pattern: 04 00 00 00 --> need next packet if (flow->pplive_stage == 0) { if (packet->payload_packet_len == 4 && packet->payload[0] > 0x04 && packet->payload[1] == 0x00 && packet->payload[2] == 0x00 && packet->payload[3] == 0x00) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: 4Byte TCP Packet Request found \n"); /* go to the 2nd Client Packet */ flow->pplive_stage = 1 + packet->packet_direction; flow->pplive_next_packet_size[packet->packet_direction] = packet->payload[0]; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "need next packet i.\n"); return; } } else if (flow->pplive_stage == 2 - packet->packet_direction) { if (packet->payload_packet_len == 4 && packet->payload[0] > 0x04 && packet->payload[1] == 0x00 && packet->payload[2] == 0x00 && packet->payload[3] == 0x00) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: 4Byte TCP Packet Response found \n"); /* go to the 2nd Client Packet */ flow->pplive_next_packet_size[packet->packet_direction] = packet->payload[0]; } flow->pplive_stage = 3; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "need next packet ii.\n"); return; } else if (flow->pplive_stage == 1 + packet->packet_direction || flow->pplive_stage == 3) { if (packet->payload_packet_len > 7 && flow->pplive_next_packet_size[packet->packet_direction] >= 4) { if (packet->payload_packet_len == flow->pplive_next_packet_size[packet->packet_direction]) { if (packet->payload[0] == 0xe9 && packet->payload[1] == 0x03 && ((packet->payload[4] == 0x98 && packet->payload[5] == 0xab && packet->payload[6] == 0x01 && packet->payload[7] == 0x02) )) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: two packet response found\n"); IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive over tcp with pattern iii.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } // packet 4 to 19 have a hex representation from 0x30 to 0x39 if (packet->payload_packet_len > 16) { a = 0; while (a < 16) { if (packet->payload[a] >= '0' && packet->payload[a] <= '9') { if (a == 15) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: new header format found\n"); IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive over tcp with pattern v.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } else { a++; } } else { break; } } } // p_len>79 and a lot of 00 in the end if (packet->payload_packet_len > 79 && get_u32(packet->payload, packet->payload_packet_len - 9) == 0x00000000 && get_u32(packet->payload, packet->payload_packet_len - 5) == 0x00000000) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "PPLIVE: Last 8 NULL bytes found.\n"); IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive over tcp with pattern vi.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } if (packet->payload_packet_len > flow->pplive_next_packet_size[packet->packet_direction]) { if (packet->payload[0] == 0xe9 && packet->payload[1] == 0x03 && packet->payload[4] == 0x98 && packet->payload[5] == 0xab && packet->payload[6] == 0x01 && packet->payload[7] == 0x02) { a = flow->pplive_next_packet_size[packet->packet_direction]; IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "a=%u.\n", a); if (packet->payload_packet_len > a + 4 && packet->payload[a + 2] == 0x00 && packet->payload[a + 3] == 0x00 && packet->payload[a] != 0) { a += ((packet->payload[a + 1] << 8) + packet->payload[a] + 4); IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "a=%u.\n", a); if (packet->payload_packet_len == a) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive over tcp with pattern vii.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } if (packet->payload_packet_len > a + 4 && packet->payload[a + 2] == 0x00 && packet->payload[a + 3] == 0x00 && packet->payload[a] != 0) { a += ((packet->payload[a + 1] << 8) + packet->payload[a] + 4); if (packet->payload_packet_len == a) { IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "found pplive over tcp with pattern viii.\n"); ipoque_int_pplive_add_connection(ipoque_struct); return; } } } } } } } } IPQ_LOG(IPOQUE_PROTOCOL_PPLIVE, ipoque_struct, IPQ_LOG_DEBUG, "exclude pplive.\n"); IPOQUE_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, IPOQUE_PROTOCOL_PPLIVE); }
static void ndpi_search_gadugadu_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; struct ndpi_id_struct *src = flow->src; struct ndpi_id_struct *dst = flow->dst; if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_GADUGADU) { if (src != NULL) src->gg_timeout = packet->tick_timestamp; if (dst != NULL) dst->gg_timeout = packet->tick_timestamp; if (packet->payload_packet_len == 311) { if (packet->payload[28] != 0) { if (src != NULL) { src->gg_timeout = packet->tick_timestamp; if (ntohs(packet->tcp->dest) == 8074 || ntohs(packet->tcp->dest) == 443) src->gadu_gadu_ft_direction = 0; else src->gadu_gadu_ft_direction = 1; src->gadu_gadu_voice = 0; } if (dst != NULL) { dst->gg_timeout = packet->tick_timestamp; if (ntohs(packet->tcp->dest) == 8074 || ntohs(packet->tcp->dest) == 443) dst->gadu_gadu_ft_direction = 0; else dst->gadu_gadu_ft_direction = 1; dst->gadu_gadu_voice = 0; } NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "gg filetransfer setup detected\n"); } else { if (src != NULL) { src->gadu_gadu_voice = 1; src->gg_timeout = packet->tick_timestamp; } if (dst != NULL) { dst->gadu_gadu_voice = 1; dst->gg_timeout = packet->tick_timestamp; } NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "gg voice setup detected \n"); } } return; } #ifdef NDPI_PROTOCOL_HTTP if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP) { #endif NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "Gadu-Gadu: HTTP CHECK FOUND\n"); if (packet->tcp != NULL && ntohs(packet->tcp->dest) == 80) if (check_for_http(ndpi_struct, flow)) return; #ifdef NDPI_PROTOCOL_HTTP } #endif /* the following code is implemented asymmetrically. */ if (packet->tcp != NULL && (ntohs(packet->tcp->dest) == 443 || ntohs(packet->tcp->dest) == 8074 || ntohs(packet->tcp->source) == 443 || ntohs(packet->tcp->source) == 8074)) { NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "Gadu-Gadu: found port 8074 or 443.\n"); if (flow->packet_counter <= 6) { if ((packet->payload_packet_len == 9 || packet->payload_packet_len == 12 || packet->payload_packet_len == 100 || (packet->payload_packet_len > 190 && packet->payload_packet_len < 210) ) && get_l32(packet->payload, 4) == packet->payload_packet_len - 8 && (ntohl(get_u_int32_t(packet->payload, 0)) == 0x01000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x02000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x03000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x12000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x19000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x31000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x35000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x10000000 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x15000000)) { flow->l4.tcp.gadugadu_stage++; NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "Gadu-Gadu: len=9,12,100,190-210, stage++.\n"); } /*detection of mirinda client .this has a different way of communicating ports */ if (packet->payload_packet_len == 114 && ntohl(get_u_int32_t(packet->payload, 0)) == 0x19000000 && get_l32(packet->payload, 4) == packet->payload_packet_len - 8) { flow->l4.tcp.gadugadu_stage++; NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "Gadu-Gadu: len=114, stage++.\n"); /* here the asymmetric implementation ends */ if (flow->l4.tcp.gadugadu_stage == 2) { if (src != NULL) { memcpy(src->gg_call_id[src->gg_next_id], &packet->payload[8], 4); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "call id parsed %d\n", packet->payload[8]); src->gg_ft_ip_address = get_u_int32_t(packet->payload, 86); src->gg_ft_port = htons(get_u_int16_t(packet->payload, 90)); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "mirinda file transfer port %d \n", ntohs(src->gg_ft_port)); } if (dst != NULL) { memcpy(dst->gg_call_id[dst->gg_next_id], &packet->payload[8], 4); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "call id parsed %d\n", packet->payload[8]); dst->gg_ft_ip_address = get_u_int32_t(packet->payload, 86); dst->gg_ft_port = htons(get_u_int16_t(packet->payload, 90)); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "mirinda file transfer port %d \n", ntohs(dst->gg_ft_port)); } } } if (flow->l4.tcp.gadugadu_stage == 2) { NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "Gadu-Gadu: add connection.\n"); ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); } return; } } /*mirinda file detection */ if (packet->tcp != NULL && src != NULL) { if (NDPI_COMPARE_PROTOCOL_TO_BITMASK (src->detected_protocol_bitmask, NDPI_PROTOCOL_GADUGADU) != 0 && ((src->gg_ft_ip_address == packet->iph->saddr && src->gg_ft_port == packet->tcp->source) || (src->gg_ft_ip_address == packet->iph->daddr && src->gg_ft_port == packet->tcp->dest))) { if ((packet->tick_timestamp - src->gg_timeout) < ndpi_struct->gadugadu_peer_connection_timeout) { ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "file transfer detected %d\n", ntohs(packet->tcp->dest)); return; } else { src->gg_ft_ip_address = 0; src->gg_ft_port = 0; } } else if (NDPI_COMPARE_PROTOCOL_TO_BITMASK (src->detected_protocol_bitmask, NDPI_PROTOCOL_GADUGADU) != 0 && (packet->tcp->dest == htons(80) || packet->tcp->source == htons(80)) && packet->payload_packet_len == 12 && (memcmp(src->gg_call_id[0], &packet->payload[5], 4) == 0 || (src->gg_call_id[1][0] && (memcmp(src->gg_call_id[1], &packet->payload[5], 4) == 0)))) { if ((packet->tick_timestamp - src->gg_timeout) < ndpi_struct->gadugadu_peer_connection_timeout) { ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "http file transfer detetced \n"); return; } else { NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "http file transfer timeout \n"); } } else if (NDPI_COMPARE_PROTOCOL_TO_BITMASK (src->detected_protocol_bitmask, NDPI_PROTOCOL_GADUGADU) != 0 && packet->payload_packet_len == 8 && (memcmp(src->gg_call_id[0], &packet->payload[0], 4) == 0 || (src->gg_call_id[1][0] && (memcmp (src->gg_call_id[1], &packet->payload[0], 4) == 0)))) { if ((packet->tick_timestamp - src->gg_timeout) < ndpi_struct->gadugadu_peer_connection_timeout) { ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "file transfer detetced %d\n", htons(packet->tcp->dest)); return; } else { NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, " file transfer timeout \n"); } } } if (packet->tcp != NULL && dst != NULL) { if (NDPI_COMPARE_PROTOCOL_TO_BITMASK (dst->detected_protocol_bitmask, NDPI_PROTOCOL_GADUGADU) != 0 && ((dst->gg_ft_ip_address == packet->iph->saddr && dst->gg_ft_port == packet->tcp->source) || (dst->gg_ft_ip_address == packet->iph->daddr && dst->gg_ft_port == packet->tcp->dest))) { if ((packet->tick_timestamp - dst->gg_timeout) < ndpi_struct->gadugadu_peer_connection_timeout) { ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "file transfer detected %d\n", ntohs(packet->tcp->dest)); return; } else { dst->gg_ft_ip_address = 0; dst->gg_ft_port = 0; } } else if (NDPI_COMPARE_PROTOCOL_TO_BITMASK (dst->detected_protocol_bitmask, NDPI_PROTOCOL_GADUGADU) != 0 && (packet->tcp->dest == htons(80) || packet->tcp->source == htons(80)) && packet->payload_packet_len == 12 && (memcmp(dst->gg_call_id[0], &packet->payload[0], 4) == 0 || (dst->gg_call_id[1][0] && (memcmp(dst->gg_call_id[1], &packet->payload[0], 4) == 0)))) { if ((packet->tick_timestamp - dst->gg_timeout) < ndpi_struct->gadugadu_peer_connection_timeout) { ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "http file transfer detetced \n"); return; } else { NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "http file transfer timeout \n"); } } else if (NDPI_COMPARE_PROTOCOL_TO_BITMASK (dst->detected_protocol_bitmask, NDPI_PROTOCOL_GADUGADU) != 0 && packet->payload_packet_len == 8 && (memcmp(dst->gg_call_id[0], &packet->payload[0], 4) == 0 || (dst->gg_call_id[1][0] && (memcmp (dst->gg_call_id[1], &packet->payload[0], 4) == 0)))) { if ((packet->tick_timestamp - dst->gg_timeout) < ndpi_struct->gadugadu_peer_connection_timeout) { ndpi_int_gadugadu_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL); NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, "file transfer detected %d\n", ntohs(packet->tcp->dest)); return; } else { NDPI_LOG(NDPI_PROTOCOL_GADUGADU, ndpi_struct, NDPI_LOG_DEBUG, " file transfer timeout \n"); } } } /** newly added start **/ if (packet->tcp != NULL && ((ntohs(packet->tcp->dest) == 80) || (ntohs(packet->tcp->source) == 80))) { if (check_for_gadugadu_payload_pattern(ndpi_struct, flow)) { return; } } NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_GADUGADU); }