00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023
00024 #include "BackDoor.h"
00025 #include "Event.h"
00026 #include "Net.h"
00027 #include "TCP.h"
00028
00029 BackDoorEndpoint::BackDoorEndpoint(TCP_Endpoint* e)
00030 : TCP_EndpointAnalyzer(e)
00031 {
00032 is_partial = 0;
00033 max_top_seq = 0;
00034
00035 rlogin_checking_done = 0;
00036 rlogin_string_separator_pos = 0;
00037 rlogin_num_null = 0;
00038 rlogin_slash_seen = 0;
00039
00040 num_pkts = num_8k0_pkts = num_8k4_pkts =
00041 num_lines = num_normal_lines = num_bytes = num_7bit_ascii = 0;
00042 }
00043
00044 #define NORMAL_LINE_LENGTH 80
00045
00046 #define TELNET_IAC 255
00047 #define IS_TELNET_NEGOTIATION_CMD(c) ((c) >= 251 && (c) <= 254)
00048
00049 #define DEFAULT_MTU 512
00050
00051 #define RLOGIN_MAX_SIGNATURE_LENGTH 256
00052
00053 void BackDoorEndpoint::FinalCheckForRlogin()
00054 {
00055 if ( ! rlogin_checking_done )
00056 {
00057 rlogin_checking_done = 1;
00058
00059 if ( rlogin_num_null > 0 )
00060 RloginSignatureFound(0);
00061 }
00062 }
00063
00064 int BackDoorEndpoint::DataSent(double , int seq,
00065 int len, int caplen, const u_char* data,
00066 const IP_Hdr* ,
00067 const struct tcphdr* )
00068 {
00069 if ( caplen < len )
00070 len = caplen;
00071
00072 if ( len <= 0 )
00073 return 0;
00074
00075 if ( Endpoint()->state == TCP_PARTIAL )
00076 is_partial = 1;
00077
00078 int ack = Endpoint()->AckSeq() - Endpoint()->StartSeq();
00079 int top_seq = seq + len;
00080
00081 if ( top_seq <= ack || top_seq <= max_top_seq )
00082
00083 return 0;
00084
00085 if ( rlogin_signature_found )
00086 CheckForRlogin(seq, len, data);
00087
00088 if ( telnet_signature_found )
00089 CheckForTelnet(seq, len, data);
00090
00091 if ( ssh_signature_found )
00092 CheckForSSH(seq, len, data);
00093
00094 if ( ftp_signature_found )
00095 CheckForFTP(seq, len, data);
00096
00097 if ( root_backdoor_signature_found )
00098 CheckForRootBackdoor(seq, len, data);
00099
00100 if ( napster_signature_found )
00101 CheckForNapster(seq, len, data);
00102
00103 if ( gnutella_signature_found )
00104 CheckForGnutella(seq, len, data);
00105
00106 if ( kazaa_signature_found )
00107 CheckForKazaa(seq, len, data);
00108
00109 if ( http_signature_found || http_proxy_signature_found )
00110 CheckForHTTP(seq, len, data);
00111
00112 if ( smtp_signature_found )
00113 CheckForSMTP(seq, len, data);
00114
00115 if ( irc_signature_found )
00116 CheckForIRC(seq, len, data);
00117
00118 if ( gaobot_signature_found )
00119 CheckForGaoBot(seq, len, data);
00120
00121 max_top_seq = top_seq;
00122
00123 return 1;
00124 }
00125
00126 RecordVal* BackDoorEndpoint::BuildStats()
00127 {
00128 RecordVal* stats = new RecordVal(backdoor_endp_stats);
00129
00130 stats->Assign(0, new Val(is_partial, TYPE_BOOL));
00131 stats->Assign(1, new Val(num_pkts, TYPE_COUNT));
00132 stats->Assign(2, new Val(num_8k0_pkts, TYPE_COUNT));
00133 stats->Assign(3, new Val(num_8k4_pkts, TYPE_COUNT));
00134 stats->Assign(4, new Val(num_lines, TYPE_COUNT));
00135 stats->Assign(5, new Val(num_normal_lines, TYPE_COUNT));
00136 stats->Assign(6, new Val(num_bytes, TYPE_COUNT));
00137 stats->Assign(7, new Val(num_7bit_ascii, TYPE_COUNT));
00138
00139 return stats;
00140 }
00141
00142 void BackDoorEndpoint::CheckForRlogin(int seq, int len, const u_char* data)
00143 {
00144 if ( rlogin_checking_done )
00145 return;
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 if ( seq == 1 )
00160 {
00161 if ( data[0] == 0 )
00162 {
00163 rlogin_num_null = 1;
00164
00165 if ( ! Endpoint()->IsOrig() )
00166 {
00167 RloginSignatureFound(len);
00168 return;
00169 }
00170
00171 rlogin_string_separator_pos = 1;
00172
00173 ++seq;
00174 ++data;
00175 --len;
00176 }
00177 else
00178 {
00179 rlogin_checking_done = 1;
00180 return;
00181 }
00182 }
00183
00184 if ( seq > max_top_seq && max_top_seq != 0 )
00185 {
00186 RloginSignatureFound(0);
00187 return;
00188 }
00189
00190 if ( seq + len <= max_top_seq )
00191 return;
00192
00193 if ( seq < max_top_seq )
00194 {
00195 int delta = max_top_seq - seq;
00196 seq += delta;
00197 data += delta;
00198 len -= delta;
00199 }
00200
00201
00202 for ( int i = 0; i < len && rlogin_num_null < 4; ++i )
00203 {
00204 if ( data[i] == 0 )
00205 {
00206 if ( i + seq == rlogin_string_separator_pos + 1 )
00207 {
00208 rlogin_checking_done = 1;
00209 return;
00210 }
00211 else
00212 {
00213 rlogin_string_separator_pos = i + seq;
00214 ++rlogin_num_null;
00215 }
00216 }
00217
00218 else if ( data[i] == '/' )
00219 {
00220 if ( rlogin_num_null == 3 )
00221 {
00222 if ( i + seq == rlogin_string_separator_pos + 1 )
00223 {
00224 rlogin_checking_done = 1;
00225 return;
00226 }
00227
00228 rlogin_string_separator_pos = i + seq;
00229 rlogin_slash_seen = 1;
00230 }
00231 }
00232
00233 else if ( data[i] >= 128 )
00234 {
00235 rlogin_checking_done = 1;
00236 return;
00237 }
00238 }
00239
00240 if ( rlogin_num_null == 4 )
00241 {
00242 if ( rlogin_slash_seen )
00243 RloginSignatureFound(0);
00244 else
00245 rlogin_checking_done = 1;
00246
00247 return;
00248 }
00249
00250 if ( seq + len > RLOGIN_MAX_SIGNATURE_LENGTH )
00251 {
00252 RloginSignatureFound(0);
00253 return;
00254 }
00255 }
00256
00257 void BackDoorEndpoint::RloginSignatureFound(int len)
00258 {
00259 if ( rlogin_checking_done )
00260 return;
00261
00262 rlogin_checking_done = 1;
00263
00264 val_list* vl = new val_list;
00265 vl->append(Conn()->BuildConnVal());
00266 vl->append(new Val(Endpoint()->IsOrig(), TYPE_BOOL));
00267 vl->append(new Val(rlogin_num_null, TYPE_COUNT));
00268 vl->append(new Val(len, TYPE_COUNT));
00269
00270 Conn()->ConnectionEvent(rlogin_signature_found, vl);
00271 }
00272
00273 void BackDoorEndpoint::CheckForTelnet(int , int len, const u_char* data)
00274 {
00275 if ( len >= 3 &&
00276 data[0] == TELNET_IAC && IS_TELNET_NEGOTIATION_CMD(data[1]) )
00277 {
00278 TelnetSignatureFound(len);
00279 return;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289 num_bytes += len;
00290
00291 int last_char = 0;
00292 int offset = 0;
00293 int option_length = 0;
00294
00295 for ( int i = 0; i < len; ++i )
00296 {
00297 unsigned int c = data[i];
00298
00299 if ( c == '\n' && last_char == '\r' )
00300 {
00301
00302 last_char = c;
00303 continue;
00304 }
00305
00306 if ( c == '\n' || c == '\r' )
00307 {
00308 ++num_lines;
00309
00310 if ( i - offset - option_length <= NORMAL_LINE_LENGTH )
00311 ++num_normal_lines;
00312
00313 option_length = 0;
00314 offset = i;
00315 }
00316
00317 else if ( c == TELNET_IAC )
00318 {
00319 ++option_length;
00320 --num_bytes;
00321
00322 if ( ++i < len )
00323 {
00324 unsigned int code = data[i];
00325 if ( code == TELNET_IAC )
00326
00327 last_char = code;
00328
00329 else if ( code >= 251 && code <= 254 )
00330 {
00331 ++i;
00332 option_length += 2;
00333 num_bytes -= 2;
00334 }
00335
00336 else
00337
00338
00339 {
00340 ++option_length;
00341 --num_bytes;
00342 }
00343 }
00344 continue;
00345 }
00346
00347 else if ( c != 0 && c < 128 )
00348 ++num_7bit_ascii;
00349
00350 last_char = c;
00351 }
00352 }
00353
00354 void BackDoorEndpoint::TelnetSignatureFound(int len)
00355 {
00356 val_list* vl = new val_list;
00357 vl->append(Conn()->BuildConnVal());
00358 vl->append(new Val(Endpoint()->IsOrig(), TYPE_BOOL));
00359 vl->append(new Val(len, TYPE_COUNT));
00360
00361 Conn()->ConnectionEvent(telnet_signature_found, vl);
00362 }
00363
00364 void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data)
00365 {
00366 if ( seq == 1 && CheckForString("SSH-", data, len) && len > 4 &&
00367 (data[4] == '1' || data[4] == '2') )
00368 {
00369 SignatureFound(ssh_signature_found, 1);
00370 return;
00371 }
00372
00373
00374
00375 if ( seq < max_top_seq || max_top_seq == 0 )
00376
00377 return;
00378
00379 if ( seq > max_top_seq )
00380 {
00381 int gap = seq - max_top_seq;
00382 num_pkts += int((gap + DEFAULT_MTU - 1) / DEFAULT_MTU);
00383 }
00384
00385 ++num_pkts;
00386
00387
00388
00389
00390 if ( len <= 127 )
00391 switch ( len & 7 ) {
00392 case 0:
00393 if ( len >= 16 )
00394 ++num_8k0_pkts;
00395 break;
00396
00397 case 4:
00398 ++num_8k4_pkts;
00399 break;
00400 }
00401 else
00402 {
00403 }
00404 }
00405
00406 void BackDoorEndpoint::CheckForRootBackdoor(int seq, int len, const u_char* data)
00407 {
00408
00409
00410 if ( seq == 1 && len == 2 && ! Endpoint()->IsOrig() &&
00411 data[0] == '#' && data[1] == ' ' )
00412 SignatureFound(root_backdoor_signature_found);
00413 }
00414
00415 void BackDoorEndpoint::CheckForFTP(int seq, int len, const u_char* data)
00416 {
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 if ( seq != 1 || Endpoint()->IsOrig() || len < 4 )
00436 return;
00437
00438 if ( CheckForString("220", data, len) &&
00439 (data[3] == ' ' || data[3] == '-') )
00440 SignatureFound(ftp_signature_found);
00441
00442 else if ( CheckForString("421", data, len) &&
00443 (data[3] == '-' || data[3] == ' ') )
00444 SignatureFound(ftp_signature_found);
00445 }
00446
00447 void BackDoorEndpoint::CheckForNapster(int seq, int len, const u_char* data)
00448 {
00449
00450
00451
00452
00453
00454
00455 if ( seq != 1 || ! Endpoint()->IsOrig() )
00456 return;
00457
00458 if ( len == 3 && CheckForString("GET", data, len) )
00459
00460 SignatureFound(napster_signature_found);
00461
00462 else if ( len == 4 && CheckForString("SEND", data, len) )
00463
00464 SignatureFound(napster_signature_found);
00465 }
00466
00467 void BackDoorEndpoint::CheckForSMTP(int seq, int len, const u_char* data)
00468 {
00469 const char* smtp_handshake[] = { "HELO", "EHLO", 0 };
00470
00471 if ( seq != 1 )
00472 return;
00473
00474 if ( CheckForStrings(smtp_handshake, data, len) )
00475 SignatureFound(smtp_signature_found);
00476 }
00477
00478 void BackDoorEndpoint::CheckForIRC(int seq, int len, const u_char* data)
00479 {
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 const char* irc_indicator[] = {
00491 "WHO", "PING", "PONG", "NODE", "IRCX", "NICK", 0
00492 };
00493
00494 if ( num_pkts > 15 || len < 5 )
00495 return;
00496
00497 if ( CheckForStrings(irc_indicator, data, len) )
00498 SignatureFound(irc_signature_found);
00499 }
00500
00501 void BackDoorEndpoint::CheckForGnutella(int seq, int len, const u_char* data)
00502 {
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 if ( seq == 1 && CheckForString("GNUTELLA ", data, len) )
00515 SignatureFound(gnutella_signature_found);
00516 }
00517
00518 void BackDoorEndpoint::CheckForGaoBot(int seq, int len, const u_char* data)
00519 {
00520 if ( seq == 1 && CheckForString("220 Bot Server (Win32)", data, len) )
00521 SignatureFound(gaobot_signature_found);
00522 }
00523
00524 void BackDoorEndpoint::CheckForKazaa(int seq, int len, const u_char* data)
00525 {
00526
00527
00528
00529
00530 if ( seq == 1 && CheckForString("GIVE ", data, len) )
00531 SignatureFound(kazaa_signature_found);
00532 }
00533
00534
00535 int is_http_whitespace(const u_char ch)
00536 {
00537 return ! isprint(ch) || isspace(ch);
00538 }
00539
00540 int skip_http_whitespace(const u_char* data, int len, int max)
00541 {
00542 int k;
00543 for ( k = 0; k < len; ++k )
00544 {
00545 if ( ! is_http_whitespace(data[k]) )
00546 break;
00547
00548
00549
00550
00551
00552 if ( data[k] == '\015' || k == max )
00553 return -1;
00554 }
00555
00556 return k < len ? k : -1;
00557 }
00558
00559 int is_absolute_url(const u_char* data, int len)
00560 {
00561
00562 const char* abs_url_sig = "://";
00563 const char* abs_url_sig_pos = abs_url_sig;
00564
00565
00566
00567
00568 for ( int pos = 0; pos < len; ++pos )
00569 {
00570 if ( *abs_url_sig_pos == '\0' )
00571 return 1;
00572
00573 if ( data[pos] == *abs_url_sig_pos )
00574 ++abs_url_sig_pos;
00575
00576 else
00577 {
00578 if ( is_http_whitespace(data[pos]) )
00579 return 0;
00580
00581 abs_url_sig_pos = abs_url_sig;
00582 if ( *abs_url_sig != '\0' &&
00583 *abs_url_sig_pos == data[pos] )
00584 ++abs_url_sig_pos;
00585 }
00586 }
00587
00588 return *abs_url_sig_pos == '\0';
00589 }
00590
00591 void BackDoorEndpoint::CheckForHTTP(int seq, int len, const u_char* data)
00592 {
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 const char* http_method[] = { "GET", "HEAD", "POST", 0 };
00609
00610 if ( seq != 1 )
00611 return;
00612
00613
00614 int pos = skip_http_whitespace (data, len, 0);
00615 if ( pos < 0 )
00616 return;
00617
00618 int method;
00619 for ( method = 0; http_method[method]; ++method )
00620 {
00621 const char* s = http_method[method];
00622 int i;
00623 for ( i = pos; i < len; ++i, ++s )
00624 if ( data[i] != *s )
00625 break;
00626
00627 if ( *s == '\0' )
00628 {
00629 pos = i;
00630 break;
00631 }
00632 }
00633
00634 if ( ! http_method[method] )
00635 return;
00636
00637 if ( pos >= len || ! is_http_whitespace(data[pos]) )
00638 return;
00639
00640 if ( http_signature_found )
00641 SignatureFound(http_signature_found);
00642
00643 if ( http_proxy_signature_found )
00644 {
00645 const u_char* rest = data + pos;
00646 int rest_len = len - pos;
00647
00648 pos = skip_http_whitespace(rest, rest_len, rest_len);
00649
00650 if ( pos >= 0 )
00651 CheckForHTTPProxy(seq, rest_len - pos, rest + pos);
00652 }
00653 }
00654
00655 void BackDoorEndpoint::CheckForHTTPProxy(int , int len,
00656 const u_char* data)
00657 {
00658
00659
00660
00661 if ( is_absolute_url(data, len) )
00662 SignatureFound(http_proxy_signature_found);
00663 }
00664
00665
00666 void BackDoorEndpoint::SignatureFound(EventHandlerPtr e, int do_orig)
00667 {
00668 val_list* vl = new val_list;
00669 vl->append(Conn()->BuildConnVal());
00670
00671 if ( do_orig )
00672 vl->append(new Val(Endpoint()->IsOrig(), TYPE_BOOL));
00673
00674 Conn()->ConnectionEvent(e, vl);
00675 }
00676
00677
00678 int BackDoorEndpoint::CheckForStrings(const char** strs,
00679 const u_char* data, int len)
00680 {
00681 for ( ; *strs; ++strs )
00682 if ( CheckForString(*strs, data, len) )
00683 return 1;
00684
00685 return 0;
00686 }
00687
00688 int BackDoorEndpoint::CheckForString(const char* str,
00689 const u_char* data, int len)
00690 {
00691 for ( ; len > 0 && *str; --len, ++data, ++str )
00692 if ( *str != *data )
00693 return 0;
00694
00695 return *str == 0;
00696 }
00697
00698
00699 BackDoorAnalyzer::BackDoorAnalyzer(TCP_Connection* c)
00700 : TCP_Analyzer(c)
00701 {
00702 orig_endp = new BackDoorEndpoint(conn->Orig());
00703 resp_endp = new BackDoorEndpoint(conn->Resp());
00704
00705 timeout = backdoor_stat_period;
00706 backoff = backdoor_stat_backoff;
00707
00708 timer_mgr->Add(new BackDoorTimer(network_time + timeout, this));
00709 }
00710
00711 BackDoorAnalyzer::~BackDoorAnalyzer()
00712 {
00713 Done();
00714
00715 Unref(orig_endp);
00716 Unref(resp_endp);
00717 }
00718
00719 void BackDoorAnalyzer::Done()
00720 {
00721 if ( ! done )
00722 {
00723 orig_endp->FinalCheckForRlogin();
00724 resp_endp->FinalCheckForRlogin();
00725
00726 if ( ! Conn()->Skipping() )
00727 StatEvent();
00728
00729 RemoveEvent();
00730 done = 1;
00731 }
00732 }
00733
00734 void BackDoorAnalyzer::StatTimer(double t, int is_expire)
00735 {
00736 if ( done || Conn()->Skipping() )
00737 return;
00738
00739 StatEvent();
00740
00741 if ( ! is_expire )
00742 {
00743 timeout *= backoff;
00744 timer_mgr->Add(new BackDoorTimer(t + timeout, this));
00745 }
00746 }
00747
00748 void BackDoorAnalyzer::StatEvent()
00749 {
00750 val_list* vl = new val_list;
00751 vl->append(Conn()->BuildConnVal());
00752 vl->append(orig_endp->BuildStats());
00753 vl->append(resp_endp->BuildStats());
00754
00755 Conn()->ConnectionEvent(backdoor_stats, vl);
00756 }
00757
00758 void BackDoorAnalyzer::RemoveEvent()
00759 {
00760 val_list* vl = new val_list;
00761 vl->append(Conn()->BuildConnVal());
00762
00763 Conn()->ConnectionEvent(backdoor_remove_conn, vl);
00764 }
00765
00766 BackDoorTimer::BackDoorTimer(double t, BackDoorAnalyzer* a)
00767 : Timer(t, TIMER_BACKDOOR)
00768 {
00769 analyzer = a;
00770 Ref(a);
00771 }
00772
00773 BackDoorTimer::~BackDoorTimer()
00774 {
00775 Unref(analyzer);
00776 }
00777
00778 void BackDoorTimer::Dispatch(double t, int is_expire)
00779 {
00780 analyzer->StatTimer(t, is_expire);
00781 }