📄 spp_anomsensor.c
字号:
int adapt3_target;// an array of past observationsdouble *adapt3hist;// a linked list of current anomaly scoresll_double *adapt3anoms;// (0-based) size of this listsint adapt3anoms_size;// number of completed observation periodint completed_obs_per;/* Spade Adapt3 module init function: set up the Adapt3 module per its args and register its preprocessor function */void SpadeAdapt3Init(u_char *args){ if (adapting) { fprintf(stderr,"Anomoly sensor threshold adapting repeadly specified, ignoring later specification: %s\n",args); return; } adapting= 1; pp_active++; need_anom= 1; /* parse the argument list from the rules file */ ParseSpadeAdapt3Args(args); /* Set the preprocessor function into the function list */ AddFuncToPreprocList(PreprocSpadeAdapt3); adapt3hist= (double *)malloc(sizeof(double)*NO); /* init list to contain 0 and 0; this is to let us assume the list has a bottom and runner-up elsewhere */ adapt3anoms= (ll_double *)malloc(sizeof(ll_double)); adapt3anoms->val= 0.0; adapt3anoms->next= (ll_double *)malloc(sizeof(ll_double)); adapt3anoms->next->val= 0.0; adapt3anoms->next->next= NULL; adapt3anoms_size= 1; completed_obs_per= 0; if (as_debug) printf("Preprocessor: SpadeAdapt3 Initialized\n");}/* Spade 'spade-Adapt3' argument parsing function */void ParseSpadeAdapt3Args(char *args){ char **toks; int numToks; toks = mSplit(args, " ", 20, &numToks, '\\'); if (numToks > 0) { adapt3_targetspec= atof(toks[0]); /* if >= 1, is an hourly count, else is a fraction of total packets */ } else { adapt3_targetspec= 0.01; } if (numToks > 1) { adapt3_obsper= atof(toks[1])*60.0; /* basic observation/adjust time in mins, converted to secs */ } else { adapt3_obsper= 15.0*60.0; } /* 10000 packets per hour is our pure guess as to the rate of packets. Is there a better way to figure out how many packets to note for our first interval when we want a percent of packets? */ adapt3_target= (int)floor(0.5+ (adapt3_targetspec >= 1 ? adapt3_targetspec*(adapt3_obsper/3600.0) : ((10000/3600.0)*adapt3_obsper)*adapt3_targetspec)); if (adapt3_target==0) adapt3_target= 1; if (numToks > 2) { NO= atoi(toks[2]); /* how many of the previous go into the time observation of ideal wait and the recent portion of the adapted weight */ } else { NO= 168; } if (as_debug) printf("Adapt3 target is %d\n",adapt3_target); if (as_debug) printf("%2f seconds in obs per; %d of these in history\n",adapt3_obsper,NO);}/* Spade Adapt3 module routine that is called with each packet */void PreprocSpadeAdapt3(Packet *p){ size_t packet_time= p->pkth->ts.tv_sec; ll_double *prev,*newstart,*next,*new; int i; // the start time of the current observation period static time_t adapt3_obsper_start=(time_t)0; // the number of packets thus far in this observation static int obscount=0; // the last calculated average packet count per interval; used to figure out when to adjust the threshold; set high initially to be sure to get a correct value before doing this static double ppi= 100000000.0; /* see if time to adjust the rate and if so, do so, and reset */ if (packet_time > (adapt3_obsper_start + adapt3_obsper)) { static int rec_int_count; if (adapt3_obsper_start == 0) { /* first packet */ adapt3_obsper_start= packet_time; rec_int_count= 0; recent_alert_count= 0; } else { /* time to update ppi */ rec_int_count++; ppi= tot_packets/(double)rec_int_count; adapt3_obsper_start+= (long)adapt3_obsper; if (as_debug) printf("End of time period %d: ppi is now %.2f\n",rec_int_count,ppi); adapt3_target= (int)floor(0.5+ (adapt3_targetspec >= 1 ? adapt3_targetspec*(adapt3_obsper/3600.0) : adapt3_targetspec*ppi)); if (adapt3_target==0) adapt3_target= 1; if (as_debug) printf("new target is %d\n",adapt3_target); if (completed_obs_per == 0) { if (adapt3anoms_size > adapt3_target) { /* remove excess */ for (i= adapt3_target, prev=adapt3anoms; (i+1) < adapt3anoms_size; i++,prev=prev->next); newstart= prev->next; prev->next= NULL; free_links(adapt3anoms); adapt3anoms= newstart; } do_adapt3(); obscount= 0; } } } if (record_maybe_skip(p)) return; /* accepted packets only past here; anom score is last_anom_score */ obscount++; if (obscount > ppi) { if (as_debug) { printf("%d alerts at end of packet period #%d (of %d)\n",recent_alert_count,completed_obs_per+1,recent_packets); } do_adapt3(); obscount= 0; } /* add anomaly score to list if it is high enough */ if (adapt3anoms_size <= adapt3_target) { new= new_link(last_anom_score); adapt3anoms_size++; } else if (last_anom_score > adapt3anoms->val) { if (last_anom_score < adapt3anoms->next->val) { adapt3anoms->val= last_anom_score; /* can just replace first */ return; } new= adapt3anoms; new->val= last_anom_score; adapt3anoms= adapt3anoms->next; } else { return; } for (prev= adapt3anoms, next=adapt3anoms->next; next != NULL && last_anom_score > next->val; prev=next,next=next->next); /* add between prev and next */ prev->next= new; new->next= next;}void do_adapt3() { ll_double *l; static double obssum= 0; // the sum of all current elements in the array double obs_thresh= (adapt3anoms->val + adapt3anoms->next->val)/2; int slot; if (as_debug) printf("observed recent ideal threshold for adapt3 is %.4f\n",obs_thresh); slot= completed_obs_per % NO; completed_obs_per++; if (completed_obs_per > NO) obssum-= adapt3hist[slot]; /* kicking a score out */ adapt3hist[slot]= obs_thresh; obssum+= obs_thresh; if (as_debug > 1) { int i; printf("adapt3hist= ["); printf("%.4f",adapt3hist[0]); for (i= 1; i < NO && i < completed_obs_per; i++) { printf(",%.4f",adapt3hist[i]); } printf("]\n"); } set_new_threshold(obssum/((completed_obs_per >= NO)?NO:completed_obs_per)); if (as_debug) printf("new threshold is %.4f\n",report_anom_thres); for (l=adapt3anoms; l != NULL; l=l->next) l->val= 0.0; recent_alert_count= 0; recent_packets= 0;}/*========================================================================*//*========================== SpadeSurvey module ==========================*//*========================================================================*//* This module surveys the anomoly scores observed across periods of timeand reports this to a specified survey file. The period #, the packetcount, the median score, the 90th percentile score, and the 99th percentilescore are recorded to the file in tab-delinated format. Interpolation isused between scores if there is no score at exactly the position implied bythe percentile. *//* efficiency note: This use linked list to represent the observed anomoly scores. While it is necessary to maintain all these scores (the current worst score might end up being the 99th percentile), a different representation (order stat tree?) should be used if the packet count gets high. *//* snort config file line: preprocessor spade-survey: [ <survey-file> [ <observation-period> ]] where: <survey-file> the file to write the survery results to (default is stdout) <observation-period> the interval for the survey in minutes (default 60)*//* global-scope variables used in the survey module */// the survey log file handleFILE *survey_log= NULL;// the list of anomaly scores for the surveyll_double *survey_list;// the length of the list (1-based)int survey_list_len;// the number of seconds in the survey intervalfloat survey_interval;// the suvery period number (starts with 1)int survey_period;/* Spade survey module init function: set up the survey module per its args and register its preprocessor function */void SpadeSurveyInit(u_char *args){ pp_active++; need_anom= 1; /* parse the argument list from the rules file */ ParseSpadeSurveyArgs(args); /* Set the preprocessor function into the function list */ AddFuncToPreprocList(PreprocSpadeSurvey); fprintf(survey_log,"%.2f minute interval #\tPacket Count\tMedian Anom\t90th Percentile Anom\t99th Percentile Anom\n",survey_interval/60.0); survey_list= NULL; survey_list_len= 0; survey_period= 1; if (as_debug) printf("Preprocessor: SpadeSurvey Initialized\n");}/* Spade 'spade-survey' argument parsing function */void ParseSpadeSurveyArgs(char *args){ char **toks; int numToks; toks = mSplit(args, " ", 20, &numToks, '\\'); if (numToks > 0) { survey_log= fopen(toks[0],"w"); if(!survey_log) FatalError("spp_anomsensor: unable to open %s to record survey",toks[0]); } else { survey_log= stdout; } if (numToks > 1) { survey_interval = (float)(atof(toks[1])*60.0); } else { survey_interval= 60*60; } if (as_debug) printf("seconds of survey interval is %d\n",(int)survey_interval);}/* Spade survey module routine that is called with each packet */void PreprocSpadeSurvey(Packet *p){ size_t packet_time= p->pkth->ts.tv_sec; double anom; ll_double *new,*prev,*next; // the start time for this survey interval static time_t survey_interval_start_time=(time_t)0; // the number of packets seen in this survey period so far static int survey_rec_count= 0; while (packet_time > (survey_interval_start_time + survey_interval)) { if (survey_interval_start_time == 0) { /* first packet */ survey_interval_start_time= packet_time; } else { fprintf(survey_log,"%d\t%d\t%.6f\t%.6f\t%.6f\n",survey_period,survey_rec_count,survey_ostat(0.5),survey_ostat(0.9),survey_ostat(0.99)); fflush(survey_log); if (survey_list) free_links(survey_list); survey_list= NULL; survey_list_len= 0; survey_rec_count=0; survey_period++; survey_interval_start_time+= (long)survey_interval; } } if (record_maybe_skip(p)) return; /* accepted packets only past here; anom score is last_anom_score */ survey_rec_count++; anom= last_anom_score; new= new_link(anom); if (survey_list == NULL) { survey_list= new; survey_list_len= 1; } else { if (anom < survey_list->val) { /* add at head */ new->next= survey_list; survey_list= new; } else { for (prev= survey_list, next=survey_list->next; next != NULL && anom > next->val; prev=next,next=next->next); /* add between prev and next */ prev->next= new; new->next= next; } survey_list_len++; }} double survey_ostat(double loc) { ll_double *pos; int p; double fromnext; double posnum; //printf("loc= %f\n",loc); if (survey_list_len == 0) return 0.0; posnum= loc*(double)survey_list_len + (1-loc);/* = (survey_list_len-1)*loc+1 */ for (p= 1, pos=survey_list; p <= posnum; p++,pos=pos->next); fromnext= posnum-(double)(p-1); if (fromnext == 0 || pos->next == NULL) { /* got it exactly */ return pos->val; } else { return (pos->val*(1-fromnext))+(pos->next->val*fromnext); }}/*********************************************************************//*********************************************************************/int record_maybe_skip(Packet *p) { valtype val[NUM_FEATURES]; ll_net *home; size_t packet_time= p->pkth->ts.tv_sec; static time_t last_scale=(time_t)0; // the last time the tree was scaled if (pp_run_on_pkt == pp_active || !pp_run_on_pkt) { /* first time this packet hit */ while (packet_time - last_scale > SCALE_FREQ) { if (last_scale == (size_t)0) { /* this is the first packet */ last_scale= packet_time; } else { if (as_debug > 1) printf("scaling by %f at time %d; discarding at %f\n",SCALE_FACTOR,packet_time,MIN_NODE_SIZE); scale_and_prune_all_trees(SCALE_FACTOR,MIN_NODE_SIZE); last_scale+= SCALE_FREQ; /* lets pretend we did this right on time */ if (as_debug > 1) printf("done with scale/prune\n"); } } skip_packet= p->iph == NULL || p->tcph == NULL || p->iph->ip_proto != IPPROTO_TCP || p->tcph->th_flags != 2; /* is this a TCP SYN? */ if (!skip_packet && homelist != NULL) { skip_packet= 1; /* skip unless is in a homenet */ for (home= homelist; home != NULL; home=home->next) { if ((p->iph->ip_dst.s_addr & home->netmask) == home->netaddr) { skip_packet= 0; break; } } } if (skip_packet) return 1; record_packet(p,val); pp_run_on_pkt= 1; last_pkt_time= packet_time; if (as_debug && (tot_packets % 10000) == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -