比较文件并在新文件中注释相同的行

问题描述

目标:我想比较两个 Suricata 规则文件并从文件 2 中的文件 1 中注释掉相同的行(警报“SID”),除非它已经注释掉了。我知道使用 Suricata 阈值文件有更好的方法来做到这一点,但不幸的是,除了我在这里可以解释的之外,我没有那种奢侈。这是为了便于更新规则,其中规则可能会更新,但“SID”在两个文件中的通用性将相同。

我不知道从哪里开始。

示例文件 1 文本:

alert $home_net any > $External_net any (msg: example; content: something; sid: 12345; rev:1)
#alert $home_net any > $External_net any (msg: example; content: something; sid: 67895; rev:1)
alert $home_net any > $External_net any (msg: example; content: something; sid: 18975; rev:1)

示例文件 2 文本:

alert $home_net any > $External_net any (msg: example; content: something; sid: 12345; rev:1)
<insert #>alert $home_net any > $External_net any (msg: example; content: something; sid: 67895; rev:1)
alert $home_net any > $External_net any (msg: example; content: something; sid: 18975; rev:1)

编辑:提供的解决方案适用于我上面提供的初始样本数据,但不适用于实际签名。所以我在下面提供实际签名。此外,规则每行之间可能有也可能没有空格。

示例文件 1 文本:

#alert tcp $EXTERNAL_NET any -> $HOME_NET 2200 (msg:"ET EXPLOIT CA BrightStor ARCserve Mobile Backup LGSERVER.EXE Heap Corruption"; flow:established,to_server; content:"|4e 3d 2c 1b|"; depth:4; isdataat:2891,relative; reference:cve,2007-0449; reference:url,doc.emergingthreats.net/bin/view/Main/2003369; classtype:attempted-admin; sid:2003369; rev:3; Metadata:created_at 2010_07_30,updated_at 2010_07_30;)

alert udp $EXTERNAL_NET any -> $HOME_NET 111 (msg:"ET EXPLOIT Computer Associates Brightstor ARCServer Backup RPC Server (Catirpc.dll) DoS"; content:"|00 00 00 00|"; offset:4; depth:4; content:"|00 00 00 03|"; distance:8; within:4; content:"|00 00 00 08|"; distance:0; within:4; content:"|00 00 00 00|"; distance:0; within:4; content:"|00 00 00 00|"; distance:4; within:4; content:"|00 00 00 00 00 00 00 00|"; distance:8; within:32; reference:url,www.milw0rm.com/exploits/3248; reference:url,doc.emergingthreats.net/bin/view/Main/2003370; classtype:attempted-dos; sid:2003370; rev:3; Metadata:created_at 2010_07_30,updated_at 2020_08_20;)

#alert tcp $EXTERNAL_NET any -> $HOME_NET 1900 (msg:"ET EXPLOIT Computer Associates Mobile Backup Service LGSERVER.EXE Stack Overflow"; flow:established,to_server; content:"0000033000"; depth:10; isdataat:1000,relative; reference:url,www.milw0rm.com/exploits/3244; reference:url,doc.emergingthreats.net/bin/view/Main/2003378; classtype:attempted-admin; sid:2003378; rev:3; Metadata:created_at 2010_07_30,updated_at 2010_07_30;)

示例文件 2 文本:

#alert tcp $EXTERNAL_NET any -> $HOME_NET 2200 (msg:"ET EXPLOIT CA BrightStor ARCserve Mobile Backup LGSERVER.EXE Heap Corruption"; flow:established,updated_at 2010_07_30;)
alert udp $EXTERNAL_NET any -> $HOME_NET 111 (msg:"ET EXPLOIT Computer Associates Brightstor ARCServer Backup RPC Server (Catirpc.dll) DoS"; content:"|00 00 00 00|"; offset:4; depth:4; content:"|00 00 00 03|"; distance:8; within:4; content:"|00 00 00 08|"; distance:0; within:4; content:"|00 00 00 00|"; distance:0; within:4; content:"|00 00 00 00|"; distance:4; within:4; content:"|00 00 00 00 00 00 00 00|"; distance:8; within:32; reference:url,updated_at 2020_08_20;)
< insert #>alert tcp $EXTERNAL_NET any -> $HOME_NET 1900 (msg:"ET EXPLOIT Computer Associates Mobile Backup Service LGSERVER.EXE Stack Overflow"; flow:established,updated_at 2010_07_30;)

解决方法

首先,检查第一个文件,找出哪些 sid 被注释掉了:

sed -En '/^#/ s/.*sid:([0-9]+).*/\1/p' file1

上面的命令打印出以 # 开头的行的 sid,每行一个 sid。现在让我们聚合这些行并构建一个以 | 分隔的 sid 列表:

sed -En '/^#/ s/.*sid:([0-9]+).*/\1/p' file1 | paste -sd '|'

好的,现在我们有了 sid1|sid2|...|sidN。正如所写,这可以用作正则表达式来标识 file2 中需要注释掉的行。让我们把这个正则表达式放在一个变量中:

sid_regex=$(sed -En '/^#/ s/.*sid:([0-9]+).*/\1/p' file1 | paste -sd '|')

现在,我们可以修改 file2,以便将 1) 与正则表达式匹配的 sid 和 2) 尚未以 # 开头的每一行都注释掉:

sed -E "/sid:($sid_regex);/ s/^[^#]/#&/" file2 > file2.new

瞧!总结一下:

$ sid_regex=$(sed -En '/^#/ s/.*sid:([0-9]+).*/\1/p' file1 | paste -sd '|')
$ sed -E "/sid:($sid_regex);/ s/^[^#]/#&/" file2 > file2.new

[更新] 你有太多的注释行,结果巨大的正则表达式使命令太大(“参数列表太长”)。让我们尝试另一种方法:我们将构建一个多行 sed 程序,而不是使用巨大的正则表达式构建单行 sed 程序,每个 sid 一行。

第一个 sed 命令生成第二个 sed 程序:

sed -En '/^#/ s|.*(sid:[0-9]+;).*|/\1/ s/^[^#]/#\&/|p' file1

结果应该是这样的:

/sid:111;/ s/^[^#]/#&/
/sid:222;/ s/^[^#]/#&/
...
/sid:123456;/ s/^[^#]/#&/

现在我们用该程序提供第二个 sed 以处理 file2:

sed -En '/^#/ s|.*(sid:[0-9]+;).*|/\1/ s/^[^#]/#\&/|p' file1 | sed -f - file2 > file2.new

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...