Re: RFC: patch to skip some service matches

David Fifield <[email protected]>
Newsgroups gmane.comp.security.nmap.devel
Message-ID <[email protected]>
On Wed, Aug 24, 2016 at 10:23:40AM -0600, David Fifield wrote:
> On Wed, Aug 24, 2016 at 12:20:37AM -0500, Daniel Miller wrote:
> > List,
> > 
> > I've spent probably too much time today enhancing Nmap's service matching
> > system to try to reduce CPU time spent in regular expression matching.
> > Unfortunately, I can't tell whether it has improved anything yet, so I'm asking
> > for help testing.
> > 
> > Since this is a CPU-time enhancement, it would only affect scans which are
> > CPU-bound. For this reason, I've CC'd Tudor and Brandon, as their GSoC project
> > resulted in speedups of certain large scans due to algorithmic improvements,
> > and I hope they can test.
> > 
> > The change involves inspecting each match line in nmap-service-probes to see if
> > it is part of a contiguous group of match lines that will only ever match a
> > string starting with a given single byte. Already, this means we are targeting
> > only the very fastest match lines, so chances are good there won't be
> > noticeable improvement. The first such match in a group will link to the last
> > one (by index) so that the entire group can be skipped if the first match fails
> > because of an incorrect initial byte. There are groups of hundreds of such
> > contiguous match lines in a few places: FTP matches starting with "2", SSH
> > matches starting with "S", and HTTP matches starting with "H" for instance.
> 
> I've thought about this problem too. I'm intrigued by the Rust
> "RegexSet" API:
> https://doc.rust-lang.org/regex/regex/struct.RegexSet.html
> "A regex set corresponds to the union of two or more regular
> expressions... it will also report *which* regular expressions in the
> set match."
> 
> A RegexSet feels like the "right" way to do our kind of matching. But I
> haven't found an equivalent API in PCRE, or in any library other than
> Rust's. It presumably requires the RE engine to use a linear-time
> matching algorithm (as in https://swtch.com/~rsc/regexp/regexp1.html) so
> that matching the union of many REs will be faster than matching each
> one individually in turn--the NFA implementation would do your
> first-byte optimization implicitly.

It turns out the C++ re2 library also has this regex set feature (the
Rust library got the idea from re2).
https://github.com/google/re2/blob/4bb66d4f2fff9c5d4b0ef72634723180aba9f320/re2/set.h

The idea is that for each Probe in nmap-service-probes, you would have a
data structure consisting of both an RE2::Set and a list of all the
Regexp patterns that compose it (including all fallbacks). You would
then match your data against the RE2::Set to get a list of matching
indices. Take the smallest index (as if you were testing Regexps
sequentially and stopping at the first match) and then re-do the match
against the Regexp at that index, in order to extract captures (the
RE2::Set doesn't give you captures).
_______________________________________________
Sent through the dev mailing list
https://nmap.org/mailman/listinfo/dev
Archived at http://seclists.org/nmap-dev/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.