mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 13:11:28 +00:00
Short-circuit os fingerprint matching if accuracy cannot be achieved
This commit is contained in:
21
osscan.cc
21
osscan.cc
@@ -339,10 +339,13 @@ static int AVal_match(const FingerTest &reference, const FingerTest &fprint, con
|
|||||||
accuracy (between 0 and 1) is returned). If MatchPoints is not NULL, it is
|
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. */
|
a special "fingerprints" which tells how many points each test is worth. */
|
||||||
double compare_fingerprints(const FingerPrint *referenceFP, const FingerPrint *observedFP,
|
double compare_fingerprints(const FingerPrint *referenceFP, const FingerPrint *observedFP,
|
||||||
const FingerPrintDef *MatchPoints, int verbose) {
|
const FingerPrintDef *MatchPoints, int verbose,
|
||||||
|
double threshold) {
|
||||||
unsigned long num_subtests = 0, num_subtests_succeeded = 0;
|
unsigned long num_subtests = 0, num_subtests_succeeded = 0;
|
||||||
assert(referenceFP);
|
assert(referenceFP);
|
||||||
assert(observedFP);
|
assert(observedFP);
|
||||||
|
// If we fall this far behind, we can't catch up
|
||||||
|
unsigned long max_mismatch = (1.0 - threshold) * referenceFP->match.numprints;
|
||||||
|
|
||||||
for (int i = 0; i < NUM_FPTESTS; i++) {
|
for (int i = 0; i < NUM_FPTESTS; i++) {
|
||||||
const FingerTest ¤t_ref = referenceFP->tests[i];
|
const FingerTest ¤t_ref = referenceFP->tests[i];
|
||||||
@@ -355,6 +358,9 @@ double compare_fingerprints(const FingerPrint *referenceFP, const FingerPrint *o
|
|||||||
&new_subtests, &new_subtests_succeeded, 0, verbose);
|
&new_subtests, &new_subtests_succeeded, 0, verbose);
|
||||||
num_subtests += new_subtests;
|
num_subtests += new_subtests;
|
||||||
num_subtests_succeeded += new_subtests_succeeded;
|
num_subtests_succeeded += new_subtests_succeeded;
|
||||||
|
if (num_subtests - num_subtests_succeeded > max_mismatch) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(num_subtests_succeeded <= num_subtests);
|
assert(num_subtests_succeeded <= num_subtests);
|
||||||
@@ -394,7 +400,7 @@ void match_fingerprint(const FingerPrint *FP, FingerPrintResultsIPv4 *FPR,
|
|||||||
for (current_os = DB->prints.begin(); current_os != DB->prints.end(); current_os++) {
|
for (current_os = DB->prints.begin(); current_os != DB->prints.end(); current_os++) {
|
||||||
skipfp = 0;
|
skipfp = 0;
|
||||||
|
|
||||||
acc = compare_fingerprints(*current_os, &FP_copy, DB->MatchPoints, 0);
|
acc = compare_fingerprints(*current_os, &FP_copy, DB->MatchPoints, 0, FPR_entrance_requirement);
|
||||||
|
|
||||||
if (acc >= FPR_entrance_requirement || acc == 1.0) {
|
if (acc >= FPR_entrance_requirement || acc == 1.0) {
|
||||||
|
|
||||||
@@ -460,6 +466,7 @@ void match_fingerprint(const FingerPrint *FP, FingerPrintResultsIPv4 *FPR,
|
|||||||
/* Calculate the new min req. */
|
/* Calculate the new min req. */
|
||||||
if (FPR->num_matches == max_prints) {
|
if (FPR->num_matches == max_prints) {
|
||||||
FPR_entrance_requirement = FPR->accuracy[max_prints - 1] + 0.00001;
|
FPR_entrance_requirement = FPR->accuracy[max_prints - 1] + 0.00001;
|
||||||
|
FPR_entrance_requirement = MIN(FPR_entrance_requirement, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,6 +650,15 @@ const char *FingerTest::getAVal(const char *attr) {
|
|||||||
return results->at(idx);
|
return results->at(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FingerTest::getMaxPoints() const {
|
||||||
|
int points = 0;
|
||||||
|
for (size_t i = 0; i < def->numAttrs; i++) {
|
||||||
|
if ((*results)[i] != NULL)
|
||||||
|
points += def->Attrs[i].points;
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is a less-than relation predicate that establishes the preferred order
|
/* 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
|
of tests when they are displayed. Returns true if and only if the test a
|
||||||
should come before the test b. */
|
should come before the test b. */
|
||||||
@@ -1043,6 +1059,7 @@ fparse:
|
|||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
current->setTest(test);
|
current->setTest(test);
|
||||||
|
current->match.numprints += test.getMaxPoints();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
osscan.h
9
osscan.h
@@ -175,14 +175,12 @@ struct FingerMatch {
|
|||||||
int line; /* For reference prints, the line # in nmap-os-db */
|
int line; /* For reference prints, the line # in nmap-os-db */
|
||||||
/* For IPv6 matches, the number of fingerprints that contributed to this
|
/* For IPv6 matches, the number of fingerprints that contributed to this
|
||||||
* classification group */
|
* classification group */
|
||||||
|
/* For IPv4 fingerprints, the number of points possible */
|
||||||
unsigned short numprints;
|
unsigned short numprints;
|
||||||
const char *OS_name;
|
const char *OS_name;
|
||||||
std::vector<OS_Classification> OS_class;
|
std::vector<OS_Classification> OS_class;
|
||||||
|
|
||||||
FingerMatch() {
|
FingerMatch() : line(-1), numprints(0), OS_name(NULL) {}
|
||||||
line = -1;
|
|
||||||
OS_name = NULL;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FingerPrintDB;
|
struct FingerPrintDB;
|
||||||
@@ -210,6 +208,7 @@ struct FingerTest {
|
|||||||
const char *getAVal(const char *attr);
|
const char *getAVal(const char *attr);
|
||||||
const char *getAValName(u8 index) const;
|
const char *getAValName(u8 index) const;
|
||||||
const char *getTestName() const { return def->name.str; }
|
const char *getTestName() const { return def->name.str; }
|
||||||
|
int getMaxPoints() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FingerPrint {
|
struct FingerPrint {
|
||||||
@@ -256,7 +255,7 @@ void free_fingerprint_file(FingerPrintDB *DB);
|
|||||||
accuracy (between 0 and 1) is returned). MatchPoints is
|
accuracy (between 0 and 1) is returned). MatchPoints is
|
||||||
a special "fingerprints" which tells how many points each test is worth. */
|
a special "fingerprints" which tells how many points each test is worth. */
|
||||||
double compare_fingerprints(const FingerPrint *referenceFP, const FingerPrint *observedFP,
|
double compare_fingerprints(const FingerPrint *referenceFP, const FingerPrint *observedFP,
|
||||||
const FingerPrintDef *MatchPoints, int verbose);
|
const FingerPrintDef *MatchPoints, int verbose, double threshold);
|
||||||
|
|
||||||
/* Takes a fingerprint and looks for matches inside the passed in
|
/* Takes a fingerprint and looks for matches inside the passed in
|
||||||
reference fingerprint DB. The results are stored in in FPR (which
|
reference fingerprint DB. The results are stored in in FPR (which
|
||||||
|
|||||||
Reference in New Issue
Block a user