📄 osscan.cc
字号:
if (!FP) FP = FPtests[i]; if (last > -1) { FPtests[last]->next = FPtests[i]; } last = i; } if (last) FPtests[last]->next = NULL; osscan_timedout: if (target->timedOut(NULL)) FP = NULL; if (rawsd >= 0) close(rawsd); /* No need to close ethptr->ethsd due to caching */ pcap_close(pd); return FP;}// Prints a note if observedFP has a classification and it is not in referenceFP// Returns 0 if they match, nonzero otherwisestatic int compareclassifications(FingerPrint *referenceFP, FingerPrint *observedFP, bool verbose) { int refclassno; struct OS_Classification *obclass, *refclass; if (observedFP->num_OS_Classifications > 0) { obclass = &(observedFP->OS_class[0]); for(refclassno = 0; refclassno < referenceFP->num_OS_Classifications; refclassno++) { refclass = &(referenceFP->OS_class[refclassno]); if (strcmp(obclass->OS_Vendor, refclass->OS_Vendor) == 0 && strcmp(obclass->OS_Family, refclass->OS_Family) == 0 && strcmp(obclass->Device_Type, refclass->Device_Type) == 0 && (obclass->OS_Generation == refclass->OS_Generation || (obclass->OS_Generation != NULL && refclass->OS_Generation != NULL && strcmp(obclass->OS_Generation, refclass->OS_Generation) == 0))) { // A match! lets get out of here return 0; } } } else { if (verbose) printf("Observed fingerprint lacks a classification\n"); return 1; } if (verbose) printf("[WARN] Classification of observed fingerprint does not appear in reference fingerprint.\n"); return 1;}static struct AVal *getattrbyname(struct AVal *AV, const char *name) { if (!AV) return NULL; do { if (!strcmp(AV->attribute, name)) return AV; AV = AV->next; } while(AV); return NULL;}static struct AVal *gettestbyname(FingerPrint *FP, const char *name) { if (!FP) return NULL; do { if (!strcmp(FP->name, name)) return FP->results; FP = FP->next; } while(FP); return NULL;}/* Returns true if perfect match -- if num_subtests & num_subtests_succeeded are non_null it ADDS THE NEW VALUES to what is already there. So initialize them to zero first if you only want to see the results from this match. if shortcircuit is zero, it does all the tests, otherwise it returns when the first one fails. If you want details of the match process printed, pass n onzero for 'verbose'. If points is non-null, it is examined to find the number of points for each test in the fprint AVal and use that the increment num_subtests and num_subtests_succeeded appropriately. If it is NULL, each test is worth 1 point. In that case, you may also pass in the group name (SEQ, T1, etc) to have that extra info printed. If you pass 0 for verbose, you might as well pass NULL for testGroupName as it won't be used. */static int AVal_match(struct AVal *reference, struct AVal *fprint, struct AVal *points, unsigned long *num_subtests, unsigned long *num_subtests_succeeded, int shortcut, int verbose, const char *testGroupName) { struct AVal *current_ref; struct AVal *current_fp; struct AVal *current_points; unsigned int number, number1; unsigned int val; char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */ char valcpy[512]; char *endptr; int andexp, orexp, expchar, numtrue; int testfailed; int subtests = 0, subtests_succeeded=0; int pointsThisTest = 1; for(current_ref = reference; current_ref; current_ref = current_ref->next) { current_fp = getattrbyname(fprint, current_ref->attribute); if (!current_fp) continue; /* OK, we compare an attribute value in current_fp->value to a potentially large expression in current_ref->value. The syntax uses < (less than), > (greather than), + (non-zero), | (or), - (range), and & (and). No parenthesis are allowed */ numtrue = andexp = orexp = 0; testfailed = 0; Strncpy(valcpy, current_ref->value, sizeof(valcpy)); p = valcpy; if (strchr(current_ref->value, '|')) { orexp = 1; expchar = '|'; } else { andexp = 1; expchar = '&'; } do { q = strchr(p, expchar); if (q) *q = '\0'; if (strcmp(p, "+") == 0) { if (!*current_fp->value) { if (andexp) { testfailed=1; break; } } else { val = strtol(current_fp->value, &endptr, 16); if (val == 0 || *endptr) { if (andexp) { testfailed=1; break; } } else { numtrue++; if (orexp) break; } } } else if (*p == '<' && isxdigit((int) p[1])) { if (!*current_fp->value) { if (andexp) { testfailed=1; break; } } number = strtol(p + 1, &endptr, 16); val = strtol(current_fp->value, &endptr, 16); if (val >= number || *endptr) { if (andexp) { testfailed=1; break; } } else { numtrue++; if (orexp) break; } } else if (*p == '>' && isxdigit((int) p[1])) { if (!*current_fp->value) { if (andexp) { testfailed=1; break; } } number = strtol(p + 1, &endptr, 16); val = strtol(current_fp->value, &endptr, 16); if (val <= number || *endptr) { if (andexp) { testfailed=1; break; } } else { numtrue++; if (orexp) break; } } else if (((q1 = strchr(p, '-')) != NULL) && isxdigit((int) p[0]) && isxdigit((int) q1[1])) { if (!*current_fp->value) { if (andexp) { testfailed=1; break; } } *q1 = '\0'; number = strtol(p, NULL, 16); number1 = strtol(q1 + 1, NULL, 16); if(number1 < number && o.debugging) { error("Range error in reference aval: %s=%s\n", current_ref->attribute, current_ref->value); } val = strtol(current_fp->value, &endptr, 16); if (val < number || val > number1 || *endptr) { if (andexp) { testfailed=1; break; } } else { numtrue++; if (orexp) break; } } else { if (strcmp(p, current_fp->value)) { if (andexp) { testfailed=1; break; } } else { numtrue++; if (orexp) break; } } if (q) p = q + 1; } while(q); if (numtrue == 0) testfailed=1; if (points) { current_points = getattrbyname(points, current_ref->attribute); if (!current_points) fatal("%s: Failed to find point amount for test %s.%s", __FUNCTION__, testGroupName? testGroupName : "", current_ref->attribute); pointsThisTest = strtol(current_points->value, &endptr, 10); if (pointsThisTest < 1) fatal("%s: Got bogus point amount (%s) for test %s.%s", __FUNCTION__, current_points->value, testGroupName? testGroupName : "", current_ref->attribute); } subtests += pointsThisTest; if (testfailed) { if (shortcut) { if (num_subtests) *num_subtests += subtests; return 0; } if (verbose) printf("%s.%s: \"%s\" NOMATCH \"%s\" (%d %s)\n", testGroupName, current_ref->attribute, current_fp->value, current_ref->value, pointsThisTest, (pointsThisTest == 1)? "point" : "points"); } else subtests_succeeded += pointsThisTest; /* Whew, we made it past one Attribute alive , on to the next! */ } if (num_subtests) *num_subtests += subtests; if (num_subtests_succeeded) *num_subtests_succeeded += subtests_succeeded; return (subtests == subtests_succeeded)? 1 : 0;}/* Compares 2 fingerprints -- a referenceFP (can have expression attributes) with an observed fingerprint (no expressions). If verbose is nonzero, differences will be printed. The comparison accuracy (between 0 and 1) is returned). If MatchPoints is not NULL, it is a special "fingerprints" which tells how many points each test is worth. */double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP, FingerPrint *MatchPoints, int verbose) { FingerPrint *currentReferenceTest; struct AVal *currentObservedTest; struct AVal *currentTestMatchPoints; unsigned long num_subtests = 0, num_subtests_succeeded = 0; unsigned long new_subtests, new_subtests_succeeded; assert(referenceFP); assert(observedFP); if (verbose) compareclassifications(referenceFP, observedFP, true); for(currentReferenceTest = referenceFP; currentReferenceTest; currentReferenceTest = currentReferenceTest->next) { currentObservedTest = gettestbyname(observedFP, currentReferenceTest->name); if (currentObservedTest) { new_subtests = new_subtests_succeeded = 0; if (MatchPoints) { currentTestMatchPoints = gettestbyname(MatchPoints, currentReferenceTest->name); if (!currentTestMatchPoints) fatal("%s: Failed to locate test %s in MatchPoints directive of fingerprint file", __FUNCTION__, currentReferenceTest->name); } else currentTestMatchPoints = NULL; AVal_match(currentReferenceTest->results, currentObservedTest, currentTestMatchPoints, &new_subtests, &new_subtests_succeeded, 0, verbose, currentReferenceTest->name); num_subtests += new_subtests; num_subtests_succeeded += new_subtests_succeeded; } } assert(num_subtests_succeeded <= num_subtests); return (num_subtests)? (num_subtests_succeeded / (double) num_subtests) : 0; }/* Takes a fingerprint and looks for matches inside the passed in reference fingerprint DB. The results are stored in in FPR (which must point to an instantiated FingerPrintResults class) -- results will be reverse-sorted by accuracy. No results below accuracy_threshhold will be included. The max matches returned is the maximum that fits in a FingerPrintResults class. */void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, FingerPrintDB *DB, double accuracy_threshold) { int i; double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be at least this big to be added to the list */ FingerPrint **reference_FPs = DB->prints; FingerPrint *current_os; double acc; int state; int skipfp; int max_prints = sizeof(FPR->prints) / sizeof(FingerPrint *); int idx; double tmp_acc=0.0, tmp_acc2; /* These are temp buffers for list swaps */ FingerPrint *tmp_FP=NULL, *tmp_FP2; assert(FP); assert(FPR); assert(accuracy_threshold >= 0 && accuracy_threshold <= 1); FPR->overall_results = OSSCAN_SUCCESS; for(i = 0; reference_FPs[i]; i++) { current_os = reference_FPs[i]; skipfp = 0; acc = compare_fingerprints(current_os, FP, DB->MatchPoints, 0); /* error("Comp to %s: %li/%li=%f", o.reference_FPs1[i]->OS_name, num_subtests_succeeded, num_subtests, acc); */ if (acc >= FPR_entrance_requirement || acc == 1.0) { state = 0; for(idx=0; idx < FPR->num_matches; idx++) { if (strcmp(FPR->prints[idx]->OS_name, current_os->OS_name) == 0) { if (FPR->accuracy[idx] >= acc) { skipfp = 1; /* Skip it -- a higher version is already in list */ } else { /* We must shift the list left to delete this sucker */ memmove(FPR->prints + idx, FPR->prints + idx + 1, (FPR->num_matches - 1 - idx) * sizeof(FingerPrint *)); memmove(FPR->accuracy + idx, FPR->accuracy + idx + 1, (FPR->num_matches - 1 - idx) * sizeof(double)); FPR->num_matches--; FPR->accuracy[FPR->num_matches] = 0; } break; /* There can only be 1 in the list with same name */ } } if (!skipfp) { /* 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;}int os_scan(Target *target) {FingerPrintResults FP_matches[3];struct seq_info si[3];int itry;int i;struct timeval now;double bestacc;int bestaccidx; int starttimems = 0; if (target->timedOut(NULL)) return 1; o.current_scantype = OS_SCAN;#ifdef WIN32 if (target->ifType() == devt_loopback) { log_write(LOG_STDOUT, "Skipping OS Scan against %s because it doesn't work against your own machine (localhost)\n", target->NameIP()); return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -