📄 service_scan.cc
字号:
/*************************************************************************** * service_scan.cc -- Routines used for service fingerprinting to determine * * what application-level protocol is listening on a given port * * (e.g. snmp, http, ftp, smtp, etc.) * * * ***********************IMPORTANT NMAP LICENSE TERMS************************ * * * The Nmap Security Scanner is (C) 1996-2008 Insecure.Com LLC. Nmap is * * also a registered trademark of Insecure.Com LLC. This program is free * * software; you may redistribute and/or modify it under the terms of the * * GNU General Public License as published by the Free Software * * Foundation; Version 2 with the clarifications and exceptions described * * below. This guarantees your right to use, modify, and redistribute * * this software under certain conditions. If you wish to embed Nmap * * technology into proprietary software, we sell alternative licenses * * (contact sales@insecure.com). Dozens of software vendors already * * license Nmap technology such as host discovery, port scanning, OS * * detection, and version detection. * * * * Note that the GPL places important restrictions on "derived works", yet * * it does not provide a detailed definition of that term. To avoid * * misunderstandings, we consider an application to constitute a * * "derivative work" for the purpose of this license if it does any of the * * following: * * o Integrates source code from Nmap * * o Reads or includes Nmap copyrighted data files, such as * * nmap-os-fingerprints or nmap-service-probes. * * o Executes Nmap and parses the results (as opposed to typical shell or * * execution-menu apps, which simply display raw Nmap output and so are * * not derivative works.) * * o Integrates/includes/aggregates Nmap into a proprietary executable * * installer, such as those produced by InstallShield. * * o Links to a library or executes a program that does any of the above * * * * The term "Nmap" should be taken to also include any portions or derived * * works of Nmap. This list is not exclusive, but is just meant to * * clarify our interpretation of derived works with some common examples. * * These restrictions only apply when you actually redistribute Nmap. For * * example, nothing stops you from writing and selling a proprietary * * front-end to Nmap. Just distribute it by itself, and point people to * * http://insecure.org/nmap/ to download Nmap. * * * * We don't consider these to be added restrictions on top of the GPL, but * * just a clarification of how we interpret "derived works" as it applies * * to our GPL-licensed Nmap product. This is similar to the way Linus * * Torvalds has announced his interpretation of how "derived works" * * applies to Linux kernel modules. Our interpretation refers only to * * Nmap - we don't speak for any other GPL products. * * * * If you have any questions about the GPL licensing restrictions on using * * Nmap in non-GPL works, we would be happy to help. As mentioned above, * * we also offer alternative license to integrate Nmap into proprietary * * applications and appliances. These contracts have been sold to dozens * * of software vendors, and generally include a perpetual license as well * * as providing for priority support and updates as well as helping to * * fund the continued development of Nmap technology. Please email * * sales@insecure.com for further information. * * * * As a special exception to the GPL terms, Insecure.Com LLC grants * * permission to link the code of this program with any version of the * * OpenSSL library which is distributed under a license identical to that * * listed in the included Copying.OpenSSL file, and distribute linked * * combinations including the two. You must obey the GNU GPL in all * * respects for all of the code used other than OpenSSL. If you modify * * this file, you may extend this exception to your version of the file, * * but you are not obligated to do so. * * * * If you received these files with a written license agreement or * * contract stating terms other than the terms above, then that * * alternative license agreement takes precedence over these comments. * * * * Source is provided to this software because we believe users have a * * right to know exactly what a program is going to do before they run it. * * This also allows you to audit the software for security holes (none * * have been found so far). * * * * Source code also allows you to port Nmap to new platforms, fix bugs, * * and add new features. You are highly encouraged to send your changes * * to fyodor@insecure.org for possible incorporation into the main * * distribution. By sending these changes to Fyodor or one the * * Insecure.Org development mailing lists, it is assumed that you are * * offering Fyodor and Insecure.Com LLC the unlimited, non-exclusive right * * to reuse, modify, and relicense the code. Nmap will always be * * available Open Source, but this is important because the inability to * * relicense code has caused devastating problems for other Free Software * * projects (such as KDE and NASM). We also occasionally relicense the * * code to third parties as discussed above. If you wish to specify * * special license conditions of your contributions, just say so when you * * send them. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details at * * http://www.gnu.org/copyleft/gpl.html , or in the COPYING file included * * with Nmap. * * * ***************************************************************************//* $Id: service_scan.cc 6633 2007-12-22 06:32:03Z fyodor $ */#include "service_scan.h"#include "timing.h"#include "NmapOps.h"#include "nsock.h"#include "Target.h"#include "utils.h"#include "nmap_tty.h"#if HAVE_OPENSSL#include <openssl/ssl.h>#endif#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#include <algorithm>#include <list>/* Workaround for lack of namespace std on HP-UX 11.00 */namespace std {};using namespace std;// Because this file uses assert()s for some security checking, we can't// have anyone turning off debugging.#undef NDEBUGextern NmapOps o;// Details on a particular service (open port) we are trying to matchclass ServiceNFO {public: ServiceNFO(AllProbes *AP); ~ServiceNFO(); // If a service response to a given probeName, this function adds // the response 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(); void addToServiceFingerprint(const char *probeName, const u8 *resp, int resplen); // Get the service fingerprint. It is NULL if there is none, such // as if there was a match before any other probes were finished (or // if no probes gave back data). Note that this is plain // NUL-terminated ASCII data, although the length is optionally // available anyway. This function terminates the service fingerprint // with a semi-colon const char *getServiceFingerprint(int *flen); // Note that the next 2 members are for convenience and are not destroyed w/the ServiceNFO Target *target; // the port belongs to this target host Port *port; // The Port that this service represents (this copy is taken from inside Target) // if a match is found, it is placed here. Otherwise NULL const char *probe_matched; // If a match is found, any product/version/info/hostname/ostype/devicetype // is placed in these 6 strings. Otherwise the string will be 0 length. char product_matched[80]; char version_matched[80]; char extrainfo_matched[128]; char hostname_matched[128]; char ostype_matched[64]; char devicetype_matched[64]; enum service_tunnel_type tunnel; /* SERVICE_TUNNEL_NONE, SERVICE_TUNNEL_SSL */ // This stores our SSL session id, which will help speed up subsequent // SSL connections. It's overwritten each time. void* is used so we don't // need to #ifdef HAVE_OPENSSL all over. We'll cast later as needed. void *ssl_session; // if a match was found (see above), this tells whether it was a "soft" // or hard match. It is always false if no match has been found. bool softMatchFound; // most recent probe executed (or in progress). If there has been a match // (probe_matched != NULL), this will be the corresponding ServiceProbe. ServiceProbe *currentProbe(); // computes the next probe to test, and ALSO CHANGES currentProbe() to // that! If newresp is true, the old response info will be lost and // invalidated. Otherwise it remains as if it had been received by // the current probe (useful after a NULL probe). ServiceProbe *nextProbe(bool newresp); // Resets the probes back to the first one. One case where this is useful is // when SSL is detected -- we redo all probes through SSL. If freeFP, any // service fingerprint is freed too. void resetProbes(bool freefp); // Number of milliseconds left to complete the present probe, or 0 if // the probe is already expired. Timeval can omitted, it is just there // as an optimization in case you have it handy. int currentprobe_timemsleft(const struct timeval *now = NULL); enum serviceprobestate probe_state; // defined in portlist.h nsock_iod niod; // The IO Descriptor being used in this probe (or NULL) u16 portno; // in host byte order u8 proto; // IPPROTO_TCP or IPPROTO_UDP // The time that the current probe was executed (meaning TCP connection // made or first UDP packet sent struct timeval currentprobe_exec_time; // Append newly-received data to the current response string (if any) void appendtocurrentproberesponse(const u8 *respstr, int respstrlen); // Get the full current response string. Note that this pointer is // INVALIDATED if you call appendtocurrentproberesponse() or nextProbe() u8 *getcurrentproberesponse(int *respstrlen); AllProbes *AP; private: // 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 addServiceChar(char c, int wrapat); // Like addServiceChar, but for a whole zero-terminated string void addServiceString(char *s, int wrapat); vector<ServiceProbe *>::iterator current_probe; u8 *currentresp; int currentresplen; char *servicefp; int servicefplen; int servicefpalloc;};// This holds the service information for a group of Targets being service scanned.class ServiceGroup {public: ServiceGroup(vector<Target *> &Targets, AllProbes *AP); ~ServiceGroup(); list<ServiceNFO *> services_finished; // Services finished (discovered or not) list<ServiceNFO *> services_in_progress; // Services currently being probed list<ServiceNFO *> services_remaining; // Probes not started yet unsigned int ideal_parallelism; // Max (and desired) number of probes out at once. ScanProgressMeter *SPM; int num_hosts_timedout; // # of hosts timed out during (or before) scan};#define SUBSTARGS_MAX_ARGS 5#define SUBSTARGS_STRLEN 128#define SUBSTARGS_ARGTYPE_NONE 0#define SUBSTARGS_ARGTYPE_STRING 1#define SUBSTARGS_ARGTYPE_INT 2struct substargs { int num_args; // Total number of arguments found char str_args[SUBSTARGS_MAX_ARGS][SUBSTARGS_STRLEN]; // This is the length of each string arg, since they can contain zeros. // The str_args[] are zero-terminated for convenience in the cases where // you know they won't contain zero. int str_args_len[SUBSTARGS_MAX_ARGS]; int int_args[SUBSTARGS_MAX_ARGS]; // The type of each argument -- see #define's above. int arg_types[SUBSTARGS_MAX_ARGS];};/******************** PROTOTYPES *******************/static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata);static void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *mydata);static void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *mydata);static void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, ServiceGroup *SG, ServiceNFO *svc, nsock_iod nsi);ServiceProbeMatch::ServiceProbeMatch() { deflineno = -1; servicename = NULL; matchstr = NULL; product_template = version_template = info_template = NULL; hostname_template = ostype_template = devicetype_template = NULL; regex_compiled = NULL; regex_extra = NULL; isInitialized = false; matchops_ignorecase = false; matchops_dotall = false; isSoft = false;}ServiceProbeMatch::~ServiceProbeMatch() { if (!isInitialized) return; if (servicename) free(servicename); if (matchstr) free(matchstr); if (product_template) free(product_template); if (version_template) free(version_template); if (info_template) free(info_template); if (hostname_template) free(hostname_template); if (ostype_template) free(ostype_template); if (devicetype_template) free(devicetype_template); matchstrlen = 0; if (regex_compiled) pcre_free(regex_compiled); if (regex_extra) pcre_free(regex_extra); isInitialized = false; matchops_anchor = -1;}// match text from the nmap-service-probes file. This must be called// before you try and do anything with this match. This function// should be passed the whole line starting with "match" or// "softmatch" in nmap-service-probes. The line number that the text// is provided so that it can be reported in error messages. This// function will abort the program if there is a syntax problem.void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) { const char *p; char *tmptemplate; char delimchar, modechar; int pcre_compile_ops = 0; const char *pcre_errptr = NULL; int pcre_erroffset = 0; unsigned int tmpbuflen = 0; char **curr_tmp = NULL; if (isInitialized) fatal("Sorry ... %s does not yet support reinitializion", __func__); if (!matchtext || !*matchtext) fatal("%s: no matchtext passed in (line %d of nmap-service-probes)", __func__, lineno); isInitialized = true; deflineno = lineno; while(isspace(*matchtext)) matchtext++; // first we find whether this is a "soft" or normal match if (strncmp(matchtext, "softmatch ", 10) == 0) { isSoft = true; matchtext += 10; } else if (strncmp(matchtext, "match ", 6) == 0) { isSoft = false; matchtext += 6; } else fatal("%s: parse error on line %d of nmap-service-probes - must begin with \"match\" or \"softmatch\"", __func__, lineno); // next comes the service name p = strchr(matchtext, ' '); if (!p) fatal("%s: parse error on line %d of nmap-service-probes: could not find service name", __func__, lineno); servicename = (char *) safe_malloc(p - matchtext + 1); memcpy(servicename, matchtext, p - matchtext); servicename[p - matchtext] = '\0'; // The next part is a perl style regular expression specifier, like: // m/^220 .*smtp/i Where 'm' means a normal regular expressions is // used, the char after m can be anything (within reason, slash in // this case) and tells us what delieates the end of the regex. // After the delineating character are any single-character // options. ('i' means "case insensitive", 's' means that . matches // newlines (both are just as in perl) matchtext = p; while(isspace(*matchtext)) matchtext++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -