📄 spp_portscan.c
字号:
if(delSource->prevNode) { delSource->prevNode->nextNode = delSource->nextNode; } else if(delSource->nextNode) { delSource->nextNode->prevNode = NULL; } if(delSource->nextNode) { delSource->nextNode->prevNode = delSource->prevNode; } else if(delSource->prevNode) { delSource->prevNode->nextNode = NULL; } } free(delSource);}/* Go through each connection and remove any connections that are old. If the removal of a node makes a parent node empty, remove that node, all the way back to the root.*/void ExpireConnections(ScanList * scanList, struct spp_timeval watchPeriod, struct spp_timeval currentTime){ SourceInfo *currentSource = scanList->listHead, *tmpSource; DestinationInfo *currentDestination, *tmpDestination; ConnectionInfo *currentConnection, *tmpConnection; /* Empty list. Get out of here. */ if(!scanList->listHead) return; while(currentSource) { /* * If this source host is scanning us, we don't want to lose any * connections so go back to top. */ if(currentSource->scanDetected) { currentSource = currentSource->nextNode; continue; } currentDestination = currentSource->destinationsList; while(currentDestination) { currentConnection = currentDestination->connectionsList; while(currentConnection) { if(currentConnection->timestamp.tv_sec + watchPeriod.tv_sec < currentTime.tv_sec) { /* Expire the connection */ tmpConnection = currentConnection; currentConnection = currentConnection->nextNode; /* * If this is the first connection, we need to update * connectionsList. */ if(tmpConnection->prevNode == NULL) { currentDestination->connectionsList = tmpConnection->nextNode; } if(tmpConnection->scanType == sUDP) { currentSource->numberOfUDPConnections--; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": ExpireConnections(): %s->numberOfUDPConnections-- (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfUDPConnections);); } else { currentSource->numberOfTCPConnections--; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": ExpireConnections(): %s->numberOfTCPConnections-- (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfTCPConnections);); } RemoveConnection(tmpConnection); currentSource->numberOfConnections--; currentDestination->numberOfConnections--; } else { currentConnection = currentConnection->nextNode; } } tmpDestination = currentDestination; currentDestination = currentDestination->nextNode; if(tmpDestination->numberOfConnections == 0) { if(tmpDestination->prevNode == NULL) { currentSource->destinationsList = tmpDestination->nextNode; } RemoveDestination(tmpDestination); currentSource->numberOfDestinations--; } } tmpSource = currentSource; currentSource = currentSource->nextNode; if(tmpSource->numberOfDestinations == 0) { /* If this is the first source, we need to update scanList. */ if(tmpSource->prevNode == NULL) { /* This is fine, even if tmpSource->nextNode is NULL */ scanList->listHead = tmpSource->nextNode; } RemoveSource(tmpSource); scanList->numberOfSources--; } } if(scanList->numberOfSources == 0) { scanList->listHead = NULL; }}/* Add the connection information and return the new number of connections for this host*/int NewScan(ScanList * scanList, Packet * p, ScanType scanType){ SourceInfo *currentSource = scanList->listHead; DestinationInfo *currentDestination; ConnectionInfo *currentConnection; int matchFound = 0; struct in_addr saddr; struct in_addr daddr; u_short sport; u_short dport; /* If list is empty, create the list and add this entry. */ if(!scanList->listHead) { scanList->listHead = NewSource(p, scanType); scanList->numberOfSources = 1; scanList->lastSource = scanList->listHead; return(scanList->listHead->numberOfConnections); } ExtractHeaderInfo(p, &saddr, &daddr, &sport, &dport); while(!matchFound) { if(currentSource->saddr.s_addr == saddr.s_addr) { currentDestination = currentSource->destinationsList; if(currentSource->destinationsList == NULL) { currentSource->destinationsList = NewDestination(p, scanType); currentSource->numberOfConnections++; if(scanType == sUDP) { currentSource->numberOfUDPConnections++; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfUDPConnections++ (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfUDPConnections);); } else { currentSource->numberOfTCPConnections++; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfTCPConnections++ (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfTCPConnections);); } currentSource->numberOfDestinations++; matchFound = 1; } currentDestination = currentSource->destinationsList; while(!matchFound) { if(currentDestination->daddr.s_addr == daddr.s_addr) { currentConnection = currentDestination->connectionsList; while(!matchFound) { /* * There should be error checking for * currentConnection == NULL, but that should never * happen. */ if(currentConnection == NULL) FatalError(MODNAME ": currentConnection is NULL!!!??\n"); if((currentConnection->dport == dport) && (currentConnection->scanType == scanType)) { /* * If the same exact connection already exists, * just update the timestamp. */ currentConnection->timestamp.tv_sec = p->pkth->ts.tv_sec; currentConnection->timestamp.tv_usec = p->pkth->ts.tv_usec; currentConnection->sport = sport; matchFound = 1; } else { /* * If not at end of list, keep going, otherwise * create a node. */ if(!currentConnection->nextNode) { currentConnection = AddConnection(currentConnection, p, scanType); currentSource->numberOfConnections++; if(scanType == sUDP) { currentSource->numberOfUDPConnections++; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfUDPConnections++ (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfUDPConnections);); } else { currentSource->numberOfTCPConnections++; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfTCPConnections++ (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfTCPConnections);); } currentDestination->numberOfConnections++; matchFound = 1; } else currentConnection = currentConnection->nextNode; } } } else { if(!currentDestination->nextNode) { currentDestination = AddDestination(currentDestination, p, scanType); currentSource->numberOfConnections++; if(scanType == sUDP) { currentSource->numberOfUDPConnections++; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfUDPConnections++ (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfUDPConnections);); } else { currentSource->numberOfTCPConnections++; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfTCPConnections++ (%d)\n", inet_ntoa(currentSource->saddr), currentSource->numberOfTCPConnections);); } currentSource->numberOfDestinations++; currentSource->totalNumberOfDestinations++; matchFound = 1; } else currentDestination = currentDestination->nextNode; } } } else { if(!currentSource->nextNode) { currentSource = AddSource(currentSource, p, scanType); currentSource->numberOfConnections = 1; if(scanType == sUDP) { currentSource->numberOfUDPConnections = 1; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfUDPConnections = 1 \n", inet_ntoa(currentSource->saddr));); } else { currentSource->numberOfTCPConnections = 1; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, MODNAME ": NewScan(): %s->numberOfTCPConnections = 1\n", inet_ntoa(currentSource->saddr));); } scanList->numberOfSources++; matchFound = 1; } else currentSource = currentSource->nextNode; } } scanList->lastSource = currentSource; return(currentSource->numberOfConnections);}ScanList *CreateScanList(void){ ScanList *newList = (ScanList *) malloc(sizeof(ScanList)); newList->listHead = NULL; newList->lastSource = NULL; newList->numberOfSources = 0; return(newList);}void PortscanPreprocFunction(Packet * p, void *context){ /* * The main loop. Whenever this is called, first we expire connections * so we don't get false positives from stale connections. Then we add * the new connection information and check if the latest connection has * passed the threshold. If it has or if a stealth technique was used, * we immediately report the scan. Then we go through the list and any * host that has been flagged as doing a portscan and has passed the * necessary amount of time between reports and has connections stored * are reported and cleared. Any host that has been flagged as doing a * portscan and has passed the necessary amount of time between reports * and does not have connections stored has the portscan flag cleared and * will automatically be flushed at next call. */ SourceInfo *currentSource; ScanType scanType; struct spp_timeval currTime; char logMessage[180]; int numPorts; Event event; if(!(p->preprocessors & PP_PORTSCAN)) { return; } /* Only do processing on IP Packets */ if(p->iph == NULL) { return; } if(p->packet_flags & PKT_REBUILT_STREAM) { return; } /* * Here we check if it is a protocol we are watching and if it is a * destination we are watching. If either fails, we return abruptly. */ switch(p->iph->ip_proto) { case IPPROTO_TCP: if(p->tcph == NULL) { /* * ZDNOTE Fragmented packets have IPH set to NULL so `nmap -f` * defeats SPP, at least until reassembly or the header pointer * is fixed. */ return; } DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"spp_portscan: Got TCP pkt\n");); scanType = CheckTCPFlags(p->tcph->th_flags); break; case IPPROTO_UDP: /* * We no longer check for NULL UDP headers here, because it really * doesn't matter anymore. We don't access it. We just use p->[sd]p * instead. */ scanType = sUDP; break; default: /* The packet isn't a protocol we watch, so get out of here. */ return; /*** RETURN ***/ break; } /* * For speed, we're going to drop out right now if this packet is not any * type of scan. My assumption is most packets on the network are not * going to be any type of scan packet (not even SYN or UDP), so this * extra check will be faster in the long run. */ if(!scanType) return; /* * The checks above are faster, so now that we know this packet is * interesting we'll check the address. */ if(!CheckAddrPort(homeAddr, 0, 0, p, (ANY_DST_PORT | homeFlags), CHECK_DST)) { return; } /* * If we ignore SYN and UDP scans from this host (presumably because it's * a server), clear out those flags so we don't get false alarms. If it's * a server, we also need to make sure there are no reserved bits set * because otherwise "2*S*****" shows as UNKNOWN instead of as SYN w/ * RESERVEDBITS. The beast below makes sure we are actually watching for * RB scans. The previous version would have let servers be left as SYN * scans if a reserved bit was set. */ if(IsServer(p) && !(scanType & sRESERVEDBITS & scansToWatch)) { scanType &= ~(sSYN | sUDP); } if(scanType & scansToWatch) { currTime.tv_sec = p->pkth->ts.tv_sec; currTime.tv_usec = p->pkth->ts.tv_usec; ExpireConnections(scanList, maxTime, currTime); /* * If more than maxPorts connections made or if stealth scan * technique was used, mark this as a portscan. */ numPorts = NewScan(scanList, p, scanType); /* Timestamp info for statistics */ scanList->lastSource->lastPacketTime = currTime; if((numPorts > maxPorts) || (scanType & ~(sSYN | sUDP))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -