📄 osscan.cc
字号:
/* First we check whether we have overflowed with perfect matches */ if (acc == 1) { /* error("DEBUG: Perfect match #%d/%d", FPR->num_perfect_matches + 1, max_prints); */ if (FPR->num_perfect_matches == max_prints) { FPR->overall_results = OSSCAN_TOOMANYMATCHES; return; } FPR->num_perfect_matches++; } /* Now we add the sucker to the list */ state = 0; /* Have not yet done the insertion */ for(idx=-1; idx < max_prints -1; idx++) { if (state == 1) { /* Push tmp_acc and tmp_FP onto the next idx */ tmp_acc2 = FPR->accuracy[idx+1]; tmp_FP2 = FPR->prints[idx+1]; FPR->accuracy[idx+1] = tmp_acc; FPR->prints[idx+1] = tmp_FP; tmp_acc = tmp_acc2; tmp_FP = tmp_FP2; } else if (FPR->accuracy[idx + 1] < acc) { /* OK, I insert the sucker into the next slot ... */ tmp_acc = FPR->accuracy[idx+1]; tmp_FP = FPR->prints[idx+1]; FPR->prints[idx+1] = current_os; FPR->accuracy[idx+1] = acc; state = 1; } } if (state != 1) { fatal("Bogus list insertion state (%d) -- num_matches = %d num_perfect_matches=%d entrance_requirement=%f", state, FPR->num_matches, FPR->num_perfect_matches, FPR_entrance_requirement); } FPR->num_matches++; /* If we are over max_prints, one was shoved off list */ if (FPR->num_matches > max_prints) FPR->num_matches = max_prints; /* Calculate the new min req. */ if (FPR->num_matches == max_prints) { FPR_entrance_requirement = FPR->accuracy[max_prints - 1] + 0.00001; } } } } if (FPR->num_matches == 0 && FPR->overall_results == OSSCAN_SUCCESS) FPR->overall_results = OSSCAN_NOMATCHES; return;}void freeFingerPrint(FingerPrint *FP) {FingerPrint *currentFP;FingerPrint *nextFP;if (!FP) return; for(currentFP = FP; currentFP; currentFP = nextFP) { nextFP = currentFP->next; if (currentFP->results) free(currentFP->results); free(currentFP); }return;}/* Writes an informational "Test" result suitable for including at the top of a fingerprint. Gives info which might be useful when the FPrint is submitted (eg Nmap version, etc). Result is written (up to ostrlen) to the ostr var passed in */static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP, const struct in_addr * const addr, int distance, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort) { struct tm *ltime; time_t timep; char dsbuf[8], otbuf[8], ctbuf[8], cubuf[8]; char macbuf[16]; timep = time(NULL); ltime = localtime(&timep); otbuf[0] = '\0'; if(openTcpPort != -1) Snprintf(otbuf, sizeof(otbuf), "%d", openTcpPort); ctbuf[0] = '\0'; if(closedTcpPort != -1) Snprintf(ctbuf, sizeof(ctbuf), "%d", closedTcpPort); cubuf[0] = '\0'; if(closedUdpPort != -1) Snprintf(cubuf, sizeof(cubuf), "%d", closedUdpPort); dsbuf[0] = '\0'; if(distance != -1) { Snprintf(dsbuf, sizeof(dsbuf), "%%DS=%d", distance); } macbuf[0] = '\0'; if (mac) Snprintf(macbuf, sizeof(macbuf), "%%M=%02X%02X%02X", mac[0], mac[1], mac[2]); Snprintf(ostr, ostrlen, "SCAN(V=%s%%D=%d/%d%%OT=%s%%CT=%s%%CU=%s%%PV=%c%s%%G=%c%s%%TM=%X%%P=%s)", NMAP_VERSION, ltime->tm_mon + 1, ltime->tm_mday, otbuf, ctbuf, cubuf, isipprivate(addr)?'Y':'N', dsbuf, isGoodFP?'Y':'N', macbuf, (int) timep, NMAP_PLATFORM);}/* Puts a textual representation of the chain of AVals beginning with AV in s. No more than n bytes will be written. Unless n is 0, the string is always null-terminated. Returns the number of bytes written, excluding the terminator. */static int AVal2str(const struct AVal *AV, char *s, size_t n) { char *p; char *end; size_t len; if (AV == NULL) { if (n > 0) *s = '\0'; return 0; } p = s; end = s + n - 1; for ( ; AV != NULL; AV = AV->next) { if (p >= end) break; /* Put a separator in front of every attribute-value pair but the first. */ if (p != s) *p++ = '%'; len = MIN((ptrdiff_t) strlen(AV->attribute), end - p); memcpy(p, AV->attribute, len); p += len; if (p >= end) break; *p++ = '='; len = MIN((ptrdiff_t) strlen(AV->value), end - p); memcpy(p, AV->value, len); p += len; } *p = '\0'; return p - s;}static struct AVal *str2AVal(char *str) { int i = 1; int count = 1; char *q = str, *p=str; struct AVal *AVs; if (!*str) return NULL; /* count the AVals */ while((q = strchr(q, '%'))) { count++; q++; } AVs = (struct AVal *) safe_zalloc(count * sizeof(struct AVal)); for(i=0; i < count; i++) { q = strchr(p, '='); if (!q) { fatal("Parse error with AVal string (%s) in nmap-os-db file", str); } *q = '\0'; AVs[i].attribute = strdup(p); p = q+1; if (i != count - 1) { q = strchr(p, '%'); if (!q) { fatal("Parse error with AVal string (%s) in nmap-os-db file", str); } *q = '\0'; AVs[i].next = &AVs[i+1]; } Strncpy(AVs[i].value, p, sizeof(AVs[i].value)); p = q + 1; } return AVs;}/* Compare two AVal chains literally, without evaluating the value of either one as an expression. This is used by mergeFPs. Unlike with AVal_match, it is always the case that AVal_match_literal(a, b) == AVal_match_literal(b, a). */static bool AVal_match_literal(struct AVal *a, struct AVal *b) { struct AVal *av_a, *av_b; /* Check that b contains all the AVals in a, with the same values. */ for (av_a = a; av_a != NULL; av_a = av_a->next) { av_b = getattrbyname(b, av_a->attribute); if (av_b == NULL || strcmp(av_a->value, av_b->value) != 0) return false; } /* Check that a contains all the AVals in b, with the same values. */ for (av_b = a; av_b != NULL; av_b = av_b->next) { av_a = getattrbyname(a, av_b->attribute); if (av_a == NULL || strcmp(av_a->value, av_b->value) != 0) return false; } return true;}/* This is a less-than relation predicate that establishes the preferred order of tests when they are displayed. Returns true if and only if the test a should come before the test b. */static bool FingerTest_lessthan(const FingerTest* a, const FingerTest* b) { /* This defines the order in which test lines should appear. */ const char *TEST_ORDER[] = { "SEQ", "OPS", "WIN", "ECN", "T1", "T2", "T3", "T4", "T5", "T6", "T7", "U1", "IE" }; unsigned int i; int ia, ib; /* The indices at which the test names were found in the list. -1 means "not found." */ ia = -1; ib = -1; /* Look up the test names in the list. */ for (i = 0; i < sizeof(TEST_ORDER) / sizeof(*TEST_ORDER); i++) { if (ia == -1 && strcmp(a->name, TEST_ORDER[i]) == 0) ia = i; if (ib == -1 && strcmp(b->name, TEST_ORDER[i]) == 0) ib = i; /* Once we've found both tests we can stop searching. */ if (ia != -1 && ib != -1) break; } /* If a test name was not found, it probably indicates an error in another part of the code. */ if (ia == -1) fatal("%s received an unknown test name \"%s\".\n", __func__, a->name); if (ib == -1) fatal("%s received an unknown test name \"%s\".\n", __func__, b->name); return ia < ib;}/* Merges the tests from several fingerprints into a character string representation. Tests that are identical between more than one fingerprint are included only once. If wrapit is true, the string is wrapped for submission. */char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP, const struct in_addr * const addr, int distance, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort, bool wrapit) { static char str[10240]; static char wrapstr[10240]; char *p; int i; char *end = str + sizeof(str) - 1; /* Last byte allowed to write into */ std::list<const FingerTest *> tests; std::list<const FingerTest *>::iterator iter; const FingerTest *ft; if (numFPs <= 0) return "(None)"; else if (numFPs > 32) return "(Too many)"; /* Copy the tests from each fingerprint into a flat list. */ for (i = 0; i < numFPs; i++) { for (ft = FPs[i]; ft != NULL; ft = ft->next) tests.push_back(ft); } /* Put the tests in the proper order and ensure that tests with identical names are contiguous. */ tests.sort(FingerTest_lessthan); /* Delete duplicate tests to ensure that all the tests are unique. One test is a duplicate of the other if it has the same name as the first and the two results lists match. */ for (iter = tests.begin(); iter != tests.end(); iter++) { std::list<const FingerTest *>::iterator tmp_i, next; tmp_i = iter; tmp_i++; while (tmp_i != tests.end() && strcmp((*iter)->name, (*tmp_i)->name) == 0) { next = tmp_i; next++; if (AVal_match_literal((*iter)->results, (*tmp_i)->results)) { /* This is a duplicate test. Remove it. */ tests.erase(tmp_i); } tmp_i = next; } } /* A safety check to make sure that no tests were lost in merging. */ for (i = 0; i < numFPs; i++) { for (ft = FPs[i]; ft != NULL; ft = ft->next) { for (iter = tests.begin(); iter != tests.end(); iter++) { if (strcmp((*iter)->name, ft->name) == 0 && AVal_match_literal((*iter)->results, ft->results)) { break; } } if (iter == tests.end()) { char buf[200]; AVal2str(ft->results, buf, sizeof(buf)); fatal("The test %s(%s) was somehow lost in %s.\n", ft->name, buf, __func__); } } } memset(str, 0, sizeof(str)); p = str; /* Lets start by writing the fake "SCAN" test for submitting fingerprints */ WriteSInfo(p, sizeof(str), isGoodFP, addr, distance, mac, openTcpPort, closedTcpPort, closedUdpPort); p = p + strlen(str); if (!wrapit) *p++ = '\n'; assert(p <= end); /* Append the string representation of each test to the result string. */ for (iter = tests.begin(); iter != tests.end(); iter++) { size_t len; ft = *iter; len = MIN((ptrdiff_t) strlen(ft->name), (end - p)); memcpy(p, ft->name, len); p += len; if (p >= end) break; *p++ = '('; len = AVal2str(ft->results, p, end - p + 1); p += len; if (p >= end) break; *p++ = ')'; if (!wrapit) { if (p >= end) break; *p++ = '\n'; } } /* If we bailed out of the loop early it was because we ran out of space. */ if (iter != tests.end() || p > end) fatal("Merged fingerprint too long in %s.\n", __func__); *p = '\0'; if(!wrapit) {return str; } else { /* Wrap the str. */ int len; char *p1 = wrapstr; end = wrapstr + sizeof(wrapstr) - 1; p = str; while(*p && end-p1 >= 3) { len = 0; strcpy(p1, "OS:"); p1 += 3; len +=3; while(*p && len <= FP_RESULT_WRAP_LINE_LEN && end-p1 > 0) { *p1++=*p++; len++; } if(end-p1<=0) { fatal("Wrapped result too long!\n"); break; } *p1++ = '\n';} *p1 = '\0'; return wrapstr; }}char *fp2ascii(FingerPrint *FP) {static char str[2048];FingerPrint *current;struct AVal *AV;char *p = str;int len;memset(str, 0, sizeof(str));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -