#include #include #include #include #include #include "osfp_common.h" #include "osfp.h" #include "osfp_log.h" unsigned int osfp_profile_enable; const char *osfp_os_class_name[OSFP_OS_CLASS_MAX] = { OSFP_OS_CLASS_NAME_UNKNOWN, OSFP_OS_CLASS_NAME_WINDOWS, OSFP_OS_CLASS_NAME_LINUX, OSFP_OS_CLASS_NAME_MAC_OS, OSFP_OS_CLASS_NAME_IOS, OSFP_OS_CLASS_NAME_ANDROID, OSFP_OS_CLASS_NAME_OTHERS }; struct osfp_profile_counter osfp_profile_fingerprinting; struct osfp_profile_counter osfp_profile_prefilter; struct osfp_profile_counter osfp_profile_score; struct osfp_profile_counter osfp_profile_result_build; struct osfp_profile_counter osfp_profile_result_export; const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class) { return osfp_os_class_name[os_class]; } enum osfp_os_class_id osfp_os_class_name_to_id(char *name) { int i, namelen; const char *os_class_name; for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { os_class_name = osfp_os_class_id_to_name(i); if (0 == strncmp(name, os_class_name, strlen(os_class_name))) { return (enum osfp_os_class_id)i; } } return OSFP_OS_CLASS_MAX; } struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score, const char *matched) { int i; unsigned int tmp_score; unsigned int likely_score; enum osfp_os_class_id likely_os_class; struct osfp_result *result; result = calloc(1, sizeof(struct osfp_result)); if (result == NULL) { goto exit; } likely_score = 0; likely_os_class = OSFP_OS_CLASS_OTHERS; // likely os score for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { tmp_score = os_class_score->scores[i]; if (likely_score < tmp_score) { likely_score = tmp_score; likely_os_class = i; } result->details[i].score = tmp_score; } // prefiltered if (likely_score == OSFP_PERCENTILE) { goto end; } // too low to tell os class if (likely_score < OSFP_LOWEST_SCORE_LIMIT) { likely_os_class = OSFP_OS_CLASS_OTHERS; goto end; } // when the tied likely scores appear between win/apple-like/unix-like, we throw unknown for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { if (likely_os_class == i) { continue; } if (likely_score != os_class_score->scores[i]) { continue; } if (likely_os_class == OSFP_OS_CLASS_LINUX && i == OSFP_OS_CLASS_ANDROID) { continue; } if (likely_os_class == OSFP_OS_CLASS_MAC_OS && i == OSFP_OS_CLASS_IOS) { continue; } likely_os_class = OSFP_OS_CLASS_UNKNOWN; break; } end: result->likely_os_class = likely_os_class; result->matched = matched; return result; exit: return NULL; } void osfp_profile_counter_print(struct osfp_profile_counter *profile, const char *name) { printf("profile %s: avg: %lu max: %lu min: %lu curr: %lu total: %lu count: %lu\n", name, profile->total_cycle / profile->count, profile->max_cycle, profile->min_cycle, profile->curr_cycle, profile->total_cycle, profile->count); } void osfp_profile_counter_update(struct osfp_profile_counter *profile, unsigned long long curr_cycle) { profile->count++; profile->curr_cycle = curr_cycle; profile->total_cycle += curr_cycle; if (profile->min_cycle == 0) { profile->min_cycle = curr_cycle; } else { if (profile->min_cycle > curr_cycle) { profile->min_cycle = curr_cycle; } } if (profile->max_cycle < curr_cycle) { profile->max_cycle = curr_cycle; } } void osfp_profile_print_stats(void) { osfp_profile_counter_print(&osfp_profile_fingerprinting, "fingerprinting"); osfp_profile_counter_print(&osfp_profile_prefilter, "prefilter"); osfp_profile_counter_print(&osfp_profile_score, "score"); osfp_profile_counter_print(&osfp_profile_result_build, "result build"); osfp_profile_counter_print(&osfp_profile_result_export, "result export"); } void osfp_profile_set(unsigned int enabled) { osfp_profile_enable = enabled; } char *osfp_read_file(char *fp_file) { int ret = -1; char *file_buffer = NULL; unsigned int file_len = 0; FILE *fp = NULL; struct stat st; if (0 > stat(fp_file, &st)) { osfp_log_error("stat() failed on '%s'.\n", fp_file); goto exit; } if (st.st_size == 0) { osfp_log_error("Empty file: '%s'.\n", fp_file); goto exit; } file_len = (unsigned int)st.st_size; file_buffer = malloc(file_len + 1); if (file_buffer == NULL) { osfp_log_error("Not enough memory for file buffer. file name: '%s'\n",fp_file); goto exit; } fp = fopen(fp_file, "r"); if (fp == NULL) { osfp_log_error("Cannot open '%s' for reading.\n", fp_file); goto exit; } ret = fread(file_buffer, 1, file_len, fp); if (ret < 0) { osfp_log_error("fread() failed on '%s'.\n", fp_file); free(file_buffer); fclose(fp); goto exit; } fclose(fp); file_buffer[file_len] = 0; return file_buffer; exit: return NULL; }