使用正则表达式(.NET)对复杂字符串(Snort规则)进行分词

3
我需要Regex专家的帮助。 我正在尝试编写一个简单的解析器,可以对Snort规则(IDS / IPS软件)的选项列表进行标记化。 问题是,我似乎找不到可行的公式,以根据它们的终止分号拆分单个规则选项。 我想出的公式将括号之间的所有选项捕获到单个组中。 我正在使用GSkinner网站上优秀的 RegExr工具,并使用以下来自Emerging Threats的示例规则选项之一(我已解析掉了规则头 - 这很容易标记化)。
(msg:"ET DELETED Majestic-12 Spider Bot User-Agent (MJ12bot)"; flow:to_server,established; content:"|0d 0a|User-Agent\: MJ12bot|0d 0a|"; classtype:trojan-activity; reference:url,www.majestic12.co.uk/; reference:url,doc.emergingthreats.net/2003409; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/POLICY/POLICY_Majestic-12; sid:2003409; rev:4;)
(msg:"ET DELETED Majestic-12 Spider Bot User-Agent Inbound (MJ12bot)"; flow:to_server,established; content:"|0d 0a|User-Agent\: MJ12bot"; classtype:trojan-activity; reference:url,www.majestic12.co.uk/; reference:url,doc.emergingthreats.net/2007762; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/POLICY/POLICY_Majestic-12; sid:2007762; rev:4;)
(msg:"ET POLICY McAfee Update User Agent (McAfee AutoUpdate)"; flow:to_server,established; content:"User-Agent|3a| "; http_header; nocase; content:"McAfee AutoUpdate"; http_header; pcre:"/User-Agent\x3a[^\n]+McAfee AutoUpdate/i"; classtype:not-suspicious; reference:url,doc.emergingthreats.net/2003381; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/POLICY/POLICY_McAffee; sid:2003381; rev:6;)
(msg:"ET DELETED Metacafe.com family filter off"; flow:established,to_server; content:"POST"; http_method; content:"Host|3a| www.metacafe.com"; http_header; fast_pattern:6,16; content:"submit=Continue+-+I%27m+over+18"; classtype:policy-violation; reference:url,doc.emergingthreats.net/2006367; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/POLICY/POLICY_Metacafe; sid:2006367; rev:7;)

这是公式:

([a-zA-Z0-9_:]+(?:[\w\s.,\-/=<>+!\[\]\(\)\{\}\"|\\;'?`~@#$%^&*])+;)

问题在于,它不能处理冒号。因此,上面两条规则的“content”选项将无法被正确解析。但是在RegExr上,每个选项都将以蓝色突出显示,包括终止分号,但不包括分号后面的空格。如果我将其输入.NET,则应该能够进行Regex.Split并正确地拆分所有标记。
如果我将冒号添加到字符列表中,则在RegExr上,整个规则集将被标记为单个文本块,这不是我想要的。进一步调整公式的尝试导致Adobe Flash崩溃,这表明我正在遇到Flash或RegExr中的错误。
我没有排除编写自己的字符串标记器,但我希望正则表达式可以让我免于处理诸如计算我的开放引号、转义字符、空格等问题。
Snort规则选项通常采用以下格式:
option:value;
option:"string value";
option:!"negated string value";
option:>num;
option:param1,param2,param3;

但是有些选项的值往往具有更加“奇特”的格式,比如byte_test。还有每个人都喜欢的“pcre”,它基本上是用于执行Perl兼容正则表达式的选项。因此,任何这样的分词器都必须避免在遇到带有正则表达式的“pcre”关键字时混淆。

你有什么想法?


编辑: 下面的内容非常接近:

([\w]+:?(?:[\x20]|)?(?:[\x00-\xff])*?;)

但是,根据RegExr的说法,它会被pcre语法弄乱:

(msg:"ET WEB_SPECIFIC_APPS Horde 3.0.9-3.1.0 Help Viewer Remote PHP Exploit"; flow:established,to_server; content:"/services/help/"; nocase; http_uri; pcre:"/module=[^\;]*\;.*\"/UGi"; classtype:web-application-attack; reference:url,www.milw0rm.com/exploits/1660; reference:cve,2006-1491; reference:bugtraq,17292; reference:url,doc.emergingthreats.net/2002867; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/WEB_SPECIFIC_APPS/WEB_Horde; sid:2002867; rev:9; http_method;)

在上面的内容中,每个选项都被突出显示为一个独立的分组,除了]*\;.*\"/。我认为\x00-\xff可以覆盖所有内容,但似乎我使用了懒惰匹配。贪婪匹配会获取所有内容,包括选项之间的所有空格,但我不希望这样。因此,我需要修改正则表达式以处理pcre文本的标记化。


编辑2:这就是解决方法:
([\w]+:?(?:[\x20]|)?(?<!\\)\"?.*?(?<!\\)\"?;)

我不得不使用一些适用于带引号字符串的正则表达式示例进行测试。最终意识到我正在查看避免被转义的引号的负向回顾。这似乎也解决了任何其他转义字符,因为转义字符只出现在未转义的引号内部。


Snort是一种入侵检测系统,基本上就像是用于网络流量的grep。它的一个规则选项被直接命名为"pcre",即Perl兼容正则表达式。在规则链中,它的格式如下:pcre:"/[a-z0-9]/i";。它通过链接到libpcre来处理任何需要的正则表达式解析。 - Kumba
关于如何进行标记化,我想抓取括号内的任何内容,在终止每个选项的分号上进行拆分,并将其放入数组中。我不能使用标准的.NET字符串拆分函数,因为像“content”或“pcre”这样的选项可能会在其中包含一个分号,这会使拆分器失效并输出不正确的结果。 - Kumba
1个回答

3
不需要使用lookaround。只需仔细编写正则表达式以精确匹配所需内容。通过在verbose free-spacing模式下编写,可以使其更加清晰(并且更易于维护),如下所示:(尽管VB.NET语法使此操作变得棘手)
Dim RegexObj As New Regex(
    "# Match set of Snort rules enclosed within parentheses." & chr(10) & _
    "\(                              # Literal opening parentheses." & chr(10) & _
    "(?:                             # Group for one or more rules." & chr(10) & _
    "  \w+                           # Required rule name." & chr(10) & _
    "  (?:                           # Group for optional rule value." & chr(10) & _
    "    :                           # Rule name/values separated by :" & chr(10) & _
    "    (?:                         # Group for rule value alternatives." & chr(10) & _
    "      ""                        # Either a double quoted string," & chr(10) & _
    "      [^""\\]*                  # {normal} Use ""Unrolling the Loop""." & chr(10) & _
    "      (?:                       # Begin {(special normal*)*} construct." & chr(10) & _
    "        \\.                     # {special} == escaped anything." & chr(10) & _
    "        [^""\\]*                # More {normal*} non-quote, non-escapes." & chr(10) & _
    "      )*                        # Finish {(special normal*)*} construct." & chr(10) & _
    "      ""                        # Closing quote." & chr(10) & _
    "    | '[^'\\]*(?:\\.[^'\\]*)*'  # or a single quoted string," & chr(10) & _
    "    | [^;]+                     # or one or more non semi-colons." & chr(10) & _
    "    )                           # End group for rule value options." & chr(10) & _
    "  )?                            # Rule value is optional." & chr(10) & _
    "  ; \s*                         # Rule ends with ;, optional ws." & chr(10) & _
    ")+                              # One or more rules." & chr(10) & _
    "\)                              # LiteraL closing parentheses.", 
    RegexOptions.IgnorePatternWhitespace)
Dim MatchResults As Match = RegexObj.Match(SubjectString)
While MatchResults.Success
    ' matched text: MatchResults.Value
    ' match start: MatchResults.Index
    ' match length: MatchResults.Length
    MatchResults = MatchResults.NextMatch()
End While

这个正则表达式展示了Jeffrey Friedl的"Unrolling the Loop"效率技巧,用于正确匹配可能包含转义字符的引用字符串。(参见: MRE3)

哦对了,还有一件事...Icarus找到你了!


我会给你答案,因为另一个人删除了他的回答,我猜他不想尝试修复它。我放弃了正则表达式 -- 当迭代多次时,它太耗费时间了。我写了一个简单的解析器,只查找反斜杠转义的双引号和反斜杠,以便我可以跟踪我在引用字符串中的位置。我不需要实际解析字符串,只需要知道我何时在引号内部,何时在引号外部,这样当我遇到分号时,我就知道我真正到达了规则选项的末尾。 - Kumba
利用我知道何时到达选项结尾的知识,使用子字符串将其复制到一个字符串列表中,然后我可以快速地分解长规则。基本上,使用正则表达式和迭代10,000次(我想),我在9,000ms范围内。使用简单解析器,我能够将其降低到约780ms左右。 - Kumba
伊卡洛斯找到我了?看起来像是《黑暗之魂》的参考。已经好几年没玩过那个游戏了。 - Kumba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接