下面是snort2.0的框架分析,相比snort之后的版本,其结构比较简单、更容易学习和理解,其次是
本人对此版本相对比较熟悉一些,可以为初次接触和学习snort的朋友提供帮助,能够快速整体全局性地
了解snort的基本框架。下面从四个方面展开描述。
一、snort插件
snort中的插件有3类,输出插件,预处理插件,规则选项检测插件
插件的好处:
灵活地选择使用哪些功能
开发人员很容易开发第三方插件,易于扩展。
1、输出插件
InitOutputPlugins //输出插件初始化函数注册
1) 注册过程,注册多个插件初始化函数(供用户配置文件选择)
把database、log_tcpdump等关键字及其相对应的初始化函数DatabaseIint、logTcpdumpIint
挂在outputKeywordList链上
2) 初始化函数的执行,通过配置配置文件灵活选择某些插件
在主程序解析snort.conf配置文件时,一旦解析到输出文件中有关键字database就会匹配outputKeywordList链上关键字
执行对应的DatabaseIint函数,DatabaseIint为特定插件初始化函数,会把预定义的Database输出插件函数注册在(挂在)_OutputFucNode链上
3) Database运行的前置条件:当有数据报警时,引擎会轮询_OutputFucNode链上的输出函数,其中Database是链上的一个。
输出插件函数有syslog、logtcpdump、database等,其调用函数有:
CallLogPlugins //while{ LogList->func()} 日志模式插件输出
CallLogFuncs 检测规则引擎输出
CallAlertPlugins //while{ AlertList->func()} 报警模式插件输出
CallAlertFuncs 检测规则引擎输出
2、预处理插件初始化
InitPreprocessors
1) 注册过程和初始化过程与输出插件相同
2) Preprocess在detect(规则选项检测)之前,轮询_PreprocessFuncNode链依次
执行预处理函数。
3) 常用的预处理插件有httpDecode Portscan Stream(tcp会话重组) Frag(ip分片重组)
ARPspoof、Flood等插件函数
3、规则选项关键字检测初始化
IinitPlugIns
1) 注册过程和初始化过程与输出插件相同
2) 在分析规则选项时,碰到选项关键字(如dsize),触发检测插件函数
3) 常用的选项关键字检测插件有PatternMatch,模型包括(content、offset、depth、nocase、distance、within)
相结合的匹配函数、dsize、tcpflag、icmptype、ttl、ackcheck等关键字匹配函数
4、插件总结:
1)注册多个关键字与初始化函数,挂在关键字初始化函数链上。
2)根据配置文件中配置选择插件关键字链上的插件初始化函数执行,使预定义的插件函数及其相关参数挂在插件链上。
3)根据插件初始化函数链结点的类型NT_OUTPUT_LOG, NT_OUTPUT_ALERT分别把插件函数注册到全局插件函数链上(AlertList、LogList)
二、规则的初始化
主函数通过调用CreateDefaultRules、ParseRulesFile、ParseRule等函数,最终创建一个三层链表如下
第一层到三层依次为_RuleListNode、_ListHead 、RuleTreeNode ,三个数据结构如下:
typedef struct _RuleTreeNode //规则头的描述、以协议作为类别,分为ip、tcp、udp、icmp四种规则树链表
{
RuleFpList *rule_func; /* match functions.. (Bidirectional etc.. ) */ //规则(ip port等)匹配函数链
int head_node_number;
int type; //RULE_PASS、RULE_ACTIVATE、RULE_ALERT、RULE_DYNAMIC、RULE_LOG
//fpLogEvent通过判断type值,分别调用ActivateAction{CallAlertFuncs CallLogFuncs}、LogAction {CallLogFuncs}
//DynamicAction {CallLogFuncs}、AlertAction{CallAlertFuncs、CallLogFuncs}函数
//CallAlertFuncs CallLogFuncs分别轮询全局输出插件函数链AlertList、LogList,执行输出插件函数
IpAddrSet *sip;
IpAddrSet *dip;
int not_sp_flag; /* not source port flag */
u_short hsp; /* hi src port */
u_short lsp; /* lo src port */
int not_dp_flag; /* not dest port flag */
u_short hdp; /* hi dest port */
u_short ldp; /* lo dest port */
u_int32_t flags; /* control flags */
/* stuff for dynamic rules activation/deactivation */
int active_flag;
int activation_counter;
int countdown;
ActivateList *activate_list;
struct _RuleTreeNode *right; /* ptr to the next RTN in the list */ //下一条规则
OptTreeNode *down; /* list of rule options to associate with this rule node */ //规则的选项部分描述
struct _ListHead *listhead;
} RuleTreeNode;
//RuleListNode节点有Alert Log Dynamic Activate pass五种类型,其具体特性通过_ListHead体现
ListHead Alert; /* Alert Block Header */
ListHead Log; /* Log Block Header */
ListHead Pass; /* Pass Block Header */
ListHead Activation; /* Activation Block Header */
ListHead Dynamic; /* Dynamic Block Header */
typedef struct _ListHead
{
RuleTreeNode *IpList;
RuleTreeNode *TcpList;
RuleTreeNode *UdpList;
RuleTreeNode *IcmpList;
struct _OutputFuncNode *LogList; //对应全局插件函数链LogList
struct _OutputFuncNode *AlertList; //对应全局插件函数链AlertList
struct _RuleListNode *ruleListNode;
} ListHead;
typedef struct _RuleListNode //list of Alert Log Dynamic Activate pass
{
ListHead *RuleList; /* The rule list associated with this node */
int mode; /* the rule mode */
int rval; /* 0 == no detection, 1 == detection event */
int evalIndex; /* eval index for this rule set */
char *name; /* name of this rule list (for debugging) */ Alert Log Dynamic Activate pass
struct _RuleListNode *next; /* the next RuleListNode */
} RuleListNode;
//规则选项关键字匹配
typedef struct _OptFpList
{
/* context data for this test */
void *context; //规则选项关键字content部分,待匹配的内容
int (*OptTestFunc)(Packet *, struct _OptTreeNode *, struct _OptFpList *);//规则选项匹配的执行函数
struct _OptFpList *next;
} OptFpList;
//规则选项链表节点,是规则的选项部分的描述
typedef struct _OptTreeNode
{
/* plugin/detection functions go here */
OptFpList *opt_func; //选项匹配处理函数链
RspFpList *rsp_func; /* response functions */
OutputFuncNode *outputFuncs; /* per sid enabled output functions */
/* the ds_list is absolutely essential for the plugin system to work,
it allows the plugin authors to associate "dynamic" data structures
with the rule system, letting them link anything they can come up
with to the rules list */?
void *ds_list[64]; /* list of plugin data struct pointers */检测深度 dsize的大小等都分别存放在不同的结构
int chain_node_number;
int type; /* what do we do when we match this rule */
int evalIndex; /* where this rule sits in the evaluation sets */
int proto; /* protocol, added for integrity checks
during rule parsing */
struct _RuleTreeNode *proto_node; /* ptr to head part... */
int session_flag; /* record session data */
char *logto; /* log file in which to write packets which
match this rule*/
/* metadata about signature */
SigInfo sigInfo;
u_int8_t stateless; /* this rule can fire regardless of session state */
u_int8_t established; /* this rule can only fire if it has been marked
as established */
Event event_data;
TagData *tag;
/* stuff for dynamic rules activation/deactivation */
int active_flag;
int activation_counter;
int countdown;
int activates;
int activated_by;
u_int8_t threshold_type; /* type of threshold we're watching */
u_int32_t threshold; /* number of events between alerts */
u_int32_t window; /* number of seconds before threshold times out */
struct _OptTreeNode *OTN_activation_ptr;
struct _RuleTreeNode *RTN_activation_ptr;
struct _OptTreeNode *next;
struct _RuleTreeNode *rtn;
} OptTreeNode;
三、数据包处理流程
ProcessPacket
(*grinder) (&p, pkthdr, pkt); //DecodeEthPkt、DecodeIP、DecodeIP从链路层到传输层逐层分析解码,
//将eth头地址、ip头地址、负载大小等信息保存到全局结构Packet*p中,供Detect等解析使用
CallLogPlugins(p) //runMode=MODE_PACKET_LOG
Preprocess(&p); //runMode=MODE_IDS
//轮询预处理插件函数链,执行tcp重组、ip分片重组、后门发现等插件函数
Frag2Defrag
PortscanPreprocFunction
BoFind
Detect(p);//检测规则引擎
fpEvalPacket
fpEvalHeaderUdp
fpEvalHeaderTcp
fpEvalHeaderSW
mpseSearch->otnx_match->fpEvalRTNSW->fpEvalOTN->(opt_func->OptTestFunc)//可通过gdb bt命令查看调用栈
fpLogEvent
AlertAction-> {CallAlertFuncs、CallLogFuncs} ->{ AlertList->func()、{ LogList->func()} } //输出检测结果 报警日志
四、快速规则匹配初始化流程
fpCreateFastPacketDetection
prmAddRule
prmAddRuleUri
prmAddRuleNC
prmxAddPortRule
p->pgHead->rnRuleData = otnx;
总结
追踪程序函数栈,可以使用gdb bt命令输出函数栈。要弄清楚整个程序的功能,主要先搞清楚整个框架模型,程序都是围绕这个框架
进行工作。snort是以两个模型开展工作,第一个模型Packet存放协议解码、包括预处理后的数据信息,作为数据模型,第二个模型是规则的三层链表,
存放解析后的所有检测规则信息,作为检测模型。Detect作为检测引擎,调用规则(ip port等)匹配函数链检测规则头,调用选项检测插件链进行选项字段匹配,
匹配成功最终以注册的输出插件函数进行报警和记录。