📄 portscan.c
字号:
return 0; if(ipset_contains(g_ps_init.watch_ip, &scanned, &(p->dp), IPV4_FAMILY)) return 0;#endif return 1; } return 0;}/*** NAME** ps_tracker_init::*//**** Right now all we do is memset, but just in case we want to do more** initialization has been extracted.*/static int ps_tracker_init(PS_TRACKER *tracker){ memset(tracker, 0x00, g_ps_tracker_size); return 0;}/*** NAME** ps_tracker_get::*//**** Get a tracker node by either finding one or starting a new one. We may** return NULL, in which case we wait till the next packet.*/static int ps_tracker_get(PS_TRACKER **ht, PS_HASH_KEY *key){ int iRet; *ht = (PS_TRACKER *)sfxhash_find(g_hash, (void *)key); if(!(*ht)) { iRet = sfxhash_add(g_hash, (void *)key, NULL); if(iRet == SFXHASH_OK) { *ht = (PS_TRACKER *)sfxhash_mru(g_hash); if(!(*ht)) return -1; ps_tracker_init(*ht); } else { return -1; } } return 0;}static int ps_tracker_lookup(PS_PKT *ps_pkt, PS_TRACKER **scanner, PS_TRACKER **scanned){ PS_HASH_KEY key; Packet *p; if(!ps_pkt->pkt) return -1; p = (Packet *)ps_pkt->pkt; /* ** Let's lookup the host that is being scanned, taking into account ** the pkt may be reversed. */ if(g_ps_init.detect_scan_type & (PS_TYPE_PORTSCAN | PS_TYPE_DECOYSCAN | PS_TYPE_DISTPORTSCAN)) { IP_CLEAR(key.scanner); if(ps_pkt->reverse_pkt) IP_COPY_VALUE(key.scanned, GET_SRC_IP(p)); else IP_COPY_VALUE(key.scanned, GET_DST_IP(p)); /* ** Get the scanned tracker. */ if(ps_tracker_get(scanned, &key)) return -1; } /* ** Let's lookup the host that is scanning. */ if(g_ps_init.detect_scan_type & PS_TYPE_PORTSWEEP) { IP_CLEAR(key.scanned); if(ps_pkt->reverse_pkt) IP_COPY_VALUE(key.scanner, GET_DST_IP(p)); else IP_COPY_VALUE(key.scanner, GET_SRC_IP(p)); /* ** Get the scanner tracker */ if(ps_tracker_get(scanner, &key)) return -1; } return 0;}/*** NAME** ps_get_proto_index::*//**** This logic finds the index to the proto array based on the** portscan configuration. We need special logic because the ** index of the protocol changes based on the configuration.*/static int ps_get_proto_index(PS_PKT *ps_pkt, int *proto_index, int *proto){ Packet *p; int found = 0; if(!ps_pkt || !ps_pkt->pkt || !proto_index || !proto) return -1; p = (Packet *)ps_pkt->pkt; *proto_index = 0; *proto = 0; if(!found && g_ps_init.detect_scans & PS_PROTO_TCP) { if(p->tcph) { found = 1; *proto = PS_PROTO_TCP; } else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH && p->icmph->code == ICMP_PORT_UNREACH && p->orig_tcph) { found = 1; *proto = PS_PROTO_TCP; } else { (*proto_index)++; } } if(!found && g_ps_init.detect_scans & PS_PROTO_UDP) { if(p->udph) { found = 1; *proto = PS_PROTO_UDP; } else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH && p->icmph->code == ICMP_PORT_UNREACH && p->orig_udph) { found = 1; *proto = PS_PROTO_UDP; } else { (*proto_index)++; } } if(!found && g_ps_init.detect_scans & PS_PROTO_IP) { if(IPH_IS_VALID(p) && !p->icmph) { found = 1; *proto = PS_PROTO_IP; } else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH && p->icmph->code == ICMP_PROT_UNREACH) { found = 1; *proto = PS_PROTO_IP; } else { (*proto_index)++; } } if(!found && g_ps_init.detect_scans & PS_PROTO_ICMP) { if(p->icmph) { found = 1; *proto = PS_PROTO_ICMP; } else { (*proto_index)++; } } if(!found) { *proto = 0; *proto_index = 0; return -1; } return 0;}/*** NAME** ps_proto_update_window::*//**** Update the proto time windows based on the portscan sensitivity** level.*/static int ps_proto_update_window(PS_PROTO *proto, time_t pkt_time){ time_t interval; switch(g_ps_init.sense_level) { case PS_SENSE_LOW: //interval = 15; interval = 60; break; case PS_SENSE_MEDIUM: //interval = 15; interval = 90; break; case PS_SENSE_HIGH: interval = 600; break; default: return -1; } /* ** If we are outside of the window, reset our ps counters. */ if(pkt_time > proto->window) { memset(proto, 0x00, sizeof(PS_PROTO)); proto->window = pkt_time + interval; return 0; } return 0;}/*** NAME** ps_proto_update::*//**** This function updates the PS_PROTO structure.**** @param PS_PROTO pointer to structure to update** @param int number to increment portscan counter** @param u_long IP address of other host** @param u_short port/ip_proto to track** @param time_t time the packet was received. update windows.*/static int ps_proto_update(PS_PROTO *proto, int ps_cnt, int pri_cnt, ip_p ip, u_short port, time_t pkt_time){ if(!proto) return 0; /* ** If the ps_cnt is negative, that means we are just taking off ** for valid connection, and we don't want to do anything else, ** like update ip/port, etc. */ if(ps_cnt < 0) { proto->connection_count += ps_cnt; if(proto->connection_count < 0) proto->connection_count = 0; return 0; } /* ** If we are updating a priority cnt, it means we already did the ** unique port and IP on the connection packet. ** ** Priority points are only added for invalid response packets. */ if(pri_cnt) { proto->priority_count += pri_cnt; if(proto->priority_count < 0) proto->priority_count = 0; return 0; } /* ** Do time check first before we update the counters, so if ** we need to reset them we do it before we update them. */ if(ps_proto_update_window(proto, pkt_time)) return -1; /* ** Update ps counter */ proto->connection_count += ps_cnt; if(proto->connection_count < 0) proto->connection_count = 0;#ifdef SUP_IP6 if(!IP_EQUALITY(&proto->u_ips, ip))#else if(!IP_EQUALITY(proto->u_ips, ip))#endif { proto->u_ip_count++; IP_COPY_VALUE(proto->u_ips, ip); } /* we need to do the IP comparisons in host order */#ifndef SUP_IP6 ip = ntohl(ip);#endif#ifdef SUP_IP6 if(sfip_is_set(&proto->low_ip)) { if(IP_GREATER(&proto->low_ip, ip)) IP_COPY_VALUE(proto->low_ip, ip); }#else if(IS_SET(proto->low_ip)) { if(IP_GREATER(proto->low_ip, ip)) IP_COPY_VALUE(proto->low_ip, ip); }#endif else { IP_COPY_VALUE(proto->low_ip, ip); } if(IS_SET(proto->high_ip)) {#ifdef SUP_IP6 if(IP_LESSER(&proto->high_ip, ip))#else if(IP_LESSER(proto->high_ip, ip))#endif IP_COPY_VALUE(proto->high_ip, ip); } else { IP_COPY_VALUE(proto->high_ip, ip); } if(proto->u_ports != port) { proto->u_port_count++; proto->u_ports = port; } if(proto->low_p) { if(proto->low_p > port) proto->low_p = port; } else { proto->low_p = port; } if(proto->high_p) { if(proto->high_p < port) proto->high_p = port; } else { proto->high_p = port; } return 0;}static int ps_update_open_ports(PS_PROTO *proto, unsigned short port){ int iCtr; for(iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++) { if(port == proto->open_ports[iCtr]) return 0; } if(iCtr < (PS_OPEN_PORTS - 1)) { proto->open_ports[iCtr] = port; proto->open_ports_cnt++; if(proto->alerts == PS_ALERT_GENERATED) { proto->alerts = PS_ALERT_OPEN_PORT; } } return 0;} /*** NAME** ps_tracker_update_tcp::*//**** Determine how to update the portscan counter depending on the type** of TCP packet we have.**** We are concerned with three types of TCP packets:** ** - initiating TCP packets (we don't care about flags)** - TCP 3-way handshake packets (we decrement the counter)** - TCP reset packets on unestablished streams.*/static int ps_tracker_update_tcp(PS_PKT *ps_pkt, PS_TRACKER *scanner, PS_TRACKER *scanned, int proto_idx){ Packet *p; time_t pkt_time; FLOW *flow; u_int32_t session_flags; ip_t cleared; IP_CLEAR(cleared); p = (Packet *)ps_pkt->pkt; pkt_time = packet_timeofday(); flow = (FLOW *)p->flow; /* ** Handle the initiating packet. ** ** If this what stream4 considers to be a valid initiator, then ** we will use the available stream4 information. Otherwise, we ** can just revert to flow and look for initiators and responders. ** ** For Stream5, depending on the configuration, there might not ** be a session created only based on the SYN packet. Stream5 ** by default has code that helps deal with SYN flood attacks, ** and may simply ignore the SYN. In this case, we fall through ** to the checks for specific TCP header files (SYN, SYN-ACK, RST). ** ** The "midstream" logic below says that, if we include sessions ** picked up midstream, then we don't care about the MIDSTREAM flag. ** Otherwise, only consider streams not picked up midstream. */ if(p->ssnptr && stream_api) { session_flags = stream_api->get_session_flags(p->ssnptr); if((session_flags & SSNFLAG_SEEN_CLIENT) && !(session_flags & SSNFLAG_SEEN_SERVER) && (g_include_midstream || !(session_flags & SSNFLAG_MIDSTREAM))) { if(scanned) { ps_proto_update(&scanned->proto[proto_idx],1,0, GET_SRC_IP(p),p->dp, pkt_time); } if(scanner) { ps_proto_update(&scanner->proto[proto_idx],1,0, GET_DST_IP(p),p->dp, pkt_time); } } /* ** Handle the final packet of the three-way handshake. */ else if(p->packet_flags & PKT_STREAM_TWH) { if(scanned) { ps_proto_update(&scanned->proto[proto_idx],-1,0,CLEARED,0,0); } if(scanner) { ps_proto_update(&scanner->proto[proto_idx],-1,0,CLEARED,0,0); } } /* ** RST packet on unestablished streams */ else if((p->packet_flags & PKT_FROM_SERVER) && (p->tcph && (p->tcph->th_flags & TH_RST)) && (!(p->packet_flags & PKT_STREAM_EST) || (session_flags & SSNFLAG_MIDSTREAM))) { if(scanned) { ps_proto_update(&scanned->proto[proto_idx],0,1,CLEARED,0,0); scanned->priority_node = 1; } if(scanner) { ps_proto_update(&scanner->proto[proto_idx],0,1,CLEARED,0,0); scanner->priority_node = 1; } } /* ** We only get here on the server's response to the intial ** client connection. ** ** That's why we use the sp, because that's the port that is ** open.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -