📄 service_scan.cc
字号:
rarity = tp;} // Takes a match line in a probe description and adds it to the // list of matches for this probe. This function should be passed // the whole line starting with "match" or "softmatch" in // nmap-service-probes. The line number is requested because this // function will bail with an error (giving the line number) if it // fails to parse the string.void ServiceProbe::addMatch(const char *match, int lineno) { const char *sname; ServiceProbeMatch *newmatch = new ServiceProbeMatch(); newmatch->InitMatch(match, lineno); sname = newmatch->getName(); if (!serviceIsPossible(sname)) detectedServices.push_back(sname); matches.push_back(newmatch);}/* Parses the given nmap-service-probes file into the AP class Must NOT be made static because I have external maintenance tools (servicematch) which use this */void parse_nmap_service_probe_file(AllProbes *AP, char *filename) { ServiceProbe *newProbe = NULL; char line[2048]; int lineno = 0; FILE *fp; // We better start by opening the file fp = fopen(filename, "r"); if (!fp) fatal("Failed to open nmap-service-probes file %s for reading", filename); while(fgets(line, sizeof(line), fp)) { lineno++; if (*line == '\n' || *line == '#') continue; if (strncmp(line, "Exclude ", 8) == 0) { if (AP->excludedports != NULL) fatal("Only 1 Exclude directive is allowed in the nmap-service-probes file"); AP->excludedports = getpts(line+8); continue; } anotherprobe: if (strncmp(line, "Probe ", 6) != 0) fatal("Parse error on line %d of nmap-service-probes file: %s -- line was expected to begin with \"Probe \" or \"Exclude \"", lineno, filename); newProbe = new ServiceProbe(); newProbe->setProbeDetails(line + 6, lineno); // Now we read the rest of the probe info while(fgets(line, sizeof(line), fp)) { lineno++; if (*line == '\n' || *line == '#') continue; if (strncmp(line, "Probe ", 6) == 0) { if (newProbe->isNullProbe()) { assert(!AP->nullProbe); AP->nullProbe = newProbe; } else { AP->probes.push_back(newProbe); } goto anotherprobe; } else if (strncmp(line, "ports ", 6) == 0) { newProbe->setProbablePorts(SERVICE_TUNNEL_NONE, line + 6, lineno); } else if (strncmp(line, "sslports ", 9) == 0) { newProbe->setProbablePorts(SERVICE_TUNNEL_SSL, line + 9, lineno); } else if (strncmp(line, "rarity ", 7) == 0) { newProbe->setRarity(line + 7, lineno); } else if (strncmp(line, "fallback ", 9) == 0) { newProbe->fallbackStr = strdup(line + 9); } else if (strncmp(line, "totalwaitms ", 12) == 0) { long waitms = strtol(line + 12, NULL, 10); if (waitms < 100 || waitms > 300000) fatal("Error on line %d of nmap-service-probes file (%s): bad totalwaitms value. Must be between 100 and 300000 milliseconds", lineno, filename); newProbe->totalwaitms = waitms; } else if (strncmp(line, "match ", 6) == 0 || strncmp(line, "softmatch ", 10) == 0) { newProbe->addMatch(line, lineno); } else if (strncmp(line, "Exclude ", 8) == 0) { fatal("The Exclude directive must precede all Probes in nmap-service-probes"); } else fatal("Parse error on line %d of nmap-service-probes file: %s -- unknown directive", lineno, filename); } } assert(newProbe); if (newProbe->isNullProbe()) { assert(!AP->nullProbe); AP->nullProbe = newProbe; } else { AP->probes.push_back(newProbe); } fclose(fp); AP->compileFallbacks();}// Parses the nmap-service-probes file, and adds each probe to// the already-created 'probes' vector.static void parse_nmap_service_probes(AllProbes *AP) { char filename[256]; if (nmap_fetchfile(filename, sizeof(filename), "nmap-service-probes") != 1){ fatal("Service scan requested but I cannot find nmap-service-probes file. It should be in %s, ~/.nmap/ or .", NMAPDATADIR); } parse_nmap_service_probe_file(AP, filename); /* Record where this data file was found. */ o.loaded_data_files["nmap-service-probes"] = filename;}AllProbes *AllProbes::global_AP;AllProbes *AllProbes::service_scan_init(void){ if(global_AP) return global_AP; global_AP = new AllProbes(); parse_nmap_service_probes(global_AP); return global_AP;}void AllProbes::service_scan_free(void){ if(global_AP){ delete global_AP; global_AP = NULL; }}// If the buf (of length buflen) matches one of the regexes in this// ServiceProbe, returns the details of the match (service name,// version number if applicable, and whether this is a "soft" match.// If the buf doesn't match, the serviceName field in the structure// will be NULL. The MatchDetails returned is only valid until the// next time this function is called. The only exception is that the// serviceName field can be saved throughought program execution. If// no version matched, that field will be NULL. This function may// return NULL if there are no match lines at all in this probe.const struct MatchDetails *ServiceProbe::testMatch(const u8 *buf, int buflen) { vector<ServiceProbeMatch *>::iterator vi; const struct MatchDetails *MD; for(vi = matches.begin(); vi != matches.end(); vi++) { MD = (*vi)->testMatch(buf, buflen); if (MD->serviceName) return MD; } return NULL;}AllProbes::AllProbes() { nullProbe = NULL; excludedports = NULL;}AllProbes::~AllProbes() { vector<ServiceProbe *>::iterator vi; // Delete all the ServiceProbe's inside the probes vector for(vi = probes.begin(); vi != probes.end(); vi++) { delete *vi; } if(nullProbe) delete nullProbe; free_scan_lists(excludedports);} // Tries to find the probe in this AllProbes class which have the // given name and protocol. It can return the NULL probe.ServiceProbe *AllProbes::getProbeByName(const char *name, int proto) { vector<ServiceProbe *>::iterator vi; if (proto == IPPROTO_TCP && nullProbe && strcmp(nullProbe->getName(), name) == 0) return nullProbe; for(vi = probes.begin(); vi != probes.end(); vi++) { if ((*vi)->getProbeProtocol() == proto && strcmp(name, (*vi)->getName()) == 0) return *vi; } return NULL;}// Returns nonzero if port was specified in the excludeports// directive in nmap-service-probes. Zero otherwise.// Proto should be IPPROTO_TCP for TCP and IPPROTO_UDP for UDP// Note that although getpts() can set protocols (for protocol// scanning), this is ignored here because you can't version// scan protocols.int AllProbes::isExcluded(unsigned short port, int proto) { unsigned short *p=NULL; int count=-1,i; if (!excludedports) return 0; if (proto == IPPROTO_TCP) { p = excludedports->tcp_ports; count = excludedports->tcp_count; } else if (proto == IPPROTO_UDP) { p = excludedports->udp_ports; count = excludedports->udp_count; } else { fatal("Bad proto number (%d) specified in %s", proto, __func__); } for (i=0; i<count; i++) if (p[i] == port) return 1; return 0;}// Before this function is called, the fallbacks exist as unparsed// comma-separated strings in the fallbackStr field of each probe.// This function fills out the fallbacks array in each probe with// an ordered list of pointers to which probes to try. This is both for// efficiency and to deal with odd cases like the NULL probe and falling// back to probes later in the file. This function also free()s all the// fallbackStrs.void AllProbes::compileFallbacks() { vector<ServiceProbe *>::iterator curr; char *tp; int i; curr = probes.begin(); // The NULL probe is a special case: nullProbe->fallbacks[0] = nullProbe; while (curr != probes.end()) { if ((*curr)->fallbackStr == NULL) { // A non-NULL probe without a fallback directive. We // just use "Itself,NULL" unless it's UDP, then just "Itself". (*curr)->fallbacks[0] = *curr; if ((*curr)->getProbeProtocol() == IPPROTO_TCP) (*curr)->fallbacks[1] = nullProbe; } else { // A non-NULL probe *with* a fallback directive. We use: // TCP: "Itself,<directive1>,...,<directiveN>,NULL" // UDP: "Itself,<directive1>,...,<directiveN>" (*curr)->fallbacks[0] = *curr; i = 1; tp = strtok((*curr)->fallbackStr, ",\r\n\t "); // \r and \n because string will be terminated with them while (tp != NULL && i<(MAXFALLBACKS-1)) { (*curr)->fallbacks[i] = getProbeByName(tp, (*curr)->getProbeProtocol()); if ((*curr)->fallbacks[i] == NULL) fatal("%s: Unknown fallback specified in Probe %s: '%s'", __func__, (*curr)->getName(), tp); i++; tp = strtok(NULL, ",\r\n\t "); } if (i == MAXFALLBACKS-1) fatal("%s: MAXFALLBACKS exceeded on probe '%s'", __func__, (*curr)->getName()); if ((*curr)->getProbeProtocol() == IPPROTO_TCP) (*curr)->fallbacks[i] = nullProbe; } if ((*curr)->fallbackStr) free((*curr)->fallbackStr); (*curr)->fallbackStr = NULL; curr++; }}ServiceNFO::ServiceNFO(AllProbes *newAP) { target = NULL; probe_matched = NULL; niod = NULL; probe_state = PROBESTATE_INITIAL; portno = proto = 0; AP = newAP; currentresp = NULL; currentresplen = 0; port = NULL; product_matched[0] = version_matched[0] = extrainfo_matched[0] = '\0'; hostname_matched[0] = ostype_matched[0] = devicetype_matched[0] = '\0'; tunnel = SERVICE_TUNNEL_NONE; ssl_session = NULL; softMatchFound = false; servicefplen = servicefpalloc = 0; servicefp = NULL; memset(¤tprobe_exec_time, 0, sizeof(currentprobe_exec_time));}ServiceNFO::~ServiceNFO() { if (currentresp) free(currentresp); if (servicefp) free(servicefp); servicefp = NULL; servicefpalloc = servicefplen = 0;#if HAVE_OPENSSL if (ssl_session) SSL_SESSION_free((SSL_SESSION*)ssl_session); ssl_session=NULL;#endif} // Adds a character to servicefp. Takes care of word wrapping if // necessary at the given (wrapat) column. Chars will only be // written if there is enough space. Otherwise it exits.void ServiceNFO::addServiceChar(char c, int wrapat) { if (servicefpalloc - servicefplen < 6) fatal("%s - out of space for servicefp", __func__); if (servicefplen % (wrapat+1) == wrapat) { // we need to start a new line memcpy(servicefp + servicefplen, "\nSF:", 4); servicefplen += 4; } servicefp[servicefplen++] = c;}// Like addServiceChar, but for a whole zero-terminated stringvoid ServiceNFO::addServiceString(char *s, int wrapat) { while(*s) addServiceChar(*s++, wrapat);}// If a service response to a given probeName, this function adds the// resonse the the fingerprint for that service. The fingerprint can// be printed when nothing matches the service. You can obtain the// fingerprint (if any) via getServiceFingerprint();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -