@@ -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+
319425int32_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}
0 commit comments