Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af67397fc9 | ||
|
|
7a2d2b5020 | ||
|
|
13721781f7 | ||
|
|
c9247d713d | ||
|
|
8832411f29 |
@@ -31,8 +31,11 @@ elseif(ENABLE_SANITIZE_THREAD)
|
||||
endif()
|
||||
# end of for ASAN
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/third_party/cJSON/)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/third_party/uthash/)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src/)
|
||||
|
||||
aux_source_directory(${PROJECT_SOURCE_DIR}/third_party/cJSON/ SRCLIST)
|
||||
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRCLIST)
|
||||
|
||||
# Shared Library Output
|
||||
@@ -73,7 +76,6 @@ target_link_libraries(${lib_name}_test ${lib_name}_static)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_test(NAME sample COMMAND ${lib_name}_sample)
|
||||
add_test(NAME test COMMAND ${lib_name}_test -f ../fp.json -t ../data.json)
|
||||
|
||||
include(Package)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define VLAN_MAX_LAYER 2
|
||||
|
||||
struct osfp_db *g_osfp_db;
|
||||
|
||||
/* Port is just a uint16_t */
|
||||
typedef uint16_t Port;
|
||||
@@ -496,6 +497,8 @@ void example_detect(struct osfp_db *osfp_db, Packet *p)
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
free(json);
|
||||
|
||||
exit:
|
||||
if (result) {
|
||||
osfp_result_free(result);
|
||||
@@ -531,7 +534,7 @@ void process_packet(char *user, struct pcap_pkthdr *h, u_char *pkt)
|
||||
|
||||
// tcp/ip header detect example for user
|
||||
int i;
|
||||
for (i = 0; i < 1; i++) {
|
||||
for (i = 0; i < 1000; i++) {
|
||||
example_detect(osfp_db, p);
|
||||
}
|
||||
|
||||
@@ -562,6 +565,8 @@ static void signal_handler(int signum)
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
osfp_db_free(g_osfp_db);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -690,6 +695,8 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_osfp_db = osfp_db;
|
||||
|
||||
// loop
|
||||
while (1) {
|
||||
int r = pcap_dispatch(pcap_handle, 0, (pcap_handler)process_packet, (void*)osfp_db);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "stdio.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "osfp.h"
|
||||
|
||||
char iph[] = {
|
||||
@@ -17,6 +18,7 @@ char tcph[] = {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *json_file_path = "./fp.json";
|
||||
char *detail_json;
|
||||
|
||||
struct iphdr *l3_hdr = (struct iphdr *)iph;
|
||||
struct tcphdr *l4_hdr = (struct tcphdr *)tcph;
|
||||
@@ -27,7 +29,9 @@ int main(int argc, char **argv)
|
||||
struct osfp_result *result = osfp_ipv4_identify(db, l3_hdr, l4_hdr, l4_hdr_len);
|
||||
if (result) {
|
||||
printf("likely os: %s\n", osfp_result_os_name_get(result));
|
||||
printf("details: \n%s\n", osfp_result_score_detail_export(result));
|
||||
detail_json = osfp_result_score_detail_export(result);
|
||||
printf("details: \n%s\n", detail_json);
|
||||
free(detail_json);
|
||||
osfp_result_free(result);
|
||||
}
|
||||
osfp_db_free(db);
|
||||
|
||||
16
fp.json
16
fp.json
@@ -72590,5 +72590,21 @@
|
||||
"tcp_flags": 2,
|
||||
"ip_tos": 0,
|
||||
"os": "Linux"
|
||||
},
|
||||
{
|
||||
"tcp_options": "M1460,N,W3,N,N,T0,S,E,E,",
|
||||
"tcp_options_ordered": "MNWNNTSEE",
|
||||
"ip_total_length": 64,
|
||||
"tcp_off": 44,
|
||||
"tcp_window_scaling": 3,
|
||||
"tcp_window_size": 31744,
|
||||
"ip_ttl": 64,
|
||||
"ip_id": 0,
|
||||
"tcp_timestamp": 1,
|
||||
"tcp_timestamp_echo_reply": 0,
|
||||
"tcp_mss": 1460,
|
||||
"tcp_flags": 2,
|
||||
"ip_tos": 0,
|
||||
"os": "iOS"
|
||||
}
|
||||
]
|
||||
183
src/osfp.c
183
src/osfp.c
@@ -1,3 +1,8 @@
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
#include "osfp_common.h"
|
||||
|
||||
#include "osfp.h"
|
||||
@@ -5,67 +10,6 @@
|
||||
#include "osfp_score_db.h"
|
||||
#include "osfp_log.h"
|
||||
|
||||
#define OSFP_LOWEST_SCORE_LIMIT 20
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
if (likely_score == OSFP_PERCENTILE) {
|
||||
// prefiltered
|
||||
;
|
||||
} else if (likely_score < OSFP_LOWEST_SCORE_LIMIT) {
|
||||
// too low to tell os class
|
||||
likely_os_class = OSFP_OS_CLASS_OTHERS;
|
||||
} else {
|
||||
// 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]) {
|
||||
if (likely_os_class == OSFP_OS_CLASS_LINUX && i == OSFP_OS_CLASS_ANDROID) {
|
||||
continue;
|
||||
} else if (likely_os_class == OSFP_OS_CLASS_MAC_OS && i == OSFP_OS_CLASS_IOS) {
|
||||
continue;
|
||||
} else {
|
||||
likely_os_class = OSFP_OS_CLASS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result->likely_os_class = likely_os_class;
|
||||
result->matched = matched;
|
||||
return result;
|
||||
exit:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *osfp_result_os_name_get(struct osfp_result *result)
|
||||
{
|
||||
enum osfp_os_class_id os_class;
|
||||
@@ -97,11 +41,7 @@ char *osfp_result_score_detail_export(struct osfp_result *result)
|
||||
osfp_profile_get_cycle(c1);
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (result->json_str != NULL) {
|
||||
return result->json_str;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
root = cJSON_CreateObject();
|
||||
@@ -141,7 +81,7 @@ char *osfp_result_score_detail_export(struct osfp_result *result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
result->json_str = result_str;
|
||||
cJSON_Delete(root);
|
||||
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_result_export, c2 - c1);
|
||||
@@ -157,14 +97,11 @@ exit:
|
||||
void osfp_result_free(struct osfp_result *result)
|
||||
{
|
||||
if (result) {
|
||||
if (result->json_str) {
|
||||
free(result->json_str);
|
||||
}
|
||||
free(result);
|
||||
}
|
||||
}
|
||||
|
||||
struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len)
|
||||
struct osfp_result *osfp_ip_identify(struct osfp_db *db, unsigned char *l3_hdr, unsigned char *l4_hdr, unsigned int l4_hdr_len, unsigned int ip_version)
|
||||
{
|
||||
int ret;
|
||||
struct osfp_fingerprint fp;
|
||||
@@ -172,39 +109,24 @@ struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr,
|
||||
struct osfp_result *result;
|
||||
const char *matched;
|
||||
|
||||
osfp_profile_cycle(c1);
|
||||
osfp_profile_cycle(c2);
|
||||
|
||||
if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr_len == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
osfp_profile_get_cycle(c1);
|
||||
ret = osfp_fingerprinting((unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, &fp, 4);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_fingerprinting, c2 - c1);
|
||||
ret = osfp_fingerprinting(l3_hdr, l4_hdr, l4_hdr_len, &fp, ip_version);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
osfp_profile_get_cycle(c1);
|
||||
matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_prefilter, c2 - c1);
|
||||
if (matched == NULL) {
|
||||
osfp_profile_get_cycle(c1);
|
||||
ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_score, c2 - c1);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
osfp_profile_get_cycle(c1);
|
||||
result = osfp_result_build(&os_class_score, matched);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_result_build, c2 - c1);
|
||||
if (result == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -214,89 +136,14 @@ exit:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len)
|
||||
{
|
||||
return osfp_ip_identify(db, (unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, 4);
|
||||
}
|
||||
|
||||
struct osfp_result *osfp_ipv6_identify(struct osfp_db *db, struct ip6_hdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len)
|
||||
{
|
||||
int ret;
|
||||
struct osfp_fingerprint fp;
|
||||
struct osfp_os_class_score os_class_score;
|
||||
struct osfp_result *result;
|
||||
const char *matched;
|
||||
|
||||
osfp_profile_cycle(c1);
|
||||
osfp_profile_cycle(c2);
|
||||
|
||||
if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr_len == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
osfp_profile_get_cycle(c1);
|
||||
ret = osfp_fingerprinting((unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, &fp, 6);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_fingerprinting, c2 - c1);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
osfp_profile_get_cycle(c1);
|
||||
matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_prefilter, c2 - c1);
|
||||
if (matched == NULL) {
|
||||
osfp_profile_get_cycle(c1);
|
||||
ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_score, c2 - c1);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
osfp_profile_get_cycle(c1);
|
||||
result = osfp_result_build(&os_class_score, matched);
|
||||
osfp_profile_get_cycle(c2);
|
||||
osfp_profile_counter_update(&osfp_profile_result_build, c2 - c1);
|
||||
if (result == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return result;
|
||||
exit:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str)
|
||||
{
|
||||
int ret = OSFP_EINVAL;
|
||||
struct osfp_fingerprint fp;
|
||||
struct osfp_os_class_score os_class_score;
|
||||
struct osfp_result *result;
|
||||
const char *matched;
|
||||
|
||||
if (db == NULL || json_str == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = osfp_fingerprint_from_json(&fp, (char *)json_str);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score);
|
||||
if (matched == NULL) {
|
||||
ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
result = osfp_result_build(&os_class_score, matched);
|
||||
if (result == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return result;
|
||||
exit:
|
||||
return NULL;
|
||||
return osfp_ip_identify(db, (unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, 6);
|
||||
}
|
||||
|
||||
struct osfp_db *osfp_db_new(const char *fp_path)
|
||||
|
||||
21
src/osfp.h
21
src/osfp.h
@@ -32,6 +32,18 @@ struct osfp_db *osfp_db_new(const char *db_json_path);
|
||||
*/
|
||||
void osfp_db_free(struct osfp_db *db);
|
||||
|
||||
/**
|
||||
* @brief 通过 IP 头部和 TCP 头部识别操作系统。
|
||||
*
|
||||
* @param db 操作系统指纹库。
|
||||
* @param l3_hdr 指向 IP 头部的指针。
|
||||
* @param l4_hdr 指向 TCP 头部的指针。
|
||||
* @param l4_hdr_len TCP 头部的长度(注意:包含TCP选项部分)。
|
||||
* @param ip_version IP头版本号,4 或 6)。
|
||||
* @return 指向操作系统识别结果的指针。
|
||||
*/
|
||||
struct osfp_result *osfp_ip_identify(struct osfp_db *db, unsigned char *l3_hdr, unsigned char *l4_hdr, unsigned int l4_hdr_len, unsigned int ip_version);
|
||||
|
||||
/**
|
||||
* @brief 通过 IPv4 头部和 TCP 头部识别操作系统。
|
||||
*
|
||||
@@ -54,15 +66,6 @@ struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr,
|
||||
*/
|
||||
struct osfp_result *osfp_ipv6_identify(struct osfp_db *db, struct ip6_hdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len);
|
||||
|
||||
/**
|
||||
* @brief 通过 json 格式的指纹识别操作系统。
|
||||
*
|
||||
* @param db 操作系统指纹库。
|
||||
* @param json_str 指纹字符串。
|
||||
* @return 指向操作系统识别结果的指针(注意:内存需要使用者释放)。
|
||||
*/
|
||||
struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str);
|
||||
|
||||
/**
|
||||
* @brief 获取操作系统识别结果的操作系统名称。
|
||||
*
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#include "osfp_common.h"
|
||||
|
||||
#include "osfp.h"
|
||||
@@ -41,6 +48,70 @@ enum osfp_os_class_id osfp_os_class_name_to_id(char *name)
|
||||
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",
|
||||
|
||||
@@ -1,27 +1,6 @@
|
||||
#ifndef __OSFP_COMMON_H__
|
||||
#define __OSFP_COMMON_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "utarray.h"
|
||||
#include "uthash.h"
|
||||
#include "utlist.h"
|
||||
#include "utringbuffer.h"
|
||||
#include "utstack.h"
|
||||
#include "utstring.h"
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
static inline unsigned long long osfp_rdtsc(void)
|
||||
{
|
||||
union {
|
||||
@@ -157,6 +136,7 @@ enum osfp_os_class_id {
|
||||
#define OSFP_OS_CLASS_FLAG_IOS OSFP_BIT_U32(OSFP_OS_CLASS_IOS)
|
||||
#define OSFP_OS_CLASS_FLAG_ANDROID OSFP_BIT_U32(OSFP_OS_CLASS_ANDROID)
|
||||
|
||||
#define OSFP_LOWEST_SCORE_LIMIT 20
|
||||
|
||||
enum osfp_error_code {
|
||||
OSFP_NOERR,
|
||||
@@ -169,6 +149,9 @@ enum osfp_error_code {
|
||||
OSFP_ERR_FINGERPRINTING_UNSUPPORTED,
|
||||
};
|
||||
|
||||
struct osfp_os_class_score {
|
||||
unsigned int scores[OSFP_OS_CLASS_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 结构体用于 osfp_result 中的详细结果。
|
||||
@@ -182,7 +165,6 @@ struct osfp_result_detail {
|
||||
* @brief 结构体用于表示操作系统识别结果。
|
||||
*/
|
||||
struct osfp_result {
|
||||
char *json_str; // JSON 字符串
|
||||
enum osfp_os_class_id likely_os_class; // 最可能的操作系统类别
|
||||
struct osfp_result_detail details[OSFP_OS_CLASS_MAX]; // 详细结果数组
|
||||
const char *matched; // 精确匹配到的指纹特征
|
||||
@@ -198,6 +180,7 @@ struct osfp_db {
|
||||
|
||||
enum osfp_os_class_id osfp_os_class_name_to_id(char *name);
|
||||
const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class);
|
||||
struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score, const char *matched);
|
||||
char *osfp_read_file(char *fp_file);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
#include "osfp_common.h"
|
||||
|
||||
#include "osfp.h"
|
||||
@@ -221,14 +228,17 @@ int osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsi
|
||||
return strlen(strbuf) + 1;
|
||||
}
|
||||
|
||||
struct osfp_fingerprint *osfp_fingerprint_from_cjson(cJSON *root)
|
||||
struct osfp_fingerprint *osfp_fingerprint_from_cjson(void *cjson_obj)
|
||||
{
|
||||
int i;
|
||||
cJSON *root;
|
||||
cJSON *field;
|
||||
void *value_ptr;
|
||||
unsigned int value_len;
|
||||
struct osfp_fingerprint *fp;
|
||||
|
||||
root = (cJSON *)cjson_obj;
|
||||
|
||||
if (root == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ static inline unsigned int osfp_fingerprint_get_field_type(enum osfp_field_id fi
|
||||
return fp_fields[field_id].type;
|
||||
}
|
||||
|
||||
struct osfp_fingerprint *osfp_fingerprint_from_cjson(cJSON *root);
|
||||
struct osfp_fingerprint *osfp_fingerprint_from_cjson(void *root);
|
||||
int osfp_fingerprint_from_json(struct osfp_fingerprint *fp, char *json_str);
|
||||
int osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsigned int buf_len, unsigned int format);
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "osfp_common.h"
|
||||
#include "osfp_log.h"
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
#include "osfp_common.h"
|
||||
|
||||
#include "osfp.h"
|
||||
@@ -301,7 +306,7 @@ int osfp_score_db_score(struct osfp_score_db *score_db, unsigned int flags, stru
|
||||
continue;
|
||||
}
|
||||
|
||||
coefficient = OSFP_PERCENTILE / PERFECT_SCORE_EXPECTED_RATE * score_db->field_weight[i] / total_weight;
|
||||
coefficient = fdb->coefficient;
|
||||
|
||||
for (j = 0; j < OSFP_OS_CLASS_MAX; j++) {
|
||||
os_entry_count = score_db->os_entry_count[j];
|
||||
@@ -408,6 +413,7 @@ static int osfp_score_db_load_entry(struct osfp_score_db *score_db, cJSON *entry
|
||||
} else {
|
||||
// TODO: same fingerprints with different os should not insert into prefilter hash table, now just tag
|
||||
element->repeated++;
|
||||
free(fp);
|
||||
}
|
||||
|
||||
// field score db
|
||||
@@ -509,10 +515,10 @@ struct osfp_score_db *osfp_score_db_create(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
score_db->field_weight[i] = osfp_fingerprint_get_field_importance(i);
|
||||
db->weight = osfp_fingerprint_get_field_importance(i);
|
||||
// tcp options ordered and tcp options overlap
|
||||
if (i != OSFP_FIELD_TCP_OPTIONS_ORDERED) {
|
||||
score_db->total_weight += score_db->field_weight[i];
|
||||
score_db->total_weight += db->weight;
|
||||
}
|
||||
|
||||
db->type = osfp_fingerprint_get_field_type(i);
|
||||
@@ -541,6 +547,11 @@ struct osfp_score_db *osfp_score_db_create(void)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < OSFP_FIELD_MAX; i++) {
|
||||
db = &score_db->field_score_dbs[i];
|
||||
db->coefficient = (OSFP_PERCENTILE / PERFECT_SCORE_EXPECTED_RATE) * ((float)db->weight / (float)score_db->total_weight);
|
||||
}
|
||||
|
||||
return score_db;
|
||||
exit:
|
||||
if (score_db) {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#ifndef __OSFP_SCORE_DB_H__
|
||||
#define __OSFP_SCORE_DB_H__
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
#include "osfp.h"
|
||||
#include "osfp_fingerprint.h"
|
||||
#include "osfp_common.h"
|
||||
|
||||
struct osfp_os_class_score {
|
||||
unsigned int scores[OSFP_OS_CLASS_MAX];
|
||||
};
|
||||
|
||||
struct osfp_field_value_count {
|
||||
unsigned int counts[OSFP_OS_CLASS_MAX];
|
||||
};
|
||||
@@ -18,6 +16,9 @@ struct osfp_field_score_db {
|
||||
unsigned int type;
|
||||
unsigned int entry_count;
|
||||
|
||||
unsigned int weight;
|
||||
float coefficient;
|
||||
|
||||
void *data;
|
||||
|
||||
void *(*create)(void);
|
||||
@@ -42,9 +43,7 @@ struct osfp_score_db {
|
||||
unsigned int entry_count;
|
||||
unsigned int os_entry_count[OSFP_OS_CLASS_MAX];
|
||||
|
||||
unsigned int perfect_score;
|
||||
unsigned int total_weight;
|
||||
unsigned int field_weight[OSFP_FIELD_MAX];
|
||||
|
||||
struct osfp_field_score_db field_score_dbs[OSFP_FIELD_MAX];
|
||||
};
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
{
|
||||
global: osfp*;GIT_VERSION_*;
|
||||
global:
|
||||
osfp_db_new;
|
||||
osfp_db_free;
|
||||
osfp_ip_identify;
|
||||
osfp_ipv4_identify;
|
||||
osfp_ipv6_identify;
|
||||
osfp_result_os_name_get;
|
||||
osfp_result_score_detail_export;
|
||||
osfp_result_free;
|
||||
local: *;
|
||||
};
|
||||
|
||||
38
test/test.c
38
test/test.c
@@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
@@ -126,6 +127,40 @@ static void print_confusion_matrix(unsigned int *result, unsigned int os_class_m
|
||||
printf("miss rate: %u%%\n", 100 * missed / (matched + missed));
|
||||
}
|
||||
|
||||
struct osfp_result *test_osfp_json_identify(struct osfp_db *db, const char *json_str)
|
||||
{
|
||||
int ret = OSFP_EINVAL;
|
||||
struct osfp_fingerprint fp;
|
||||
struct osfp_os_class_score os_class_score;
|
||||
struct osfp_result *result;
|
||||
const char *matched;
|
||||
|
||||
if (db == NULL || json_str == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = osfp_fingerprint_from_json(&fp, (char *)json_str);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score);
|
||||
if (matched == NULL) {
|
||||
ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
result = osfp_result_build(&os_class_score, matched);
|
||||
if (result == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return result;
|
||||
exit:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void test_data_prepare()
|
||||
{
|
||||
@@ -229,7 +264,7 @@ void test_miss_rate()
|
||||
osfp_fingerprint_to_json_buf(&fp, str_buf, 2048, 0);
|
||||
fprintf(log_file_ptr, "%s\n", str_buf);
|
||||
|
||||
struct osfp_result *result = osfp_json_identify(osfp_db, fp_str);
|
||||
struct osfp_result *result = test_osfp_json_identify(osfp_db, fp_str);
|
||||
if (result == NULL) {
|
||||
identify_failed_count++;
|
||||
continue;
|
||||
@@ -265,6 +300,7 @@ void test_miss_rate()
|
||||
char *result_json = osfp_result_score_detail_export(result);
|
||||
if (result_json) {
|
||||
fprintf(log_file_ptr, "%s\n", result_json);
|
||||
free(result_json);
|
||||
} else {
|
||||
fprintf(log_file_ptr, "result detail error:%p\n", result);
|
||||
}
|
||||
|
||||
0
src/cJSON.c → third_party/cJSON/cJSON.c
vendored
0
src/cJSON.c → third_party/cJSON/cJSON.c
vendored
0
src/cJSON.h → third_party/cJSON/cJSON.h
vendored
0
src/cJSON.h → third_party/cJSON/cJSON.h
vendored
Reference in New Issue
Block a user