Skip to content

Commit 976520a

Browse files
committed
feat: First implementation of weighted scoring (TTL/IPID/WINDOW)
1 parent f9ca246 commit 976520a

File tree

2 files changed

+216
-49
lines changed

2 files changed

+216
-49
lines changed

EthernetAppDemo/modules/os_detector_module.c

Lines changed: 201 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,80 @@ double varianza(int32_t* d, int len) {
3434
return (suma2 / len) - (media * media);
3535
}
3636

37-
void clasificar_ipid(uint16_t* id, int n, uint8_t* value_ptr) {
38-
int32_t d[100];
39-
int positivos = 0, negativos = 0;
37+
static ipid_pattern_t detectar_patron_ipid(uint16_t* ids, int n) {
38+
if(n < 3) return IPID_UNKNOWN;
39+
40+
// ---- Detectar todos cero ----
41+
bool all_zero = true;
42+
for(int i = 0; i < n; i++) {
43+
if(ids[i] != 0) {
44+
all_zero = false;
45+
break;
46+
}
47+
}
48+
if(all_zero) return IPID_ZERO;
49+
50+
// ---- Detectar constante ----
51+
bool constante = true;
52+
for(int i = 1; i < n; i++) {
53+
if(ids[i] != ids[0]) {
54+
constante = false;
55+
break;
56+
}
57+
}
58+
if(constante) return IPID_CONSTANT;
59+
60+
// ---- Calcular diferencias ----
61+
int32_t diffs[100] = {0};
62+
int positivos = 0;
63+
int pequenos = 0;
64+
int grandes = 0;
4065

4166
for(int i = 0; i < n - 1; i++) {
42-
d[i] = ipid_diff(id[i], id[i + 1]);
67+
diffs[i] = ipid_diff(ids[i], ids[i + 1]);
68+
69+
if(diffs[i] > 0) positivos++;
70+
71+
if(diffs[i] > 0 && diffs[i] < 1000) pequenos++;
4372

44-
if(d[i] > 0)
45-
positivos++;
46-
else
47-
negativos++;
73+
if(diffs[i] >= 1000) grandes++;
4874
}
4975

50-
double var = varianza(d, n - 1);
76+
double var = varianza(diffs, n - 1);
5177

52-
// regla simple para clasificar
53-
if(positivos >= 0.75 * (n - 1) && var < 5000) {
54-
*value_ptr = LINUX;
55-
} else {
56-
*value_ptr = IOS;
78+
// ---- Incremental pequeño (Linux clásico) ----
79+
if(positivos >= 0.8 * (n - 1) && pequenos >= 0.7 * (n - 1) && var < 20000) {
80+
return IPID_INCREMENTAL;
81+
}
82+
83+
// ---- Incremental con saltos grandes ----
84+
if(positivos >= 0.8 * (n - 1) && grandes >= 0.5 * (n - 1)) {
85+
return IPID_INCREMENTAL_LARGE;
86+
}
87+
88+
// ---- Random ----
89+
if(var > 500000) {
90+
return IPID_RANDOM;
91+
}
92+
93+
return IPID_UNKNOWN;
94+
}
95+
96+
static uint8_t clasificar_ipid_por_patron(ipid_pattern_t pattern) {
97+
switch(pattern) {
98+
case IPID_ZERO:
99+
case IPID_CONSTANT:
100+
return WINDOWS;
101+
102+
case IPID_INCREMENTAL:
103+
case IPID_INCREMENTAL_LARGE:
104+
return LINUX;
105+
106+
case IPID_RANDOM:
107+
return IOS;
108+
109+
default:
110+
return NO_DETECTED;
57111
}
58112
}
59113

@@ -316,7 +370,61 @@ void ofp_tseq(App* app, uint8_t* target_ip) {
316370
}
317371
}
318372

373+
static void os_scoreboard_init(os_scoreboard_t* sb) {
374+
sb->windows_score = 0;
375+
sb->linux_score = 0;
376+
sb->ios_score = 0;
377+
}
378+
379+
static void os_score_add(os_scoreboard_t* sb, OS_DETECTOR_OS os, int weight) {
380+
switch(os) {
381+
case WINDOWS:
382+
sb->windows_score += weight;
383+
break;
384+
case LINUX:
385+
sb->linux_score += weight;
386+
break;
387+
case IOS:
388+
sb->ios_score += weight;
389+
break;
390+
default:
391+
break;
392+
}
393+
}
394+
395+
static OS_DETECTOR_OS os_score_resolve(os_scoreboard_t* sb) {
396+
printf("Resolving...\n");
397+
398+
if(sb->windows_score == sb->linux_score && sb->linux_score == sb->ios_score)
399+
return NO_DETECTED;
400+
401+
int max = sb->windows_score;
402+
OS_DETECTOR_OS result = WINDOWS;
403+
404+
if(sb->linux_score > max) {
405+
max = sb->linux_score;
406+
result = LINUX;
407+
}
408+
409+
if(sb->ios_score > max) {
410+
max = sb->ios_score;
411+
result = IOS;
412+
}
413+
414+
// empate parcial
415+
if((result == WINDOWS && sb->windows_score == sb->linux_score) ||
416+
(result == LINUX && sb->linux_score == sb->ios_score) ||
417+
(result == WINDOWS && sb->windows_score == sb->ios_score))
418+
return NO_DETECTED;
419+
420+
if(max < 5) return NO_DETECTED;
421+
422+
return result;
423+
}
424+
319425
int32_t os_scan(void* context, uint8_t* target_ip) {
426+
os_scoreboard_t sb;
427+
os_scoreboard_init(&sb);
320428
App* app = context;
321429

322430
// TSEQ unabled
@@ -325,8 +433,6 @@ int32_t os_scan(void* context, uint8_t* target_ip) {
325433
uint8_t ttl = 0;
326434
uint32_t rtt = 0;
327435

328-
uint8_t value = NO_DETECTED;
329-
330436
bool ttl_valid = false;
331437
uint8_t ttl_tcp = 0;
332438

@@ -491,43 +597,89 @@ int32_t os_scan(void* context, uint8_t* target_ip) {
491597
printf("[OS] ICMP probe failed\n");
492598
}
493599

494-
if(ttl_valid && ttl_tcp > 64 && ttl_tcp <= 128) {
495-
value = WINDOWS;
496-
} else if(!ttl_valid && icmp_valid && ttl_icmp > 64 && ttl_icmp <= 128) {
497-
value = WINDOWS;
498-
} else {
499-
uint8_t sum_true = 0;
500-
uint8_t an_index = 0;
501-
for(uint8_t i = 0; i < packet_count; i++) {
502-
sum_true += respuestas[i] ? 1 : 0;
503-
if(respuestas[i]) {
504-
ids_an[an_index] = ids[i];
505-
an_index++;
506-
}
600+
uint8_t sum_true = 0;
601+
uint8_t an_index = 0;
602+
for(uint8_t i = 0; i < packet_count; i++) {
603+
sum_true += respuestas[i] ? 1 : 0;
604+
if(respuestas[i]) {
605+
ids_an[an_index] = ids[i];
606+
an_index++;
507607
}
608+
}
609+
610+
if(sum_true) {
611+
/* ---------- TTL SCORING ---------- */
612+
613+
uint8_t ttl_guess = 0;
614+
uint8_t ttl_weight = 0;
615+
616+
if(ttl_valid) {
617+
/* Estimación de TTL inicial */
618+
if(ttl_tcp <= 64) {
619+
ttl_guess = 64;
620+
}
508621

509-
if(sum_true) {
510-
uint8_t value_ipid = NO_DETECTED;
511-
uint8_t value_win = NO_DETECTED;
512-
uint8_t value_ttl = NO_DETECTED;
513-
514-
clasificar_ipid(ids_an, sum_true, &value_ipid);
515-
clasificar_window(windows, sum_true, &value_win);
516-
517-
// Heurística combinada simple
518-
if(value_win == value_ttl && value_win != NO_DETECTED) {
519-
value = value_win; // Coincidencia fuerte
520-
} else if(value_win != NO_DETECTED) {
521-
value = value_win; // Window pesa más
522-
} else if(value_ttl != NO_DETECTED) {
523-
value = value_ttl;
524-
} else {
525-
value = value_ipid;
622+
else if(ttl_tcp <= 128) {
623+
ttl_guess = 128;
526624
}
527-
} else {
528-
value = NO_DETECTED;
625+
626+
else {
627+
ttl_guess = 255;
628+
}
629+
630+
ttl_weight = 5; // TCP pesa más
631+
} else if(icmp_valid) {
632+
if(ttl_icmp <= 64)
633+
ttl_guess = 64;
634+
else if(ttl_icmp <= 128)
635+
ttl_guess = 128;
636+
else
637+
ttl_guess = 255;
638+
639+
ttl_weight = 3; // ICMP pesa menos
529640
}
641+
642+
/* Asignación de puntuación */
643+
if(ttl_guess == 64) {
644+
os_score_add(&sb, LINUX, ttl_weight);
645+
}
646+
647+
else if(ttl_guess == 128) {
648+
os_score_add(&sb, WINDOWS, ttl_weight);
649+
}
650+
651+
else if(ttl_guess == 255) {
652+
os_score_add(&sb, IOS, ttl_weight);
653+
}
654+
655+
/* ---------- IPID SCORING ---------- */
656+
ipid_pattern_t pattern = detectar_patron_ipid(ids_an, sum_true);
657+
uint8_t ipid_guess = clasificar_ipid_por_patron(pattern);
658+
if(ipid_guess == ttl_guess && ipid_guess != NO_DETECTED) {
659+
os_score_add(&sb, ipid_guess, 2);
660+
}
661+
if(ipid_guess != NO_DETECTED) {
662+
os_score_add(&sb, ipid_guess, 3);
663+
}
664+
const char* ipid_names[] = {
665+
"UNKNOWN", "CONSTANT", "INCREMENTAL", "INCREMENTAL_LARGE", "RANDOM", "ZERO"};
666+
667+
printf("[IPID] Pattern: %s\n", ipid_names[pattern]);
668+
669+
/* ---------- WINDOW SCORING ---------- */
670+
uint8_t value_win = NO_DETECTED;
671+
clasificar_window(windows, sum_true, &value_win);
672+
673+
if(value_win == LINUX)
674+
os_score_add(&sb, LINUX, 4);
675+
else if(value_win == WINDOWS)
676+
os_score_add(&sb, WINDOWS, 4);
530677
}
531678

532-
return value;
679+
printf("\n[SCORE]\n");
680+
printf("WINDOWS: %d\n", sb.windows_score);
681+
printf("LINUX: %d\n", sb.linux_score);
682+
printf("IOS: %d\n\n", sb.ios_score);
683+
684+
return os_score_resolve(&sb);
533685
}

EthernetAppDemo/modules/os_detector_module.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,19 @@ typedef enum {
1818
OFP_TUDP,
1919
} OFP_PROBES_TYPE;
2020

21+
typedef enum {
22+
IPID_UNKNOWN = 0,
23+
IPID_CONSTANT,
24+
IPID_INCREMENTAL,
25+
IPID_INCREMENTAL_LARGE,
26+
IPID_RANDOM,
27+
IPID_ZERO
28+
} ipid_pattern_t;
29+
30+
typedef struct {
31+
int windows_score;
32+
int linux_score;
33+
int ios_score;
34+
} os_scoreboard_t;
35+
2136
int32_t os_scan(void* context, uint8_t* target_ip);

0 commit comments

Comments
 (0)