Snort3源码学习

作为一个几乎没什么C/C++基础的我一接到这个任务的时候感觉有点懵,虽然总说开发人员不要纠结于语言,但是新学一门编程语言还是需要一定时间的。 但是,snort毕竟是入侵检测系统的鼻祖,而最新snort3也是完成过一波重构的版本,作为以安全研发为目标的从业人员,还是应该尽力学习项目源码。

Snort安装部署

留坑,等笔记定稿后更新。

开发环境配置

CLion远程调试 + CentOS 8.2 + Snort 3.1.4 + cmake/gdb等。

Snort 2.9.16规则解析

在Snort中,检测规则在内存中被组织成二维链表的形式。 在二维链表中,一维被称为链表头或者规则头,另外一维被称为链表选项或者规则选项。

以一下规则为例,误报迅雷启动项为木马控制的排查。

第一行是规则头,()中的是规则项:

alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS 
(
msg:"MALWARE-CNC Win.Trojan.Donvibs variant outbound connection"; 
flow:to_server,established; 
content:"WinHttp.WinHttpRequest.5"; 
fast_pattern:only; 
http_header; 
urilen:6<>10; 
content:"GET"; http_method; 
content:"Accept: */*|0D 0A|User-Agent:"; http_header; 
content:!"Referer|3A|"; http_header; content:!"Via|3A|"; http_header; 
content:!"Content-Type|3A|"; http_header; 
metadata:impact_flag red, policy balanced-ips drop, policy security-ips drop, service http; reference:url,virustotal.com/en/file/0A6D9E6BBBDAA4536DA8B1D83CEC607ED5EC4CBD4E95F8B9BCFA2A1FF24A929D/analysis/; 
classtype:trojan-activity; sid:43523; rev:4;
)

规则头分析

alert  snort的动作
tcp    TCP协议
$HOME_NET    源IP地址 (支持网段)
any    源端口,这里是任意端口
->     通信方向,即数据包的方向
$EXTERNAL_NET    目的IP地址(支持网段)       
$HTTP_PORTS      目的端口(http协议端口, 支持范围,单个端口 或 任意组合)

规则选项分析

msg        将指定的文本消息写入日志或者警报信息,相对应的选项参数是希望显示的文本信息。
flow       数据流的配置。to_server: 客户端从A to B的请求; established: 仅建立TCP连接。
content    在数据包负载中搜索特定内容的信息从而触发相应动作,content选项的参数形式多样,可以是纯文本,也可以是二进制数据(16进制数形式),还可以两者混用。
fast_pattern   从属于前面的content,only表示在构建规则选项树的时候,不会加入它所描述的content内容

源端口   any表示任意
方向:-> 出去
目的端口:http协议端口
http协议端口包含:
[36,80,81,82,83,84,85,86,87,88,89,90,311,383,555,591,593,631,801,808,818,901,972,1158,1220,1414,1533,1741,1830,1942,2231,2301,2381,2578,2809,2980,3029,3037,3057,3128,3443,3702,4000,4343,4848,5000,5117,5250,5600,6080,6173,6988,7000,7001,7071,7144,7145,7510,7770,7777,7778,7779,8000,8008,8014,8028,8080,8081,8082,8085,8088,8090,8118,8123,8180,8181,8222,8243,8280,8300,8333,8344,8500,8509,8800,8888,8899,8983,9000,9060,9080,9090,9091,9111,9290,9443,9999,10000,11371,12601,13014,15489,29991,33300,34412,34443,34444,41080,44449,50000,50002,51423,53331,55252,55555,56712] 

http_method:GET请求
http_header:
包含WinHttp.WinHttpRequest.5
包含Accept: */*|0D 0A|User-Agent:
uri长度大于或等于6以及小于等于10(迅雷 /?appid=77 等于10)
不包含Referer|3A|(Referer:)
不包含Via|3A|(Via:)
不包含Content-Type|3A|(Content-Type:)

http_header:和http_uri一样
http_client_body:与http_header一样
metadata:可能是键值对或者只有键,在规则匹配成功后使用
classtype: 规则类型
gid:规则的group id
sid:在规则索引时和gid一起使用
rev: 版本

ref:

snort 源码分析之规则结构分析(一)

snort-rule-doesnt-generate-alerts-when-hosts-responding-simultaneously

snort 2.9.16官方文档

关于urilen

$request_uri里也会有个/的,所以关于uri从url的哪部分算起

例子: urilen:2<>10

注意: - Snort解释为:URI长度必须是 大于或等于 2,和 小于或等于 10英寸。 - Suricata将此解释:URI长度必须为 大于 2 和 小于 10英寸。

Snort参数备注

nocase 大小写不敏感

Snort 3 源码分析

留坑,等笔记写完再整合

REF

  1. snort 3官方开发文档,特别是:snort_devel.html
  2. Snort源码分析
  3. Snort 入侵检测系统源码分析--独孤九贱 (294页pdf,虽然是snort2的分析)
  4. Snort2.9.7的解析
  5. SNORT入侵检测系统

Other

PF_RING

ref: https://www.cnblogs.com/lxgeek/p/3893790.html

1) 未使用PF_RING时,收包存在的问题: 第一:inpterrupt livelock, 当收到包的时候,网卡驱动程序就会产生一次中断。在大流量的情况下,操作系统将花费大量时间用于处理中断,而只有 少量的时间用于其他任务。 第二:将包从网卡移动到用户层花费的时间太久。

2) PF_RING的目标 1. 充分利用 device polling 机制 2. 减少内核开销,开辟一条新的通道将收包从网卡传输到用户态

PF_RING架构图如下: PF_RING架构图

3)PF_RING实现功能

1. 创建一种新的套接字类型 PF_RING, 用于将收包拷贝到一个环形缓冲区
2. 环形缓冲区和PF_RING套接字一同创建和销毁,各个缓冲区为套接字私有
3.如果一个网卡适配器被PF_RING套接字利用系统调用bind()绑定,这个网卡只能用于只读直到套接字销毁
4.对于PF_RING套接字,收包将会被拷贝到套接字缓冲区或被丢包
5.套接字缓冲区将会利用mmap功能
6.用户态程序通过mmap()系统调用访问套接字缓冲区
7.内核拷贝包到环形队列并移动写指针,用户态程序读包并移动读指针
8.新来的包将会覆盖原有包,因此不需要进行内存的分配和释放
9.套接字的缓冲区的长度和桶大小可被用户配置