├── Introduction └── OS-Fingerprinting ├── Attack ├── Makefile ├── interface_ip.c ├── interface_ip.cpp ├── net_utils.c ├── net_utils.h ├── ofp_tool ├── tool.c ├── tool.cpp └── tool.h ├── Detection ├── Makefile ├── detect.c ├── detect.h ├── interface_ip.c ├── net_utils.c └── net_utils.h ├── README.md └── TCP-IP Stack Parameters ├── Makefile ├── a.out ├── change ├── change.c ├── default ├── default.c └── readme /Introduction: -------------------------------------------------------------------------------- 1 | Passive OS detection using fingerprinting technique TCP/IP protocols. Detection of OS has been the starting step for any cyber security service and it can be done either by passive finger printing or active fingerprinting.There are in built tools like Nmap ,Zenmap,Ettercap,pOf in Kali Linux which can be used to detect the OS and much more info of the system.In this project we have implemented only passive OS finger printing technique 2 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/Makefile: -------------------------------------------------------------------------------- 1 | all: tool 2 | 3 | tool: clean 4 | g++ -g -Wno-deprecated net_utils.h net_utils.c tool.cpp -o ofp_tool -lpcap -lpthread 5 | 6 | clean: 7 | rm -rf *~ ofp_tool 8 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/interface_ip.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for ifstream 3 | #include // for cout and endl 4 | #include // for unlink() 5 | #include 6 | 7 | 8 | std::string interface_ip() 9 | { 10 | // attempt to obtain ifconfig information 11 | system( "/sbin/ifconfig eth0 2> /dev/null" 12 | "| /bin/grep -m 1 addr: | /usr/bin/cut -d : -f2" 13 | "| /usr/bin/cut -d ' ' -f1 > /tmp/sysinfo;" ); 14 | 15 | system( "/sbin/ifconfig eth0 2> /dev/null" 16 | "| /bin/grep -m 1 Bcast: | /usr/bin/cut -d : -f3" 17 | "| /usr/bin/cut -d ' ' -f1 >> /tmp/sysinfo;" ); 18 | 19 | system( "/sbin/ifconfig eth0 2> /dev/null" 20 | "| /bin/grep -m 1 Mask: | /usr/bin/cut -d : -f4 >> /tmp/sysinfo;" ); 21 | 22 | // read ifconfig information from flat-file 23 | const std::string TBD("unknown"); 24 | std::string ipAddr(TBD); 25 | std::string broadcast(TBD ); 26 | std::string netmask(TBD ); 27 | 28 | std::ifstream sysinfo("/tmp/sysinfo"); 29 | 30 | if (sysinfo) 31 | { 32 | if (sysinfo.peek() != '\0') 33 | { 34 | sysinfo >> ipAddr; 35 | } 36 | if (sysinfo.peek() != '\0') 37 | { 38 | sysinfo >> broadcast; 39 | } 40 | if (sysinfo.peek() != '\0') 41 | { 42 | sysinfo >> netmask; 43 | } 44 | 45 | sysinfo.close(); 46 | 47 | unlink("/tmp/sysinfo"); 48 | } 49 | 50 | //std::cout << "IP = " << ipAddr << std::endl; 51 | //std::cout << "BCAST = " << broadcast << std::endl; 52 | //std::cout << "MASK = " << netmask << std::endl; 53 | 54 | return ipAddr; 55 | }//end interface_ip 56 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/interface_ip.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for ifstream 3 | #include // for cout and endl 4 | #include // for unlink() 5 | #include 6 | 7 | 8 | std::string interface_ip() 9 | { 10 | // attempt to obtain ifconfig information 11 | system( "/sbin/ifconfig eth0 2> /dev/null" 12 | "| /bin/grep -m 1 addr: | /usr/bin/cut -d : -f2" 13 | "| /usr/bin/cut -d ' ' -f1 > /tmp/sysinfo;" ); 14 | 15 | system( "/sbin/ifconfig eth0 2> /dev/null" 16 | "| /bin/grep -m 1 Bcast: | /usr/bin/cut -d : -f3" 17 | "| /usr/bin/cut -d ' ' -f1 >> /tmp/sysinfo;" ); 18 | 19 | system( "/sbin/ifconfig eth0 2> /dev/null" 20 | "| /bin/grep -m 1 Mask: | /usr/bin/cut -d : -f4 >> /tmp/sysinfo;" ); 21 | 22 | // read ifconfig information from flat-file 23 | const std::string TBD("unknown"); 24 | std::string ipAddr(TBD); 25 | std::string broadcast(TBD ); 26 | std::string netmask(TBD ); 27 | 28 | std::ifstream sysinfo("/tmp/sysinfo"); 29 | 30 | if (sysinfo) 31 | { 32 | if (sysinfo.peek() != '\0') 33 | { 34 | sysinfo >> ipAddr; 35 | } 36 | if (sysinfo.peek() != '\0') 37 | { 38 | sysinfo >> broadcast; 39 | } 40 | if (sysinfo.peek() != '\0') 41 | { 42 | sysinfo >> netmask; 43 | } 44 | 45 | sysinfo.close(); 46 | 47 | unlink("/tmp/sysinfo"); 48 | } 49 | 50 | //std::cout << "IP = " << ipAddr << std::endl; 51 | //std::cout << "BCAST = " << broadcast << std::endl; 52 | //std::cout << "MASK = " << netmask << std::endl; 53 | 54 | return ipAddr; 55 | }//end interface_ip 56 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/net_utils.c: -------------------------------------------------------------------------------- 1 | #include "net_utils.h" 2 | 3 | uint16_t calc_cksum(uint8_t* hdr, int len) 4 | { 5 | long sum = 0; 6 | 7 | while(len > 1) 8 | { 9 | sum += *((unsigned short*)hdr); 10 | hdr = hdr + 2; 11 | if(sum & 0x80000000) 12 | { 13 | sum = (sum & 0xFFFF) + (sum >> 16); 14 | } 15 | len -= 2; 16 | } 17 | 18 | if(len) 19 | { 20 | sum += (unsigned short) *(unsigned char *)hdr; 21 | } 22 | 23 | while(sum>>16) 24 | { 25 | sum = (sum & 0xFFFF) + (sum >> 16); 26 | } 27 | 28 | return ~sum; 29 | } 30 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/net_utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | 22 | #define TCPOPT_EOL 0 /* End of options */ 23 | #define TCPOPT_NOP 1 /* Nothing */ 24 | #define TCPOPT_MAXSEG 2 /* MSS */ 25 | #define TCPOPT_WSCALE 3 /* Window scaling */ 26 | #define TCPOPT_SACKOK 4 /* Selective ACK permitted */ 27 | #define TCPOPT_TIMESTAMP 8 /* Stamp out timestamping! */ 28 | 29 | 30 | #ifndef IP_NO_FRAGMENT 31 | #define IP_NO_FRAGMENT 0x4000 32 | #endif 33 | 34 | #ifndef IP_PROTO_ICMP 35 | #define IP_PROTO_ICMP 1 /* ICMP protocol */ 36 | #endif 37 | 38 | #ifndef IP_PROTO_TCP 39 | #define IP_PROTO_TCP 6 /* TCP protocol */ 40 | #endif 41 | 42 | #ifndef IP_PROTO_UDP 43 | #define IP_PROTO_UDP 17 /* UDP protocol */ 44 | #endif 45 | 46 | #define ICMP_ECHO_REQUEST_TYPE 8 47 | #define ICMP_ECHO_REQUEST_CODE 0 48 | 49 | #define ICMP_ECHO_REPLY_TYPE 0 50 | #define ICMP_ECHO_REPLY_CODE 0 51 | 52 | #define ICMP_ECHO_REQUEST_DATA_LENGTH 50 53 | 54 | struct ip_hdr 55 | { 56 | #if __BYTE_ORDER == __LITTLE_ENDIAN 57 | unsigned int ip_hl:4; /* header length */ 58 | unsigned int ip_v:4; /* version */ 59 | #elif __BYTE_ORDER == __BIG_ENDIAN 60 | unsigned int ip_v:4; /* version */ 61 | unsigned int ip_hl:4; /* header length */ 62 | #else 63 | #error "Byte ordering not specified " 64 | #endif 65 | uint8_t ip_tos; /* type of service */ 66 | uint16_t ip_len; /* total length */ 67 | uint16_t ip_id; /* identification */ 68 | uint16_t ip_off; /* fragment offset field */ 69 | #define IP_RF 0x8000 /* reserved fragment flag */ 70 | #define IP_DF 0x4000 /* dont fragment flag */ 71 | #define IP_MF 0x2000 /* more fragments flag */ 72 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 73 | uint8_t ip_ttl; /* time to live */ 74 | uint8_t ip_p; /* protocol */ 75 | uint16_t ip_sum; /* checksum */ 76 | struct in_addr ip_src, ip_dst; /* source and dest address */ 77 | } __attribute__ ((packed)); 78 | 79 | struct icmp_hdr 80 | { 81 | uint8_t icmp_type; /* type of the ICMP */ 82 | uint8_t icmp_code; /* code of the ICMO */ 83 | uint16_t icmp_cksum; /* checksum */ 84 | uint16_t icmp_id; /* identification */ 85 | uint16_t icmp_seq_n; /* sequence number */ 86 | } __attribute__ ((packed)); 87 | 88 | struct tcp_hdr 89 | { 90 | uint16_t tcp_src_prt; 91 | uint16_t tcp_dst_prt; 92 | uint32_t tcp_seq_num; 93 | uint32_t tcp_ack_num; 94 | #if __BYTE_ORDER == __LITTLE_ENDIAN 95 | unsigned int tcp_rsrvd:4; 96 | unsigned int tcp_dt_ofst:4; 97 | #elif __BYTE_ORDER == __BIG_ENDIAN 98 | unsigned int tcp_dt_ofst:4; 99 | unsigned int tcp_rsrvd:4; 100 | #else 101 | #error "Byte ordering not specified " 102 | #endif 103 | uint8_t tcp_flags; 104 | uint16_t tcp_window; 105 | uint16_t tcp_cksum; 106 | uint16_t tcp_urg_ptr; 107 | } __attribute__ ((packed)); 108 | 109 | 110 | struct ps_tcp_hdr 111 | { 112 | uint32_t src_addr; 113 | uint32_t dst_addr; 114 | uint8_t rsrv; 115 | uint8_t proto; 116 | uint16_t tcp_len; 117 | 118 | 119 | } __attribute__ ((packed)); 120 | 121 | 122 | 123 | uint16_t calc_cksum(uint8_t*, int); 124 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/ofp_tool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agirishkumar/passive-os-detection/b279b6f8e414aa08b84e724c6d425a8daf45d032/OS-Fingerprinting/Attack/ofp_tool -------------------------------------------------------------------------------- /OS-Fingerprinting/Attack/tool.c: -------------------------------------------------------------------------------- 1 | #include "interface_ip.c" 2 | #include "tool.h" 3 | 4 | using std::string; 5 | using std::istringstream; 6 | 7 | 8 | /* DEFINE THE PARAMETERS NEEDED FOR THE CONNECTION */ 9 | #define TCP_SOURCE_PORT 10567 10 | #define TCP_DEST_PORT 80 11 | 12 | #define MAC_HEADER_LEN 14 13 | 14 | 15 | /* GLOBAL VARIABLES AND FUNCTIONS */ 16 | void initialize_os_matrix(); 17 | void* initialize_sniffer(void*); 18 | void send_http_request(int port_number); 19 | void sniffer(u_char* useless, const struct pcap_pkthdr* pkthdr, const u_char* packet); 20 | void Process_IP(uint8_t * packet, int length); 21 | void Process_TCP(uint8_t * packet, int length); 22 | void Process_ICMP(uint8_t * packet, int length); 23 | void print_decision(); 24 | 25 | 26 | string Banner = ""; // to server version obtained from http reply banner 27 | 28 | struct os_prop os_matrix[KNOWN_OS]; 29 | struct imp_tests tests; 30 | 31 | pthread_t sniffer_thread; 32 | 33 | pcap_t* descr; 34 | 35 | struct in_addr local_ip; 36 | struct in_addr remote_ip; 37 | 38 | 39 | 40 | 41 | int main(int argc, char* argv[]) 42 | { 43 | printf("\n\n"); 44 | 45 | struct timeval tv; 46 | 47 | if (argc != 2) 48 | { 49 | printf("#############################################\n"); 50 | printf("# This tool performs OS fingerprinting #\n"); 51 | printf("# Enter a valid IP in dotted notation #\n"); 52 | printf("# #\n"); 53 | printf("# Example: ofp_tool 192.168.1.45 #\n"); 54 | printf("#############################################\n\n\n"); 55 | return 1; 56 | } 57 | 58 | 59 | initialize_os_matrix(); 60 | 61 | /*to take the ip address of current machine*/ 62 | std::string eth0_ip = interface_ip(); 63 | int addr_len = eth0_ip.length(); 64 | char* my_interface_ip = ((char*)(malloc(sizeof(char) * addr_len + 1 ))); //allocate a string as long as data + 1 (for '\0') 65 | eth0_ip.copy(my_interface_ip,addr_len,0); // copy the ip address of the current machine to my_interface_ip 66 | my_interface_ip[addr_len]='\0'; 67 | 68 | 69 | inet_aton(my_interface_ip, &local_ip); 70 | inet_aton(argv[1], &remote_ip); 71 | 72 | int port_number = 80; 73 | 74 | 75 | printf("Initializing the packet sniffer...\n"); 76 | pthread_create(&sniffer_thread, NULL, initialize_sniffer, NULL); 77 | 78 | for (int i = 0; i < 100000; i++); 79 | sleep(4); 80 | 81 | printf("OS fingerprinting the network device [%s] through port [%d]...\n", argv[1], port_number); 82 | 83 | send_http_request(port_number); 84 | 85 | sleep(4); 86 | 87 | pcap_breakloop(descr); // use this to stop the pcap_loop 88 | 89 | print_decision(); 90 | 91 | //while(1); // to keep the program running since another thread is alive 92 | 93 | printf("\n\n\n"); 94 | 95 | }//end main 96 | 97 | 98 | 99 | void initialize_os_matrix() 100 | { 101 | // 0: "Linux 2.1" 102 | // 1: "Linux 2.0" 103 | // 2: "Linux 2.0.3x" 104 | // 3: "Linux 2.2" 105 | // 4: "Linux 2.4" 106 | // 5: "Linux 2.6" 107 | 108 | // 6: "Windows 3.11" 109 | // 7: "Windows 95" 110 | // 8: "Windows 95b" 111 | // 9: "Windows 98" 112 | //10: "Windows ME no SP" 113 | //11: "Windows NT 4.0 SP6a" 114 | //12: "Windows 2000 SP2+" 115 | //13: "Windows 2000 SP3" 116 | //14: "Windows 2000 SP4" 117 | //15: "Windows XP SP1+" 118 | //16: "Windows 2K3" 119 | //17: "Windows Vista (beta)" 120 | 121 | //18: "MacOS 7.3-8.6 (OTTCP)" 122 | //19: "MacOS 8.1-8.6 (OTTCP)" 123 | //20: "MacOS 8.6" 124 | //21: "MacOS 9.0-9.2" 125 | //22: "MacOS 9.1 (OT 2.7.4)" 126 | //23: "MacOS 10.2.6" 127 | 128 | memset(os_matrix, 0, sizeof(os_prop) * KNOWN_OS); 129 | 130 | strcpy(os_matrix[0].name, "Linux 2.1"); 131 | strcpy(os_matrix[1].name, "Linux 2.0"); 132 | strcpy(os_matrix[2].name, "Linux 2.0.3x"); 133 | strcpy(os_matrix[3].name, "Linux 2.2"); 134 | strcpy(os_matrix[4].name, "Linux 2.4"); 135 | strcpy(os_matrix[5].name, "Linux 2.6"); 136 | 137 | strcpy(os_matrix[6].name, "Windows 3.11"); 138 | strcpy(os_matrix[7].name, "Windows 95"); 139 | strcpy(os_matrix[8].name, "Windows 95b"); 140 | strcpy(os_matrix[9].name, "Windows 98"); 141 | strcpy(os_matrix[10].name, "Windows ME no SP"); 142 | strcpy(os_matrix[11].name, "Windows NT 4.0 SP6a"); 143 | strcpy(os_matrix[12].name, "Windows 2000 SP2+"); 144 | strcpy(os_matrix[13].name, "Windows 2000 SP3"); 145 | strcpy(os_matrix[14].name, "Windows 2000 SP4"); 146 | strcpy(os_matrix[15].name, "Windows XP SP1+"); 147 | strcpy(os_matrix[16].name, "Windows 2K3"); 148 | strcpy(os_matrix[17].name, "Windows Vista (beta)"); 149 | 150 | strcpy(os_matrix[18].name, "MacOS 7.3-8.6 (OTTCP)"); 151 | strcpy(os_matrix[19].name, "MacOS 8.1-8.6 (OTTCP)"); 152 | strcpy(os_matrix[20].name, "MacOS 8.6"); 153 | strcpy(os_matrix[21].name, "MacOS 9.0-9.2"); 154 | strcpy(os_matrix[22].name, "MacOS 9.1 (OT 2.7.4)"); 155 | strcpy(os_matrix[23].name, "MacOS 10.2.6"); 156 | 157 | 158 | 159 | tests.ttl = false; 160 | tests.df = false; 161 | tests.ipid = false; 162 | 163 | tests.tcp_mss = false; 164 | tests.window_scale = false; 165 | tests.window_size = false; 166 | tests.syn_pkt_size = false; 167 | tests.options_order = false; 168 | 169 | tests.banner_grabber = false; 170 | }//end initialize_os_matrix 171 | 172 | 173 | 174 | void* initialize_sniffer(void*) 175 | { 176 | char* dev; 177 | char errbuf[PCAP_ERRBUF_SIZE]; 178 | const u_char *packet; 179 | struct pcap_pkthdr hdr; 180 | struct ether_header *eptr; 181 | 182 | 183 | /* select device to catpture from*/ 184 | dev = pcap_lookupdev(errbuf); 185 | if(dev == NULL) 186 | { 187 | printf("**** Error selecting a decive to capture from ****\n"); 188 | return NULL; 189 | } 190 | 191 | /* open selected device for reading */ 192 | descr = pcap_open_live(dev, BUFSIZ, 0, -1, errbuf); 193 | if(descr == NULL) 194 | { 195 | printf("**** Error opening the selected device for reading ****\n"); 196 | return NULL; 197 | } 198 | 199 | pcap_loop(descr, 0, sniffer, NULL); 200 | }//end initialize_sniffer 201 | 202 | 203 | 204 | void send_http_request(int port_number) 205 | { 206 | int sockfd, portno, n; 207 | struct sockaddr_in serv_addr; 208 | struct hostent *server; 209 | 210 | 211 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 212 | { 213 | printf("**** Error while creating the socket ****\n\n\n"); 214 | return ; 215 | } 216 | 217 | serv_addr.sin_family = AF_INET; 218 | serv_addr.sin_port = htons(port_number); 219 | serv_addr.sin_addr.s_addr = remote_ip.s_addr; 220 | 221 | 222 | if (connect(sockfd, ((sockaddr*)(&serv_addr)), sizeof(serv_addr)) < 0) 223 | { 224 | printf("**** Error while connecting ****\n\n\n"); 225 | return ; 226 | } 227 | 228 | 229 | char* http_request = ((char*)("GET / HTTP/1.0\n\n")); 230 | 231 | send(sockfd, http_request, strlen(http_request), 0); 232 | 233 | /* remove comments for ONLY ONE to shutdown or close the port */ 234 | //close(sockfd); 235 | //shutdown(sockfd,SHUT_RDWR); 236 | }//end send_http_request 237 | 238 | 239 | 240 | void sniffer(u_char* useless, const struct pcap_pkthdr* pkthdr, const u_char* packet) 241 | { 242 | if(!((packet[12] == 8) && (packet[13] == 0))) // ip packet 243 | { 244 | return; 245 | } 246 | 247 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + 14)); 248 | 249 | if((rx_ip_hdr-> ip_src.s_addr != remote_ip.s_addr) || (rx_ip_hdr-> ip_dst.s_addr != local_ip.s_addr)) 250 | { 251 | return; 252 | } 253 | 254 | Process_IP((uint8_t*)packet, pkthdr->len); 255 | 256 | switch(rx_ip_hdr->ip_p) 257 | { 258 | case IP_PROTO_TCP: 259 | Process_TCP((uint8_t*)packet, pkthdr->len); 260 | break; 261 | 262 | case IP_PROTO_ICMP: 263 | Process_ICMP((uint8_t*)packet, pkthdr->len); 264 | break; 265 | 266 | default: 267 | break; 268 | 269 | }//end switch 270 | } //end sniffer 271 | 272 | 273 | 274 | void Process_IP(uint8_t * packet, int length) 275 | { 276 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + 14)); 277 | 278 | int length_ip_header = rx_ip_hdr->ip_hl * 4; // obtain the length of header in bytes to check for options 279 | 280 | 281 | /* TTL Test */ 282 | if (tests.ttl == false) 283 | { 284 | if (rx_ip_hdr->ip_ttl > 0 & rx_ip_hdr->ip_ttl <= 32) 285 | { 286 | os_matrix[6].score += 0.5; // Windows 3.11 287 | os_matrix[9].score += 0.5; // Windows 98 288 | os_matrix[16].score += 0.5; // Windows 2K3 289 | } 290 | else if (rx_ip_hdr->ip_ttl > 32 & rx_ip_hdr->ip_ttl <= 64) 291 | { 292 | os_matrix[0].score += 0.5; // Linux 1.2 293 | os_matrix[1].score += 0.5; // Linux 2.0 294 | os_matrix[2].score += 0.5; // Linux 2.0.3x 295 | os_matrix[3].score += 0.5; // Linux 2.2 296 | os_matrix[4].score += 0.5; // Linux 2.4 297 | os_matrix[5].score += 0.5; // Linux 2.6 298 | 299 | os_matrix[7].score += 0.5; // Windows 95 300 | // Windows 98 [h?] 301 | os_matrix[10].score += 0.5; // Windows ME no SP 302 | os_matrix[16].score += 0.5; // Windows 2K3 303 | 304 | os_matrix[23].score += 0.5; // MacOS 10.2.6 305 | } 306 | else if (rx_ip_hdr->ip_ttl > 64 & rx_ip_hdr->ip_ttl <= 128) 307 | { 308 | os_matrix[8].score += 0.5; // Windows 95b 309 | // Windows 98 [h?] 310 | os_matrix[11].score += 0.5; // Windows NT 4.0 SP6a 311 | os_matrix[12].score += 0.5; // Windows 2K SP2+ 312 | os_matrix[13].score += 0.5; // Windows 2K SP3 313 | os_matrix[14].score += 0.5; // Windows 2K SP4 314 | os_matrix[15].score += 0.5; // Windows XP SP1+ 315 | os_matrix[16].score += 0.5; // Windows 2K3 316 | os_matrix[17].score += 0.5; // Windows Vista (beta) 317 | } 318 | else if (rx_ip_hdr->ip_ttl > 128 & rx_ip_hdr->ip_ttl <= 255) 319 | { 320 | os_matrix[18].score += 0.5; // MacOS 7.3-8.6 321 | os_matrix[19].score += 0.5; // MacOS 8.1-8.6 322 | os_matrix[20].score += 0.5; // MacOS 8.6 323 | os_matrix[21].score += 0.5; // MacOS 9.0-9.2 324 | os_matrix[22].score += 0.5; // MacOS 9.1 325 | } 326 | 327 | tests.ttl = true; 328 | } 329 | 330 | 331 | /* DF Test */ 332 | if (tests.df == false) 333 | { 334 | if ((htons(rx_ip_hdr->ip_off) & 0x4000) == 0x0000) //DF = 0 335 | { 336 | os_matrix[0].score++; // Linux 1.2 337 | os_matrix[1].score++; // Linux 2.0 338 | os_matrix[2].score++; // Linux 2.0.3x 339 | 340 | os_matrix[10].score++; // Windows ME no SP 341 | os_matrix[16].score++; // Windows 2K3 342 | } 343 | else if ((htons(rx_ip_hdr->ip_off) & 0x4000) == 0x4000) //DF = 1 344 | { 345 | os_matrix[3].score++; // Linux 2.2 346 | os_matrix[4].score++; // Linux 2.4 347 | os_matrix[5].score++; // Linux 2.6 348 | 349 | os_matrix[6].score++; // Windows 3.11 350 | os_matrix[7].score++; // Windows 95 351 | os_matrix[8].score++; // Windows 95b 352 | os_matrix[9].score++; // Windows 98 353 | os_matrix[11].score++; // Windows NT 4.0 SP6a 354 | os_matrix[12].score++; // Windows 2K SP2+ 355 | os_matrix[13].score++; // Windows 2K SP3 356 | os_matrix[14].score++; // Windows 2K SP4 357 | os_matrix[15].score++; // Windows XP SP1+ 358 | // Windows 2K3 [h?] 359 | os_matrix[17].score++; // Windows Vista (beta) 360 | 361 | os_matrix[18].score++; // MacOS 7.3-8.6 362 | os_matrix[19].score++; // MacOS 8.1-8.6 363 | os_matrix[20].score++; // MacOS 8.6 364 | os_matrix[21].score++; // MacOS 9.0-9.2 365 | os_matrix[22].score++; // MacOS 9.1 366 | os_matrix[23].score++; // MacOS 10.2.6 367 | } 368 | 369 | tests.df = true; 370 | } 371 | }//end Process_IP 372 | 373 | 374 | 375 | void Process_ICMP(uint8_t * packet, int length) 376 | { 377 | /* No code is added here since we are not 378 | using ICMP packet for IS fingerprinting */ 379 | 380 | }//end function Process_ICMP 381 | 382 | 383 | 384 | void Process_TCP(uint8_t * packet, int length) 385 | { 386 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + 14)); 387 | int length_ip_header = rx_ip_hdr->ip_hl * 4; // obtain the length of header in bytes to check for options 388 | 389 | struct tcp_hdr* rx_tcp_hdr = ((tcp_hdr*)(packet + 14 + length_ip_header)); 390 | int length_tcp_header = rx_tcp_hdr->tcp_dt_ofst * 4; // obtain the length of header in bytes to check for options 391 | int length_tcp_options = length_tcp_header - 20; 392 | 393 | 394 | 395 | uint16_t tcp_mss = 0; 396 | int window_scale = -1; 397 | 398 | if ((rx_tcp_hdr->tcp_flags & 2) == 2) 399 | { 400 | /* Getting TCP MSS and Window Scale from TCP options */ 401 | int option_index = 0; 402 | bool end_of_options = false; 403 | while(end_of_options == false & option_index < length_tcp_options) 404 | { 405 | switch(packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index]) 406 | { 407 | case TCPOPT_EOL: 408 | end_of_options = true; 409 | break; 410 | 411 | case TCPOPT_NOP: 412 | option_index++; 413 | break; 414 | 415 | case TCPOPT_MAXSEG: 416 | tcp_mss = (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2] * 256) + 417 | packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 3]; 418 | option_index += 4; 419 | break; 420 | 421 | case TCPOPT_WSCALE: 422 | window_scale = packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2]; 423 | option_index += 3; 424 | break; 425 | 426 | case TCPOPT_SACKOK: 427 | option_index += 2; 428 | break; 429 | 430 | case TCPOPT_TIMESTAMP: 431 | option_index += 10; 432 | break; 433 | } 434 | } 435 | 436 | 437 | /* Checking TCP MMS */ 438 | if(tests.tcp_mss == false) 439 | { 440 | if (tcp_mss == 1380) 441 | { 442 | os_matrix[22].score++; // MacOS 9.1 443 | } 444 | 445 | tests.tcp_mss = true; 446 | } 447 | 448 | 449 | /* Window Scale Test */ 450 | if(tests.window_scale == false) 451 | { 452 | if (window_scale == -1) //no window scale appears in tcp options 453 | { 454 | os_matrix[0].score++; // Linux 1.2 455 | os_matrix[1].score++; // Linux 2.0 456 | os_matrix[2].score++; // Linux 2.0.3x 457 | 458 | os_matrix[6].score++; // Windows 3.11 459 | os_matrix[7].score++; // Windows 95 460 | os_matrix[8].score++; // Windows 95b 461 | os_matrix[9].score++; // Windows 98 462 | os_matrix[10].score++; // Windows ME no SP 463 | os_matrix[11].score++; // Windows NT 4.0 SP6a 464 | os_matrix[12].score++; // Windows 2K SP2+ 465 | os_matrix[13].score++; // Windows 2K SP3 466 | // Windows 2K SP4 [h?] 467 | os_matrix[15].score++; // Windows XP SP1+ 468 | os_matrix[16].score++; // Windows 2K3 469 | 470 | os_matrix[19].score++; // MacOS 8.1-8.6 471 | os_matrix[22].score++; // MacOS 9.1 472 | } 473 | else if (window_scale == 0) 474 | { 475 | os_matrix[3].score++; // Linux 2.2 476 | os_matrix[4].score++; // Linux 2.4 477 | os_matrix[5].score++; // Linux 2.6 478 | 479 | // Windows 98 [h?] 480 | // Windows 2K SP4 [h?] 481 | os_matrix[15].score++; // Windows XP SP1+ 482 | os_matrix[16].score++; // Windows 2K3 483 | 484 | os_matrix[18].score++; // MacOS 7.3-8.6 485 | os_matrix[20].score++; // MacOS 8.6 486 | os_matrix[21].score++; // MacOS 9.0-9.2 487 | os_matrix[23].score++; // MacOS 10.2.6 488 | } 489 | else if (window_scale == 1) 490 | { 491 | os_matrix[4].score++; // Linux 2.4 492 | os_matrix[5].score++; // Linux 2.6 493 | } 494 | else if (window_scale == 2) 495 | { 496 | os_matrix[4].score++; // Linux 2.4 497 | os_matrix[5].score++; // Linux 2.6 498 | 499 | // Windows 98 [h?] 500 | os_matrix[16].score++; // Windows 2K3 501 | } 502 | 503 | // Windows 98 [h?] wc = 3 504 | 505 | else if ((window_scale == 5) | (window_scale == 6) | (window_scale == 7)) 506 | { 507 | os_matrix[5].score++; // Linux 2.6 508 | } 509 | else if (window_scale == 8) 510 | { 511 | os_matrix[17].score++; // Windows Vista (beta) 512 | } 513 | 514 | tests.window_scale = true; 515 | } 516 | 517 | 518 | /* Window Size Test */ 519 | if(tests.window_size == false) 520 | { 521 | int temp_window = htons(rx_tcp_hdr->tcp_window); 522 | 523 | if ((temp_window <= (tcp_mss + 50)) & (temp_window >= (tcp_mss - 50))) 524 | { 525 | os_matrix[0].score++; // Linux 1.2 526 | } 527 | 528 | if ((temp_window <= (32736 + 70)) & (temp_window >= (32736 - 70))) 529 | { 530 | os_matrix[1].score++; // Linux 2.0 531 | } 532 | 533 | if (((temp_window <= (512 + 50)) & (temp_window >= (512 - 50))) | 534 | ((temp_window <= (16384 + 70)) & (temp_window >= (16384 - 70)))) 535 | { 536 | // Linux 2.0.3x [h?] 537 | } 538 | 539 | 540 | if (((temp_window <= (tcp_mss * 11) + 70) & (temp_window >= (tcp_mss * 11) - 70 )) | 541 | ((temp_window <= (tcp_mss * 20) + 70) & (temp_window >= (tcp_mss * 20) - 70 ))) 542 | { 543 | os_matrix[3].score++; // Linux 2.2 544 | } 545 | 546 | if (((temp_window <= (tcp_mss * 2) + 70) & (temp_window >= (tcp_mss * 2) - 70 )) | 547 | ((temp_window <= (tcp_mss * 3) + 70) & (temp_window >= (tcp_mss * 3) - 70 )) | 548 | ((temp_window <= (tcp_mss * 4) + 70) & (temp_window >= (tcp_mss * 4) - 70 ))) 549 | { 550 | os_matrix[4].score++; // Linux 2.4 551 | os_matrix[5].score++; // Linux 2.6 552 | } 553 | 554 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70))) 555 | { 556 | os_matrix[6].score++; // Windows 3.11 557 | } 558 | 559 | if (((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 ))) 560 | { 561 | os_matrix[7].score++; // Windows 95 562 | } 563 | 564 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70))) 565 | { 566 | os_matrix[8].score++; // Windows 95b 567 | } 568 | 569 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 570 | (temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70)) | 571 | (temp_window <= (32767 + 70)) & (temp_window >= (32767 - 70)) | 572 | (temp_window <= (37300 + 70)) & (temp_window >= (37300 - 70)) | 573 | (temp_window <= (46080 + 70)) & (temp_window >= (46080 - 70)) | 574 | (temp_window <= (60352 + 70)) & (temp_window >= (60352 - 70)) | 575 | ((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 )) | 576 | ((temp_window <= (tcp_mss * 4) + 70) & (temp_window >= (tcp_mss * 4) - 70 )) | 577 | ((temp_window <= (tcp_mss * 6) + 70) & (temp_window >= (tcp_mss * 6) - 70 )) | 578 | ((temp_window <= (tcp_mss * 12) + 70) & (temp_window >= (tcp_mss * 12) - 70 )) | 579 | ((temp_window <= (tcp_mss * 16) + 70) & (temp_window >= (tcp_mss * 16) - 70 )) | 580 | ((temp_window <= (tcp_mss * 26) + 70) & (temp_window >= (tcp_mss * 26) - 70 ))) 581 | { 582 | os_matrix[9].score++; // Windows 98 583 | } 584 | 585 | if ((temp_window <= (44620 + 70)) & (temp_window >= (44620 - 70))) 586 | { 587 | os_matrix[10].score++; // Windows ME no SP 588 | } 589 | 590 | if ((temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70))) 591 | { 592 | os_matrix[11].score++; // Windows NT 4.0 SP6a 593 | } 594 | 595 | if ((temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70))) 596 | { 597 | os_matrix[11].score++; // Windows NT 4.0 SP6a 598 | } 599 | 600 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70)) | 601 | ((temp_window <= (tcp_mss * 6) + 70) & (temp_window >= (tcp_mss * 6) - 70 ))) 602 | { 603 | os_matrix[12].score++; // Windows 2K SP2+ 604 | } 605 | 606 | if ((temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70)) | 607 | ((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 ))) 608 | { 609 | os_matrix[13].score++; // Windows 2K SP3 610 | } 611 | 612 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 613 | (temp_window <= (40320 + 70)) & (temp_window >= (40320 - 70)) | 614 | (temp_window <= (32767 + 70)) & (temp_window >= (32767 - 70)) | 615 | ((temp_window <= (tcp_mss * 45) + 70) & (temp_window >= (tcp_mss * 45) - 70 ))) 616 | { 617 | os_matrix[14].score++; // Windows 2K SP4 618 | } 619 | 620 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 621 | (temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70)) | 622 | (temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70)) | 623 | (temp_window <= (32767 + 70)) & (temp_window >= (32767 - 70)) | 624 | ((temp_window <= (tcp_mss * 45) + 70) & (temp_window >= (tcp_mss * 45) - 70 )) | 625 | ((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 )) | 626 | ((temp_window <= (tcp_mss * 12) + 70) & (temp_window >= (tcp_mss * 12) - 70 ))) 627 | { 628 | os_matrix[15].score++; // Windows XP SP1+ 629 | } 630 | 631 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 632 | (temp_window <= (32768 + 70)) & (temp_window >= (32768 - 70)) | 633 | (temp_window <= (16384 + 70)) & (temp_window >= (16384 - 70))) 634 | { 635 | os_matrix[16].score++; // Windows 2K3 636 | } 637 | 638 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70))) 639 | { 640 | os_matrix[17].score++; // Windows Vista (beta) 641 | } 642 | 643 | 644 | if ((temp_window <= (16616 + 70)) & (temp_window >= (16616 - 70))) 645 | { 646 | os_matrix[18].score++; // MacOS 7.3-8.6 647 | os_matrix[19].score++; // MacOS 8.1-8.6 648 | } 649 | 650 | if (((temp_window <= (tcp_mss * 2) + 70) & (temp_window >= (tcp_mss * 2) - 70 ))) 651 | { 652 | os_matrix[20].score++; // MacOS 8.6 653 | } 654 | 655 | if ((temp_window <= (32768 + 70)) & (temp_window >= (32768 - 70))) 656 | { 657 | os_matrix[21].score++; // MacOS 9.0-9.2 658 | } 659 | 660 | if (((temp_window <= (32768 + 70)) & (temp_window >= (32768 - 70))) | 661 | ((temp_window <= 65535) & (temp_window >= (65535 - 70)))) 662 | { 663 | os_matrix[22].score++; // MacOS 9.1 664 | } 665 | 666 | if ((temp_window <= (33304 + 70)) & (temp_window >= (33304 - 70))) 667 | { 668 | os_matrix[23].score++; // MacOS 10.2.6 669 | } 670 | 671 | tests.window_size = true; 672 | } 673 | 674 | 675 | /* Total SYN packet size */ 676 | if(tests.syn_pkt_size == false) 677 | { 678 | if (htons(rx_ip_hdr->ip_len) == 44) 679 | { 680 | os_matrix[0].score++; // Linux 1.2 681 | os_matrix[1].score++; // Linux 2.0 682 | os_matrix[2].score++; // Linux 2.0.3x 683 | 684 | os_matrix[6].score++; // Windows 3.11 685 | os_matrix[9].score++; // Windows 98 686 | os_matrix[11].score++; // Windows NT 4.0 SP6a 687 | os_matrix[16].score++; // Windows 2K3 688 | } 689 | else if (htons(rx_ip_hdr->ip_len) == 48) 690 | { 691 | os_matrix[9].score++; // Windows 98 692 | os_matrix[10].score++; // Windows ME no SP 693 | os_matrix[12].score++; // Windows 2K SP2+ 694 | os_matrix[13].score++; // Windows 2K SP3 695 | os_matrix[14].score++; // Windows 2K SP4 696 | os_matrix[15].score++; // Windows XP SP1+ 697 | os_matrix[16].score++; // Windows 2K3 698 | 699 | os_matrix[18].score++; // MacOS 7.3-8.6 700 | os_matrix[19].score++; // MacOS 8.1-8.6 701 | os_matrix[20].score++; // MacOS 8.6 702 | os_matrix[21].score++; // MacOS 9.0-9.2 703 | os_matrix[22].score++; // MacOS 9.1 704 | } 705 | else if (htons(rx_ip_hdr->ip_len) == 52) 706 | { 707 | os_matrix[9].score++; // Windows 98 708 | os_matrix[16].score++; // Windows 2K3 709 | os_matrix[17].score++; // Windows Vista (beta) 710 | } 711 | 712 | else if (htons(rx_ip_hdr->ip_len) == 60) 713 | { 714 | os_matrix[3].score++; // Linux 2.2 715 | os_matrix[4].score++; // Linux 2.4 716 | os_matrix[5].score++; // Linux 2.6 717 | 718 | os_matrix[7].score++; // Windows 95 719 | os_matrix[8].score++; // Windows 95b 720 | 721 | os_matrix[23].score++; // MacOS 10.2.6 722 | } 723 | 724 | tests.syn_pkt_size = true; 725 | } 726 | 727 | 728 | /* TCP options order */ 729 | if(tests.options_order == false) 730 | { 731 | option_index = 0; 732 | end_of_options = false; 733 | 734 | char* options = ((char*)(malloc(sizeof(char) * 20))); 735 | memset(options, 0, 20); 736 | 737 | while(end_of_options == false & option_index < length_tcp_options) 738 | { 739 | switch(packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index]) 740 | { 741 | case TCPOPT_EOL: 742 | end_of_options = true; 743 | break; 744 | 745 | case TCPOPT_NOP: 746 | strcat(options, "N"); 747 | option_index++; 748 | break; 749 | 750 | case TCPOPT_MAXSEG: 751 | strcat(options, "M"); 752 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 753 | break; 754 | 755 | case TCPOPT_WSCALE: 756 | strcat(options, "W"); 757 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 758 | break; 759 | 760 | case TCPOPT_SACKOK: 761 | strcat(options, "S"); 762 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 763 | break; 764 | 765 | case TCPOPT_TIMESTAMP: 766 | strcat(options, "T"); 767 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 768 | break; 769 | } 770 | } 771 | 772 | if (strcmp(options, "M") == 0) 773 | { 774 | os_matrix[0].score += 2.5; // Linux 1.2 775 | os_matrix[1].score += 2.5; // Linux 2.0 776 | os_matrix[2].score += 2.5; // Linux 2.0.3x 777 | 778 | os_matrix[6].score += 2.5; // Windows 3.11 779 | os_matrix[11].score += 2.5; // Windows NT 4.0 SP6a 780 | os_matrix[16].score += 2.5; // Windows 2K3 781 | } 782 | else if (strcmp(options, "MSTNW") == 0) 783 | { 784 | os_matrix[3].score += 2.5; // Linux 2.2 785 | os_matrix[4].score += 2.5; // Linux 2.4 786 | os_matrix[5].score += 2.5; // Linux 2.6 787 | } 788 | 789 | if (strcmp(options, "MNWNNTNNS") == 0) 790 | { 791 | os_matrix[7].score += 2.5; // Windows 95 792 | os_matrix[8].score += 2.5; // Windows 95b 793 | os_matrix[14].score += 2.5; // Windows 2K SP4 794 | os_matrix[15].score += 2.5; // Windows XP SP1+ 795 | os_matrix[16].score += 2.5; // Windows 2K3 796 | } 797 | 798 | if ((strcmp(options, "MNNS") == 0) | (strcmp(options, "MNWNNTNNS") == 0) | (strcmp(options, "MNWNNS") == 0)) 799 | { 800 | os_matrix[9].score += 2.5; // Windows 98 801 | } 802 | 803 | if (strcmp(options, "MNNS") == 0) 804 | { 805 | os_matrix[10].score += 2.5; // Windows ME no SP 806 | os_matrix[12].score += 2.5; // Windows 2K SP2+ 807 | os_matrix[13].score += 2.5; // Windows 2K SP3 808 | os_matrix[14].score += 2.5; // Windows 2K SP4 809 | os_matrix[15].score += 2.5; // Windows XP SP1+ 810 | } 811 | 812 | if ((strcmp(options, "MNWNNS") == 0) | (strcmp(options, "MNNS") == 0)) 813 | { 814 | os_matrix[16].score += 2.5; // Windows 2K3 815 | } 816 | 817 | if (strcmp(options, "MWNNNS") == 0) 818 | { 819 | os_matrix[17].score += 2.5; // Windows Vista (beta) 820 | } 821 | 822 | 823 | if (strcmp(options, "MW") == 0) 824 | { 825 | os_matrix[18].score += 2.5; // MacOS 7.3-8.6 826 | os_matrix[20].score += 2.5; // MacOS 8.6 827 | } 828 | 829 | if (strcmp(options, "MNNN") == 0) 830 | { 831 | os_matrix[19].score += 2.5; // MacOS 8.1-8.6 832 | } 833 | 834 | if (strcmp(options, "MWN") == 0) 835 | { 836 | os_matrix[21].score += 2.5; // MacOS 9.0-9.2 837 | } 838 | 839 | if (strcmp(options, "MNNNN") == 0) 840 | { 841 | os_matrix[22].score += 2.5; // MacOS 9.1 842 | } 843 | 844 | if (strcmp(options, "MNWNNT") == 0) 845 | { 846 | os_matrix[23].score += 2.5; // MacOS 10.2.6 847 | } 848 | 849 | tests.options_order = true; 850 | } 851 | 852 | 853 | /* IPID Test */ 854 | if (tests.ipid == false) 855 | { 856 | if (htons(rx_ip_hdr->ip_id) != 0) //IPID != 0 857 | { 858 | os_matrix[0].score++; // Linux 1.2 859 | os_matrix[1].score++; // Linux 2.0 860 | os_matrix[2].score++; // Linux 2.0.3x 861 | os_matrix[3].score++; // Linux 2.2 862 | 863 | os_matrix[6].score++; // Windows 3.11 864 | os_matrix[7].score++; // Windows 95 865 | os_matrix[8].score++; // Windows 95b 866 | os_matrix[9].score++; // Windows 98 867 | os_matrix[10].score++; // Windows ME no SP 868 | os_matrix[11].score++; // Windows NT 4.0 SP6a 869 | os_matrix[12].score++; // Windows 2K SP2+ 870 | os_matrix[13].score++; // Windows 2K SP3 871 | os_matrix[14].score++; // Windows 2K SP4 872 | os_matrix[15].score++; // Windows XP SP1+ 873 | os_matrix[16].score++; // Windows 2K3 874 | os_matrix[17].score++; // Windows Vista (beta) 875 | 876 | os_matrix[18].score++; // MacOS 7.3-8.6 877 | os_matrix[19].score++; // MacOS 8.1-8.6 878 | os_matrix[20].score++; // MacOS 8.6 879 | os_matrix[21].score++; // MacOS 9.0-9.2 880 | os_matrix[22].score++; // MacOS 9.1 881 | os_matrix[23].score++; // MacOS 10.2.6 882 | } 883 | else if (htons(rx_ip_hdr->ip_id) == 0) //IPID = 0 884 | { 885 | os_matrix[4].score++; // Linux 2.4 886 | os_matrix[5].score++; // Linux 2.6 887 | } 888 | 889 | tests.ipid = true; 890 | } 891 | } 892 | 893 | 894 | /* Banner Grabbing */ 895 | 896 | if (length - (MAC_HEADER_LEN + length_ip_header + length_tcp_header) != 0) 897 | { 898 | int headers_length = (MAC_HEADER_LEN + length_ip_header + length_tcp_header); 899 | int data_length = length - headers_length; 900 | 901 | char* http_text = ((char*)(malloc(sizeof(char) * (data_length + 1)))); //allocate a string as long as data + 1 (for '\0') 902 | memset(http_text, 0, data_length + 1); //set all to 0 903 | 904 | strncpy(http_text, ((char*)(packet + headers_length)),data_length); 905 | 906 | 907 | if (strncmp(http_text, "HTTP", 4) == 0) 908 | { 909 | string str_http_text(http_text); 910 | string str_server("Server"); 911 | int server_index = str_http_text.find(str_server); 912 | 913 | if(server_index != string::npos) 914 | { 915 | int new_len = data_length - server_index; 916 | 917 | string myStr = str_http_text.substr(server_index,new_len); //take the string from "Server" and on 918 | 919 | char* myStr1 = ((char*)(malloc(sizeof(char) * (new_len + 1)))); 920 | myStr.copy(myStr1, new_len, 0); 921 | myStr1[new_len] = '\0'; 922 | 923 | if (strncmp(myStr1, "Server", 6) == 0) 924 | { 925 | int sp_index = myStr.find_first_of("\r"); 926 | Banner = myStr.substr(0,sp_index); 927 | } 928 | 929 | free(myStr1); 930 | } 931 | } 932 | 933 | free(http_text); 934 | } 935 | }//end Process_TCP 936 | 937 | 938 | 939 | void print_decision() 940 | { 941 | printf("\n-> Operating Systems probability weight:\n"); 942 | printf(" -------------------------------------\n"); 943 | for (int i = 0; i < KNOWN_OS; i++) 944 | { 945 | printf("---> %-31s%.1f\n", os_matrix[i].name, os_matrix[i].score); 946 | } 947 | 948 | printf("\n-> Possible Operating Systems:\n"); 949 | printf("--------------------------------\n"); 950 | 951 | float max_score = os_matrix[0].score; 952 | for (int i = 1; i < KNOWN_OS; i++) 953 | { 954 | if (os_matrix[i].score > max_score) 955 | { 956 | max_score = os_matrix[i].score; 957 | } 958 | } 959 | 960 | 961 | for (int i = 0; i < KNOWN_OS; i++) 962 | { 963 | if (os_matrix[i].score == max_score) 964 | { 965 | printf("---> %s\n", os_matrix[i].name); 966 | } 967 | } 968 | 969 | if(Banner != "") 970 | { 971 | printf("---> Running Web "); 972 | std::cout< ip_src.s_addr != remote_ip.s_addr) || (rx_ip_hdr-> ip_dst.s_addr != local_ip.s_addr)) 250 | { 251 | return; 252 | } 253 | 254 | Process_IP((uint8_t*)packet, pkthdr->len); 255 | 256 | switch(rx_ip_hdr->ip_p) 257 | { 258 | case IP_PROTO_TCP: 259 | Process_TCP((uint8_t*)packet, pkthdr->len); 260 | break; 261 | 262 | case IP_PROTO_ICMP: 263 | Process_ICMP((uint8_t*)packet, pkthdr->len); 264 | break; 265 | 266 | default: 267 | break; 268 | 269 | }//end switch 270 | } //end sniffer 271 | 272 | 273 | 274 | void Process_IP(uint8_t * packet, int length) 275 | { 276 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + 14)); 277 | 278 | int length_ip_header = rx_ip_hdr->ip_hl * 4; // obtain the length of header in bytes to check for options 279 | 280 | 281 | /* TTL Test */ 282 | if (tests.ttl == false) 283 | { 284 | if (rx_ip_hdr->ip_ttl > 0 & rx_ip_hdr->ip_ttl <= 32) 285 | { 286 | os_matrix[6].score += 0.5; // Windows 3.11 287 | os_matrix[9].score += 0.5; // Windows 98 288 | os_matrix[16].score += 0.5; // Windows 2K3 289 | } 290 | else if (rx_ip_hdr->ip_ttl > 32 & rx_ip_hdr->ip_ttl <= 64) 291 | { 292 | os_matrix[0].score += 0.5; // Linux 1.2 293 | os_matrix[1].score += 0.5; // Linux 2.0 294 | os_matrix[2].score += 0.5; // Linux 2.0.3x 295 | os_matrix[3].score += 0.5; // Linux 2.2 296 | os_matrix[4].score += 0.5; // Linux 2.4 297 | os_matrix[5].score += 0.5; // Linux 2.6 298 | 299 | os_matrix[7].score += 0.5; // Windows 95 300 | // Windows 98 [h?] 301 | os_matrix[10].score += 0.5; // Windows ME no SP 302 | os_matrix[16].score += 0.5; // Windows 2K3 303 | 304 | os_matrix[23].score += 0.5; // MacOS 10.2.6 305 | } 306 | else if (rx_ip_hdr->ip_ttl > 64 & rx_ip_hdr->ip_ttl <= 128) 307 | { 308 | os_matrix[8].score += 0.5; // Windows 95b 309 | // Windows 98 [h?] 310 | os_matrix[11].score += 0.5; // Windows NT 4.0 SP6a 311 | os_matrix[12].score += 0.5; // Windows 2K SP2+ 312 | os_matrix[13].score += 0.5; // Windows 2K SP3 313 | os_matrix[14].score += 0.5; // Windows 2K SP4 314 | os_matrix[15].score += 0.5; // Windows XP SP1+ 315 | os_matrix[16].score += 0.5; // Windows 2K3 316 | os_matrix[17].score += 0.5; // Windows Vista (beta) 317 | } 318 | else if (rx_ip_hdr->ip_ttl > 128 & rx_ip_hdr->ip_ttl <= 255) 319 | { 320 | os_matrix[18].score += 0.5; // MacOS 7.3-8.6 321 | os_matrix[19].score += 0.5; // MacOS 8.1-8.6 322 | os_matrix[20].score += 0.5; // MacOS 8.6 323 | os_matrix[21].score += 0.5; // MacOS 9.0-9.2 324 | os_matrix[22].score += 0.5; // MacOS 9.1 325 | } 326 | 327 | tests.ttl = true; 328 | } 329 | 330 | 331 | /* DF Test */ 332 | if (tests.df == false) 333 | { 334 | if ((htons(rx_ip_hdr->ip_off) & 0x4000) == 0x0000) //DF = 0 335 | { 336 | os_matrix[0].score++; // Linux 1.2 337 | os_matrix[1].score++; // Linux 2.0 338 | os_matrix[2].score++; // Linux 2.0.3x 339 | 340 | os_matrix[10].score++; // Windows ME no SP 341 | os_matrix[16].score++; // Windows 2K3 342 | } 343 | else if ((htons(rx_ip_hdr->ip_off) & 0x4000) == 0x4000) //DF = 1 344 | { 345 | os_matrix[3].score++; // Linux 2.2 346 | os_matrix[4].score++; // Linux 2.4 347 | os_matrix[5].score++; // Linux 2.6 348 | 349 | os_matrix[6].score++; // Windows 3.11 350 | os_matrix[7].score++; // Windows 95 351 | os_matrix[8].score++; // Windows 95b 352 | os_matrix[9].score++; // Windows 98 353 | os_matrix[11].score++; // Windows NT 4.0 SP6a 354 | os_matrix[12].score++; // Windows 2K SP2+ 355 | os_matrix[13].score++; // Windows 2K SP3 356 | os_matrix[14].score++; // Windows 2K SP4 357 | os_matrix[15].score++; // Windows XP SP1+ 358 | // Windows 2K3 [h?] 359 | os_matrix[17].score++; // Windows Vista (beta) 360 | 361 | os_matrix[18].score++; // MacOS 7.3-8.6 362 | os_matrix[19].score++; // MacOS 8.1-8.6 363 | os_matrix[20].score++; // MacOS 8.6 364 | os_matrix[21].score++; // MacOS 9.0-9.2 365 | os_matrix[22].score++; // MacOS 9.1 366 | os_matrix[23].score++; // MacOS 10.2.6 367 | } 368 | 369 | tests.df = true; 370 | } 371 | }//end Process_IP 372 | 373 | 374 | 375 | void Process_ICMP(uint8_t * packet, int length) 376 | { 377 | /* No code is added here since we are not 378 | using ICMP packet for IS fingerprinting */ 379 | 380 | }//end function Process_ICMP 381 | 382 | 383 | 384 | void Process_TCP(uint8_t * packet, int length) 385 | { 386 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + 14)); 387 | int length_ip_header = rx_ip_hdr->ip_hl * 4; // obtain the length of header in bytes to check for options 388 | 389 | struct tcp_hdr* rx_tcp_hdr = ((tcp_hdr*)(packet + 14 + length_ip_header)); 390 | int length_tcp_header = rx_tcp_hdr->tcp_dt_ofst * 4; // obtain the length of header in bytes to check for options 391 | int length_tcp_options = length_tcp_header - 20; 392 | 393 | 394 | 395 | uint16_t tcp_mss = 0; 396 | int window_scale = -1; 397 | 398 | if ((rx_tcp_hdr->tcp_flags & 2) == 2) 399 | { 400 | /* Getting TCP MSS and Window Scale from TCP options */ 401 | int option_index = 0; 402 | bool end_of_options = false; 403 | while(end_of_options == false & option_index < length_tcp_options) 404 | { 405 | switch(packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index]) 406 | { 407 | case TCPOPT_EOL: 408 | end_of_options = true; 409 | break; 410 | 411 | case TCPOPT_NOP: 412 | option_index++; 413 | break; 414 | 415 | case TCPOPT_MAXSEG: 416 | tcp_mss = (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2] * 256) + 417 | packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 3]; 418 | option_index += 4; 419 | break; 420 | 421 | case TCPOPT_WSCALE: 422 | window_scale = packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2]; 423 | option_index += 3; 424 | break; 425 | 426 | case TCPOPT_SACKOK: 427 | option_index += 2; 428 | break; 429 | 430 | case TCPOPT_TIMESTAMP: 431 | option_index += 10; 432 | break; 433 | } 434 | } 435 | 436 | 437 | /* Checking TCP MMS */ 438 | if(tests.tcp_mss == false) 439 | { 440 | if (tcp_mss == 1380) 441 | { 442 | os_matrix[22].score++; // MacOS 9.1 443 | } 444 | 445 | tests.tcp_mss = true; 446 | } 447 | 448 | 449 | /* Window Scale Test */ 450 | if(tests.window_scale == false) 451 | { 452 | if (window_scale == -1) //no window scale appears in tcp options 453 | { 454 | os_matrix[0].score++; // Linux 1.2 455 | os_matrix[1].score++; // Linux 2.0 456 | os_matrix[2].score++; // Linux 2.0.3x 457 | 458 | os_matrix[6].score++; // Windows 3.11 459 | os_matrix[7].score++; // Windows 95 460 | os_matrix[8].score++; // Windows 95b 461 | os_matrix[9].score++; // Windows 98 462 | os_matrix[10].score++; // Windows ME no SP 463 | os_matrix[11].score++; // Windows NT 4.0 SP6a 464 | os_matrix[12].score++; // Windows 2K SP2+ 465 | os_matrix[13].score++; // Windows 2K SP3 466 | // Windows 2K SP4 [h?] 467 | os_matrix[15].score++; // Windows XP SP1+ 468 | os_matrix[16].score++; // Windows 2K3 469 | 470 | os_matrix[19].score++; // MacOS 8.1-8.6 471 | os_matrix[22].score++; // MacOS 9.1 472 | } 473 | else if (window_scale == 0) 474 | { 475 | os_matrix[3].score++; // Linux 2.2 476 | os_matrix[4].score++; // Linux 2.4 477 | os_matrix[5].score++; // Linux 2.6 478 | 479 | // Windows 98 [h?] 480 | // Windows 2K SP4 [h?] 481 | os_matrix[15].score++; // Windows XP SP1+ 482 | os_matrix[16].score++; // Windows 2K3 483 | 484 | os_matrix[18].score++; // MacOS 7.3-8.6 485 | os_matrix[20].score++; // MacOS 8.6 486 | os_matrix[21].score++; // MacOS 9.0-9.2 487 | os_matrix[23].score++; // MacOS 10.2.6 488 | } 489 | else if (window_scale == 1) 490 | { 491 | os_matrix[4].score++; // Linux 2.4 492 | os_matrix[5].score++; // Linux 2.6 493 | } 494 | else if (window_scale == 2) 495 | { 496 | os_matrix[4].score++; // Linux 2.4 497 | os_matrix[5].score++; // Linux 2.6 498 | 499 | // Windows 98 [h?] 500 | os_matrix[16].score++; // Windows 2K3 501 | } 502 | 503 | // Windows 98 [h?] wc = 3 504 | 505 | else if ((window_scale == 5) | (window_scale == 6) | (window_scale == 7)) 506 | { 507 | os_matrix[5].score++; // Linux 2.6 508 | } 509 | else if (window_scale == 8) 510 | { 511 | os_matrix[17].score++; // Windows Vista (beta) 512 | } 513 | 514 | tests.window_scale = true; 515 | } 516 | 517 | 518 | /* Window Size Test */ 519 | if(tests.window_size == false) 520 | { 521 | int temp_window = htons(rx_tcp_hdr->tcp_window); 522 | 523 | if ((temp_window <= (tcp_mss + 50)) & (temp_window >= (tcp_mss - 50))) 524 | { 525 | os_matrix[0].score++; // Linux 1.2 526 | } 527 | 528 | if ((temp_window <= (32736 + 70)) & (temp_window >= (32736 - 70))) 529 | { 530 | os_matrix[1].score++; // Linux 2.0 531 | } 532 | 533 | if (((temp_window <= (512 + 50)) & (temp_window >= (512 - 50))) | 534 | ((temp_window <= (16384 + 70)) & (temp_window >= (16384 - 70)))) 535 | { 536 | // Linux 2.0.3x [h?] 537 | } 538 | 539 | 540 | if (((temp_window <= (tcp_mss * 11) + 70) & (temp_window >= (tcp_mss * 11) - 70 )) | 541 | ((temp_window <= (tcp_mss * 20) + 70) & (temp_window >= (tcp_mss * 20) - 70 ))) 542 | { 543 | os_matrix[3].score++; // Linux 2.2 544 | } 545 | 546 | if (((temp_window <= (tcp_mss * 2) + 70) & (temp_window >= (tcp_mss * 2) - 70 )) | 547 | ((temp_window <= (tcp_mss * 3) + 70) & (temp_window >= (tcp_mss * 3) - 70 )) | 548 | ((temp_window <= (tcp_mss * 4) + 70) & (temp_window >= (tcp_mss * 4) - 70 ))) 549 | { 550 | os_matrix[4].score++; // Linux 2.4 551 | os_matrix[5].score++; // Linux 2.6 552 | } 553 | 554 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70))) 555 | { 556 | os_matrix[6].score++; // Windows 3.11 557 | } 558 | 559 | if (((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 ))) 560 | { 561 | os_matrix[7].score++; // Windows 95 562 | } 563 | 564 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70))) 565 | { 566 | os_matrix[8].score++; // Windows 95b 567 | } 568 | 569 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 570 | (temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70)) | 571 | (temp_window <= (32767 + 70)) & (temp_window >= (32767 - 70)) | 572 | (temp_window <= (37300 + 70)) & (temp_window >= (37300 - 70)) | 573 | (temp_window <= (46080 + 70)) & (temp_window >= (46080 - 70)) | 574 | (temp_window <= (60352 + 70)) & (temp_window >= (60352 - 70)) | 575 | ((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 )) | 576 | ((temp_window <= (tcp_mss * 4) + 70) & (temp_window >= (tcp_mss * 4) - 70 )) | 577 | ((temp_window <= (tcp_mss * 6) + 70) & (temp_window >= (tcp_mss * 6) - 70 )) | 578 | ((temp_window <= (tcp_mss * 12) + 70) & (temp_window >= (tcp_mss * 12) - 70 )) | 579 | ((temp_window <= (tcp_mss * 16) + 70) & (temp_window >= (tcp_mss * 16) - 70 )) | 580 | ((temp_window <= (tcp_mss * 26) + 70) & (temp_window >= (tcp_mss * 26) - 70 ))) 581 | { 582 | os_matrix[9].score++; // Windows 98 583 | } 584 | 585 | if ((temp_window <= (44620 + 70)) & (temp_window >= (44620 - 70))) 586 | { 587 | os_matrix[10].score++; // Windows ME no SP 588 | } 589 | 590 | if ((temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70))) 591 | { 592 | os_matrix[11].score++; // Windows NT 4.0 SP6a 593 | } 594 | 595 | if ((temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70))) 596 | { 597 | os_matrix[11].score++; // Windows NT 4.0 SP6a 598 | } 599 | 600 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70)) | 601 | ((temp_window <= (tcp_mss * 6) + 70) & (temp_window >= (tcp_mss * 6) - 70 ))) 602 | { 603 | os_matrix[12].score++; // Windows 2K SP2+ 604 | } 605 | 606 | if ((temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70)) | 607 | ((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 ))) 608 | { 609 | os_matrix[13].score++; // Windows 2K SP3 610 | } 611 | 612 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 613 | (temp_window <= (40320 + 70)) & (temp_window >= (40320 - 70)) | 614 | (temp_window <= (32767 + 70)) & (temp_window >= (32767 - 70)) | 615 | ((temp_window <= (tcp_mss * 45) + 70) & (temp_window >= (tcp_mss * 45) - 70 ))) 616 | { 617 | os_matrix[14].score++; // Windows 2K SP4 618 | } 619 | 620 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 621 | (temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70)) | 622 | (temp_window <= (64512 + 70)) & (temp_window >= (64512 - 70)) | 623 | (temp_window <= (32767 + 70)) & (temp_window >= (32767 - 70)) | 624 | ((temp_window <= (tcp_mss * 45) + 70) & (temp_window >= (tcp_mss * 45) - 70 )) | 625 | ((temp_window <= (tcp_mss * 44) + 70) & (temp_window >= (tcp_mss * 44) - 70 )) | 626 | ((temp_window <= (tcp_mss * 12) + 70) & (temp_window >= (tcp_mss * 12) - 70 ))) 627 | { 628 | os_matrix[15].score++; // Windows XP SP1+ 629 | } 630 | 631 | if ((temp_window <= 65535) & (temp_window >= (65535 - 70)) | 632 | (temp_window <= (32768 + 70)) & (temp_window >= (32768 - 70)) | 633 | (temp_window <= (16384 + 70)) & (temp_window >= (16384 - 70))) 634 | { 635 | os_matrix[16].score++; // Windows 2K3 636 | } 637 | 638 | if ((temp_window <= (8192 + 70)) & (temp_window >= (8192 - 70))) 639 | { 640 | os_matrix[17].score++; // Windows Vista (beta) 641 | } 642 | 643 | 644 | if ((temp_window <= (16616 + 70)) & (temp_window >= (16616 - 70))) 645 | { 646 | os_matrix[18].score++; // MacOS 7.3-8.6 647 | os_matrix[19].score++; // MacOS 8.1-8.6 648 | } 649 | 650 | if (((temp_window <= (tcp_mss * 2) + 70) & (temp_window >= (tcp_mss * 2) - 70 ))) 651 | { 652 | os_matrix[20].score++; // MacOS 8.6 653 | } 654 | 655 | if ((temp_window <= (32768 + 70)) & (temp_window >= (32768 - 70))) 656 | { 657 | os_matrix[21].score++; // MacOS 9.0-9.2 658 | } 659 | 660 | if (((temp_window <= (32768 + 70)) & (temp_window >= (32768 - 70))) | 661 | ((temp_window <= 65535) & (temp_window >= (65535 - 70)))) 662 | { 663 | os_matrix[22].score++; // MacOS 9.1 664 | } 665 | 666 | if ((temp_window <= (33304 + 70)) & (temp_window >= (33304 - 70))) 667 | { 668 | os_matrix[23].score++; // MacOS 10.2.6 669 | } 670 | 671 | tests.window_size = true; 672 | } 673 | 674 | 675 | /* Total SYN packet size */ 676 | if(tests.syn_pkt_size == false) 677 | { 678 | if (htons(rx_ip_hdr->ip_len) == 44) 679 | { 680 | os_matrix[0].score++; // Linux 1.2 681 | os_matrix[1].score++; // Linux 2.0 682 | os_matrix[2].score++; // Linux 2.0.3x 683 | 684 | os_matrix[6].score++; // Windows 3.11 685 | os_matrix[9].score++; // Windows 98 686 | os_matrix[11].score++; // Windows NT 4.0 SP6a 687 | os_matrix[16].score++; // Windows 2K3 688 | } 689 | else if (htons(rx_ip_hdr->ip_len) == 48) 690 | { 691 | os_matrix[9].score++; // Windows 98 692 | os_matrix[10].score++; // Windows ME no SP 693 | os_matrix[12].score++; // Windows 2K SP2+ 694 | os_matrix[13].score++; // Windows 2K SP3 695 | os_matrix[14].score++; // Windows 2K SP4 696 | os_matrix[15].score++; // Windows XP SP1+ 697 | os_matrix[16].score++; // Windows 2K3 698 | 699 | os_matrix[18].score++; // MacOS 7.3-8.6 700 | os_matrix[19].score++; // MacOS 8.1-8.6 701 | os_matrix[20].score++; // MacOS 8.6 702 | os_matrix[21].score++; // MacOS 9.0-9.2 703 | os_matrix[22].score++; // MacOS 9.1 704 | } 705 | else if (htons(rx_ip_hdr->ip_len) == 52) 706 | { 707 | os_matrix[9].score++; // Windows 98 708 | os_matrix[16].score++; // Windows 2K3 709 | os_matrix[17].score++; // Windows Vista (beta) 710 | } 711 | 712 | else if (htons(rx_ip_hdr->ip_len) == 60) 713 | { 714 | os_matrix[3].score++; // Linux 2.2 715 | os_matrix[4].score++; // Linux 2.4 716 | os_matrix[5].score++; // Linux 2.6 717 | 718 | os_matrix[7].score++; // Windows 95 719 | os_matrix[8].score++; // Windows 95b 720 | 721 | os_matrix[23].score++; // MacOS 10.2.6 722 | } 723 | 724 | tests.syn_pkt_size = true; 725 | } 726 | 727 | 728 | /* TCP options order */ 729 | if(tests.options_order == false) 730 | { 731 | option_index = 0; 732 | end_of_options = false; 733 | 734 | char* options = ((char*)(malloc(sizeof(char) * 20))); 735 | memset(options, 0, 20); 736 | 737 | while(end_of_options == false & option_index < length_tcp_options) 738 | { 739 | switch(packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index]) 740 | { 741 | case TCPOPT_EOL: 742 | end_of_options = true; 743 | break; 744 | 745 | case TCPOPT_NOP: 746 | strcat(options, "N"); 747 | option_index++; 748 | break; 749 | 750 | case TCPOPT_MAXSEG: 751 | strcat(options, "M"); 752 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 753 | break; 754 | 755 | case TCPOPT_WSCALE: 756 | strcat(options, "W"); 757 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 758 | break; 759 | 760 | case TCPOPT_SACKOK: 761 | strcat(options, "S"); 762 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 763 | break; 764 | 765 | case TCPOPT_TIMESTAMP: 766 | strcat(options, "T"); 767 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 768 | break; 769 | } 770 | } 771 | 772 | if (strcmp(options, "M") == 0) 773 | { 774 | os_matrix[0].score += 2.5; // Linux 1.2 775 | os_matrix[1].score += 2.5; // Linux 2.0 776 | os_matrix[2].score += 2.5; // Linux 2.0.3x 777 | 778 | os_matrix[6].score += 2.5; // Windows 3.11 779 | os_matrix[11].score += 2.5; // Windows NT 4.0 SP6a 780 | os_matrix[16].score += 2.5; // Windows 2K3 781 | } 782 | else if (strcmp(options, "MSTNW") == 0) 783 | { 784 | os_matrix[3].score += 2.5; // Linux 2.2 785 | os_matrix[4].score += 2.5; // Linux 2.4 786 | os_matrix[5].score += 2.5; // Linux 2.6 787 | } 788 | 789 | if (strcmp(options, "MNWNNTNNS") == 0) 790 | { 791 | os_matrix[7].score += 2.5; // Windows 95 792 | os_matrix[8].score += 2.5; // Windows 95b 793 | os_matrix[14].score += 2.5; // Windows 2K SP4 794 | os_matrix[15].score += 2.5; // Windows XP SP1+ 795 | os_matrix[16].score += 2.5; // Windows 2K3 796 | } 797 | 798 | if ((strcmp(options, "MNNS") == 0) | (strcmp(options, "MNWNNTNNS") == 0) | (strcmp(options, "MNWNNS") == 0)) 799 | { 800 | os_matrix[9].score += 2.5; // Windows 98 801 | } 802 | 803 | if (strcmp(options, "MNNS") == 0) 804 | { 805 | os_matrix[10].score += 2.5; // Windows ME no SP 806 | os_matrix[12].score += 2.5; // Windows 2K SP2+ 807 | os_matrix[13].score += 2.5; // Windows 2K SP3 808 | os_matrix[14].score += 2.5; // Windows 2K SP4 809 | os_matrix[15].score += 2.5; // Windows XP SP1+ 810 | } 811 | 812 | if ((strcmp(options, "MNWNNS") == 0) | (strcmp(options, "MNNS") == 0)) 813 | { 814 | os_matrix[16].score += 2.5; // Windows 2K3 815 | } 816 | 817 | if (strcmp(options, "MWNNNS") == 0) 818 | { 819 | os_matrix[17].score += 2.5; // Windows Vista (beta) 820 | } 821 | 822 | 823 | if (strcmp(options, "MW") == 0) 824 | { 825 | os_matrix[18].score += 2.5; // MacOS 7.3-8.6 826 | os_matrix[20].score += 2.5; // MacOS 8.6 827 | } 828 | 829 | if (strcmp(options, "MNNN") == 0) 830 | { 831 | os_matrix[19].score += 2.5; // MacOS 8.1-8.6 832 | } 833 | 834 | if (strcmp(options, "MWN") == 0) 835 | { 836 | os_matrix[21].score += 2.5; // MacOS 9.0-9.2 837 | } 838 | 839 | if (strcmp(options, "MNNNN") == 0) 840 | { 841 | os_matrix[22].score += 2.5; // MacOS 9.1 842 | } 843 | 844 | if (strcmp(options, "MNWNNT") == 0) 845 | { 846 | os_matrix[23].score += 2.5; // MacOS 10.2.6 847 | } 848 | 849 | tests.options_order = true; 850 | } 851 | 852 | 853 | /* IPID Test */ 854 | if (tests.ipid == false) 855 | { 856 | if (htons(rx_ip_hdr->ip_id) != 0) //IPID != 0 857 | { 858 | os_matrix[0].score++; // Linux 1.2 859 | os_matrix[1].score++; // Linux 2.0 860 | os_matrix[2].score++; // Linux 2.0.3x 861 | os_matrix[3].score++; // Linux 2.2 862 | 863 | os_matrix[6].score++; // Windows 3.11 864 | os_matrix[7].score++; // Windows 95 865 | os_matrix[8].score++; // Windows 95b 866 | os_matrix[9].score++; // Windows 98 867 | os_matrix[10].score++; // Windows ME no SP 868 | os_matrix[11].score++; // Windows NT 4.0 SP6a 869 | os_matrix[12].score++; // Windows 2K SP2+ 870 | os_matrix[13].score++; // Windows 2K SP3 871 | os_matrix[14].score++; // Windows 2K SP4 872 | os_matrix[15].score++; // Windows XP SP1+ 873 | os_matrix[16].score++; // Windows 2K3 874 | os_matrix[17].score++; // Windows Vista (beta) 875 | 876 | os_matrix[18].score++; // MacOS 7.3-8.6 877 | os_matrix[19].score++; // MacOS 8.1-8.6 878 | os_matrix[20].score++; // MacOS 8.6 879 | os_matrix[21].score++; // MacOS 9.0-9.2 880 | os_matrix[22].score++; // MacOS 9.1 881 | os_matrix[23].score++; // MacOS 10.2.6 882 | } 883 | else if (htons(rx_ip_hdr->ip_id) == 0) //IPID = 0 884 | { 885 | os_matrix[4].score++; // Linux 2.4 886 | os_matrix[5].score++; // Linux 2.6 887 | } 888 | 889 | tests.ipid = true; 890 | } 891 | } 892 | 893 | 894 | /* Banner Grabbing */ 895 | 896 | if (length - (MAC_HEADER_LEN + length_ip_header + length_tcp_header) != 0) 897 | { 898 | int headers_length = (MAC_HEADER_LEN + length_ip_header + length_tcp_header); 899 | int data_length = length - headers_length; 900 | 901 | char* http_text = ((char*)(malloc(sizeof(char) * (data_length + 1)))); //allocate a string as long as data + 1 (for '\0') 902 | memset(http_text, 0, data_length + 1); //set all to 0 903 | 904 | strncpy(http_text, ((char*)(packet + headers_length)),data_length); 905 | 906 | 907 | if (strncmp(http_text, "HTTP", 4) == 0) 908 | { 909 | string str_http_text(http_text); 910 | string str_server("Server"); 911 | int server_index = str_http_text.find(str_server); 912 | 913 | if(server_index != string::npos) 914 | { 915 | int new_len = data_length - server_index; 916 | 917 | string myStr = str_http_text.substr(server_index,new_len); //take the string from "Server" and on 918 | 919 | char* myStr1 = ((char*)(malloc(sizeof(char) * (new_len + 1)))); 920 | myStr.copy(myStr1, new_len, 0); 921 | myStr1[new_len] = '\0'; 922 | 923 | if (strncmp(myStr1, "Server", 6) == 0) 924 | { 925 | int sp_index = myStr.find_first_of("\r"); 926 | Banner = myStr.substr(0,sp_index); 927 | } 928 | 929 | free(myStr1); 930 | } 931 | } 932 | 933 | free(http_text); 934 | } 935 | }//end Process_TCP 936 | 937 | 938 | 939 | void print_decision() 940 | { 941 | printf("\n-> Operating Systems probability weight:\n"); 942 | printf(" -------------------------------------\n"); 943 | for (int i = 0; i < KNOWN_OS; i++) 944 | { 945 | printf("---> %-31s%.1f\n", os_matrix[i].name, os_matrix[i].score); 946 | } 947 | 948 | printf("\n-> Possible Operating Systems:\n"); 949 | printf("--------------------------------\n"); 950 | 951 | float max_score = os_matrix[0].score; 952 | for (int i = 1; i < KNOWN_OS; i++) 953 | { 954 | if (os_matrix[i].score > max_score) 955 | { 956 | max_score = os_matrix[i].score; 957 | } 958 | } 959 | 960 | 961 | for (int i = 0; i < KNOWN_OS; i++) 962 | { 963 | if (os_matrix[i].score == max_score) 964 | { 965 | printf("---> %s\n", os_matrix[i].name); 966 | } 967 | } 968 | 969 | if(Banner != "") 970 | { 971 | printf("---> Running Web "); 972 | std::cout< 3 | #include 4 | #include 5 | 6 | 7 | 8 | #define KNOWN_OS 24 9 | 10 | struct os_prop 11 | { 12 | char name[100]; 13 | float score; 14 | }; 15 | 16 | struct imp_tests 17 | { 18 | //ip tests 19 | bool ttl; 20 | bool df; 21 | 22 | //tcp tests 23 | bool tcp_mss; 24 | bool window_scale; 25 | bool window_size; 26 | bool syn_pkt_size; 27 | bool options_order; 28 | bool ipid; 29 | 30 | //http tests 31 | bool banner_grabber; 32 | }; 33 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Detection/Makefile: -------------------------------------------------------------------------------- 1 | all: detect 2 | 3 | detect: clean 4 | g++ -g -Wno-deprecated net_utils.h net_utils.c detect.c -o ofp_detect -lpcap -lpthread 5 | 6 | clean: 7 | rm -rf *~ ofp_detect 8 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Detection/detect.c: -------------------------------------------------------------------------------- 1 | #include "detect.h" 2 | #include "interface_ip.c" 3 | 4 | using std::string; 5 | 6 | pcap_t* descr; 7 | 8 | struct in_addr local_ip; 9 | 10 | pthread_t analyze_thread; 11 | pthread_t handle_packet_thread; 12 | 13 | struct attacker attackers[MAX_ATTACKERS_NUM]; 14 | int attackers_index; 15 | 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | /*to take the ip address of current machine*/ 20 | std::string eth0_ip = interface_ip(); 21 | int addr_len = eth0_ip.length(); 22 | char* my_interface_ip = ((char*)(malloc(sizeof(char) * addr_len + 1))); //allocate a string as long as data + 1 (for '\0') 23 | eth0_ip.copy(my_interface_ip, addr_len, 0); // copy the ip address of the current machine to my_interface_ip 24 | my_interface_ip[addr_len] = '\0'; 25 | 26 | inet_aton(my_interface_ip, &local_ip); 27 | 28 | memset(attackers, 0, sizeof(attacker) * MAX_ATTACKERS_NUM); 29 | attackers_index = 0; 30 | 31 | 32 | char* dev; 33 | char errbuf[PCAP_ERRBUF_SIZE]; 34 | const u_char *packet; 35 | struct pcap_pkthdr hdr; 36 | struct ether_header *eptr; 37 | 38 | /*** Selecting device to capture from ***/ 39 | dev = pcap_lookupdev(errbuf); 40 | if(dev == NULL) 41 | { 42 | printf("%s\n", errbuf); 43 | return 1; 44 | } 45 | 46 | /*** Opening the selected device ***/ 47 | descr = pcap_open_live(dev, BUFSIZ, 0, -1, errbuf); 48 | if(descr == NULL) 49 | { 50 | printf("pcap_open_live(): %s\n", errbuf); 51 | return 1; 52 | } 53 | 54 | pthread_create(&analyze_thread, NULL, analyze_traffic, NULL); 55 | 56 | pcap_loop(descr, 0, sniffer, NULL); 57 | 58 | 59 | return 0; 60 | } 61 | 62 | void sniffer(u_char* useless, const struct pcap_pkthdr* pkthdr, const u_char* packet) 63 | { 64 | struct handle_packet_params* params = ((handle_packet_params*)(malloc(sizeof(handle_packet_params)))); 65 | memset(params->packet, 0, 1500); 66 | memcpy(params->packet, packet, pkthdr->len); 67 | params->length = pkthdr->len; 68 | 69 | pthread_create(&handle_packet_thread, NULL, handle_packet, params); 70 | 71 | //pcap_breakloop(descr); use this to stop the 'pcap_loop' 72 | } 73 | 74 | 75 | void* handle_packet(void* args) 76 | { 77 | struct handle_packet_params* params = ((handle_packet_params*)(args)); 78 | 79 | if(!((params->packet[12] == 8) && (params->packet[13] == 0))) // ip packet 80 | { 81 | return NULL; 82 | } 83 | 84 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(params->packet + ETH_HEADER_SIZE)); 85 | 86 | if(rx_ip_hdr-> ip_dst.s_addr != local_ip.s_addr) 87 | { 88 | return NULL; 89 | } 90 | 91 | Process_IP((uint8_t*)params->packet, params->length); 92 | 93 | switch(rx_ip_hdr->ip_p) 94 | { 95 | case IP_PROTO_TCP: 96 | Process_TCP((uint8_t*)params->packet, params->length); 97 | break; 98 | 99 | case IP_PROTO_UDP: 100 | Process_UDP((uint8_t*)params->packet, params->length); 101 | break; 102 | 103 | case IP_PROTO_ICMP: 104 | Process_ICMP((uint8_t*)params->packet, params->length); 105 | break; 106 | 107 | default: 108 | break; 109 | } 110 | } 111 | 112 | 113 | void Process_IP(uint8_t * packet, int length) 114 | { 115 | 116 | }//end function Process IP 117 | 118 | 119 | void Process_TCP(uint8_t * packet, int length) 120 | { 121 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + ETH_HEADER_SIZE)); 122 | int length_ip_header = rx_ip_hdr->ip_hl * 4; // obtain the length of header in bytes to check for options 123 | char* attacker_ip = inet_ntoa(rx_ip_hdr->ip_src); 124 | 125 | struct tcp_hdr* rx_tcp_hdr = ((tcp_hdr*)(packet + ETH_HEADER_SIZE + length_ip_header)); 126 | int length_tcp_header = rx_tcp_hdr->tcp_dt_ofst * 4; // obtain the length of header in bytes to check for options 127 | int length_tcp_options = length_tcp_header - 20; 128 | 129 | 130 | /* Connectionless Attacks */ 131 | 132 | if (rx_tcp_hdr->tcp_flags == 8) 133 | { 134 | printf("-> "); 135 | print_timestamp(); 136 | printf(": [%s] sent a TCP packet containing only PSH flag (suspecting OSF).\a\n", attacker_ip); 137 | return; 138 | } 139 | 140 | if ((rx_tcp_hdr->tcp_flags & 34) == 34) 141 | { 142 | printf("-> "); 143 | print_timestamp(); 144 | printf(": [%s] sent a TCP packet with SYN and URG flags set (suspecting OSF).\a\n", attacker_ip); 145 | return; 146 | } 147 | 148 | if ((rx_tcp_hdr->tcp_flags & 33) == 33) 149 | { 150 | printf("-> "); 151 | print_timestamp(); 152 | printf(": [%s] sent a TCP packet with FIN and URG flags set (suspecting OSF).\a\n", attacker_ip); 153 | return; 154 | } 155 | 156 | if ((rx_tcp_hdr->tcp_flags & 36) == 36) 157 | { 158 | printf("-> "); 159 | print_timestamp(); 160 | printf(": [%s] sent a TCP packet with RST and URG flags set (suspecting OSF).\a\n", attacker_ip); 161 | return; 162 | } 163 | 164 | if (rx_tcp_hdr->tcp_flags == 0) 165 | { 166 | printf("-> "); 167 | print_timestamp(); 168 | printf(": [%s] sent a TCP null [no flags set] (suspecting OSF).\a\n", attacker_ip); 169 | return; 170 | } 171 | 172 | if ((rx_tcp_hdr->tcp_flags & 3) == 3) 173 | { 174 | printf("-> "); 175 | print_timestamp(); 176 | printf(": [%s] sent a TCP packet with SYN and FIN flags set (suspecting OSF).\a\n", attacker_ip); 177 | return; 178 | } 179 | 180 | if ((rx_tcp_hdr->tcp_flags & 5) == 5) 181 | { 182 | printf("-> "); 183 | print_timestamp(); 184 | printf(": [%s] sent a TCP packet with RST and FIN flags set (suspecting OSF).\a\n", attacker_ip); 185 | return; 186 | } 187 | 188 | if ((rx_tcp_hdr->tcp_flags & 6) == 6) 189 | { 190 | printf("-> "); 191 | print_timestamp(); 192 | printf(": [%s] sent a TCP packet with RST and SYN flags set (suspecting OSF).\a\n", attacker_ip); 193 | return; 194 | } 195 | 196 | if ((rx_tcp_hdr->tcp_flags & 16 == 16) & (rx_ip_hdr->ip_off && 0x4000 == 0x4000) & (htons(rx_tcp_hdr->tcp_window) == 1024)) 197 | { 198 | printf("-> "); 199 | print_timestamp(); 200 | printf(": [%s] sent a TCP ACK packet with IP DF and a window size of 1024 (suspecting OSF).\a\n", attacker_ip); 201 | return; 202 | } 203 | 204 | if ((rx_tcp_hdr->tcp_flags & 2 == 2) & (rx_ip_hdr->ip_off && 0x4000 == 0x0000) & (htons(rx_tcp_hdr->tcp_window) == 31337) & 205 | (htons(rx_tcp_hdr->tcp_dst_prt) != 80)) //80 is the only opened port 206 | { 207 | printf("-> "); 208 | print_timestamp(); 209 | printf(": [%s] sent a TCP SYN packet without IP DF and a window size of 31337 to a closed port (suspecting OSF).\a\n", attacker_ip); 210 | return; 211 | } 212 | 213 | if ((rx_tcp_hdr->tcp_flags & 2 == 2) & (rx_ip_hdr->ip_off && 0x4000 == 0x4000) & (htons(rx_tcp_hdr->tcp_window) == 32768) & 214 | (htons(rx_tcp_hdr->tcp_dst_prt) != 80)) //80 is the only opened port 215 | { 216 | printf("-> "); 217 | print_timestamp(); 218 | printf(": [%s] sent a TCP SYN packet with IP DF and a window size of 32768 to a closed port (suspecting OSF).\a\n", attacker_ip); 219 | return; 220 | } 221 | 222 | if ((rx_tcp_hdr->tcp_flags & 41) == 41) 223 | { 224 | printf("-> "); 225 | print_timestamp(); 226 | printf(": [%s] sent a TCP packet with the FIN, PSH, and URG flags set [Xmas tree scan] (suspecting OSF).\a\n", attacker_ip); 227 | return; 228 | } 229 | 230 | if ((rx_tcp_hdr->tcp_flags & 43) == 43) 231 | { 232 | printf("-> "); 233 | print_timestamp(); 234 | printf(": [%s] sent a TCP packet with the SYN, FIN, PSH, and URG flags set (suspecting OSF).\a\n", attacker_ip); 235 | return; 236 | } 237 | 238 | if ((rx_tcp_hdr->tcp_flags & 194) == 194) 239 | { 240 | printf("-> "); 241 | print_timestamp(); 242 | printf(": [%s] sent a TCP packet with the SYN, ECN, and CWR flags set (suspecting OSF).\a\n", attacker_ip); 243 | return; 244 | } 245 | 246 | /*####################################################################################################################################*/ 247 | 248 | /* Keep State of the Attacker */ 249 | 250 | //finding the attacker 251 | int attacker_index = find_attacker(rx_ip_hdr->ip_src); 252 | if (attacker_index == -1) //attacker not found then add it 253 | { 254 | attacker_index = attackers_index; 255 | attackers_index = (attackers_index + 1) % MAX_ATTACKERS_NUM; //increment the index pointing to last attacker in the array 256 | 257 | memset(&attackers[attacker_index], 0, sizeof(attacker)); 258 | 259 | attackers[attacker_index].attacker_ip.s_addr = rx_ip_hdr->ip_src.s_addr; 260 | } 261 | 262 | //finding the connection 263 | int tcp_conn_i = -1; //-1 = no matching connection found from this attacker 264 | for (int i = 0; i < attackers[attacker_index].tcp_conns_number; i++) 265 | { 266 | if ((attackers[attacker_index].tcp_conns[i].src_port == /*htons(*/rx_tcp_hdr->tcp_src_prt/*)*/) & 267 | (attackers[attacker_index].tcp_conns[i].dst_port == /*htons(*/rx_tcp_hdr->tcp_dst_prt/*)*/)) 268 | { 269 | tcp_conn_i = i; //return the index of the connection 270 | break; 271 | } 272 | } 273 | 274 | if (tcp_conn_i == -1) //the first packet in the connection 275 | { 276 | if ((rx_tcp_hdr->tcp_flags & 2) != 2) //the packet is not SYN 277 | { 278 | printf("-> "); 279 | print_timestamp(); 280 | printf(": [%s] sending TCP packets to port [%d] (flags = [%x]) with no established connection (suspecting OSF).\a\n", 281 | attacker_ip, htons(rx_tcp_hdr->tcp_dst_prt), rx_tcp_hdr->tcp_flags); 282 | } 283 | else if ((rx_tcp_hdr->tcp_flags & 2) == 2) //the packet is a SYN trying to establish a connection 284 | { 285 | //add a connection definition to the array 286 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].src_port = /*htons(*/rx_tcp_hdr->tcp_src_prt/*)*/; 287 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].dst_port = /*htons(*/rx_tcp_hdr->tcp_dst_prt/*)*/; 288 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].syn = true; 289 | 290 | time_t time_stamp; 291 | time(&time_stamp); 292 | attackers[attacker_index].tcp_conns[ attackers[attacker_index].tcp_conns_index].time_stamp = ((int)(time_stamp)); 293 | 294 | //increment the number of connections for this IP and add one to the index 295 | attackers[attacker_index].tcp_conns_number++; 296 | attackers[attacker_index].tcp_conns_index = (attackers[attacker_index].tcp_conns_index +1) % MAX_CONNECTION_NUM; 297 | 298 | //increment the number of SYN packets received on this connection 299 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].number_of_syn++; 300 | } 301 | } 302 | else //connection already exists 303 | { 304 | if ((rx_tcp_hdr->tcp_flags & 2) == 2) //the packet is SYN 305 | { 306 | //increment the number of SYN packets received on this connection 307 | attackers[attacker_index].tcp_conns[tcp_conn_i].number_of_syn++; 308 | } 309 | else if ((rx_tcp_hdr->tcp_flags & 16) == 16) //the packet is ACK 310 | { 311 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].ack = true; 312 | } 313 | else if ((rx_tcp_hdr->tcp_flags & 4) == 4) //the packet is RST 314 | { 315 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].rst = true; 316 | 317 | if ((attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].syn == true) & 318 | (attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].ack == false)) 319 | { 320 | attackers[attacker_index].tcp_syn_and_rst_num++; 321 | } 322 | } 323 | else if ((rx_tcp_hdr->tcp_flags & 1) == 1) //the packet is RST 324 | { 325 | attackers[attacker_index].tcp_conns[attackers[attacker_index].tcp_conns_index].fin = true; 326 | } 327 | } 328 | 329 | 330 | /* Check the received options */ 331 | int option_index = 0; 332 | bool end_of_options = false; 333 | 334 | char* options = ((char*)(malloc(sizeof(char) * 20))); 335 | memset(options, 0, 20); 336 | 337 | int mss = 0; 338 | int window_scale = 0; 339 | bool sack; 340 | uint32_t ts_val = 0; 341 | uint32_t ts_ecr = 0; 342 | 343 | while(end_of_options == false & option_index < length_tcp_options) 344 | { 345 | switch(packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index]) 346 | { 347 | case TCPOPT_EOL: 348 | end_of_options = true; 349 | break; 350 | 351 | case TCPOPT_NOP: 352 | strcat(options, "N"); 353 | option_index++; 354 | break; 355 | 356 | case TCPOPT_MAXSEG: 357 | strcat(options, "M"); 358 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 359 | mss = (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2] * 256) + 360 | packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 3]; 361 | break; 362 | 363 | case TCPOPT_WSCALE: 364 | strcat(options, "W"); 365 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 366 | window_scale = packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2]; 367 | break; 368 | 369 | case TCPOPT_SACKOK: 370 | strcat(options, "S"); 371 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 372 | sack = true; 373 | break; 374 | 375 | case TCPOPT_TIMESTAMP: 376 | strcat(options, "T"); 377 | option_index += packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 1]; 378 | ts_val = (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2] * 256 * 256 * 256) + 379 | (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 2] * 256 * 256) + 380 | (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 4] * 256) + 381 | packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 5]; 382 | ts_ecr = (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 6] * 256 * 256 * 256) + 383 | (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 7] * 256 * 256) + 384 | (packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 8] * 256) + 385 | packet[MAC_HEADER_LEN + length_ip_header + 20 + option_index + 9]; 386 | break; 387 | } 388 | } 389 | 390 | if (strcmp(options, "WNMTS") == 0) 391 | { 392 | if ((window_scale == 10) & (mss == 1460) & (ts_val == 0xffffffff) & (ts_ecr == 0) & (sack == true) & htons(rx_tcp_hdr->tcp_window) == 1) 393 | { 394 | printf("-> "); 395 | print_timestamp(); 396 | printf(": [%s] sending strange TCP options combination [WNMTS] (suspecting OSF).\a\n", attacker_ip, htons(rx_tcp_hdr->tcp_dst_prt)); 397 | } 398 | } 399 | 400 | if (strcmp(options, "MWST") == 0) 401 | { 402 | if ((mss == 1400) & (window_scale == 0) & (sack == true) & (ts_val == 0xffffffff) & (ts_ecr == 0) & htons(rx_tcp_hdr->tcp_window) == 63) 403 | { 404 | printf("-> "); 405 | print_timestamp(); 406 | printf(": [%s] sending strange TCP options combination [MWST] (suspecting OSF).\a\n", attacker_ip, htons(rx_tcp_hdr->tcp_dst_prt)); 407 | } 408 | } 409 | 410 | if (strcmp(options, "TNNWNM") == 0) 411 | { 412 | if ((ts_val == 0xffffffff) & (ts_ecr == 0) & (window_scale == 5) & (mss == 640) & htons(rx_tcp_hdr->tcp_window) == 4) 413 | { 414 | printf("-> "); 415 | print_timestamp(); 416 | printf(": [%s] sending strange TCP options combination [TNNWNM] (suspecting OSF).\a\n", attacker_ip, htons(rx_tcp_hdr->tcp_dst_prt)); 417 | } 418 | } 419 | 420 | if (strcmp(options, "STW") == 0) 421 | { 422 | if ((sack == true) & (ts_val == 0xffffffff) & (ts_ecr == 0) & (window_scale == 10) & htons(rx_tcp_hdr->tcp_window) == 4) 423 | { 424 | printf("-> "); 425 | print_timestamp(); 426 | printf(": [%s] sending strange TCP options combination [STW] (suspecting OSF).\a\n", attacker_ip, htons(rx_tcp_hdr->tcp_dst_prt)); 427 | } 428 | } 429 | 430 | if (strcmp(options, "MSTW") == 0) 431 | { 432 | if ((mss == 536) & (sack == true) & (ts_val == 0xffffffff) & (ts_ecr == 0) & (window_scale == 10) & htons(rx_tcp_hdr->tcp_window) == 16) 433 | { 434 | printf("-> "); 435 | print_timestamp(); 436 | printf(": [%s] sending strange TCP options combination [MSTW] (suspecting OSF).\a\n", attacker_ip, htons(rx_tcp_hdr->tcp_dst_prt)); 437 | } 438 | } 439 | 440 | if (strcmp(options, "MST") == 0) 441 | { 442 | if ((mss == 256) & (sack == true) & (ts_val == 0xffffffff) & (ts_ecr == 0) & htons(rx_tcp_hdr->tcp_window) == 512) 443 | { 444 | printf("-> "); 445 | print_timestamp(); 446 | printf(": [%s] sending strange TCP options combination [options = MST] (suspecting OSF).\a\n", attacker_ip, 447 | htons(rx_tcp_hdr->tcp_dst_prt)); 448 | } 449 | } 450 | }//end function Process TCP 451 | 452 | 453 | void Process_UDP(uint8_t * packet, int length) 454 | { 455 | } 456 | 457 | 458 | void Process_ICMP(uint8_t * packet, int length) 459 | { 460 | struct ip_hdr* rx_ip_hdr = ((ip_hdr*)(packet + ETH_HEADER_SIZE)); 461 | int length_ip_header = rx_ip_hdr->ip_hl * 4; // obtain the length of header in bytes to check for options 462 | char* attacker_ip = inet_ntoa(rx_ip_hdr->ip_src); 463 | 464 | struct icmp_hdr* rx_icmp_hdr = ((icmp_hdr*)(packet + ETH_HEADER_SIZE + length_ip_header)); 465 | 466 | if ((rx_icmp_hdr->icmp_type == 8) & (rx_icmp_hdr->icmp_code > 0)) 467 | { 468 | printf("-> "); 469 | print_timestamp(); 470 | printf(": [%s] sent a ICMP Echo packet with invalid 'code' value (suspecting OSF).\a\n", attacker_ip); 471 | } 472 | 473 | if ((rx_icmp_hdr->icmp_type == 1) | (rx_icmp_hdr->icmp_code == 2) | (rx_icmp_hdr->icmp_code == 7) | 474 | ((rx_icmp_hdr->icmp_code >= 19) & (rx_icmp_hdr->icmp_code <= 29)) | (rx_icmp_hdr->icmp_code >= 42)) 475 | { 476 | printf("-> "); 477 | print_timestamp(); 478 | printf(": [%s] sent a ICMP packet with reserved 'type' value (suspecting OSF).\a\n", attacker_ip); 479 | } 480 | } 481 | 482 | 483 | void* analyze_traffic(void*) 484 | { 485 | while(1) 486 | { 487 | for (int i = 0; i < MAX_ATTACKERS_NUM; i++) 488 | { 489 | if (attackers[i].attacker_ip.s_addr == 0) 490 | { 491 | continue; 492 | } 493 | 494 | 495 | int open_conx = 0; // all open connections to the server 496 | time_t time_stamp; 497 | int current_time_stamp; 498 | 499 | for (int j = 0; j < /*attackers[i].tcp_conns_number*/MAX_CONNECTION_NUM; j++) 500 | { 501 | open_conx += attackers[i].tcp_conns[j].number_of_syn; 502 | 503 | 504 | 505 | if(((attackers[i].tcp_conns[j].number_of_syn) >= MAX_ALLOWED_CONNECTIONS) && (attackers[i].tcp_conns[j].port_scan_detected == false)) 506 | { 507 | // to show the message only once if detected the port scan 508 | attackers[i].tcp_conns[j].port_scan_detected = true; 509 | 510 | char* attacker_ip = inet_ntoa(attackers[i].attacker_ip); 511 | printf("-> "); 512 | print_timestamp(); 513 | printf(": [%s] connected multiple times with the same {src_prt = %d} and {dst_prt = %d} (suspecting OSF).\a\n", attacker_ip, 514 | htons(attackers[i].tcp_conns[j].src_port), htons(attackers[i].tcp_conns[j].dst_port)); 515 | } 516 | 517 | 518 | 519 | int half_opened_num = 0; // number of half-opened connections 520 | 521 | if (attackers[i].tcp_conns[j].half_opened_detected == false) 522 | { 523 | time(&time_stamp); 524 | current_time_stamp = ((int)(time_stamp)); 525 | 526 | if ((attackers[i].tcp_conns[j].syn == true) & (attackers[i].tcp_conns[j].ack == false) & 527 | (attackers[i].tcp_conns[j].rst == false) & (attackers[i].tcp_conns[j].fin == false) & 528 | ((current_time_stamp - attackers[i].tcp_conns[j].time_stamp) >= MAX_ALLOWED_HALF_OPENED_LIFE)) 529 | { 530 | half_opened_num++; 531 | } 532 | 533 | for (int k = 0; k < /*attackers[i].tcp_conns_number*/MAX_CONNECTION_NUM; k++) 534 | { 535 | if (k == j) 536 | { 537 | continue; 538 | } 539 | 540 | if (attackers[i].tcp_conns[k].half_opened_detected == false) 541 | { 542 | if (attackers[i].tcp_conns[k].dst_port == attackers[i].tcp_conns[j].dst_port) 543 | { 544 | time(&time_stamp); 545 | current_time_stamp = ((int)(time_stamp)); 546 | 547 | if ((attackers[i].tcp_conns[k].syn == true) & (attackers[i].tcp_conns[k].ack == false) & 548 | (attackers[i].tcp_conns[k].rst == false) & (attackers[i].tcp_conns[k].fin == false) & 549 | ((current_time_stamp - attackers[i].tcp_conns[k].time_stamp) >= MAX_ALLOWED_HALF_OPENED_LIFE)) 550 | { 551 | half_opened_num++; 552 | } 553 | } 554 | } 555 | } 556 | 557 | if (half_opened_num >= MAX_ALLOWED_HALF_OPENED) 558 | { 559 | attackers[i].tcp_conns[j].half_opened_detected = true; 560 | 561 | for (int k = 0; k < /*attackers[i].tcp_conns_number*/MAX_CONNECTION_NUM; k++) 562 | { 563 | if (attackers[i].tcp_conns[k].dst_port == attackers[i].tcp_conns[j].dst_port) 564 | { 565 | attackers[i].tcp_conns[k].half_opened_detected = true; 566 | } 567 | } 568 | 569 | char* attacker_ip = inet_ntoa(attackers[i].attacker_ip); 570 | printf("-> "); 571 | print_timestamp(); 572 | printf(": [%s] established multiple half-opened connections to port [%d] [each with life > %d secs] (suspecting OSF).\a\n", 573 | attacker_ip, htons(attackers[i].tcp_conns[j].dst_port), MAX_ALLOWED_HALF_OPENED_LIFE); 574 | } 575 | } 576 | } 577 | 578 | if(open_conx > (MAX_ALLOWED_CONNECTIONS * 3) && (attackers[i].all_port_scan_detected == false)) 579 | { 580 | attackers[i].all_port_scan_detected = true; 581 | 582 | char* attacker_ip = inet_ntoa(attackers[i].attacker_ip); 583 | printf("-> "); 584 | print_timestamp(); 585 | printf(": [%s] attempting a port scan (suspecting OSF).\a\n", attacker_ip); 586 | //printf(": [%s] IS attempting a Port scan.\a\n", attacker_ip); 587 | } 588 | 589 | if ((attackers[i].tcp_syn_and_rst_num >= MAX_ALLOWED_SYN_RST) & (attackers[i].tcp_syn_and_rst_num_detected == false)) 590 | { 591 | attackers[i].tcp_syn_and_rst_num_detected = true; 592 | 593 | char* attacker_ip = inet_ntoa(attackers[i].attacker_ip); 594 | printf("-> "); 595 | print_timestamp(); 596 | printf(": [%s] sending multiple SYN then RST TCP packet to multiple ports (suspecting OSF).\a\n", attacker_ip); 597 | } 598 | } 599 | 600 | //sleep(1); 601 | } 602 | } 603 | 604 | 605 | int find_attacker(struct in_addr attacker_ip) 606 | { 607 | for (int i = 0; i < MAX_ATTACKERS_NUM; i++) 608 | { 609 | if (attackers[i].attacker_ip.s_addr == attacker_ip.s_addr) 610 | { 611 | return i; 612 | } 613 | } 614 | 615 | return -1; 616 | } 617 | 618 | 619 | void print_timestamp() 620 | { 621 | struct timeval tv; 622 | struct tm* ptm; 623 | char time_string[40]; 624 | long microseconds; 625 | 626 | gettimeofday(&tv, NULL); 627 | ptm = localtime(&tv.tv_sec); 628 | strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); 629 | microseconds = tv.tv_usec; 630 | 631 | printf("%s.%06ld", time_string, microseconds); 632 | } 633 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Detection/detect.h: -------------------------------------------------------------------------------- 1 | #include "net_utils.h" 2 | 3 | #include 4 | #include 5 | 6 | #define MAX_CONNECTION_NUM 2000 7 | #define MAX_ATTACKERS_NUM 100 8 | 9 | #define MAX_ALLOWED_CONNECTIONS 5 10 | #define MAX_ALLOWED_SYN_RST 5 11 | 12 | #define MAX_ALLOWED_HALF_OPENED_LIFE 20 13 | #define MAX_ALLOWED_HALF_OPENED 5 14 | 15 | 16 | void sniffer(u_char* useless, const struct pcap_pkthdr* pkthdr, const u_char* packet); 17 | void* handle_packet(void*); 18 | 19 | void Process_IP(uint8_t * packet, int length); 20 | void Process_TCP(uint8_t * packet, int length); 21 | void Process_UDP(uint8_t * packet, int length); 22 | void Process_ICMP(uint8_t * packet, int length); 23 | void* analyze_traffic(void*); 24 | int find_attacker(struct in_addr attacker_ip); 25 | void print_timestamp(); 26 | 27 | 28 | struct handle_packet_params 29 | { 30 | char packet[1500]; 31 | int length; 32 | }; 33 | 34 | 35 | 36 | 37 | struct tcp_connection 38 | { 39 | uint16_t src_port; 40 | uint16_t dst_port; 41 | bool syn; 42 | bool ack; 43 | bool fin; 44 | bool rst; 45 | 46 | int number_of_syn; 47 | int time_stamp; 48 | 49 | bool port_scan_detected; 50 | bool half_opened_detected; 51 | } __attribute__ ((packed)) ; 52 | 53 | struct udp_connection 54 | { 55 | uint16_t src_port; 56 | uint16_t dst_port; 57 | } __attribute__ ((packed)) ; 58 | 59 | struct attacker 60 | { 61 | struct in_addr attacker_ip; 62 | 63 | struct tcp_connection tcp_conns[MAX_CONNECTION_NUM]; 64 | int tcp_conns_number; 65 | int tcp_conns_index; 66 | 67 | struct udp_connection udp_conns[MAX_CONNECTION_NUM]; 68 | int udp_conns_number; 69 | int udp_conns_index; 70 | 71 | int tcp_syn_and_rst_num; 72 | 73 | bool all_port_scan_detected; 74 | bool tcp_syn_and_rst_num_detected; 75 | } __attribute__ ((packed)) ; 76 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Detection/interface_ip.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for ifstream 3 | #include // for cout and endl 4 | #include // for unlink() 5 | #include 6 | 7 | std::string interface_ip() 8 | { 9 | // attempt to obtain ifconfig information 10 | system( "/sbin/ifconfig eth0 2> /dev/null" 11 | "| /bin/grep -m 1 addr: | /usr/bin/cut -d : -f2" 12 | "| /usr/bin/cut -d ' ' -f1 > /tmp/sysinfo;" ); 13 | 14 | system( "/sbin/ifconfig eth0 2> /dev/null" 15 | "| /bin/grep -m 1 Bcast: | /usr/bin/cut -d : -f3" 16 | "| /usr/bin/cut -d ' ' -f1 >> /tmp/sysinfo;" ); 17 | 18 | system( "/sbin/ifconfig eth0 2> /dev/null" 19 | "| /bin/grep -m 1 Mask: | /usr/bin/cut -d : -f4 >> /tmp/sysinfo;" ); 20 | 21 | // read ifconfig information from flat-file 22 | const std::string TBD( "unknown" ); 23 | std::string ipAddr( TBD ); 24 | std::string broadcast( TBD ); 25 | std::string netmask( TBD ); 26 | 27 | std::ifstream sysinfo( "/tmp/sysinfo" ); 28 | 29 | if ( sysinfo ) 30 | { 31 | if ( sysinfo.peek() != '\0' ) sysinfo >> ipAddr; 32 | if ( sysinfo.peek() != '\0' ) sysinfo >> broadcast; 33 | if ( sysinfo.peek() != '\0' ) sysinfo >> netmask; 34 | 35 | sysinfo.close(); 36 | 37 | unlink( "/tmp/sysinfo" ); 38 | } 39 | 40 | //std::cout << "IP = " << ipAddr << std::endl; 41 | //std::cout << "BCAST = " << broadcast << std::endl; 42 | //std::cout << "MASK = " << netmask << std::endl; 43 | 44 | return ipAddr; 45 | 46 | }//return main 47 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Detection/net_utils.c: -------------------------------------------------------------------------------- 1 | #include "net_utils.h" 2 | 3 | uint16_t calc_cksum(uint8_t* hdr, int len) 4 | { 5 | long sum = 0; 6 | 7 | while(len > 1) 8 | { 9 | sum += *((unsigned short*)hdr); 10 | hdr = hdr + 2; 11 | if(sum & 0x80000000) 12 | { 13 | sum = (sum & 0xFFFF) + (sum >> 16); 14 | } 15 | len -= 2; 16 | } 17 | 18 | if(len) 19 | { 20 | sum += (unsigned short) *(unsigned char *)hdr; 21 | } 22 | 23 | while(sum>>16) 24 | { 25 | sum = (sum & 0xFFFF) + (sum >> 16); 26 | } 27 | 28 | return ~sum; 29 | } 30 | -------------------------------------------------------------------------------- /OS-Fingerprinting/Detection/net_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef NET_UTILS 2 | #define NET_UTILS 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | #define TCPOPT_EOL 0 /* End of options */ 24 | #define TCPOPT_NOP 1 /* Nothing */ 25 | #define TCPOPT_MAXSEG 2 /* MSS */ 26 | #define TCPOPT_WSCALE 3 /* Window scaling */ 27 | #define TCPOPT_SACKOK 4 /* Selective ACK permitted */ 28 | #define TCPOPT_TIMESTAMP 8 /* Stamp out timestamping! */ 29 | 30 | #define MAC_HEADER_LEN 14 31 | 32 | #ifndef IP_NO_FRAGMENT 33 | #define IP_NO_FRAGMENT 0x4000 34 | #endif 35 | 36 | #ifndef IP_PROTO_ICMP 37 | #define IP_PROTO_ICMP 1 /* ICMP protocol */ 38 | #endif 39 | 40 | #ifndef IP_PROTO_TCP 41 | #define IP_PROTO_TCP 6 /* TCP protocol */ 42 | #endif 43 | 44 | #ifndef IP_PROTO_UDP 45 | #define IP_PROTO_UDP 17 /* UDP protocol */ 46 | #endif 47 | 48 | #define ICMP_ECHO_REQUEST_TYPE 8 49 | #define ICMP_ECHO_REQUEST_CODE 0 50 | 51 | #define ICMP_ECHO_REPLY_TYPE 0 52 | #define ICMP_ECHO_REPLY_CODE 0 53 | 54 | #define ICMP_ECHO_REQUEST_DATA_LENGTH 50 55 | 56 | #define ETH_HEADER_SIZE 14 57 | 58 | 59 | struct sr_ethernet_hdr 60 | { 61 | #ifndef ETHER_ADDR_LEN 62 | #define ETHER_ADDR_LEN 6 63 | #endif 64 | uint8_t ether_dhost[ETHER_ADDR_LEN]; /* destination ethernet address */ 65 | uint8_t ether_shost[ETHER_ADDR_LEN]; /* source ethernet address */ 66 | uint16_t ether_type; /* packet type ID */ 67 | } __attribute__ ((packed)) ; 68 | 69 | struct ip_hdr 70 | { 71 | #if __BYTE_ORDER == __LITTLE_ENDIAN 72 | unsigned int ip_hl:4; /* header length */ 73 | unsigned int ip_v:4; /* version */ 74 | #elif __BYTE_ORDER == __BIG_ENDIAN 75 | unsigned int ip_v:4; /* version */ 76 | unsigned int ip_hl:4; /* header length */ 77 | #else 78 | #error "Byte ordering not specified " 79 | #endif 80 | uint8_t ip_tos; /* type of service */ 81 | uint16_t ip_len; /* total length */ 82 | uint16_t ip_id; /* identification */ 83 | uint16_t ip_off; /* fragment offset field */ 84 | #define IP_RF 0x8000 /* reserved fragment flag */ 85 | #define IP_DF 0x4000 /* dont fragment flag */ 86 | #define IP_MF 0x2000 /* more fragments flag */ 87 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 88 | uint8_t ip_ttl; /* time to live */ 89 | uint8_t ip_p; /* protocol */ 90 | uint16_t ip_sum; /* checksum */ 91 | struct in_addr ip_src, ip_dst; /* source and dest address */ 92 | } __attribute__ ((packed)); 93 | 94 | struct icmp_hdr 95 | { 96 | uint8_t icmp_type; /* type of the ICMP */ 97 | uint8_t icmp_code; /* code of the ICMO */ 98 | uint16_t icmp_cksum; /* checksum */ 99 | uint16_t icmp_id; /* identification */ 100 | uint16_t icmp_seq_n; /* sequence number */ 101 | } __attribute__ ((packed)); 102 | 103 | struct tcp_hdr 104 | { 105 | uint16_t tcp_src_prt; 106 | uint16_t tcp_dst_prt; 107 | uint32_t tcp_seq_num; 108 | uint32_t tcp_ack_num; 109 | #if __BYTE_ORDER == __LITTLE_ENDIAN 110 | unsigned int tcp_rsrvd_1:4; 111 | unsigned int tcp_dt_ofst:4; 112 | #elif __BYTE_ORDER == __BIG_ENDIAN 113 | unsigned int tcp_dt_ofst:4; 114 | unsigned int tcp_rsrvd_1:4; 115 | #else 116 | #error "Byte ordering not specified " 117 | #endif 118 | uint8_t tcp_flags; 119 | uint16_t tcp_window; 120 | uint16_t tcp_cksum; 121 | uint16_t tcp_urg_ptr; 122 | } __attribute__ ((packed)); 123 | 124 | 125 | uint16_t calc_cksum(uint8_t*, int); 126 | 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /OS-Fingerprinting/README.md: -------------------------------------------------------------------------------- 1 | OS-Fingerprinting 2 | ================= 3 | 4 | Objectives 5 | ---------- 6 | * Develop an OS fingerprinting tool 7 | * Develop a tool that detects OS fingerprinting 8 | 9 | Requirements 10 | ------------ 11 | * The tools can be developed under the OS of your choice. 12 | * OS fingerprinting can be done using any combination of techniques. 13 | * Use any approach that might help you avoid detection. 14 | * Give a list of potential OS running on your opponent’s machine with a justification. 15 | * The detection tool must print an alert when a potential fingerprinting is detected with the potential. 16 | * IP address of the source of the attack. 17 | * Your detection tool must not mistake legitimate traffic as a fingerprinting attempt. 18 | * Your host must be running a web server on port 80. Extra credit if you identify the web server used by your opponent with a justification. 19 | 20 | Overview 21 | -------- 22 | The project consists of two main tools. The first performs OS fingerprinting for a target machine, and the second detects any attempts trying to fingerprint the running OS. The detection tool was tested against the famous tool “NMAP” and the results show that it was able to detect malicious packets and OS fingerprinting attempts, without interfering with the normal process of the running web server. The fingerprinting tool was targeted on three different machines with three different OSes and web servers. The results show that it was able to detect their operating systems as well as the installed web servers. 23 | 24 | Attack Tool 25 | ----------- 26 | Each Operating System (OS) has unique characteristics in its TCP/IP stack implementation that may serve to identify it on a network. There is a wide range of techniques and methods that helped us get a good estimate of the operating system running on a certain remote machine. 27 | 28 | One approach is to use active fingerprinting. That is, special “probe” packets are sent to a certain machine, and based on its response, a certain OS is assumed. 29 | 30 | Another approach is to use passive fingerprinting (as used in our project), where legitimate traffic is analyzed and compared for certain key differences in the TCP/IP stack implementation on different versions and types of operating systems. 31 | 32 | This tool sends a legitimate HTTP request to the victim’s web server, and based on the response packets, different tests are applied to determine the installed OS and web server. 33 | 34 | A total of ten techniques are used to filter out a final choice from 24 OS Versions. These techniques have different weight values based on their accuracy. 35 | 36 | Technique | Description | Weight 37 | :---: | :--- | :---: 38 | **TTL** | Test the initial TTL value used by the OS | 0.5 39 | **DF** | Some OSes set the DF bit in the IP header while others don’t | 1 40 | **IP ID** | Different IPIDs may be sent in the IP header | 1 41 | **Window Size** | Differentiate implementations based on default Window Size in TCP | 1 42 | **SYN Packet Size** | May differ between different OSes | 1 43 | **Window Scale Option (TCP)** | Not all OSes implementation use this option | 1 44 | **TCP Options Order** | The order of TCP options may vary from one system to another | 2.5 45 | **ACK Flag** | Differentiate OSes based on the value of the Acknowledgment Number field in the TCP header when the ACK flag is set to zero | 1 46 | **URG flag** | Differentiate OSes based on the value of the Urgent Pointer field in the TCP header when the URG flag is set to zero | 1 47 | **Banner Grabbing** | The HTTP reply from the web server may contain valuable information revealing the web server name and version as well as the OS name in some cases | 48 | 49 | You can run the attack tool by issuing the following command: 50 | 51 | > ./ofp_tool victim_ip 52 | 53 | Detection Tool 54 | -------------- 55 | The detector takes into consideration different kinds of attacks that may occur instantaneously or over a time interval. Upon detection of malicious behavior, the detector displays an alarm message containing the time of the attack along with the attacker’s IP and further information about the incident. 56 | 57 | The tool first performs sanity checks on different packets (including TCP, UDP, and ICMP) to ensure correctness. More than twelve different “stateless” attacks are reported by the detector. The following shows a list of `stateless` common OS Fingerprinting attacks that are detectable: 58 | 59 | * TCP packet with the PSH flag only set. 60 | * TCP packet with the SYN and URG flags set. 61 | * TCP packet with the FIN and URG flags set. 62 | * TCP packet with the SYN, RST and URG flags set. 63 | * TCP packet with the no flags set. 64 | * TCP packet with the SYN and FIN flags are set. 65 | * TCP packet with the RST and FIN flags are set. 66 | * TCP packet with the SYN and URG flags are set. 67 | * TCP packet with the RST and SYN flags are set. 68 | * TCP packet with the SYN, FIN, and URG flags are set. 69 | * TCP packet with the SYN, FIN, PUSH and URG flags are set. 70 | * TCP packet with the SYN, ECN, CWR and URG flags are set. 71 | * An IP packet with DF set, and containing TCP segment with the ACK flag set and advertising a window size of 1024 (common used probe). 72 | * An IP packet with DF set, and containing TCP segment targeting a closed port with the SYN flag set and advertising a window size of 31337 (common used probe). 73 | * An IP packet with DF set, and containing TCP segment targeting a closed port with the SYN flag set and advertising a window size of 32768 (common used probe). 74 | * Strange options combination in TCP packet. 75 | * ICMP Echo message with invalid code value. 76 | 77 | A record of each client is stored at the server, where a state variable keeps info about the client’s connections from different ports to different services. A “checker” thread that runs in parallel with the main thread is used to ensure proper communication patterns as well as efficient use of resources. Therefore, the tool will be able to detect malicious behavior such as port scanning or unusual packet patterns. The following shows a list of `statefull` common OS Fingerprinting attacks that are detectable: 78 | 79 | * Multiple TCP connection with the same source port to the same destination port is suspected as possible OS Fingerprinting. 80 | * Multiple half-opened connection each with lifetime more than a configurable threshold is suspected as possible OS Fingerprinting. 81 | * Port scan is suspected as possible OS Fingerprinting. 82 | * Multiple pairs of SYN and RST TCP packets to multiple ports is suspected as possible OS Fingerprinting. 83 | 84 | Furthermore, to protect against Banner Grabbing, the banner information in the source code of the Apache Web Server is modified, recompiled and reinstalled it. In addition, a script is written to change the Linux default TCP/IP stack parameters to avoid getting fingerprinted. 85 | 86 | You can run the attack tool by issuing the following command: 87 | 88 | > ./ofp_detect 89 | 90 | 91 | -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/Makefile: -------------------------------------------------------------------------------- 1 | all: clean 2 | g++ -g -Wno-deprecated change.c -o change 3 | g++ -g -Wno-deprecated default.c -o default 4 | 5 | clean: 6 | rm -rf *~ change default 7 | -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agirishkumar/passive-os-detection/b279b6f8e414aa08b84e724c6d425a8daf45d032/OS-Fingerprinting/TCP-IP Stack Parameters/a.out -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/change: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agirishkumar/passive-os-detection/b279b6f8e414aa08b84e724c6d425a8daf45d032/OS-Fingerprinting/TCP-IP Stack Parameters/change -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/change.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | FILE* file; 6 | int value; 7 | int value2; 8 | 9 | 10 | file = fopen("/proc/sys/net/ipv4/ip_default_ttl", "w"); 11 | if (file != NULL) 12 | { 13 | value = 128; 14 | printf("-> Changing ip_default_ttl to [%d]\n", value); 15 | fprintf(file, "%d", value); 16 | fclose(file); 17 | } 18 | else 19 | { 20 | printf("-> Error in ip_default_ttl\n"); 21 | } 22 | 23 | 24 | file = fopen("/proc/sys/net/ipv4/icmp_echo_ignore_all", "w"); 25 | if (file != NULL) 26 | { 27 | value = 1; 28 | printf("-> Changing icmp_echo_ignore_all to [%d]\n", value); 29 | fprintf(file, "%d", value); 30 | fclose(file); 31 | } 32 | else 33 | { 34 | printf("-> Error in icmp_echo_ignore_all\n"); 35 | } 36 | 37 | 38 | file = fopen("/proc/sys/net/ipv4/ip_local_port_range", "w"); 39 | if (file != NULL) 40 | { 41 | value = 10000; 42 | value2 = 20000; 43 | printf("-> Changing ip_local_port_range to [%d\t%d]\n", value, value2); 44 | fprintf(file, "%d\t%d", value, value2); 45 | fclose(file); 46 | } 47 | else 48 | { 49 | printf("-> Error in ip_local_port_range\n"); 50 | } 51 | 52 | 53 | file = fopen("/proc/sys/net/ipv4/tcp_adv_win_scale", "w"); 54 | if (file != NULL) 55 | { 56 | value = -2; 57 | printf("-> Changing tcp_adv_win_scale to [%d]\n", value); 58 | fprintf(file, "%d", value); 59 | fclose(file); 60 | } 61 | else 62 | { 63 | printf("-> Error in tcp_adv_win_scale\n"); 64 | } 65 | 66 | 67 | file = fopen("/proc/sys/net/ipv4/tcp_dsack", "w"); 68 | if (file != NULL) 69 | { 70 | value = 0; 71 | printf("-> Changing tcp_dsack to [%d]\n", value); 72 | fprintf(file, "%d", value); 73 | fclose(file); 74 | } 75 | else 76 | { 77 | printf("-> Error in tcp_dsack\n"); 78 | } 79 | 80 | 81 | file = fopen("/proc/sys/net/ipv4/tcp_sack", "w"); 82 | if (file != NULL) 83 | { 84 | value = 0; 85 | printf("-> Changing tcp_sack to [%d]\n", value); 86 | fprintf(file, "%d", value); 87 | fclose(file); 88 | } 89 | else 90 | { 91 | printf("-> Error in tcp_sack\n"); 92 | } 93 | 94 | 95 | file = fopen("/proc/sys/net/ipv4/tcp_rfc1337", "w"); 96 | if (file != NULL) 97 | { 98 | value = 1; 99 | printf("-> Changing tcp_rfc1337 to [%d]\n", value); 100 | fprintf(file, "%d", value); 101 | fclose(file); 102 | } 103 | else 104 | { 105 | printf("-> Error in tcp_rfc1337\n"); 106 | } 107 | 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/default: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agirishkumar/passive-os-detection/b279b6f8e414aa08b84e724c6d425a8daf45d032/OS-Fingerprinting/TCP-IP Stack Parameters/default -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/default.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | FILE* file; 6 | int value; 7 | int value2; 8 | 9 | file = fopen("/proc/sys/net/ipv4/ip_default_ttl", "w"); 10 | if (file != NULL) 11 | { 12 | value = 64; 13 | printf("-> Changing ip_default_ttl to [%d]\n", value); 14 | fprintf(file, "%d", value); 15 | fclose(file); 16 | } 17 | else 18 | { 19 | printf("-> Error in ip_default_ttl\n"); 20 | } 21 | 22 | 23 | file = fopen("/proc/sys/net/ipv4/icmp_echo_ignore_all", "w"); 24 | if (file != NULL) 25 | { 26 | value = 0; 27 | printf("-> Changing icmp_echo_ignore_all to [%d]\n", value); 28 | fprintf(file, "%d", value); 29 | fclose(file); 30 | } 31 | else 32 | { 33 | printf("-> Error in icmp_echo_ignore_all\n"); 34 | } 35 | 36 | 37 | file = fopen("/proc/sys/net/ipv4/ip_local_port_range", "w"); 38 | if (file != NULL) 39 | { 40 | value = 32768; 41 | value2 = 61000; 42 | printf("-> Changing ip_local_port_range to [%d\t%d]\n", value, value2); 43 | fprintf(file, "%d\t%d", value, value2); 44 | fclose(file); 45 | } 46 | else 47 | { 48 | printf("-> Error in ip_local_port_range\n"); 49 | } 50 | 51 | 52 | file = fopen("/proc/sys/net/ipv4/tcp_adv_win_scale", "w"); 53 | if (file != NULL) 54 | { 55 | value = 2; 56 | printf("-> Changing tcp_adv_win_scale to [%d]\n", value); 57 | fprintf(file, "%d", value); 58 | fclose(file); 59 | } 60 | else 61 | { 62 | printf("-> Error in tcp_adv_win_scale\n"); 63 | } 64 | 65 | 66 | file = fopen("/proc/sys/net/ipv4/tcp_dsack", "w"); 67 | if (file != NULL) 68 | { 69 | value = 1; 70 | printf("-> Changing tcp_dsack to [%d]\n", value); 71 | fprintf(file, "%d", value); 72 | fclose(file); 73 | } 74 | else 75 | { 76 | printf("-> Error in tcp_dsack\n"); 77 | } 78 | 79 | 80 | file = fopen("/proc/sys/net/ipv4/tcp_sack", "w"); 81 | if (file != NULL) 82 | { 83 | value = 1; 84 | printf("-> Changing tcp_sack to [%d]\n", value); 85 | fprintf(file, "%d", value); 86 | fclose(file); 87 | } 88 | else 89 | { 90 | printf("-> Error in tcp_sack\n"); 91 | } 92 | 93 | 94 | file = fopen("/proc/sys/net/ipv4/tcp_rfc1337", "w"); 95 | if (file != NULL) 96 | { 97 | value = 0; 98 | printf("-> Changing tcp_rfc1337 to [%d]\n", value); 99 | fprintf(file, "%d", value); 100 | fclose(file); 101 | } 102 | else 103 | { 104 | printf("-> Error in tcp_rfc1337\n"); 105 | } 106 | 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /OS-Fingerprinting/TCP-IP Stack Parameters/readme: -------------------------------------------------------------------------------- 1 | To modify the linux TCP/IP stack parameters such as Default TTL, change the values of the files in /proc/sys/net/ipv4 2 | --------------------------------------------------------------------------------