00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "OSFinger.h"
00019 #include "net_util.h"
00020 #include "util.h"
00021 #include "Var.h"
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <ctype.h>
00025
00026
00027
00028 OSFingerprint::OSFingerprint(FingerprintMode mode)
00029 {
00030 err = 0;
00031
00032 sigcnt=gencnt=0;
00033 problems=0;
00034 char* fname;
00035
00036 memset(sig, 0, sizeof(struct fp_entry)*MAXSIGS);
00037 memset(bh, 0, sizeof(struct fp_entry*)*OSHSIZE);
00038
00039 if (mode == SYN_FINGERPRINT_MODE)
00040 {
00041 fname = copy_string(internal_val("passive_fingerprint_file")->AsString()->CheckString());
00042 load_config(fname);
00043 }
00044 else if (mode == SYN_ACK_FINGERPRINT_MODE)
00045 {
00046 load_config("p0fsynack.sig");
00047 }
00048 else if (mode == RST_FINGERPRINT_MODE)
00049 {
00050 load_config("p0frst.sig");
00051 }
00052 else
00053 {
00054 Error("OS fingerprinting: unknown mode!");
00055 }
00056 }
00057
00058 bool OSFingerprint::CacheMatch(uint32 addr, int id)
00059 {
00060 HashKey key = HashKey(&addr, 1);
00061 int* pid = new int;
00062 *pid=id;
00063 int* prev = os_matches.Insert(&key, pid);
00064 bool ret = (prev ? *prev != id : 1);
00065 if (prev)
00066 delete prev;
00067 return ret;
00068 }
00069
00070
00071
00072 void OSFingerprint::collide(uint32 id)
00073 {
00074 uint32 i,j;
00075 uint32 cur;
00076
00077 if (sig[id].ttl % 32 && sig[id].ttl != 255 && sig[id].ttl % 30)
00078 {
00079 problems=1;
00080 warn(fmt("OS fingerprinting: [!] Unusual TTL (%d) for signature '%s %s' (line %d).",
00081 sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line));
00082 }
00083
00084 for (i=0;i<id;i++)
00085 {
00086 if (!strcmp(sig[i].os,sig[id].os) &&
00087 !strcmp(sig[i].desc,sig[id].desc)) {
00088 problems=1;
00089 warn(fmt("OS fingerprinting: [!] Duplicate signature name: '%s %s' (line %d and %d).",
00090 sig[i].os,sig[i].desc,sig[i].line,sig[id].line));
00091 }
00092
00093
00094
00095 if (abs((int)sig[id].ttl - (int)sig[i].ttl) > 25) continue;
00096
00097 if (sig[id].df ^ sig[i].df) continue;
00098 if (sig[id].zero_stamp ^ sig[i].zero_stamp) continue;
00099
00100
00101 if (sig[id].size) { if (sig[id].size ^ sig[i].size) continue; }
00102 else if (sig[i].size < PACKET_BIG) continue;
00103
00104 if (sig[id].optcnt ^ sig[i].optcnt) continue;
00105 if (sig[id].quirks ^ sig[i].quirks) continue;
00106
00107 switch (sig[id].wsize_mod) {
00108
00109 case 0:
00110
00111 cur=sig[id].wsize;
00112
00113 do_const:
00114
00115 switch (sig[i].wsize_mod) {
00116
00117 case 0:
00118
00119
00120 if (cur ^ sig[i].wsize) continue;
00121 break;
00122
00123 case MOD_CONST:
00124
00125
00126 if (cur % sig[i].wsize) continue;
00127 break;
00128
00129 case MOD_MSS:
00130
00131 if (sig[i].mss_mod || sig[i].wsize *
00132 (sig[i].mss ? sig[i].mss : 1460 ) != (int) cur)
00133 continue;
00134
00135 break;
00136
00137 case MOD_MTU:
00138
00139 if (sig[i].mss_mod || sig[i].wsize * (
00140 (sig[i].mss ? sig[i].mss : 1460 )+40) != (int) cur)
00141 continue;
00142
00143 break;
00144
00145 }
00146
00147 break;
00148
00149 case 1:
00150
00151
00152
00153
00154 if (sig[i].wsize_mod != MOD_CONST) continue;
00155 if (sig[id].wsize % sig[i].wsize) continue;
00156
00157 break;
00158
00159 case MOD_MSS:
00160
00161
00162
00163
00164
00165
00166
00167 if (sig[i].wsize_mod != MOD_CONST || sig[i].wsize >= 8) {
00168 if (!sig[id].mss_mod) {
00169 cur = (sig[id].mss ? sig[id].mss : 1460 ) * sig[id].wsize;
00170 goto do_const;
00171 }
00172 continue;
00173 }
00174
00175 break;
00176
00177 case MOD_MTU:
00178
00179 if (sig[i].wsize_mod != MOD_CONST || sig[i].wsize <= 8) {
00180 if (!sig[id].mss_mod) {
00181 cur = ( (sig[id].mss ? sig[id].mss : 1460 ) +40) * sig[id].wsize;
00182 goto do_const;
00183 }
00184 continue;
00185 }
00186
00187 break;
00188
00189 }
00190
00191
00192 switch (sig[id].wsc_mod) {
00193
00194 case 0:
00195
00196 cur=sig[id].wsc;
00197
00198 switch (sig[i].wsc_mod) {
00199
00200 case 0:
00201
00202
00203 if (cur ^ sig[i].wsc) continue;
00204 break;
00205
00206 case 1:
00207
00208
00209 if (cur % sig[i].wsc) continue;
00210 break;
00211
00212 }
00213
00214 break;
00215
00216 case MOD_CONST:
00217
00218
00219
00220
00221 if (!sig[i].wsc_mod) continue;
00222 if (sig[id].wsc % sig[i].wsc) continue;
00223
00224 break;
00225
00226 }
00227
00228
00229 switch (sig[id].mss_mod) {
00230
00231 case 0:
00232
00233 cur=sig[id].mss;
00234
00235 switch (sig[i].mss_mod) {
00236
00237 case 0:
00238
00239
00240 if (cur ^ sig[i].mss) continue;
00241 break;
00242
00243 case 1:
00244
00245
00246 if (cur % sig[i].mss) continue;
00247 break;
00248
00249 }
00250
00251 break;
00252
00253 case MOD_CONST:
00254
00255
00256
00257
00258 if (!sig[i].mss_mod) continue;
00259 if ((sig[id].mss ? sig[id].mss : 1460 ) %
00260 (sig[i].mss ? sig[i].mss : 1460 )) continue;
00261
00262 break;
00263
00264 }
00265
00266
00267
00268 for (j=0;j<sig[id].optcnt;j++)
00269 if (sig[id].opt[j] ^ sig[i].opt[j]) goto reloop;
00270
00271 problems=1;
00272 warn(fmt("OS fingerprinting: [!] Signature '%s %s' (line %d)\n"
00273 " is already covered by '%s %s' (line %d).",
00274 sig[id].os,sig[id].desc,sig[id].line,sig[i].os,sig[i].desc,
00275 sig[i].line));
00276
00277 reloop:
00278 ;
00279 }
00280 }
00281
00282
00283 void OSFingerprint::load_config(char* file)
00284 {
00285 uint32 ln=0;
00286 char buf[MAXLINE];
00287 char* p;
00288 FILE* c = search_for_file( file, "osf", 0);
00289
00290 if (!c)
00291 {
00292 Error("Can't open OS passive fingerprinting signature file", file);
00293 return;
00294 }
00295 sigcnt=0;
00296 while ((p=fgets(buf,sizeof(buf),c)))
00297 {
00298 uint32 l;
00299
00300 char obuf[MAXLINE],genre[MAXLINE],desc[MAXLINE],quirks[MAXLINE];
00301 char w[MAXLINE],sb[MAXLINE];
00302 char* gptr = genre;
00303 uint32 t,d,s;
00304 struct fp_entry* e;
00305
00306 ln++;
00307
00308
00309 while (isspace(*p)) p++;
00310 l=strlen(p);
00311 while (l && isspace(*(p+l-1))) *(p+(l--)-1)=0;
00312
00313
00314 if (!l) continue;
00315 if (*p == '#') continue;
00316
00317 if (sscanf(p,"%[0-9%*()ST]:%d:%d:%[0-9()*]:%[^:]:%[^ :]:%[^:]:%[^:]",
00318 w, &t,&d,sb, obuf, quirks,genre,desc) != 8)
00319 Error("OS fingerprinting: Syntax error in p0f signature config line %d.\n",(uint32)ln);
00320
00321 gptr = genre;
00322
00323 if (*sb != '*') s = atoi(sb); else s = 0;
00324
00325 reparse_ptr:
00326
00327 switch (*gptr)
00328 {
00329 case '-': sig[sigcnt].userland = 1; gptr++; goto reparse_ptr;
00330 case '*': sig[sigcnt].no_detail = 1; gptr++; goto reparse_ptr;
00331 case '@': sig[sigcnt].generic = 1; gptr++; gencnt++; goto reparse_ptr;
00332 case 0: Error("OS fingerprinting: Empty OS genre in line",(uint32)ln);
00333 }
00334
00335 sig[sigcnt].os = strdup(gptr);
00336 sig[sigcnt].desc = strdup(desc);
00337 sig[sigcnt].ttl = t;
00338 sig[sigcnt].size = s;
00339 sig[sigcnt].df = d;
00340
00341 if (w[0] == '*')
00342 {
00343 sig[sigcnt].wsize = 1;
00344 sig[sigcnt].wsize_mod = MOD_CONST;
00345 }
00346 else if (tolower(w[0]) == 's')
00347 {
00348 sig[sigcnt].wsize_mod = MOD_MSS;
00349 if (!isdigit(*(w+1)))
00350 Error("OS fingerprinting: Bad Snn value in WSS in line",(uint32)ln);
00351 sig[sigcnt].wsize = atoi(w+1);
00352 }
00353 else if (tolower(w[0]) == 't')
00354 {
00355 sig[sigcnt].wsize_mod = MOD_MTU;
00356 if (!isdigit(*(w+1)))
00357 Error("OS fingerprinting: Bad Tnn value in WSS in line",(uint32)ln);
00358 sig[sigcnt].wsize = atoi(w+1);
00359 }
00360 else if (w[0] == '%')
00361 {
00362 if (!(sig[sigcnt].wsize = atoi(w+1)))
00363 Error("OS fingerprinting: Null modulo for window size in config line",(uint32)ln);
00364 sig[sigcnt].wsize_mod = MOD_CONST;
00365 }
00366 else
00367 sig[sigcnt].wsize = atoi(w);
00368
00369
00370
00371 p=obuf;
00372
00373 sig[sigcnt].zero_stamp = 1;
00374
00375 if (*p=='.') p++;
00376
00377 while (*p)
00378 {
00379 uint8 optcnt = sig[sigcnt].optcnt;
00380 switch (tolower(*p))
00381 {
00382 case 'n': sig[sigcnt].opt[optcnt] = TCPOPT_NOP;
00383 break;
00384
00385 case 'e': sig[sigcnt].opt[optcnt] = TCPOPT_EOL;
00386 if (*(p+1))
00387 Error("OS fingerprinting: EOL not the last option, line",(uint32)ln);
00388 break;
00389
00390 case 's': sig[sigcnt].opt[optcnt] = TCPOPT_SACK_PERMITTED;
00391 break;
00392
00393 case 't': sig[sigcnt].opt[optcnt] = TCPOPT_TIMESTAMP;
00394 if (*(p+1)!='0')
00395 {
00396 sig[sigcnt].zero_stamp=0;
00397 if (isdigit(*(p+1)))
00398 Error("OS fingerprinting: Bogus Tstamp specification in line",(uint32)ln);
00399 }
00400 break;
00401
00402 case 'w': sig[sigcnt].opt[optcnt] = TCPOPT_WINDOW;
00403 if (p[1] == '*')
00404 {
00405 sig[sigcnt].wsc = 1;
00406 sig[sigcnt].wsc_mod = MOD_CONST;
00407 }
00408 else if (p[1] == '%')
00409 {
00410 if (!(sig[sigcnt].wsc = atoi(p+2)))
00411 Error("OS fingerprinting: Null modulo for wscale in config line",(uint32)ln);
00412 sig[sigcnt].wsc_mod = MOD_CONST;
00413 }
00414 else if (!isdigit(*(p+1)))
00415 Error("OS fingerprinting: Incorrect W value in line",(uint32)ln);
00416 else sig[sigcnt].wsc = atoi(p+1);
00417 break;
00418
00419 case 'm': sig[sigcnt].opt[optcnt] = TCPOPT_MAXSEG;
00420 if (p[1] == '*')
00421 {
00422 sig[sigcnt].mss = 1;
00423 sig[sigcnt].mss_mod = MOD_CONST;
00424 }
00425 else if (p[1] == '%')
00426 {
00427 if (!(sig[sigcnt].mss = atoi(p+2)))
00428 Error("OS fingerprinting: Null modulo for MSS in config line",(uint32)ln);
00429 sig[sigcnt].mss_mod = MOD_CONST;
00430 }
00431 else if (!isdigit(*(p+1)))
00432 Error("OS fingerprinting: Incorrect M value in line",(uint32)ln);
00433 else sig[sigcnt].mss = atoi(p+1);
00434 break;
00435
00436
00437 case '?': if (!isdigit(*(p+1)))
00438 Error("OS fingerprinting: Bogus ?nn value in line",(uint32)ln);
00439 else sig[sigcnt].opt[optcnt] = atoi(p+1);
00440 break;
00441
00442 default: Error("OS fingerprinting: Unknown TCP option in config line",(uint32)ln);
00443 }
00444
00445 if (++sig[sigcnt].optcnt >= MAXOPT)
00446 Error("OS fingerprinting: Too many TCP options specified in config line",(uint32)ln);
00447
00448
00449 do { p++; } while (*p && !isalpha(*p) && *p != '?');
00450
00451 }
00452
00453 sig[sigcnt].line = ln;
00454
00455 p = quirks;
00456
00457 while (*p)
00458 switch (toupper(*(p++)))
00459 {
00460 case 'E':
00461 Error("OS fingerprinting: Quirk 'E' is obsolete. Remove it, append E to the options. Line",(uint32)ln);
00462
00463 case 'K':
00464 if ( mode != RST_FINGERPRINT_MODE )
00465 Error("OS fingerprinting: Quirk 'K' is valid only in RST+ (-R) mode (wrong config file?). Line",(uint32)ln);
00466 sig[sigcnt].quirks |= QUIRK_RSTACK;
00467 break;
00468
00469 case 'Q': sig[sigcnt].quirks |= QUIRK_SEQEQ; break;
00470 case '0': sig[sigcnt].quirks |= QUIRK_SEQ0; break;
00471 case 'P': sig[sigcnt].quirks |= QUIRK_PAST; break;
00472 case 'Z': sig[sigcnt].quirks |= QUIRK_ZEROID; break;
00473 case 'I': sig[sigcnt].quirks |= QUIRK_IPOPT; break;
00474 case 'U': sig[sigcnt].quirks |= QUIRK_URG; break;
00475 case 'X': sig[sigcnt].quirks |= QUIRK_X2; break;
00476 case 'A': sig[sigcnt].quirks |= QUIRK_ACK; break;
00477 case 'T': sig[sigcnt].quirks |= QUIRK_T2; break;
00478 case 'F': sig[sigcnt].quirks |= QUIRK_FLAGS; break;
00479 case 'D': sig[sigcnt].quirks |= QUIRK_DATA; break;
00480 case '!': sig[sigcnt].quirks |= QUIRK_BROKEN; break;
00481 case '.': break;
00482 default: Error("OS fingerprinting: Bad quirk in line",(uint32)ln);
00483 }
00484
00485 e = bh[SIGHASH(s,sig[sigcnt].optcnt,sig[sigcnt].quirks,d)];
00486
00487 if (!e)
00488 {
00489 bh[SIGHASH(s,sig[sigcnt].optcnt,sig[sigcnt].quirks,d)] = &sig[sigcnt];
00490 }
00491 else
00492 {
00493 while (e->next) e = e->next;
00494 e->next = &sig[sigcnt];
00495 }
00496
00497 collide(sigcnt);
00498 if (++sigcnt >= MAXSIGS)
00499 Error("OS fingerprinting: Maximum signature count exceeded.\n");
00500
00501 }
00502
00503 fclose(c);
00504
00505 if (!sigcnt)
00506 Error("OS fingerprinting: no signatures loaded from config file.");
00507
00508 }
00509
00510
00511
00512
00513 int OSFingerprint::FindMatch(struct os_type* retval, uint16 tot,uint8 df,
00514 uint8 ttl,uint16 wss,uint8 ocnt,uint8* op,
00515 uint16 mss,uint8 wsc,uint32 tstamp,
00516 uint32 quirks,uint8 ecn) const
00517 {
00518 uint32 j;
00519 struct fp_entry* p;
00520 uint8 orig_df = df;
00521
00522 struct fp_entry* fuzzy = 0;
00523 uint8 fuzzy_now = 0;
00524 int id = 0;
00525
00526 retval->os="UNKNOWN";
00527 retval->desc=NULL;
00528 retval->gadgets=0;
00529 retval->match=0;
00530 retval->uptime=0;
00531
00532 re_lookup:
00533
00534 p = bh[SIGHASH(tot,ocnt,quirks,df)];
00535
00536 while (p)
00537 {
00538
00539
00540 if (p->size) { if (tot ^ p->size) { p = p->next; continue; } }
00541 else if (tot < PACKET_BIG) { p = p->next; continue; }
00542
00543 if (ocnt ^ p->optcnt) { p = p->next; continue; }
00544
00545 if (p->zero_stamp ^ (!tstamp)) { p = p->next; continue; }
00546 if (p->df ^ df) { p = p->next; continue; }
00547 if (p->quirks ^ quirks) { p = p->next; continue; }
00548
00549
00550 if (!p->mss_mod) {
00551 if (mss ^ p->mss) { p = p->next; continue; }
00552 } else if (mss % p->mss) { p = p->next; continue; }
00553
00554 if (!p->wsc_mod) {
00555 if (wsc ^ p->wsc) { p = p->next; continue; }
00556 } else if (wsc % p->wsc) { p = p->next; continue; }
00557
00558
00559 switch (p->wsize_mod)
00560 {
00561 case 0:
00562 if (wss ^ p->wsize) { p = p->next; continue; }
00563 break;
00564 case MOD_CONST:
00565 if (wss % p->wsize) { p = p->next; continue; }
00566 break;
00567 case MOD_MSS:
00568 if (mss && !(wss % mss))
00569 {
00570 if ((wss / mss) ^ p->wsize) { p = p->next; continue; }
00571 }
00572 else if (!(wss % 1460))
00573 {
00574 if ((wss / 1460) ^ p->wsize) { p = p->next; continue; }
00575 }
00576 else { p = p->next; continue; }
00577 break;
00578 case MOD_MTU:
00579 if (mss && !(wss % (mss+40)))
00580 {
00581 if ((wss / (mss+40)) ^ p->wsize) { p = p->next; continue; }
00582 }
00583 else if (!(wss % 1500))
00584 {
00585 if ((wss / 1500) ^ p->wsize) { p = p->next; continue; }
00586 }
00587 else { p = p->next; continue; }
00588 break;
00589 }
00590
00591
00592 for (j=0;j<ocnt;j++)
00593 if (p->opt[j] ^ op[j]) goto continue_search;
00594
00595
00596 if (p->ttl < ttl)
00597 {
00598 if ( mode != RST_FINGERPRINT_MODE )fuzzy = p;
00599 p = p->next;
00600 continue;
00601 }
00602
00603
00604 if (!p->no_detail)
00605 if (p->ttl - ttl > MAXDIST)
00606 {
00607 if (mode != RST_FINGERPRINT_MODE ) fuzzy = p;
00608 p = p->next;
00609 continue;
00610 }
00611
00612 continue_fuzzy:
00613
00614
00615 id = p->line;
00616 if (mss & wss)
00617 {
00618 if (p->wsize_mod == MOD_MSS)
00619 {
00620 if ((wss % mss) && !(wss % 1460)) retval->gadgets|=GADGETNAT;
00621 }
00622 else if (p->wsize_mod == MOD_MTU)
00623 {
00624 if ((wss % (mss+40)) && !(wss % 1500)) retval->gadgets|=GADGETNAT2;
00625 }
00626 }
00627
00628 retval->os=p->os;
00629 retval->desc=p->desc;
00630 retval->dist=p->ttl-ttl;
00631
00632 if (ecn) retval->gadgets|=GADGETECN;
00633 if (orig_df ^ df) retval->gadgets|=GADGETFIREWALL;
00634
00635 if (p->generic) retval->match=MATCHGENERIC;
00636 if (fuzzy_now) retval->match=MATCHFUZZY;
00637
00638 if (!p->no_detail && tstamp)
00639 {
00640 retval->uptime=tstamp/360000;
00641 retval->gadgets|=GADGETUPTIME;
00642 }
00643
00644 return id;
00645
00646 continue_search:
00647
00648 p = p->next;
00649
00650 }
00651
00652 if (!df) { df = 1; goto re_lookup; }
00653
00654 if (fuzzy)
00655 {
00656 df = orig_df;
00657 fuzzy_now = 1;
00658 p = fuzzy;
00659 fuzzy = 0;
00660 goto continue_fuzzy;
00661 }
00662
00663 if (mss & wss)
00664 {
00665 if ((wss % mss) && !(wss % 1460)) retval->gadgets|=GADGETNAT;
00666 else if ((wss % (mss+40)) && !(wss % 1500)) retval->gadgets|=GADGETNAT2;
00667 }
00668
00669 if (ecn) retval->gadgets|=GADGETECN;
00670
00671 if (tstamp)
00672 {
00673 retval->uptime=tstamp/360000;
00674 retval->gadgets|=GADGETUPTIME;
00675 }
00676
00677 return id;
00678 }