📄 spp_frag2.c
字号:
/* $Id$ *//*** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* * Bugfixes; * * Aug 1 15:28:36 MDT 2001, cpw: changed to use packet time for all time * comparisons. Modified calling sequence on a number subroutines to * pass down current FragTracker and time to PruneFragCache. The * current FragTracker was getting released early by PruneFragCache * which led to a segmentation fault. I'd suggest a look see at * PruneFragCache to see that is doing things in the right order. Not * knowing how it all works, I assumed that the loop was from oldest to * newest. * Using snort compiled with this version I was able to successfully * process a gaggle of frags (GOF). An individual packet looked like this: * 14:11:21.020324 a.11071 > b.11070: udp 8000 (frag 62829:1480@0+) * 14:11:21.020327 a > b: frag 1480 (frag 62829:1480@1480+) * 14:11:21.020329 a > b: frag 1480 (frag 62829:1480@2960+) * 14:11:21.020412 a > b: frag 1480 (frag 62829:1480@4440+) * 14:11:21.020416 a > b: frag 1480 (frag 62829:1480@5920+) * 14:11:21.020418 a > 134.253.164.21: frag 608 (frag 62829:608@7400) * There were about 301066 full packets read from a 821947618 byte file. * * Prior to this patch, I got the following seg fault: * #0 ubi_btInsert (RootPtr=0x48, NewNode=0x8a94f10, ItemPtr=0x8a94f10, * OldNode=0xbfffee7c) at ubi_BinTree.c:637 * #1 0x8077825 in ubi_sptInsert (RootPtr=0x48, NewNode=0x8a94f10, * ItemPtr=0x8a94f10, OldNode=0x0) at ubi_SplayTree.c:317 * #2 0x807c08e in InsertFrag (p=0xbfffef5c, ft=0x874bdc8) at spp_frag2.c:534 * #3 0x807be82 in Frag2Defrag (p=0xbfffef5c) at spp_frag2.c:430 * #4 0x8058416 in Preprocess (p=0xbfffef5c) at rules.c:3427 * ... *//* I N C L U D E S ************************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <sys/types.h>#include <stdlib.h>#include <ctype.h>#include <rpc/types.h>#include "bounds.h"#include "generators.h"#include "log.h"#include "detect.h"#include "decode.h"#include "event.h"#include "util.h"#include "debug.h"#include "plugbase.h"#include "parser.h"#include "mstring.h"#include "checksum.h"#include "perf.h"#include "event_queue.h"#include "ubi_BinTree.h"#include "ubi_SplayTree.h"#include "snort.h"void Frag2Init(u_char *args);/* D E F I N E S **************************************************/#define FRAG_GOT_FIRST 0x00000001#define FRAG_GOT_LAST 0x00000002#define FRAG_REBUILT 0x00000004#define FRAG_OUTOFORDER 0x00000008 /* did we get other frags than MF Offset 0 first? */#define FRAG_PRUNE_QUANTA 60#define FRAG_MEMCAP 4194304#define FRAG2_TTL_LIMIT 5#define FRAG2_MIN_TTL 0#if defined (SOLARIS) || defined (SUNOS) || defined (__sparc__) || defined(__sparc64__) || defined (HPUX)#define SPARC_TWIDDLE 2#else#define SPARC_TWIDDLE 0#endif#define DATASIZE (ETHERNET_HEADER_LEN+65536)/* values for the smartbits detector/self perservation */#define SELF_PRES_THRESHOLD 500#define SELF_PRES_PERIOD 90#define SUSPEND_THRESHOLD 1000#define SUSPEND_PERIOD 30#define OPS_NORMAL 0#define OPS_SELF_PRESERVATION 1#define OPS_SUSPEND 2/* D A T A S T R U C T U R E S **********************************/typedef struct _Frag2Data{ u_int8_t os_flags; u_int32_t memcap; u_int32_t frag_timeout; u_int32_t last_prune_time; u_int8_t stop_traverse; u_int8_t min_ttl; /* Minimum TTL to accept */ u_int8_t ttl_limit; /* Size of ttls to avoid detection on */ char frag2_alerts; /* Wether or not frag2 alerts are enabled */ u_int32_t sp_threshold; u_int32_t sp_period; u_int32_t suspend_threshold; u_int32_t suspend_period; char state_protection; SPMemControl frag_sp_data; /* self preservation data */} Frag2Data;typedef struct _Frag2Frag{ ubi_trNode Node; u_int8_t *data; u_int16_t size; u_int16_t offset;} Frag2Frag;typedef struct _FragTracker{ ubi_trNode Node; u_int32_t sip; /* src IP */ u_int32_t dip; /* dst IP */ u_int16_t id; /* IP ID */ u_int8_t protocol; /* IP protocol */ u_int8_t ttl; /* ttl used to detect evasions */ u_int8_t alerted; u_int32_t frag_flags; u_int32_t last_frag_time; u_int32_t frag_bytes; u_int32_t calculated_size; u_int32_t frag_pkts; ubi_trRoot fraglist; ubi_trRootPtr fraglistPtr;} FragTracker;typedef struct _CompletionData{ u_int8_t complete; u_int8_t teardrop; u_int8_t outoforder;} CompletionData;typedef struct _F2Emergency{ long end_time; unsigned long new_frag_count; int status;} F2Emergency;typedef struct _F2SPControl{ FragTracker *ft; time_t cur_time; } F2SPControl;/* G L O B A L S **************************************************/static ubi_trRoot f_cache;static ubi_trRootPtr FragRootPtr = &f_cache; extern char *file_name;extern int file_line;static int frag_mem_usage;static u_int16_t next_offset;static u_int32_t frag2_alloc_faults;static Frag2Data f2data;static Packet *defrag_pkt;F2Emergency f2_emergency;/* P R O T O T Y P E S ********************************************/void ParseFrag2Args(u_char *);void Frag2Defrag(Packet *, void *);FragTracker *GetFragTracker(Packet *);FragTracker *NewFragTracker(Packet *);int InsertFrag(Packet *, FragTracker *);int FragIsComplete(FragTracker *, CompletionData *);void RebuildFrag(FragTracker *, Packet *);void Frag2DeleteFrag(FragTracker *);int Frag2SelfPreserve(struct _SPMemControl *);int PruneFragCache(FragTracker *, u_int32_t, u_int32_t);void ZapFrag(FragTracker *);void Frag2InitPkt();void Frag2CleanExit(int, void *);void Frag2Restart(int, void *);int Frag2SelfPreserve(struct _SPMemControl *spmc){ F2SPControl *ctrl = (F2SPControl *)spmc->control; frag2_alloc_faults++; pc.frag_mem_faults++; sfPerf.sfBase.iFragFaults++; if(!PruneFragCache(ctrl->ft, (u_int32_t)ctrl->cur_time, 0)) { /* if we can't prune due to time, just nuke 5 random sessions */ PruneFragCache(ctrl->ft, 0, 5); } return 0;}void *Frag2Alloc(FragTracker *cft, int tv_sec, u_int32_t size){ void *tmp; frag_mem_usage += size; /* if we use up all of our RAM, try to free up some stale frags */ if( (u_int32_t)frag_mem_usage > f2data.memcap) { frag2_alloc_faults++; pc.frag_mem_faults++; sfPerf.sfBase.iFragFaults++; if(!PruneFragCache(cft, (u_int32_t)tv_sec, 0)) { /* if we can't prune due to time, just nuke 5 random sessions */ PruneFragCache(cft, 0, 5); } } tmp = (void *) calloc(size, sizeof(char)); if(tmp == NULL) { FatalError("spp_defrag: Unable to allocate memory! " "(%u bytes in use)\n", frag_mem_usage); } return tmp;}static int Frag2CompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr){ FragTracker *nFt; FragTracker *iFt; nFt = (FragTracker *) NodePtr; iFt = (FragTracker *) ItemPtr; DEBUG_WRAP(DebugMessage(DEBUG_FRAG,"NodePtr: sip: 0x%X dip: 0x%X ip: 0x%X " "proto: 0x%X\n", nFt->sip, nFt->dip, nFt->id, nFt->protocol); DebugMessage(DEBUG_FRAG,"ItemPtr: sip: 0x%X dip: 0x%X ip: 0x%X " "proto: 0x%X\n", iFt->sip, iFt->dip, iFt->id, iFt->protocol);); if(nFt->sip < iFt->sip) return 1; if(nFt->sip > iFt->sip) return -1; if(nFt->dip < iFt->dip) return 1; if(nFt->dip > iFt->dip) return -1; if(nFt->id < iFt->id) return 1; if(nFt->id > iFt->id) return -1; if(nFt->protocol < iFt->protocol) return 1; if(nFt->protocol > iFt->protocol) return -1; return 0;}static int Frag2FragCompare(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr){ Frag2Frag *nFrag; Frag2Frag *iFrag; nFrag = (Frag2Frag *) NodePtr; iFrag = (Frag2Frag *) ItemPtr; if(nFrag->offset < iFrag->offset) return 1; if(nFrag->offset > iFrag->offset) return -1; return 0;}static void CompletionTraverse(ubi_trNodePtr NodePtr, void *complete){ Frag2Frag *frag; CompletionData *comp = (CompletionData *) complete; frag = (Frag2Frag *) NodePtr; if(frag->offset == next_offset) { next_offset = frag->offset + frag->size; } else if(frag->offset < next_offset) { /* flag a teardrop attack detection */ comp->teardrop = 1; if(frag->size + frag->offset > next_offset) { next_offset = frag->offset + frag->size; } } else if(frag->offset > next_offset) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Holes in completion check... (%u > %u)\n", frag->offset, next_offset);); comp->complete = 0; } return;}static void RebuildTraverse(ubi_trNodePtr NodePtr, void *buffer){ Frag2Frag *frag; u_int8_t *buf = (u_int8_t *)buffer; if(f2data.stop_traverse) return; frag = (Frag2Frag *)NodePtr; DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "frag offset: 0x%X size: %lu pointer: %p\n", (unsigned int) frag->offset, (unsigned long) frag->size, (buf+frag->offset));); if((frag->offset + frag->size) < 65516) { SafeMemcpy(buf+frag->offset, frag->data, frag->size, defrag_pkt->pkt, defrag_pkt->pkt + DATASIZE); pc.rebuild_element++; } else { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "frag2: pkt rebuild size violation\n");); f2data.stop_traverse = 1; } return;}static void KillFrag(ubi_trNodePtr NodePtr){ Frag2Frag *frag; frag = (Frag2Frag *) NodePtr; //frag_mem_usage -= frag->size; f2data.frag_sp_data.mem_usage -= frag->size; free(frag->data); //frag_mem_usage -= sizeof(Frag2Frag); f2data.frag_sp_data.mem_usage -= sizeof(Frag2Frag); free(frag); }void SetupFrag2(){ RegisterPreprocessor("frag2", Frag2Init); DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Preprocessor: frag2 is setup...\n"););}void Frag2Init(u_char *args){ DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Initializing frag2\n");); f2data.last_prune_time = 0; f2data.frag2_alerts = 0; f2data.min_ttl = FRAG2_MIN_TTL; f2data.ttl_limit = FRAG2_TTL_LIMIT; f2data.sp_threshold = SELF_PRES_THRESHOLD; f2data.sp_period = SELF_PRES_PERIOD; f2data.suspend_threshold = SUSPEND_THRESHOLD; f2data.suspend_period = SUSPEND_PERIOD; f2data.state_protection = 0; /* initialize the f2 Emergency stuff */ f2_emergency.end_time = 0; f2_emergency.new_frag_count = 0; f2_emergency.status = OPS_NORMAL; ParseFrag2Args(args); (void)ubi_trInitTree(FragRootPtr, /* ptr to the tree head */ Frag2CompareFunc, /* comparison function */ 0); /* no dups */ defrag_pkt = (Packet *)calloc(sizeof(Packet), sizeof(char)); if(!defrag_pkt) { FatalError("Unable to allocate defrag packet!\n"); } Frag2InitPkt(); AddFuncToPreprocList(Frag2Defrag); AddFuncToCleanExitList(Frag2CleanExit, NULL); AddFuncToRestartList(Frag2Restart, NULL);}void ParseFrag2Args(u_char *args){ char **toks; int num_toks; int i; char *index; char **stoks = NULL; int s_toks; if(args == NULL || strlen(args) == 0) { f2data.memcap = FRAG_MEMCAP; /* 4MB */ f2data.frag_timeout = FRAG_PRUNE_QUANTA; /* 60 seconds */ f2data.ttl_limit = FRAG2_TTL_LIMIT; f2data.min_ttl = FRAG2_MIN_TTL; f2data.frag2_alerts = 0; f2data.frag_sp_data.memcap = FRAG_MEMCAP; f2data.frag_sp_data.mem_usage = 0; f2data.frag_sp_data.fault_count = 0; f2data.frag_sp_data.sp_func = Frag2SelfPreserve; if(!pv.quiet_flag) { LogMessage("No arguments to frag2 directive, " "setting defaults to:\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -