1前言
Snort是一个优秀的轻量级,以开放源代码形式发行的网络入侵检测系统(NIDS),由Martin Roesch编写,由全世界的众多程序员共同维护和升级。Snort运行在Libpcap库函数基础之上,具有实时数据流量分析和记录IP网络数据包的能力,能够进行协议分析,对内容匹配/搜索;它能检测不同的攻击方式,对检测到的攻击进行实时的警报;并且现在的Snort 已经能支持多种系统。
从检测模式而言,snort基本上是误用检测(misuse detection)。尽管snort在实现上没有什么高深的检测策略,但是它给我们提供了一个非常优秀的公开源代码的入侵检测系统范例。我们可以通过对其代码的分析,搞清IDS 究竟是如何工作的,并在此基础上添加自己的想法。
snort的编程风格非常优秀,代码阅读起来并不困难,整个程序结构清晰,函数调用关系也不算复杂。但是,snort的源文件不少,函数总数也很多。
阅读它的规范代码是我们迅速学习了解入侵检测系统机制的一种方式,阅读它的冗长代码需要坚定的信念。因为小组成员是第一次阅读这样大量的代码,为了方便小组成员的分析阅读,我书写了这个文档,进行源代码的概要分析,让阅读者能通过这份文档,大致了解系统的结构和代码的层次结构。
在阅读代码之前,小组成员应该有一定的基础知识:
●C语言基础知识
●Socket网络编程
●LibPcap库函数
并且,应该有一定的动手能力:
●搭建混杂模式和分布式模式的Snort
●了解snort的配置方法
2Snort系统框架
日志输出
数据包规则匹配
数据包预处理
截获数据包
构建规则快速匹配引擎规则链表初始化
插件初始化
打开数据包截获接口
系统初始化循环
系统框架图
不是入侵行为
检测到入侵
开始
解释命令行
初始化pcap 库
设置解码函数
预处理、检测引擎、输出模块(插件)的初始化
解释规则文件生成所需的规则链
设置警告/日志输出函数
对数据报文解码
如有需要,打印报文
调用所有的预处理器对报文进行处理
对报文匹配所有的规则,检测入侵
调用所有的输出插件
继续
终止
主体流程图
是
否
4.1 总体模块图
4.2 各模块功能分析 4.2.1 主控模块
实现的功能包括所有模块的初始化、命令行解释、配置文件解释、数据包捕获库libpcap 的初始化,然后调用libpcap 开始捕获数据包,并进行解码检测入侵;
主控模块中的插件管理功能实现对所有插件的管理,包括所有插件的初始化和启动等。
4.2.2 包解码模块
包一被收集到,Snort 必须对每一个具体的协议元素进行解码。把从网络上抓取的原始数据包,从下向上沿各个协议栈(从较低的数据连接协议开始,逐层上移)进行解码,解码后的包数据将填充满相应的数据结构,以便规则处理模块处理。
预处理模块(插件) 检测引擎模块(插件) 输出模块(插件)
规则处理模块
包解码模块
主控模块
日志模块
辅助模块
使用/调用
Snort
总体 模块 图
4.2.3 规则处理模块
实现对这些报文进行基于规则的模式匹配工作,检测出入侵行为;在初始化阶段同时负责完成规则文件的解释和规则语法树的构建工作。
规则处理模块在执行检测工作时使用了三种形式的插件,分别为预处理插件模块、检测引擎插件模块和输出插件模块,他们在源代码中处于绝对的文件数量优势。
4.2.4 预处理模块(插件)
在模式匹配之前进行,对报文进行分片重组、流重组和异常检查等预处理操作。
Snort 的预处理分为两类。他们可以用来针对可疑行为检查包或者修改包以便检测引擎能对其正确解释。有很多攻击通过特征匹配都不能被检测引擎检测出来。因此,“检查”预处理走进了这一领域,来监测可疑行为。这类预处理对发现非基于特征的攻击是不可缺少的。另一类预处理负责对流量标准化以便监测引擎能准确匹配特征。这类预处理通过对流量的模式进行处理使攻击无法躲避Snort 检测引擎的检测。
另外,Snort 使包通过每一个预处理程序来发现攻击,这就需要不止一个预处理程序对包进行监测。如果Snort 在预处理对某个包发出警报后就停止对其可以属性的检查,那么攻击者就能利用这一不足隐藏攻击。(假定恶意黑客以某种方法对一个恶意的远程利用攻击进行编码,故意使某个预处理会对他发出一个低级别的警报。如果对包的处理就在这一点结束,而不再让它通过其他预处理,该攻击就能触发一次故意的警报,而真正的远程利用就不会被Snort 发现,达隐藏流量的真正本质。)
预处理模块的编程采用“插件”模式,即各种检测功能都是通过各种插件模块来完成。采用此种灵活的结构模式,有利于用户加入自己编写的检测模块来增强系统功能,或者定制用户特殊需求的系统。完成功能主要如下几类:
● 模拟TCP/IP 堆栈功能的插件,如IP 碎片重组、TCP 流重组插件;
● 各种解码插件:Http 解码插件、Unicode 解码插件、RPC 解码插件、Telnet 协商插
件等。
● 模式匹配无法进行攻击检测时所用的检测插件:端口扫描插件、spade 异常入侵检
测插件、bo 检测插件、arp 欺骗检测插件等。
(可以参见《Snort 入侵检测使用解决方案》第36-47页中的13种预处理)
解码数据 连接协议
解码网 络协议
解码传 输协议
Libpcap 捕包
预处理程序检查包
包解码模块流程
4.2.5检测引擎模块(插件)
检测引擎是Snort的一个主要部件。主要检查数据包的各个方面,包括数据包的大小、协议类型、IP/ICMP/TCP/UDP等的选项等,辅助规则匹配完成检测功能。
他有两个功能:规则分析和特征监测。检测引擎通过分析Snort规则来建立攻击特征。Snort规则按行读取并被载入内部数据结构。规则只有在Snort服务启动时才载入,这意味着修改、添加或删除规则必须更新Snort守护进程。
检测引擎将流量与规则按其载入内存的顺序一次进行匹配。可以根据需要规定来组织规则的先后次序。规则按功能分为两个部分:规则头(规则树节点)和规则选项(选项树节点)。规则头包含特征应用的条件信息。可以在规则头中规定协议、源IP、目的IP地址范围、端口和日志类型等。
检测引擎对规则头和规则选项进行不同的处理。检测引擎建立一个链表判断树。树的节点对进来的包用逐渐精确的特征元素进行检验。需要强调的是,Snort是在发现一个特征与包匹配后才开始对其检验。即时在检验时包可能与另一个特征匹配,检测引擎也不再继续处理而转向下一个包。因此合理组织规则非常重要,应该先载入最恶意的特征。
检测引擎的编程采用“插件”模式,每一个插件都会与对应的规则关键字进行绑定,以保证在执行检测引擎是被正确调用。
主要功能如下:
●X协议各字段的检查。如TCPFlag、IcmpType、IcmpCode、IpiId、TcpAck、TcpSeq、
Dsize、IpOption、Rpc、IcmpId、IcmpSeq、IpTos、FragBits、TcpWin、IpProto和
IpSame等。
●一些辅助功能,如Respond、Priority、PatternMatch、Session、React、Reference等,
这些插件分别完成了响应(关闭连接)、严重界别、模式匹配(内容)、会话记录、
攻击响应(高级的响应机制)、攻击参考信息等功能
4.2.6输出模块(插件)
实现在检测到攻击后执行各种输出和反应的功能。
输出插件接受Snort传来的入侵数据。输出插件的目的是将报警数据转储到另一种资源或文件中。各种输出插件用于各种不同的功能。
输出插件是Snort的主要瓶颈。Snort能对包进行快速读取和处理,但在试图写入一个慢速数据库或通过网络写入是却力不从心。数据库输出插件不能用于高带宽环境。建议配置Snort以统一格式输出并且由Snort的标准日志应用程序Barnyard接管输出。Snort有12种输出插件,他们以不同格式输出数据。
(类型参见《Snort入侵检测使用解决方案》第48 -51页)
4.2.7日志模块
实现按各种报文日志功能,也就是把各类的报文记录到各种类型的日志中。
4.2.8辅助模块
程序运行运用了一些辅助模块:书结构定义子模块定义了集中snort使用到的二叉树结构和相关的处理函数,tag处理子模块完成了和tag相关的功能,灵位一些子模块也提供了一些公用的函数,如字符串处理等。
5Snort源代码整体结构
Snort源代码文件书写的非常规范,每个函数前都有英文的详细注释,所以下面我只是简要的分析功能,每个源代码文件的名说明了它的具体实现功能概要,在参见内部的英文注释就会很清楚
5.1 按模块
5.1.1主控模块
snort.c(h)
主程序所在的文件,实现了main函数和一系列辅助函数。完成命令行参数解析,全局变量的
解析,各种处理模块的初始化,检测规则的解析,libpcap库的初始化,启动数据包解码和处
理进程。
plugbase.c(h)
实现了初始化检测以及登记检测规则的一组函数,完成所有插件的管理和服务功能,包括所有
插件的安装,初始化函数以及部分插件使用的一些公共函数。snort中的检测规则以链表的形
式存储,每条规则通过登记(Register)过程添加到链表中。
5.1.2包解码模块
decode.c(h)
把数据包层层剥开,完成报文的解码过程,确定pcap从网络上捕捉到的报文格式struce
pcap_pkthdr解码成snort内部格式packet,即分析该包属于何种协议,有什么特征。并标
记到全局结构变量pv中。可以实现对各种链路层的解码以及对ip、ipv6、arp、tcp、udp、icmp、ipx等协议的解码。
5.1.3规则处理模块
rules.c(h)
实现了规则设置和入侵检测所需要的函数。规则设置主要的作用是把一个规则文件转化为实际
运作中的规则链表。检测函数根据规则实施攻击特征的检测。
parser.c(h)
辅助完成与规则相关处理的功能。
5.1.4预处理模块(插件)
spp_*.c(.h)(preprocessors目录下)
实现预处理(preprocess)规则。包括http解码(即把http请求中的%XX这样的字
符用对应的ascii字符代替,避免忽略了恶意的请求)、最小片断检查(避免恶意利
用tcp协议中重组的功能)和端口扫描检测。
5.1.5检测引擎模块(插件)
fpcreate.c(h)
构建快速规则匹配引擎
Preprocessors目录下所有
sp_*_check.c(.h) (detection-plugins目录下)
是不同类型的检测规则的具体实现。很容易就可以从文件名得知所实现的规则。例
如,sp_dsize_check针对的是包的数据大小,sp_icmp_type_check针对icmp包的类
型,sp_tcp_flag_check针对tcp包的标志位。不再详述。
5.1.6输出模块(插件)
output-plugins目录下所有,13对.c和.h文件
spo_*.c(.h)
实现输出(output)规则。spo_alert_syslog把事件记录到syslog中;spo_log_tcpdump
利用libpcap中的日志函数,进行日志记录。
5.1.7日志模块
log.c(.h)
实现日志和报警功能。snort有多种日志格式,一种是按tcpdump二进制的格式存
储,另一种按snort编码的ascii格式存储在日志目录下,日志目录的名字根据"外"
主机的ip地址命名。报警有不同的级别和方式,可以记录到syslog中,或者记录
到用户指定的文件,另外还可以通过unix socket发送报警消息,以及利用SMB向
Windows系统发送winpopup消息。
5.1.8辅助模块
checksum.h
实现校验和算法
codes.c(h)
只有一个函数init_codes,其功能是将unicode_data的内容添加到codes[65536]字符
数组中。由spp_unidecode预处理器调用,进行unicode解码初始化。定义了
unicode_entry结构以及unicode_entry类型的数组unicode_data,该数组包含建立
unicode与ASCII码之间映射所需要的数据。
debug.c(h)
对debug级别定义和参数变量的格式化输出。
mstring.c(h)
字符串处理。
snprintf.c(h)
定义了一些增强的输出函数。(configure定义是否使用)
strlcatu.c(h)
只有一个函数strlcat(char *dst, const char *src, size_t siz),把src字符串追加到dst
的后面,siz用来限制sdt的最终长度
strlcpyu.c(h)
只有一个函数strlcpy(char *dst, const char *src, size_t siz),把src字符拷贝到dst,siz
用来限定复制的长度。
ubi_BinTree.c(h)
实现二叉树。
ubi_SplayTree.c(h)
实现伸展二叉树和相关功能(伸展二叉树是二叉树的一个特例,它的特点是每当一
个节点被访问时,就对树的结构进行重新排列。)。
tag.c(h)
在规则匹配之后进行更多的相关信息记录,以便对后面的数据进行分析。
5.2 按文件夹
需要分析的源代码分类(例子的目录夹排除在外)
目录名子
目
录
数
子目录名主要功能子
文
件
夹
子文件夹名称.h
文
件
数
量
.c文
件
数
量
Snort 7 所有模块
的初始化、
命令行解
释、配置文
件解释等
46 30
detection-plugins 实现检测
引擎插件
无32 32
dynamic-plugins 动态插件,
含快速模
式匹配有7 3
sf_engine 3 11
dynamic-preprocessors 动态预处
理有0 0
dcerpc 10 7
dns 2 1
ftptelnet 21 13 sf_dynamic_initialize
smtp 8 7
ssh 1 2
output-plugins 输出插件无13 13 parser IP分析程
序
无 1 1 preprocessors 预处理有23 22
在Flow,HttpInspect,Stream5三个
目录下有还有多个子目录,没有详细
统计
sfutil 快速模式
匹配的一
些基础函
数
无22 19
6代码解读建议
大家可能对Unix下的代码分析方式不熟悉或者不习惯,我们在分析snort的时候可以现在windows下分析,snort现在支持跨平台的搭建,区别就是有些库函数因为操作系统的不同用的不一样,不过功能很接近。这对于我们理解snort的机制和分析源代码大有帮助,不熟悉的成员可以根据自己的喜好在windows环境下进行代码的分析,增加了标注的源代码在unix环境下解读时,会方便很多。
Windows下环境介绍:
Winxp + VC6.0 + VC的红番茄插件
打开windows环境下的工程的步骤:
打开源代码文件→ win32→ WIN32-Prj→ snort.dsw
7部分缩写
Sp snort plugin snort插件
spp Snort plugin preprocessors snort预处理插件str stream 流