📄 376.htm
字号:
<br>
垆边人似月,皓腕凝霜雪 <br>
<br>
<br>
※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.69.59] <br>
发信人: shuke (莫失莫忘), 信区: Security <br>
标 题: snort源码分析(5) <br>
发信站: BBS 水木清华站 (Fri Oct 13 11:20:55 2000) <br>
<br>
<br>
<br>
Proprocess函数很短,首先调用预处理规则处理数据包p,然后调用检测 <br>
函数Detect进行规则匹配实现检测,如果实现匹配,那么调用函数CallOutput <br>
Plugins根据输出规则进行报警或日志。函数如下: <br>
<br>
void Preprocess(Packet *p) <br>
{ <br>
PreprocessFuncNode *idx; <br>
<br>
do_detect = 1; <br>
idx = PreprocessList; //指向预处理规则链表头 <br>
<br>
while(idx != NULL) //调用预处理函数处理包p <br>
{ <br>
idx->func(p); <br>
idx = idx->next; <br>
} <br>
<br>
if(!p->frag_flag && do_detect) <br>
{ <br>
if(Detect(p)) //调用检测函数 <br>
{ <br>
CallOutputPlugins(p); //如果匹配,根据规则输出 <br>
} <br>
} <br>
} <br>
<br>
尽管这个函数很简洁,但是在第1行我们看到定义了ProprocessFuncNode <br>
结构类型的指针,所以下面,我们不得不开始涉及到snort的各种复杂 <br>
的数据结构。前面的分析,我一直按照程序运行的调用顺序,忽略了许多函 <br>
数(其实有不少非常重要),以期描述出snort执行的主线,避免因为程序中 <br>
大量的调用关系而产生混乱。到现在,我们还没有接触到snort核心的数据结构 <br>
和算法。有不少关键的问题需要解决:规则是如何静态描述的?运行时这些 <br>
规则按照什么结构动态存储?每条规则的处理函数如何被调用?snort给了 <br>
我们提供了非常好的方法。 <br>
<br>
snort一个非常成功的思想是利用了plugin机制,规则处理函数并非固定在 <br>
源程序中,而是根据每次运行时的参数设定,从规则文件中读入规则,再把每个 <br>
规则所需要的处理函数挂接到链表上。实际检测时,遍历这些链表,调用链表上 <br>
相应的函数来分析。 <br>
<br>
snort主要的数据结构是链表,几乎都是链表来链表去。我们下面做个总的 <br>
介绍。 <br>
<br>
我们有必要先回过头来,看一看main函数中对规则初始化时涉及到的一些 <br>
数据结构。 <br>
<br>
在main函数初始化规则的时候,先建立了几个链表,全局变量定义如下 <br>
(plugbase.c中): <br>
<br>
KeywordXlateList *KeywordList; <br>
PreprocessKeywordList *PreprocessKeywords; <br>
PreprocessFuncNode *PreprocessList; <br>
OutputKeywordList *OutputKeywords; <br>
OutputFuncNode *OutputList; <br>
<br>
这几种结构的具体定义省略。这一初始化的过程把snort中预定义的关键 <br>
字和处理函数按类别连接在不同的链表上。然后,在解析规则文件的时候, <br>
如果一条规则的选项中包含了某个关键字,就会从上边初始化好的对应的链表 <br>
中查找,把必要的信息和处理函数添加到表示这条规则的节点(用RuleTreeNode <br>
类型来表示,下面详述)的特定域(OptTreeNode类型)中。 <br>
<br>
同时,main函数中初始化规则的最后,对指定的规则文件进行解析。在最 <br>
高的层次上,有3个全局变量保存规则(rules.c): <br>
<br>
ListHead Alert; /* Alert Block Header */ <br>
ListHead Log; /* Log Block Header */ <br>
ListHead Pass; /* Pass Block Header */ <br>
<br>
这几个变量是ListHead类型的,正如名称所说,指示链表头。Alert中登记 <br>
了需要报警的规则,Log中登记了需要进行日志的规则,Pass中登记的规则在处 <br>
理过程忽略(不进行任何处理)。ListHead定义如下: <br>
<br>
typedef struct _ListHead <br>
{ <br>
RuleTreeNode *TcpList; <br>
RuleTreeNode *UdpList; <br>
RuleTreeNode *IcmpList; <br>
} ListHead; <br>
<br>
可以看到,每个ListHead结构中有三个指针,分别指向处理Tcp/Udp/Icmp包 <br>
规则的链表头。这里又出现了新的结构RuleTreeNode,为了说明链表的层次关系, <br>
下面列出RuleTreeNode的定义,但是忽略了大部分域: <br>
<br>
typedef struct _RuleTreeNode <br>
{ <br>
RuleFpList *rule_func; <br>
<br>
...... //忽略 <br>
<br>
struct _RuleTreeNode *right; <br>
<br>
OptTreeNode *down; /* list of rule options to associate with this <br>
rule node */ <br>
<br>
} RuleTreeNode; <br>
<br>
RuleTreeNode中包含上述3个指针域,分别又能形成3个链表。RuleTreeNode* <br>
类型的right指向下一个RuleTreeNode,相当于普通链表中的next域,只不过这里 <br>
用right来命名。这样就形成了规则链表。 <br>
<br>
RuleFpList类的指针rule_func记录的是该规则的处理函数的链表。一条规则 <br>
有时候需要调用多个处理函数来分析。所以,有必要做成链表。我们看看下面的 <br>
定义,除了next域,还有一个函数指针: <br>
<br>
typedef struct _RuleFpList <br>
{ <br>
/* rule check function pointer */ <br>
int (*RuleHeadFunc)(Packet *, struct _RuleTreeNode *, struct _RuleFpList *); <br>
<br>
/* pointer to the next rule function node */ <br>
struct _RuleFpList *next; <br>
<br>
} RuleFpList; <br>
<br>
第3个指针域是OptTreeNode类的指针down,该行后面的注释说的很清楚,这是 <br>
与这个规则节点相联系的规则选项的链表。很不幸,OptTreeNode的结构也相当复 <br>
杂,而且又引出了几个新的链表。忽略一些域,OptTreeNode定义如下: <br>
<br>
typedef struct _OptTreeNode <br>
{ <br>
/* plugin/detection functions go here */ <br>
OptFpList *opt_func; <br>
<br>
/* the ds_list is absolutely essential for the plugin system to work, <br>
it allows the plugin authors to associate "dynamic" data structures <br>
with the rule system, letting them link anything they can come up <br>
with to the rules list */ <br>
void *ds_list[512]; /* list of plugin data struct pointers */ <br>
<br>
.......//省略了一些域 <br>
<br>
struct _OptTreeNode *next; <br>
<br>
} OptTreeNode; <br>
<br>
next指向链表的下一个节点,无需多说。OptFpList类型的指针opt_func指向 <br>
选项函数链表,同前面说的RuleFpList没什么大差别。值得注意的是指针数组 <br>
ds_list,用来记录该条规则中涉及到的预定义处理过程。每个元素的类型是void*。 <br>
在实际表示规则的时候,ds_list被强制转换成不同的预定义类型。 <br>
-- <br>
<br>
垆边人似月,皓腕凝霜雪 <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="370.htm">上一层</a>][<a href="377.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -