📄 service_scan.cc
字号:
if (*matchtext == 'm') { if (!*(matchtext+1)) fatal("%s: parse error on line %d of nmap-service-probes: matchtext must begin with 'm'", __func__, lineno); matchtype = SERVICEMATCH_REGEX; delimchar = *(++matchtext); ++matchtext; // find the end of the regex p = strchr(matchtext, delimchar); if (!p) fatal("%s: parse error on line %d of nmap-service-probes: could not find end delimiter for regex", __func__, lineno); matchstrlen = p - matchtext; matchstr = (char *) safe_malloc(matchstrlen + 1); memcpy(matchstr, matchtext, matchstrlen); matchstr[matchstrlen] = '\0'; matchtext = p + 1; // skip past the delim // any options? while(*matchtext && !isspace(*matchtext)) { if (*matchtext == 'i') matchops_ignorecase = true; else if (*matchtext == 's') matchops_dotall = true; else fatal("%s: illegal regexp option on line %d of nmap-service-probes", __func__, lineno); matchtext++; } // Next we compile and study the regular expression to match if (matchops_ignorecase) pcre_compile_ops |= PCRE_CASELESS; if (matchops_dotall) pcre_compile_ops |= PCRE_DOTALL; regex_compiled = pcre_compile(matchstr, pcre_compile_ops, &pcre_errptr, &pcre_erroffset, NULL); if (regex_compiled == NULL) fatal("%s: illegal regexp on line %d of nmap-service-probes (at regexp offset %d): %s\n", __func__, lineno, pcre_erroffset, pcre_errptr); // Now study the regexp for greater efficiency regex_extra = pcre_study(regex_compiled, 0, &pcre_errptr); if (pcre_errptr != NULL) fatal("%s: failed to pcre_study regexp on line %d of nmap-service-probes: %s\n", __func__, lineno, pcre_errptr); } else { /* Invalid matchtext */ fatal("%s: parse error on line %d of nmap-service-probes: match string must begin with 'm'", __func__, lineno); } /* OK! Now we look for any templates of the form ?/.../ * where ? is either p, v, i, h, o, or d. / is any * delimiter character and ... is a template */ while(1) { while(isspace(*matchtext)) matchtext++; if (*matchtext == '\0' || *matchtext == '\r' || *matchtext == '\n') break; modechar = *(matchtext++); if (*matchtext == 0 || *matchtext == '\r' || *matchtext == '\n') fatal("%s: parse error on line %d of nmap-service-probes", __func__, lineno); delimchar = *(matchtext++); p = strchr(matchtext, delimchar); if (!p) fatal("%s: parse error on line %d of nmap-service-probes", __func__, lineno); tmptemplate = NULL; tmpbuflen = p - matchtext; if (tmpbuflen > 0) { tmptemplate = (char *) safe_malloc(tmpbuflen + 1); memcpy(tmptemplate, matchtext, tmpbuflen); tmptemplate[tmpbuflen] = '\0'; } switch(modechar){ case 'p': curr_tmp = &product_template; break; case 'v': curr_tmp = &version_template; break; case 'i': curr_tmp = &info_template; break; case 'h': curr_tmp = &hostname_template; break; case 'o': curr_tmp = &ostype_template; break; case 'd': curr_tmp = &devicetype_template; break; default: fatal("%s: Unknown template specifier '%c' on line %d of nmap-service-probes", __func__, modechar, lineno); } if(*curr_tmp){ if(o.debugging) error("WARNING: Template \"%c/%s/\" replaced with \"%c/%s/\" on line %d of nmap-service-probes", modechar, *curr_tmp, modechar, tmptemplate, lineno); free(*curr_tmp); } *curr_tmp = tmptemplate; matchtext = p + 1; } isInitialized = 1;} // If the buf (of length buflen) match the regex in this // ServiceProbeMatch, 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 sructure 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.const struct MatchDetails *ServiceProbeMatch::testMatch(const u8 *buf, int buflen) { int rc; int i; static char product[80]; static char version[80]; static char info[128]; static char hostname[80]; static char ostype[32]; static char devicetype[32]; char *bufc = (char *) buf; int ovector[150]; // allows 50 substring matches (including the overall match) assert(isInitialized); assert (matchtype == SERVICEMATCH_REGEX); // Clear out the output struct memset(&MD_return, 0, sizeof(MD_return)); MD_return.isSoft = isSoft; rc = pcre_exec(regex_compiled, regex_extra, bufc, buflen, 0, 0, ovector, sizeof(ovector) / sizeof(*ovector)); if (rc < 0) {#ifdef PCRE_ERROR_MATCHLIMIT // earlier PCRE versions lack this if (rc == PCRE_ERROR_MATCHLIMIT) { if (o.debugging || o.verbose > 1) error("Warning: Hit PCRE_ERROR_MATCHLIMIT when probing for service %s with the regex '%s'", servicename, matchstr); } else#endif // PCRE_ERROR_MATCHLIMIT if (rc != PCRE_ERROR_NOMATCH) { fatal("Unexpected PCRE error (%d) when probing for service %s with the regex '%s'", rc, servicename, matchstr); } } else { // Yeah! Match apparently succeeded. // Now lets get the version number if available i = getVersionStr(buf, buflen, ovector, rc, product, sizeof(product), version, sizeof(version), info, sizeof(info), hostname, sizeof(hostname), ostype, sizeof(ostype), devicetype, sizeof(devicetype)); if (*product) MD_return.product = product; if (*version) MD_return.version = version; if (*info) MD_return.info = info; if (*hostname) MD_return.hostname = hostname; if (*ostype) MD_return.ostype = ostype; if (*devicetype) MD_return.devicetype = devicetype; MD_return.serviceName = servicename; } return &MD_return;}// This simple function parses arguments out of a string. The string// starts with the first argument. Each argument can be a string or// an integer. Strings must be enclosed in double quotes (""). Most// standard C-style escapes are supported. If this is successful, the// number of args found is returned, args is filled appropriately, and// args_end (if non-null) is set to the character after the closing// ')'. Otherwise we return -1 and the values of args and args_end// are undefined.static int getsubstcommandargs(struct substargs *args, char *args_start, char **args_end) { char *p; unsigned int len; if (!args || !args_start) return -1; memset(args, 0, sizeof(*args)); while(*args_start && *args_start != ')') { // Find the next argument. while(isspace(*args_start)) args_start++; if (*args_start == ')') break; else if (*args_start == '"') { // OK - it is a string // Do we have space for another arg? if (args->num_args == SUBSTARGS_MAX_ARGS) return -1; do { args_start++; if (*args_start == '"' && (*(args_start - 1) != '\\' || *(args_start - 2) == '\\')) break; len = args->str_args_len[args->num_args]; if (len >= SUBSTARGS_STRLEN - 1) return -1; args->str_args[args->num_args][len] = *args_start; args->str_args_len[args->num_args]++; } while(*args_start); len = args->str_args_len[args->num_args]; args->str_args[args->num_args][len] = '\0'; // Now handle escaped characters and such if (!cstring_unescape(args->str_args[args->num_args], &len)) return -1; args->str_args_len[args->num_args] = len; args->arg_types[args->num_args] = SUBSTARGS_ARGTYPE_STRING; args->num_args++; args_start++; args_start = strpbrk(args_start, ",)"); if (!args_start) return -1; if (*args_start == ',') args_start++; } else { // Must be an integer argument args->int_args[args->num_args] = (int) strtol(args_start, &p, 0); if (p <= args_start) return -1; args_start = p; args->arg_types[args->num_args] = SUBSTARGS_ARGTYPE_INT; args->num_args++; args_start = strpbrk(args_start, ",)"); if (!args_start) return -1; if (*args_start == ',') args_start++; } } if (*args_start == ')') args_start++; if (args_end) *args_end = args_start; return args->num_args;}// This function does the actual substitution of a placeholder like $2// or $U(4) into the given buffer. It returns the number of chars// written, or -1 if it fails. tmplvar is a template variable, such// as "$U(2)". We determine the appropriate string representing that,// and place it in newstr (as long as it doesn't exceed newstrlen).// We then set *tmplvarend to the character after the// variable. subject, subjectlen, ovector, and nummatches mean the// same as in dotmplsubst().static int substvar(char *tmplvar, char **tmplvarend, char *newstr, int newstrlen, const u8 *subject, int subjectlen, int *ovector, int nummatches) { char substcommand[16]; char *p = NULL; char *p_end; int len; int subnum = 0; int offstart, offend; int byteswritten = 0; // for return val int rc; int i; struct substargs command_args; // skip the '$' if (*tmplvar != '$') return -1; tmplvar++; if (!isdigit(*tmplvar)) { p = strchr(tmplvar, '('); if (!p) return -1; len = p - tmplvar; if (!len || len >= (int) sizeof(substcommand)) return -1; memcpy(substcommand, tmplvar, len); substcommand[len] = '\0'; tmplvar = p+1; // Now we grab the arguments. rc = getsubstcommandargs(&command_args, tmplvar, &p_end); if (rc <= 0) return -1; tmplvar = p_end; } else { substcommand[0] = '\0'; subnum = *tmplvar - '0'; tmplvar++; } if (tmplvarend) *tmplvarend = tmplvar; if (!*substcommand) { if (subnum > 9 || subnum <= 0) return -1; if (subnum >= nummatches) return -1; offstart = ovector[subnum * 2]; offend = ovector[subnum * 2 + 1]; assert(offstart >= 0 && offstart < subjectlen); assert(offend >= 0 && offend <= subjectlen); len = offend - offstart; // A plain-jane copy if (newstrlen <= len - 1) return -1; memcpy(newstr, subject + offstart, len); byteswritten = len; } else if (strcmp(substcommand, "P") == 0) { if (command_args.arg_types[0] != SUBSTARGS_ARGTYPE_INT) return -1; subnum = command_args.int_args[0]; if (subnum > 9 || subnum <= 0) return -1; if (subnum >= nummatches) return -1; offstart = ovector[subnum * 2]; offend = ovector[subnum * 2 + 1]; assert(offstart >= 0 && offstart < subjectlen); assert(offend >= 0 && offend <= subjectlen); // This filter only includes printable characters. It is particularly // useful for collapsing unicode text that looks like // "W\0O\0R\0K\0G\0R\0O\0U\0P\0" for(i=offstart; i < offend; i++) if (isprint((int) subject[i])) { if (byteswritten >= newstrlen - 1) return -1; newstr[byteswritten++] = subject[i]; } } else if (strcmp(substcommand, "SUBST") == 0) { char *findstr, *replstr; int findstrlen, replstrlen; if (command_args.arg_types[0] != SUBSTARGS_ARGTYPE_INT) return -1; subnum = command_args.int_args[0]; if (subnum > 9 || subnum <= 0) return -1; if (subnum >= nummatches) return -1; offstart = ovector[subnum * 2]; offend = ovector[subnum * 2 + 1]; assert(offstart >= 0 && offstart < subjectlen); assert(offend >= 0 && offend <= subjectlen); if (command_args.arg_types[1] != SUBSTARGS_ARGTYPE_STRING || command_args.arg_types[2] != SUBSTARGS_ARGTYPE_STRING) return -1; findstr = command_args.str_args[1]; findstrlen = command_args.str_args_len[1]; replstr = command_args.str_args[2]; replstrlen = command_args.str_args_len[2]; for(i=offstart; i < offend; ) { if (byteswritten >= newstrlen - 1) return -1; if (offend - i < findstrlen) newstr[byteswritten++] = subject[i++]; // No room for match else if (memcmp(subject + i, findstr, findstrlen) != 0) newstr[byteswritten++] = subject[i++]; // no match else { // The find string was found, copy it to newstring if (newstrlen - 1 - byteswritten < replstrlen) return -1; memcpy(newstr + byteswritten, replstr, replstrlen); byteswritten += replstrlen; i += findstrlen; } } } else return -1; // Unknown command if (byteswritten >= newstrlen) return -1; newstr[byteswritten] = '\0'; return byteswritten;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -