diff options
author | Matteo Bracci <matteobracci1@gmail.com> | 2015-07-17 13:38:41 +0200 |
---|---|---|
committer | Matteo Bracci <matteobracci1@gmail.com> | 2015-07-17 13:38:41 +0200 |
commit | 5f460c95ccdf2a95ff49aae04710aedceffbeac1 (patch) | |
tree | 72fca12ff75133809fa7b68d1b103b72b0d6d88e /src | |
parent | 73358d5ec2f877ca30ac0b20c12530d1f338ca5b (diff) |
Create starcraft2.c
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/protocols/starcraft2.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/src/lib/protocols/starcraft2.c b/src/lib/protocols/starcraft2.c new file mode 100644 index 000000000..1f91df573 --- /dev/null +++ b/src/lib/protocols/starcraft2.c @@ -0,0 +1,280 @@ +/* +* starcraft2.c +* +* Copyright (C) 2009-2011 by ipoque GmbH +* Copyright (C) 2011-15 - ntop.org +* +* This file is part of nDPI, an open source deep packet inspection +* library based on the OpenDPI and PACE technology by ipoque GmbH +* +* nDPI is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* nDPI is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with nDPI. If not, see <http://www.gnu.org/licenses/>. +* +*/ + + +#include "ndpi_protocols.h" +#ifdef NDPI_PROTOCOL_STARCRAFT2 + +<<<<<<< HEAD +/* +HTTP traffic seems to almost exclusively be requests for xml docs, jpgs or .s2* files. +The first two are easy to detect, for the latter a partial string search is needed. +*/ +u_int8_t ndpi_check_starcraft2_http(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) +{ + struct ndpi_packet_struct* packet = &flow->packet; + //printf("HTTP Test\n"); + if (packet->user_agent_line.ptr == NULL) + ndpi_parse_packet_line_info(ndpi_struct, flow); + + /* First look for the Battle.net client user agent */ + if (packet->user_agent_line.ptr != NULL + && packet->user_agent_line.len == NDPI_STATICSTRING_LEN("Battle.net Web Client") + && match_first_bytes(packet->user_agent_line.ptr, "Battle.net Web Client")) + { + /* Now make sure it's actually Starcraft 2 and not some other Blizzard software */ + + /* The destination port has to be either 1119 or 80 */ + if (packet->tcp->dest != htons(1119) && packet->tcp->dest != htons(80)) + return 0; + + if (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("GET /") + && match_first_bytes(packet->payload, "GET /")) + { + + /* Requests may start with a semi common pattern... */ + if (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("S2") + && match_first_bytes(packet->payload + NDPI_STATICSTRING_LEN("GET /"), "S2")) + return 1; + + + if (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("s2") + && match_first_bytes(packet->payload + NDPI_STATICSTRING_LEN("GET /"), "s2")) + return 1; + + if (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("sc2") + && match_first_bytes(packet->payload + NDPI_STATICSTRING_LEN("GET /"), "sc2")) + return 1; + + /* ..or end with a specific file format. */ + int i = 0; + while (i < packet->payload_packet_len && packet->payload[i] != '.') /* look for the extension of the requested file */ + i++; + + if (i + 5 < packet->payload_packet_len && packet->payload[i] == '.' + && match_first_bytes(packet->payload + i + 1, "s2") /* the format can be one between s2mh, s2ml, s2mv, s2ma, s2qh */ + && match_first_bytes(packet->payload + i + 5, " ")) /* make sure the file name is over and it's not just a lucky coincidence */ + return 1; + } + } + + return 2; +} + +======= +>>>>>>> FETCH_HEAD +u_int8_t sc2_using_bnetgame_tcp_port(struct ndpi_packet_struct* packet) +{ + return ((packet->tcp->source == htons(1119)) || (packet->tcp->dest == htons(1119))); +} + +u_int8_t sc2_using_bnetgame_udp_port(struct ndpi_packet_struct* packet) +{ + return ((packet->udp->source == htons(1119)) || (packet->udp->dest == htons(1119))); +} + +u_int8_t sc2_match_logon_ip(struct ndpi_packet_struct* packet) +{ + u_int32_t source_ip = ntohl(packet->iph->saddr); + u_int32_t dest_ip = ntohl(packet->iph->daddr); + return (ndpi_ips_match(source_ip, dest_ip, 0xD5F87F82, 32) // EU 213.248.127.130 + || ndpi_ips_match(source_ip, dest_ip, 0x0C81CE82, 32) // US 12.129.206.130 + || ndpi_ips_match(source_ip, dest_ip, 0x79FEC882, 32) // KR 121.254.200.130 + || ndpi_ips_match(source_ip, dest_ip, 0xCA09424C, 32) // SG 202.9.66.76 + || ndpi_ips_match(source_ip, dest_ip, 0x0C81ECFE, 32)); // BETA 12.129.236.254 +} + +/* +The main TCP flow starts with the user login and stays alive until the logout. +<<<<<<< HEAD +Although hard to read, judging from what happens elsewhere this flow probably contains all the data +transfer generated by the user interaction with the client, e.g. chatting or looking at someone's +======= +Although hard to read, judging from what happens elsewhere this flow probably contains all the data +transfer generated by the user interaction with the client, e.g. chatting or looking at someone's +>>>>>>> FETCH_HEAD +match history. The current way to detect this is plain dumb packet matching. +*/ +u_int8_t ndpi_check_starcraft2_tcp(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) +{ + if (!sc2_match_logon_ip(&flow->packet)) + return 2; + + if (flow->packet.payload_packet_len >= 10 + && match_first_bytes(flow->packet.payload, "\x4a\x00\x00\x0a\x66\x02\x0a\xed\x2d\x66")) + return 1; + + return 0; +} + +/* +UPD traffic is the actual game data and it uses a port owned by Blizzard itself, 1119. Therefore the +<<<<<<< HEAD +real key point here is to make sure that it's actually Starcraft 2 that is using the port and not +======= +real key point here is to make sure that it's actually Starcraft 2 that is using the port and not +>>>>>>> FETCH_HEAD +some other Blizzard software. +The flow is taken if a pattern in the size of some subsequent packets is found. +*/ +u_int8_t ndpi_check_starcraft2_udp(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) +{ + struct ndpi_packet_struct* packet = &flow->packet; + + /* First filter out traffic not using port 1119 */ + if (!sc2_using_bnetgame_udp_port(packet)) + return 2; + +<<<<<<< HEAD + /* Then use a simple automa to detect the size pattern */ + switch (flow->starcraft2_udp_stage) + { + case 0: + start: + if (packet->payload_packet_len == 548) + flow->starcraft2_udp_stage = 1; + else + flow->starcraft2_udp_stage = 0; + break; + case 1: + if (packet->payload_packet_len == 548) + flow->starcraft2_udp_stage = 2; + else + goto start; + break; + case 2: + if (packet->payload_packet_len == 548) +======= + /* Then use a simple automaton to detect the size pattern */ + switch (flow->starcraft2_udp_stage) + { + case 0: + start : + if (packet->payload_packet_len == 548) + flow->starcraft2_udp_stage = 1; + else + flow->starcraft2_udp_stage = 0; + break; + case 1: + if (packet->payload_packet_len == 548) + flow->starcraft2_udp_stage = 2; + else + goto start; + break; + case 2: + if (packet->payload_packet_len == 548) +>>>>>>> FETCH_HEAD + flow->starcraft2_udp_stage = 3; + else + goto start; + break; + case 3: +<<<<<<< HEAD + if (packet->payload_packet_len == 484) + return 1; + else +======= + if (packet->payload_packet_len == 484) + return 1; + else +>>>>>>> FETCH_HEAD + goto start; + break; + } + + return 0; +} + +void ndpi_check_starcraft2(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) +{ + struct ndpi_packet_struct* packet = &flow->packet; + u_int8_t result = 0; +<<<<<<< HEAD + u_int8_t kill = 0; +======= +>>>>>>> FETCH_HEAD + + if (packet->udp != NULL) + { + result = ndpi_check_starcraft2_udp(ndpi_struct, flow); +<<<<<<< HEAD + kill = result == 2; + if(result == 1) +======= + if (result == 1) +>>>>>>> FETCH_HEAD + { + printf("Found Starcraft 2 [Game, UDP]\n"); + NDPI_LOG(NDPI_PROTOCOL_STARCRAFT2, ndpi_struct, NDPI_LOG_DEBUG, "Found Starcraft 2 [Game, UDP]\n"); + } + } + else if (packet->tcp != NULL) + { +<<<<<<< HEAD + result = ndpi_check_starcraft2_http(ndpi_struct, flow); + kill = result == 2; + if (result == 1) + { + printf("Found Starcraft 2 [Client, HTTP]\n"); + NDPI_LOG(NDPI_PROTOCOL_STARCRAFT2, ndpi_struct, NDPI_LOG_DEBUG, "Found Starcraft 2 [Client, HTTP]\n"); + } + else + { + result = ndpi_check_starcraft2_tcp(ndpi_struct, flow); + kill = kill || result == 2; + if (result == 1) + { + printf("Found Starcraft 2 [Client, TCP]\n"); + NDPI_LOG(NDPI_PROTOCOL_STARCRAFT2, ndpi_struct, NDPI_LOG_DEBUG, "Found Starcraft 2 [Client, TCP]\n"); + } +======= + result = ndpi_check_starcraft2_tcp(ndpi_struct, flow); + if (result == 1) + { + printf("Found Starcraft 2 [Client, TCP]\n"); + NDPI_LOG(NDPI_PROTOCOL_STARCRAFT2, ndpi_struct, NDPI_LOG_DEBUG, "Found Starcraft 2 [Client, TCP]\n"); +>>>>>>> FETCH_HEAD + } + } + + if (result == 1) + ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STARCRAFT2, NDPI_REAL_PROTOCOL); +<<<<<<< HEAD + else if (kill) +======= + else if (result == 2) +>>>>>>> FETCH_HEAD + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_STARCRAFT2); +} + +void ndpi_search_starcraft2(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) +{ + NDPI_LOG(NDPI_PROTOCOL_STARCRAFT2, ndpi_struct, NDPI_LOG_DEBUG, "Starcraft2 protocol detection...\n"); + if (flow->packet.detected_protocol_stack[0] != NDPI_PROTOCOL_STARCRAFT2) + { + ndpi_check_starcraft2(ndpi_struct, flow); + } +} + +#endif |