diff --git a/FPEngine.cc b/FPEngine.cc index e50763d..8dc20f3 100644 --- a/FPEngine.cc +++ b/FPEngine.cc @@ -1081,26 +1081,28 @@ static void classify(FingerPrintResultsIPv6 *FPR) { } if (FPR->num_perfect_matches == 0) { FPR->overall_results = OSSCAN_NOMATCHES; - } else if (FPR->num_perfect_matches == 1) { + } else { double novelty; - - novelty = novelty_of(features, labels[0].label); - if (o.debugging > 1) - log_write(LOG_PLAIN, "Novelty of closest match is %.3f.\n", novelty); - - if (novelty < FP_NOVELTY_THRESHOLD) { + int lowest_nov, idx_low_nov; + + lowest_nov = FP_NOVELTY_THRESHOLD; + idx_low_nov = -1; + for (i = 0; i < FPR->num_perfect_matches; i++) { + novelty = novelty_of(features, labels[i].label); + if (o.debugging > 1) + log_write(LOG_PLAIN, "Novelty of possible match is %.3f.\n", novelty); + if (novelty < FP_NOVELTY_THRESHOLD && (novelty < lowest_nov || lowest_nov == -1)) { + lowest_nov = novelty; + idx_low_nov = i; + } + } + if (lowest_nov != -1) { FPR->overall_results = OSSCAN_SUCCESS; + FPR->idx_perf_match_low_nov = idx_low_nov; } else { - if (o.debugging > 0) { - log_write(LOG_PLAIN, "Novelty of closest match is %.3f > %.3f; ignoring.\n", - novelty, FP_NOVELTY_THRESHOLD); - } FPR->overall_results = OSSCAN_NOMATCHES; FPR->num_perfect_matches = 0; } - } else { - FPR->overall_results = OSSCAN_NOMATCHES; - FPR->num_perfect_matches = 0; } delete[] features; diff --git a/FPEngine.h b/FPEngine.h index da9ae3e..6c2f961 100644 --- a/FPEngine.h +++ b/FPEngine.h @@ -155,7 +155,7 @@ class FingerPrintResultsIPv6; /* Even with a successful classification, we may not consider a match good if it is too different from other members of the class. */ -#define FP_NOVELTY_THRESHOLD 15.0 +#define FP_NOVELTY_THRESHOLD 50 const unsigned int OSDETECT_FLOW_LABEL = 0x12345; @@ -456,7 +456,6 @@ class FPHost6 : public FPHost { const FPResponse *getResponse(const char *id); void fill_FPR(FingerPrintResultsIPv6 *FPR); - }; diff --git a/FingerPrintResults.cc b/FingerPrintResults.cc index 0a86a13..34b5314 100644 --- a/FingerPrintResults.cc +++ b/FingerPrintResults.cc @@ -131,6 +131,7 @@ extern NmapOps o; FingerPrintResults::FingerPrintResults() { num_perfect_matches = num_matches = 0; + idx_perf_match_low_nov = 0; overall_results = OSSCAN_NOMATCHES; memset(accuracy, 0, sizeof(accuracy)); isClassified = false; diff --git a/FingerPrintResults.h b/FingerPrintResults.h index 1c7b79d..5a19d46 100644 --- a/FingerPrintResults.h +++ b/FingerPrintResults.h @@ -164,6 +164,7 @@ class FingerPrintResults { highest accuracy matches first */ int num_perfect_matches; /* Number of 1.0 accuracy matches in matches[] */ int num_matches; /* Total number of matches in matches[] */ + int idx_perf_match_low_nov; /* Index of the perfect match with low novelty in matches[] */ int overall_results; /* OSSCAN_TOOMANYMATCHES, OSSCAN_NOMATCHES, OSSCAN_SUCCESS, etc */ diff --git a/output.cc b/output.cc index 3dabb51..af29b6f 100644 --- a/output.cc +++ b/output.cc @@ -1911,16 +1911,20 @@ void printosscanoutput(Target *currenths) { /* Success, not too many perfect matches. */ if (FPR->num_perfect_matches > 0) { /* Some perfect matches. */ - for (i = 0; i < FPR->num_perfect_matches; i++) - write_xml_osmatch(FPR->matches[i], FPR->accuracy[i]); - - log_write(LOG_MACHINE, "\tOS: %s", FPR->matches[0]->OS_name); - for (i = 1; i < FPR->num_perfect_matches; i++) - log_write(LOG_MACHINE, "|%s", FPR->matches[i]->OS_name); - - log_write(LOG_PLAIN, "OS details: %s", FPR->matches[0]->OS_name); - for (i = 1; i < FPR->num_perfect_matches; i++) - log_write(LOG_PLAIN, ", %s", FPR->matches[i]->OS_name); + write_xml_osmatch(FPR->matches[FPR->idx_perf_match_low_nov], FPR->accuracy[FPR->idx_perf_match_low_nov]); + if (o.af() == AF_INET) + for (i = 1; i < FPR->num_perfect_matches; i++) + write_xml_osmatch(FPR->matches[i], FPR->accuracy[i]); + + log_write(LOG_MACHINE, "\tOS: %s", FPR->matches[FPR->idx_perf_match_low_nov]->OS_name); + if (o.af() == AF_INET) + for (i = 1; i < FPR->num_perfect_matches; i++) + log_write(LOG_MACHINE, "|%s", FPR->matches[i]->OS_name); + + log_write(LOG_PLAIN, "OS details: %s", FPR->matches[FPR->idx_perf_match_low_nov]->OS_name); + if (o.af() == AF_INET) + for (i = 1; i < FPR->num_perfect_matches; i++) + log_write(LOG_PLAIN, ", %s", FPR->matches[i]->OS_name); log_write(LOG_PLAIN, "\n"); if (o.debugging || o.verbose > 1)