linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘建议留言网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > article > unix > unix提高 >
栏目导栏
资料搜索
热门文章
·20%的SOLARIS知识解决80%的问题
·Solaris启动过程详解 zt
·查看Solaris系统硬件配置的命令
·Unix系列shell程序编写(中)
·STRUTS 源码学习笔记
·SOLARIS技巧篇
·snort源码分析
·Unix系列shell程序编写(下)
·在solaris 10/x86下安装oracle
·solaris 10 硬盘安装
·Solaris安全配置手册
·Apache源代码分析——关于模块
·HP-UX基本指令快速参考
· Tomcat Server源码启动分析
·Solaris8 双网卡配置(路由器用
最新文章
·solaris系统安全配置
·RHEL5.0操作系统下NFS服务的配
·Solaris Linux 9下Vsftpd的配置
·在HP-UX下建立只归属于某个目录
·SolarWinds2002使用说明
·从外部存储划盘并加入vg,为fs扩
·因带库问题导致系统光纤卡报错
·Unix下多线程中条件变量的使用
·UNIX和Linux中信号的个数
·不同的类UNIX操作系统密码破解
·AIX系统下Domino邮件服务器安装
·限制ROOT用户远程登陆UNIX系统
·Unix操作系统入侵追踪反击战
·AIX CDE不能启动的故障一般性解
·CentOS4.4用VSFTPD架设FTP服务
Google
 
snort源码分析
[ 作者:  加入时间:2006-06-20 12:17:51  来自: ]
下面我写一点snort源代码的分析。 e23Linux联盟
呵呵,我是面面,有理解的不对的地方,一起讨论。有些地方我读得比较e23Linux联盟
e23Linux联盟
细,有些地方就比较粗糙,所以写起来也含糊其词。 e23Linux联盟
我做事总拖拖拉拉,希望这次能尽快写完。 e23Linux联盟
首先对snort做一个概括的评论。 e23Linux联盟
从工作原理而言,snort是一个NIDS。 网络传输数据的采集 e23Linux联盟
利用了工具包libpcap。snort对libpcap采集来的数据进行分析,从而判断e23Linux联盟
是否 e23Linux联盟
存在可疑的网络活动。 e23Linux联盟
从检测模式而言,snort基本上是误用检测(misuse detection)。具体实e23Linux联盟
现上,仅仅是对数据进行最直接最简单 e23Linux联盟
的搜索匹配,并没有涉及更复杂的入侵检测办法。 e23Linux联盟
尽管snort在实现上没有什么高深的检测策略,但是它给我们提供了一个非e23Linux联盟
e23Linux联盟
优秀的公开源代码的入侵检测系统范例。我们可以通过对其代码的分析,e23Linux联盟
搞清IDS e23Linux联盟
究竟是如何工作的,并在此基础上添加自己的想法。 e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(1) e23Linux联盟
发信站: BBS 水木清华站 (Sun Oct 8 11:39:33 2000) e23Linux联盟
首先对snort做一个概括的评论。 e23Linux联盟
从工作原理而言,snort是一个NIDS。 网络传输数据的采集 e23Linux联盟
利用了工具包libpcap。snort对libpcap采集来的数据进行分析,从而判断e23Linux联盟
是否 e23Linux联盟
存在可疑的网络活动。 e23Linux联盟
从检测模式而言,snort基本上是误用检测(misuse detection)。具体实e23Linux联盟
现上,仅仅是对数据进行最直接最简单 e23Linux联盟
的搜索匹配,并没有涉及更复杂的入侵检测办法。 e23Linux联盟
尽管snort在实现上没有什么高深的检测策略,但是它给我们提供了一个非e23Linux联盟
e23Linux联盟
优秀的公开源代码的入侵检测系统范例。我们可以通过对其代码的分析,e23Linux联盟
搞清IDS e23Linux联盟
究竟是如何工作的,并在此基础上添加自己的想法。 e23Linux联盟
异常检测(anomaly detection)。]具体实现上,仅仅是对数据进行最直e23Linux联盟
接最简单 e23Linux联盟
的搜索匹配,并没有涉及更复杂的入侵检测办法。 e23Linux联盟
尽管snort在实现上没有什么高深的检测策略,但是它给我们提供了一个非e23Linux联盟
e23Linux联盟
优秀的公开源代码的入侵检测系统范例。我们可以通过对其代码的分析,e23Linux联盟
搞清IDS e23Linux联盟
究竟是如何工作的,并在此基础上添加自己的想法。 e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(1) e23Linux联盟
发信站: BBS 水木清华站 (Sun Oct 8 11:39:33 2000) e23Linux联盟
首先对snort做一个概括的评论。 e23Linux联盟
从工作原理而言,snort是一个NIDS。 网络传输数据的采集 e23Linux联盟
利用了工具包libpcap。snort对libpcap采集来的数据进行分析,从而判断e23Linux联盟
是否 e23Linux联盟
存在可疑的网络活动。 e23Linux联盟
从检测模式而言,snort基本上是误用检测(misuse detection)。具体实e23Linux联盟
现上,仅仅是对数据进行最直接最简单 e23Linux联盟
的搜索匹配,并没有涉及更复杂的入侵检测办法。 e23Linux联盟
尽管snort在实现上没有什么高深的检测策略,但是它给我们提供了一个非e23Linux联盟
e23Linux联盟
优秀的公开源代码的入侵检测系统范例。我们可以通过对其代码的分析,e23Linux联盟
搞清IDS e23Linux联盟
究竟是如何工作的,并在此基础上添加自己的想法。 e23Linux联盟
snort的编程风格非常优秀,代码阅读起来并不困难,整个程序结构清晰,e23Linux联盟
e23Linux联盟
数调用关系也不算复杂。但是,snort的源文件不少,函数总数也很多,所e23Linux联盟
以不太 e23Linux联盟
容易讲清楚。因此,最好把代码完整看一两遍,能更清楚点。 e23Linux联盟
下面看看snort的整体结构。展开snort压缩包,有约50个c程序和头文件,e23Linux联盟
另有 e23Linux联盟
约30个其它文件(工程、数据或者说明文件)。下面对源代码文件分组 e23Linux联盟
说明。 e23Linux联盟
snort.c(.h)是主程序所在的文件,实现了main函数和一系列辅助函数。 e23Linux联盟
e23Linux联盟
decode.c(.h)把数据包层层剥开,确定该包属于何种协议,有什么特征。e23Linux联盟
e23Linux联盟
标记到全局结构变量pv中。 e23Linux联盟
log.c(.h)实现日志和报警功能。snort有多种日志格式,一种是按tcpdue23Linux联盟
mp e23Linux联盟
二进制的格式存储,另一种按snort编码的ascii格式存储在日志目录下,e23Linux联盟
日志目 e23Linux联盟
录的名字根据"外"主机的ip地址命名。报警有不同的级别和方e23Linux联盟
式,可以记录到 e23Linux联盟
syslog中,或者记录到用户指定的文件,另外还可以通过unix socket发送e23Linux联盟
报警 e23Linux联盟
消息,以及利用SMB向Windows系统发送winpopup消息。 e23Linux联盟
mstring.c(.h)实现字符串匹配算法。在snort中,采用的是Boyer-Moore算e23Linux联盟
法。 e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(2) e23Linux联盟
发信站: BBS 水木清华站 (Sun Oct 8 11:40:44 2000) e23Linux联盟
下面看看snort的整体结构。展开snort压缩包,有约50个c程序和头文件,e23Linux联盟
另有 e23Linux联盟
约30个其它文件(工程、数据或者说明文件)。下面对源代码文件分组 e23Linux联盟
snort的编程风格非常优秀,代码阅读起来并不困难,整个程序结构清晰,e23Linux联盟
e23Linux联盟
数调用关系也不算复杂。但是,snort的源文件不少,函数总数也很多,所e23Linux联盟
以不太 e23Linux联盟
容易讲清楚。因此,最好把代码完整看一两遍,能更清楚点。 e23Linux联盟
下面看看snort的整体结构。展开snort压缩包,有约50个c程序和头文件,e23Linux联盟
另有 e23Linux联盟
约30个其它文件(工程、数据或者说明文件)。下面对源代码文件分组 e23Linux联盟
说明。 e23Linux联盟
snort.c(.h)是主程序所在的文件,实现了main函数和一系列辅助函数。 e23Linux联盟
e23Linux联盟
decode.c(.h)把数据包层层剥开,确定该包属于何种协议,有什么特征。e23Linux联盟
e23Linux联盟
标记到全局结构变量pv中。 e23Linux联盟
log.c(.h)实现日志和报警功能。snort有多种日志格式,一种是按tcpdue23Linux联盟
mp e23Linux联盟
二进制的格式存储,另一种按snort编码的ascii格式存储在日志目录下,e23Linux联盟
日志目 e23Linux联盟
录的名字根据"外"主机的ip地址命名。报警有不同的级别和方e23Linux联盟
式,可以记录到 e23Linux联盟
syslog中,或者记录到用户指定的文件,另外还可以通过unix socket发送e23Linux联盟
报警 e23Linux联盟
消息,以及利用SMB向Windows系统发送winpopup消息。 e23Linux联盟
mstring.c(.h)实现字符串匹配算法。在snort中,采用的是Boyer-Moore算e23Linux联盟
法。 e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(2) e23Linux联盟
发信站: BBS 水木清华站 (Sun Oct 8 11:40:44 2000) e23Linux联盟
下面看看snort的整体结构。展开snort压缩包,有约50个c程序和头文件,e23Linux联盟
另有 e23Linux联盟
约30个其它文件(工程、数据或者说明文件)。下面对源代码文件分组 e23Linux联盟
说明。 e23Linux联盟
snort.c(.h)是主程序所在的文件,实现了main函数和一系列辅助函数。 e23Linux联盟
e23Linux联盟
decode.c(.h)把数据包层层剥开,确定该包属于何种协议,有什么特征。e23Linux联盟
e23Linux联盟
标记到全局结构变量pv中。 e23Linux联盟
log.c(.h)实现日志和报警功能。snort有多种日志格式,一种是按tcpdue23Linux联盟
mp e23Linux联盟
二进制的格式存储,另一种按snort编码的ascii格式存储在日志目录下,e23Linux联盟
日志目 e23Linux联盟
录的名字根据"外"主机的ip地址命名。报警有不同的级别和方e23Linux联盟
式,可以记录到 e23Linux联盟
syslog中,或者记录到用户指定的文件,另外还可以通过unix socket发送e23Linux联盟
报警 e23Linux联盟
消息,以及利用SMB向Windows系统发送winpopup消息。 e23Linux联盟
mstring.c(.h)实现字符串匹配算法。在snort中,采用的是Boyer-Moore算e23Linux联盟
法。 e23Linux联盟
算法书上一般都有。 e23Linux联盟
plugbase.c(.h)实现了初始化检测以及登记检测规则的一组函数。snort中e23Linux联盟
e23Linux联盟
检测规则以链表的形式存储,每条规则通过登记(Register)过程添加到e23Linux联盟
链表中。 e23Linux联盟
response.c(.h)进行响应,即向攻击方主动发送数据包。这里实现了两种e23Linux联盟
响应。 e23Linux联盟
一种是发送ICMP的主机不可到达的假信息,另一种针对TCP,发送RST包,e23Linux联盟
断开连接。 e23Linux联盟
rule.c(.h)实现了规则设置和入侵检测所需要的函数。规则设置主要的作e23Linux联盟
用是 e23Linux联盟
把一个规则文件转化为实际运作中的规则链表。检测函数根据规则实施攻e23Linux联盟
击特征的 e23Linux联盟
检测。 e23Linux联盟
sp_*_check.c(.h)是不同类型的检测规则的具体实现。很容易就可以从文e23Linux联盟
件名 e23Linux联盟
得知所实现的规则。例如,sp_dsize_check针对的是包的数据大小,sp_ie23Linux联盟
cmp_type e23Linux联盟
_check针对icmp包的类型,sp_tcp_flag_check针对tcp包的标志位。不再e23Linux联盟
详述。 e23Linux联盟
spo_*.c(.h)实现输出(output)规则。spo_alert_syslog把事件记录到se23Linux联盟
yslog e23Linux联盟
中;spo_log_tcpdump利用libpcap中的日志函数,进行日志记录。 e23Linux联盟
spp_*.c(.h)实现预处理(preprocess)规则。包括http解码(即把http请e23Linux联盟
求中 e23Linux联盟
的%XX这样的字符用对应的ascii字符代替,避免忽略了恶意的请求)、最e23Linux联盟
小片断检 e23Linux联盟
查(避免恶意利用tcp协议中重组的功能)和端口扫描检测。 e23Linux联盟
下面描述main函数的工作流程。先来说明两个结构的定义。 e23Linux联盟
在snort.h中,定义了两个结构:PV和PacketCount。PV用来记录命令行参e23Linux联盟
数, e23Linux联盟
snort根据这些命令行参数来确定其工作方式。PV类型的全局变量pv用来实e23Linux联盟
际记录具体 e23Linux联盟
工作方式。结构定义可以参看snort.h,在下边的main函数中,会多次遇到e23Linux联盟
pv中各个域 e23Linux联盟
的设定,到时再一个一个解释。 e23Linux联盟
结构PacketCount用来统计流量,每处理一个数据包,该结构类型的全局变e23Linux联盟
量pc e23Linux联盟
把对应的域加1。相当于一个计数器。 e23Linux联盟
接下来解释main函数。 e23Linux联盟
初始化设定一些缺省值;然后解析命令行参数,根据命令行参数,填充结e23Linux联盟
构变 e23Linux联盟
量pv;根据pv的值(也就是解析命令行的结果)确定工作方式,需要注意e23Linux联盟
e23Linux联盟
如果是运行在Daemon方式,通过GoDaemon函数,创建守护进程,重定向标e23Linux联盟
准输入 e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(3) e23Linux联盟
发信站: BBS 水木清华站 (Sun Oct 8 15:51:03 2000) e23Linux联盟
下面描述main函数的工作流程。先来说明两个结构的定义。 e23Linux联盟
在snort.h中,定义了两个结构:PV和PacketCount。PV用来记录命令行参e23Linux联盟
数, e23Linux联盟
snort根据这些命令行参数来确定其工作方式。PV类型的全局变量pv用来实e23Linux联盟
际记录具体 e23Linux联盟
工作方式。结构定义可以参看snort.h,在下边的main函数中,会多次遇到e23Linux联盟
pv中各个域 e23Linux联盟
的设定,到时再一个一个解释。 e23Linux联盟
结构PacketCount用来统计流量,每处理一个数据包,该结构类型的全局变e23Linux联盟
量pc e23Linux联盟
把对应的域加1。相当于一个计数器。 e23Linux联盟
接下来解释main函数。 e23Linux联盟
初始化设定一些缺省值;然后解析命令行参数,根据命令行参数,填充结e23Linux联盟
构变 e23Linux联盟
量pv;根据pv的值(也就是解析命令行的结果)确定工作方式,需要注意e23Linux联盟
e23Linux联盟
如果是运行在Daemon方式,通过GoDaemon函数,创建守护进程,重定向标e23Linux联盟
准输入 e23Linux联盟
输出,实现daamon状态,并结束父进程。 e23Linux联盟
snort可以实时采集网络数据,也可以从文件读取数据进行分析。这两种情e23Linux联盟
况并 e23Linux联盟
没有本质区别。如果是读取文件进行分析(并非直接从网卡实时采集来的e23Linux联盟
),以该文 e23Linux联盟
件名作为libpcap的函数OpenPcap的参数,打开采集过程;如果是从网卡实e23Linux联盟
时采集, e23Linux联盟
就把网卡接口作为OpenPcap的参数,利用libpcap的函数打开该网卡接口。e23Linux联盟
在unix中, e23Linux联盟
设备也被看作是文件,所以这和读取文件分析没有多大的差别。 e23Linux联盟
接着,指定数据包的拆包函数。不同的数据链路网络,拆包的函数也不同e23Linux联盟
。利用 e23Linux联盟
函数SetPktProcessor,根据全局变量datalink的值,来设定不同的拆包函e23Linux联盟
数。例如, e23Linux联盟
以太网,拆包函数为DecodeEthPkt;令牌环网,拆包函数为DecodeTRPkt,e23Linux联盟
等等。这些 e23Linux联盟
Decode*函数,在decode.c中实现。 e23Linux联盟
如果使用了检测规则,那么下面就要初始化这些检测规则,并解析规则文e23Linux联盟
件,转 e23Linux联盟
化成规则链表。规则有三大类:预处理(preprocessor),插件(plugine23Linux联盟
),输出插 e23Linux联盟
件(outputplugin)。这里plugin就是具体的检测规则,而outputplugine23Linux联盟
是定义日志 e23Linux联盟
和报警方式的规则。 e23Linux联盟
然后根据报警模式,设定报警函数;根据日志模式,设定日志函数;如果e23Linux联盟
指定了 e23Linux联盟
能够进行响应,就打开raw socket,准备用于响应。 e23Linux联盟
最后进入读取数据包的循环,pcap_loop对每个采集来的数据包都用Procee23Linux联盟
ssPacket e23Linux联盟
函数进行处理,如果出现错误或者到达指定的处理包数(pv.pkt_cnt定义e23Linux联盟
),就退出 e23Linux联盟
该函数。这里ProcessPacket是关键程序, e23Linux联盟
最后,关闭采集过程。 e23Linux联盟
现在看看snort如何实现对数据包的分析和检测入侵的。 e23Linux联盟
在main函数的最后部分有如下语句,比较重要: e23Linux联盟
/* Read all packets on the device. Continue until cnt packets ree23Linux联盟
ad */ e23Linux联盟
if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler)ProcessPacket, NULL) e23Linux联盟
< 0) e23Linux联盟
{ e23Linux联盟
...... e23Linux联盟
} e23Linux联盟
这里pcap_loop函数有4个参数,分别解释: e23Linux联盟
pd是一个全局变量,表示文件描述符,在前面OpenPcap的调用中已经被正e23Linux联盟
确地 e23Linux联盟
赋值。前面说过,snort可以实时采集网络数据,也可以从文件读取数据进e23Linux联盟
行分析。 e23Linux联盟
在不同情况打开文件(或设备)时,pd分别用来处理文件,或者网卡设备e23Linux联盟
接口。 e23Linux联盟
pd是struct pcap类型的指针,该结构包括实际的文件描述符,缓冲区,等e23Linux联盟
e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(4) e23Linux联盟
发信站: BBS 水木清华站 (Tue Oct 10 11:42:22 2000) e23Linux联盟
现在看看snort如何实现对数据包的分析和检测入侵的。 e23Linux联盟
在main函数的最后部分有如下语句,比较重要: e23Linux联盟
/* Read all packets on the device. Continue until cnt packets ree23Linux联盟
ad */ e23Linux联盟
if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler)ProcessPacket, NULL) e23Linux联盟
< 0) e23Linux联盟
{ e23Linux联盟
...... e23Linux联盟
} e23Linux联盟
这里pcap_loop函数有4个参数,分别解释: e23Linux联盟
pd是一个全局变量,表示文件描述符,在前面OpenPcap的调用中已经被正e23Linux联盟
确地 e23Linux联盟
赋值。前面说过,snort可以实时采集网络数据,也可以从文件读取数据进e23Linux联盟
行分析。 e23Linux联盟
在不同情况打开文件(或设备)时,pd分别用来处理文件,或者网卡设备e23Linux联盟
接口。 e23Linux联盟
pd是struct pcap类型的指针,该结构包括实际的文件描述符,缓冲区,等e23Linux联盟
e23Linux联盟
域,用来处理从相应的文件获取信息。 e23Linux联盟
OpenPcap函数中对pd赋值的语句分别为: e23Linux联盟
/* get the device file descriptor,打开网卡接口 */ e23Linux联盟
pd = pcap_open_live(pv.interface, snaplen, e23Linux联盟
pv.promisc_flag ? PROMISC : 0, READ_TIMEOUT, errorbuf); e23Linux联盟
或者 e23Linux联盟
/* open the file,打开文件 */ e23Linux联盟
pd = pcap_open_offline(intf, errorbuf); e23Linux联盟
于是,这个参数表明从哪里取得待分析的数据。 e23Linux联盟
第2个参数是pv.pkt_cnt,表示总共要捕捉的包的数量。在main函数初始化e23Linux联盟
时, e23Linux联盟
缺省设置为-1,成为永真循环,一直捕捉直到程序退出: e23Linux联盟
/* initialize the packet counter to loop forever */ e23Linux联盟
pv.pkt_cnt = -1; e23Linux联盟
或者在命令行中设置要捕捉的包的数量。前面ParseCmdLine(解析命令行e23Linux联盟
)函数 e23Linux联盟
的调用中,遇到参数n,重新设定pv.pkt_cnt的值。ParseCmdLine中相关语e23Linux联盟
句如下: e23Linux联盟
case 'n': /* grab x packets and exit */ e23Linux联盟
pv.pkt_cnt = atoi(optarg); e23Linux联盟
第3个参数是回调函数,该回调函数处理捕捉到的数据包。这里为函数 e23Linux联盟
ProcessPacket,下面将详细解释该函数。 e23Linux联盟
第4个参数是字符串指针,表示用户,这里设置为空。 e23Linux联盟
在说明处理包的函数ProcessPacket之前,有必要解释一下pcap_loop的实e23Linux联盟
现。 e23Linux联盟
我们看到main函数只在if条件判断中调用了一次pacp_loop,那么循环一定e23Linux联盟
是在 e23Linux联盟
pcap_loop中做的了。察看pcap.c文件中pcap_loop的实现部分,我们发现e23Linux联盟
的确如此: e23Linux联盟
int e23Linux联盟
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *usee23Linux联盟
r) e23Linux联盟
{ e23Linux联盟
register int n; e23Linux联盟
for (;;) { //for循环 e23Linux联盟
if (p->sf.rfile != NULL) e23Linux联盟
n = pcap_offline_read(p, cnt, callback, user); e23Linux联盟
else { e23Linux联盟
/* e23Linux联盟
* XXX keep reading until we get something e23Linux联盟
* (or an error occurs) e23Linux联盟
*/ e23Linux联盟
do { //do循环 e23Linux联盟
n = pcap_read(p, cnt, callback, user); e23Linux联盟
} while (n == 0); e23Linux联盟
} e23Linux联盟
if (n <= 0) e23Linux联盟
return (n); //遇到错误,返回 e23Linux联盟
if (cnt > 0) { e23Linux联盟
cnt -= n; e23Linux联盟
if (cnt <= 0) e23Linux联盟
return (0); //到达指定数量,返回 e23Linux联盟
} e23Linux联盟
//只有以上两种返回情况 e23Linux联盟
} e23Linux联盟
} e23Linux联盟
现在看看ProcessPacket的实现了,这个回调函数用来处理数据包。该函数e23Linux联盟
e23Linux联盟
是pcap_handler类型的,pcap.h中类型的定义如下: e23Linux联盟
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr e23Linux联盟
*, e23Linux联盟
const u_char *); e23Linux联盟
第1个参数这里没有什么用; e23Linux联盟
第2个参数为pcap_pkthdr结构指针,记录时间戳、包长、捕捉的长度; e23Linux联盟
第3个参数字符串指针为数据包。 e23Linux联盟
函数如下: e23Linux联盟
void ProcessPacket(char *user, struct pcap_pkthdr *pkthdr, u_chae23Linux联盟
r *pkt) e23Linux联盟
{ e23Linux联盟
Packet p; //Packet结构在decode.h中定义,用来记录数据包的各种信息e23Linux联盟
e23Linux联盟
/* call the packet decoder,调用拆包函数,这里grinder是一个全局 e23Linux联盟
e23Linux联盟
函数指针,已经在main的SetPktProcessor调用中设置为正确的拆包函数 e23Linux联盟
*/ e23Linux联盟
(*grinder)(&p, pkthdr, pkt); e23Linux联盟
/* print the packet to the screen,如果选择了详细显示方式, e23Linux联盟
那么把包的数据,显示到标准输出 */ e23Linux联盟
if(pv.verbose_flag) e23Linux联盟
{ e23Linux联盟
...... //省略 e23Linux联盟
} e23Linux联盟
/* check or log the packet as necessary e23Linux联盟
如果工作在使用检测规则的方式,就调用Preprocess进行检测, e23Linux联盟
否则,仅仅进行日志,记录该包的信息*/ e23Linux联盟
if(!pv.use_rules) e23Linux联盟
{ e23Linux联盟
... //进行日志,省略 e23Linux联盟
} e23Linux联盟
else e23Linux联盟
{ e23Linux联盟
Preprocess(&p); e23Linux联盟
} e23Linux联盟
//清除缓冲区 e23Linux联盟
ClearDumpBuf(); e23Linux联盟
} e23Linux联盟
这里Preprocess函数进行实际检测。 e23Linux联盟
Proprocess函数很短,首先调用预处理规则处理数据包p,然后调用检测 e23Linux联盟
e23Linux联盟
函数Detect进行规则匹配实现检测,如果实现匹配,那么调用函数CallOue23Linux联盟
tput e23Linux联盟
Plugins根据输出规则进行报警或日志。函数如下: e23Linux联盟
void Preprocess(Packet *p) e23Linux联盟
{ e23Linux联盟
PreprocessFuncNode *idx; e23Linux联盟
do_detect = 1; e23Linux联盟
idx = PreprocessList; //指向预处理规则链表头 e23Linux联盟
while(idx != NULL) //调用预处理函数处理包p e23Linux联盟
{ e23Linux联盟
idx->func(p); e23Linux联盟
idx = idx->next; e23Linux联盟
} e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(5) e23Linux联盟
发信站: BBS 水木清华站 (Fri Oct 13 11:20:55 2000) e23Linux联盟
Proprocess函数很短,首先调用预处理规则处理数据包p,然后调用检测 e23Linux联盟
e23Linux联盟
函数Detect进行规则匹配实现检测,如果实现匹配,那么调用函数CallOue23Linux联盟
tput e23Linux联盟
Plugins根据输出规则进行报警或日志。函数如下: e23Linux联盟
void Preprocess(Packet *p) e23Linux联盟
{ e23Linux联盟
PreprocessFuncNode *idx; e23Linux联盟
do_detect = 1; e23Linux联盟
idx = PreprocessList; //指向预处理规则链表头 e23Linux联盟
while(idx != NULL) //调用预处理函数处理包p e23Linux联盟
{ e23Linux联盟
idx->func(p); e23Linux联盟
idx = idx->next; e23Linux联盟
} e23Linux联盟
if(!p->frag_flag && do_detect) e23Linux联盟
{ e23Linux联盟
if(Detect(p)) //调用检测函数 e23Linux联盟
{ e23Linux联盟
CallOutputPlugins(p); //如果匹配,根据规则输出 e23Linux联盟
} e23Linux联盟
} e23Linux联盟
} e23Linux联盟
尽管这个函数很简洁,但是在第1行我们看到定义了ProprocessFuncNode e23Linux联盟
e23Linux联盟
结构类型的指针,所以下面,我们不得不开始涉及到snort的各种复杂 e23Linux联盟
的数据结构。前面的分析,我一直按照程序运行的调用顺序,忽略了许多e23Linux联盟
e23Linux联盟
数(其实有不少非常重要),以期描述出snort执行的主线,避免因为程序e23Linux联盟
e23Linux联盟
大量的调用关系而产生混乱。到现在,我们还没有接触到snort核心的数据e23Linux联盟
结构 e23Linux联盟
和算法。有不少关键的问题需要解决:规则是如何静态描述的?运行时这e23Linux联盟
e23Linux联盟
规则按照什么结构动态存储?每条规则的处理函数如何被调用?snort给了e23Linux联盟
e23Linux联盟
我们提供了非常好的方法。 e23Linux联盟
snort一个非常成功的思想是利用了plugin机制,规则处理函数并非固定在e23Linux联盟
e23Linux联盟
源程序中,而是根据每次运行时的参数设定,从规则文件中读入规则,再e23Linux联盟
把每个 e23Linux联盟
规则所需要的处理函数挂接到链表上。实际检测时,遍历这些链表,调用e23Linux联盟
链表上 e23Linux联盟
相应的函数来分析。 e23Linux联盟
snort主要的数据结构是链表,几乎都是链表来链表去。我们下面做个总的e23Linux联盟
e23Linux联盟
介绍。 e23Linux联盟
我们有必要先回过头来,看一看main函数中对规则初始化时涉及到的一些e23Linux联盟
e23Linux联盟
数据结构。 e23Linux联盟
在main函数初始化规则的时候,先建立了几个链表,全局变量定义如下 e23Linux联盟
(plugbase.c中): e23Linux联盟
KeywordXlateList *KeywordList; e23Linux联盟
PreprocessKeywordList *PreprocessKeywords; e23Linux联盟
PreprocessFuncNode *PreprocessList; e23Linux联盟
OutputKeywordList *OutputKeywords; e23Linux联盟
OutputFuncNode *OutputList; e23Linux联盟
这几种结构的具体定义省略。这一初始化的过程把snort中预定义的关键 e23Linux联盟
e23Linux联盟
字和处理函数按类别连接在不同的链表上。然后,在解析规则文件的时候e23Linux联盟
e23Linux联盟
如果一条规则的选项中包含了某个关键字,就会从上边初始化好的对应的e23Linux联盟
链表 e23Linux联盟
中查找,把必要的信息和处理函数添加到表示这条规则的节点(用RuleTree23Linux联盟
eNode e23Linux联盟
类型来表示,下面详述)的特定域(OptTreeNode类型)中。 e23Linux联盟
同时,main函数中初始化规则的最后,对指定的规则文件进行解析。在最e23Linux联盟
e23Linux联盟
高的层次上,有3个全局变量保存规则(rules.c): e23Linux联盟
ListHead Alert; /* Alert Block Header */ e23Linux联盟
ListHead Log; /* Log Block Header */ e23Linux联盟
ListHead Pass; /* Pass Block Header */ e23Linux联盟
这几个变量是ListHead类型的,正如名称所说,指示链表头。Alert中登记e23Linux联盟
e23Linux联盟
了需要报警的规则,Log中登记了需要进行日志的规则,Pass中登记的规则e23Linux联盟
在处 e23Linux联盟
理过程忽略(不进行任何处理)。ListHead定义如下: e23Linux联盟
typedef struct _ListHead e23Linux联盟
{ e23Linux联盟
RuleTreeNode *TcpList; e23Linux联盟
RuleTreeNode *UdpList; e23Linux联盟
RuleTreeNode *IcmpList; e23Linux联盟
} ListHead; e23Linux联盟
可以看到,每个ListHead结构中有三个指针,分别指向处理Tcp/Udp/Icmpe23Linux联盟
e23Linux联盟
规则的链表头。这里又出现了新的结构RuleTreeNode,为了说明链表的层e23Linux联盟
次关系, e23Linux联盟
下面列出RuleTreeNode的定义,但是忽略了大部分域: e23Linux联盟
typedef struct _RuleTreeNode e23Linux联盟
{ e23Linux联盟
RuleFpList *rule_func; e23Linux联盟
...... //忽略 e23Linux联盟
struct _RuleTreeNode *right; e23Linux联盟
OptTreeNode *down; /* list of rule options to associate with thie23Linux联盟
s e23Linux联盟
rule node */ e23Linux联盟
} RuleTreeNode; e23Linux联盟
RuleTreeNode中包含上述3个指针域,分别又能形成3个链表。RuleTreeNoe23Linux联盟
de* e23Linux联盟
类型的right指向下一个RuleTreeNode,相当于普通链表中的next域,只不e23Linux联盟
过这里 e23Linux联盟
用right来命名。这样就形成了规则链表。 e23Linux联盟
RuleFpList类的指针rule_func记录的是该规则的处理函数的链表。一条规e23Linux联盟
e23Linux联盟
有时候需要调用多个处理函数来分析。所以,有必要做成链表。我们看看e23Linux联盟
下面的 e23Linux联盟
定义,除了next域,还有一个函数指针: e23Linux联盟
typedef struct _RuleFpList e23Linux联盟
{ e23Linux联盟
/* rule check function pointer */ e23Linux联盟
int (*RuleHeadFunc)(Packet *, struct _RuleTreeNode *, struct _Rue23Linux联盟
leFpList *); e23Linux联盟
/* pointer to the next rule function node */ e23Linux联盟
struct _RuleFpList *next; e23Linux联盟
} RuleFpList; e23Linux联盟
第3个指针域是OptTreeNode类的指针down,该行后面的注释说的很清楚,e23Linux联盟
这是 e23Linux联盟
与这个规则节点相联系的规则选项的链表。很不幸,OptTreeNode的结构也e23Linux联盟
相当复 e23Linux联盟
杂,而且又引出了几个新的链表。忽略一些域,OptTreeNode定义如下: e23Linux联盟
e23Linux联盟
typedef struct _OptTreeNode e23Linux联盟
{ e23Linux联盟
/* plugin/detection functions go here */ e23Linux联盟
OptFpList *opt_func; e23Linux联盟
/* the ds_list is absolutely essential for the plugin system to e23Linux联盟
work, e23Linux联盟
it allows the plugin authors to associate "dynamic" dae23Linux联盟
ta structures e23Linux联盟
with the rule system, letting them link anything they can come ue23Linux联盟
p e23Linux联盟
with to the rules list */ e23Linux联盟
void *ds_list; /* list of plugin data struct pointers */ e23Linux联盟
.......//省略了一些域 e23Linux联盟
struct _OptTreeNode *next; e23Linux联盟
} OptTreeNode; e23Linux联盟
next指向链表的下一个节点,无需多说。OptFpList类型的指针opt_func指e23Linux联盟
e23Linux联盟
选项函数链表,同前面说的RuleFpList没什么大差别。值得注意的是指针e23Linux联盟
数组 e23Linux联盟
ds_list,用来记录该条规则中涉及到的预定义处理过程。每个元素的类型e23Linux联盟
是void*。 e23Linux联盟
在实际表示规则的时候,ds_list被强制转换成不同的预定义类型。 e23Linux联盟
-- e23Linux联盟
垆边人似月,皓腕凝霜雪 e23Linux联盟
※ 来源:·BBS 水木清华站 smth.org· e23Linux联盟
发信人: shuke (莫失莫忘), 信区: Security e23Linux联盟
标 题: snort源码分析(5) e23Linux联盟
发信站: BBS 水木清华站 (Fri Oct 13 11:20:55 2000) e23Linux联盟
Proprocess函数很短,首先调用预处理规则处理数据包p,然后调用检测 e23Linux联盟
e23Linux联盟
函数Detect进行规则匹配实现检测,如果实现匹配,那么调用函数CallOue23Linux联盟
tput e23Linux联盟
Plugins根据输出规则进行报警或日志。函数如下: e23Linux联盟
void Preprocess(Packet *p) e23Linux联盟
{ e23Linux联盟
PreprocessFuncNode *idx; e23Linux联盟
do_detect = 1; e23Linux联盟
idx = PreprocessList; //指向预处理规则链表头 e23Linux联盟
while(idx != NULL) //调用预处理函数处理包p e23Linux联盟
{ e23Linux联盟
idx->func(p); e23Linux联盟
idx = idx->next; e23Linux联盟
} e23Linux联盟
if(!p->frag_flag && do_detect) e23Linux联盟
{ e23Linux联盟
if(Detect(p)) //调用检测函数 e23Linux联盟
{ e23Linux联盟
CallOutputPlugins(p); //如果匹配,根据规则输出 e23Linux联盟
} e23Linux联盟
} e23Linux联盟
} e23Linux联盟
尽管这个函数很简洁,但是在第1行我们看到定义了ProprocessFuncNode e23Linux联盟
e23Linux联盟
结构类型的指针,所以下面,我们不得不开始涉及到snort的各种复杂 e23Linux联盟
的数据结构。前面的分析,我一直按照程序运行的调用顺序,忽略了许多e23Linux联盟
e23Linux联盟
数(其实有不少非常重要),以期描述出snort执行的主线,避免因为程序e23Linux联盟
e23Linux联盟
大量的调用关系而产生混乱。到现在,我们还没有接触到snort核心的数据e23Linux联盟
结构 e23Linux联盟
和算法。有不少关键的问题需要解决:规则是如何静态描述的?运行时这e23Linux联盟
e23Linux联盟
规则按照什么结构动态存储?每条规则的处理函数如何被调用?snort给了e23Linux联盟
e23Linux联盟
我们提供了非常好的方法。 e23Linux联盟
snort一个非常成功的思想是利用了plugin机制,规则处理函数并非固定在e23Linux联盟
e23Linux联盟
源程序中,而是根据每次运行时的参数设定,从规则文件中读入规则,再e23Linux联盟
把每个 e23Linux联盟
规则所需要的处理函数挂接到链表上。实际检测时,遍历这些链表,调用e23Linux联盟
链表上 e23Linux联盟
相应的函数来分析。 e23Linux联盟
snort主要的数据结构是链表,几乎都是链表来链表去。我们下面做个总的e23Linux联盟
e23Linux联盟
介绍。 e23Linux联盟
我们有必要先回过头来,看一看main函数中对规则初始化时涉及到的一些e23Linux联盟
e23Linux联盟
数据结构。 e23Linux联盟
在main函数初始化规则的时候,先建立了几个链表,全局变量定义如下 e23Linux联盟
(plugbase.c中): e23Linux联盟
KeywordXlateList *KeywordList; e23Linux联盟
PreprocessKeywordList *PreprocessKeywords; e23Linux联盟
PreprocessFuncNode *PreprocessList; e23Linux联盟
OutputKeywordList *OutputKeywords; e23Linux联盟
OutputFuncNode *OutputList; e23Linux联盟
这几种结构的具体定义省略。这一初始化的过程把snort中预定义的关键 e23Linux联盟
e23Linux联盟
字和处理函数按类别连接在不同的链表上。然后,在解析规则文件的时候e23Linux联盟
e23Linux联盟
如果一条规则的选项中包含了某个关键字,就会从上边初始化好的对应的e23Linux联盟
链表 e23Linux联盟
中查找,把必要的信息和处理函数添加到表示这条规则的节点(用RuleTree23Linux联盟
eNode e23Linux联盟
类型来表示,下面详述)的特定域(OptTreeNode类型)中。 e23Linux联盟
同时,main函数中初始化规则的最后,对指定的规则文件进行解析。在最e23Linux联盟
e23Linux联盟
高的层次上,有3个全局变量保存规则(rules.c): e23Linux联盟
ListHead Alert; /* Alert Block Header */ e23Linux联盟
ListHead Log; /* Log Block Header */ e23Linux联盟
ListHead Pass; /* Pass Block Header */ e23Linux联盟
这几个变量是ListHead类型的,正如名称所说,指示链表头。Alert中登记e23Linux联盟
e23Linux联盟
了需要报警的规则,Log中登记了需要进行日志的规则,Pass中登记的规则e23Linux联盟
在处 e23Linux联盟
理过程忽略(不进行任何处理)。ListHead定义如下: e23Linux联盟
typedef struct _ListHead e23Linux联盟
{ e23Linux联盟
RuleTreeNode *TcpList; e23Linux联盟
RuleTreeNode *UdpList; e23Linux联盟
RuleTreeNode *IcmpList; e23Linux联盟
} ListHead; e23Linux联盟
可以看到,每个ListHead结构中有三个指针,分别指向处理Tcp/Udp/Icmpe23Linux联盟
e23Linux联盟
规则的链表头。这里又出现了新的结构RuleTreeNode,为了说明链表的层e23Linux联盟
次关系, e23Linux联盟
下面列出RuleTreeNode的定义,但是忽略了大部分域: e23Linux联盟
typedef struct _RuleTreeNode e23Linux联盟
{ e23Linux联盟
RuleFpList *rule_func; e23Linux联盟
...... //忽略 e23Linux联盟
struct _RuleTreeNode *right; e23Linux联盟
OptTreeNode *down; /* list of rule options to associate with thie23Linux联盟
s e23Linux联盟
rule node */ e23Linux联盟
} RuleTreeNode; e23Linux联盟
RuleTreeNode中包含上述3个指针域,分别又能形成3个链表。RuleTreeNoe23Linux联盟
de* e23Linux联盟
类型的right指向下一个RuleTreeNode,相当于普通链表中的next域,只不e23Linux联盟
过这里 e23Linux联盟
用right来命名。这样就形成了规则链表。 e23Linux联盟
RuleFpList类的指针rule_func记录的是该规则的处理函数的链表。一条规e23Linux联盟
e23Linux联盟
有时候需要调用多个处理函数来分析。所以,有必要做成链表。我们看看e23Linux联盟
下面的 e23Linux联盟
定义,除了next域,还有一个函数指针: e23Linux联盟
typedef struct _RuleFpList e23Linux联盟
{ e23Linux联盟
/* rule check function pointer */ e23Linux联盟
int (*RuleHeadFunc)(Packet *, struct _RuleTreeNode *, struct _Rue23Linux联盟
leFpList *); e23Linux联盟
/* pointer to the next rule function node */ e23Linux联盟
struct _RuleFpList *next; e23Linux联盟
} RuleFpList; e23Linux联盟
第3个指针域是OptTreeNode类的指针down,该行后面的注释说的很清楚,e23Linux联盟
这是 e23Linux联盟
与这个规则节点相联系的规则选项的链表。很不幸,OptTreeNode的结构也e23Linux联盟
相当复 e23Linux联盟
杂,而且又引出了几个新的链表。忽略一些域,OptTreeNode定义如下: e23Linux联盟
e23Linux联盟
typedef struct _OptTreeNode e23Linux联盟
{ e23Linux联盟
/* plugin/detection functions go here */ e23Linux联盟
OptFpList *opt_func; e23Linux联盟
/* the ds_list is absolutely essential for the plugin system to e23Linux联盟
work, e23Linux联盟
it allows the plugin authors to associate "dynamic" dae23Linux联盟
ta structures e23Linux联盟
with the rule system, letting them link anything they can come ue23Linux联盟
p e23Linux联盟
with to the rules list */ e23Linux联盟
void *ds_list; /* list of plugin data struct pointers */ e23Linux联盟
.......//省略了一些域 e23Linux联盟
struct _OptTreeNode *next; e23Linux联盟
} OptTreeNode; e23Linux联盟
next指向链表的下一个节点,无需多说。OptFpList类型的指针opt_func指e23Linux联盟
e23Linux联盟
选项函数链表,同前面说的RuleFpList没什么大差别。值得注意的是指针e23Linux联盟
数组 e23Linux联盟
ds_list,用来记录该条规则中涉及到的预定义处理过程。每个元素的类型e23Linux联盟
是void*。 e23Linux联盟
在实际表示规则的时候,ds_list被强制转换成不同的预定义类型。 e23Linux联盟
Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
无相关信息