Add the new signature structure - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 6d4ec6d54551bc27269e9202e8ed3ebfb62b952d
 (DIR) parent a919a76a13611af8105aff7c96fad4a714e3c6c7
 (HTM) Author: HD Moore <hd_moore@rapid7.com>
       Date:   Tue, 19 May 2009 02:30:46 +0000
       
       Add the new signature structure
       
       Diffstat:
         A etc/sigs/01.default.rb              |      96 +++++++++++++++++++++++++++++++
         A etc/sigs/99.default.rb              |      10 ++++++++++
         M etc/warvox.conf                     |       5 +++++
         M lib/warvox/config.rb                |      23 +++++++++++++++++++++++
         M lib/warvox/jobs/analysis.rb         |      66 ++++++-------------------------
       
       5 files changed, 146 insertions(+), 54 deletions(-)
       ---
 (DIR) diff --git a/etc/sigs/01.default.rb b/etc/sigs/01.default.rb
       @@ -0,0 +1,96 @@
       +#
       +# WarVOX Default Signatures
       +#
       +
       +#
       +# Variables:
       +#        pks  = peak frequencies
       +#        ppz  = top 10 frequencies per sample
       +#        flow = flow signature
       +#
       +
       +#
       +# These signatures are used first and catch the majority of common
       +# systems. If you want to force a different type of detection, add
       +# your signatures to a file starting with "00." and place it in
       +# this directory. Signature files are processed numerically from
       +# lowest to highest (like RC scripts)
       +#
       +
       +
       +#
       +# Look for silence by checking for any significant noise
       +#
       +if(flow.split(/\s+/).grep(/^H,/).length == 0)
       +        line_type = 'silence'
       +        break
       +end
       +
       +
       +#
       +# Look for modems by detecting a peak 2250hz tone
       +#
       +f_2250 = 0
       +pks.each{|f| f_2250 += 1 if(f[0] > 2240 and f[0] < 2260) }
       +if(f_2250 > 2)
       +        line_type = 'modem'
       +        break                                
       +end
       +
       +
       +#
       +# Most faxes have at least two of the following tones
       +# This can false positive if the modem signature above
       +# is removed.
       +#
       +f_1625 = f_1660 = f_1825 = f_2100 = false
       +pks.each do |f|
       +        f_1625 = true if(f[0] > 1620 and f[0] < 1630)
       +        f_1660 = true if(f[0] > 1655 and f[0] < 1665)
       +        f_1825 = true if(f[0] > 1820 and f[0] < 1830)
       +        f_2100 = true if(f[0] > 2090 and f[0] < 2110)                                                                                
       +end
       +if([ f_1625, f_1660, f_1825, f_2100 ].grep(true).length >= 2)
       +        line_type = 'fax'
       +        break
       +end
       +
       +
       +#
       +# Dial tone detection (more precise to use pkz over pks)
       +# Look for a combination of 440hz + 350hz signals
       +#
       +f_440 = 0
       +f_350 = 0
       +pkz.each do |fb|
       +        fb.each do |f|
       +                f_440  += 0.1 if (f[0] > 437 and f[0] < 444)        
       +                f_350  += 0.1 if (f[0] > 345 and f[0] < 355)
       +        end
       +end
       +if(f_440 > 1.0 and f_350 > 1.0)
       +        line_type = 'dialtone'
       +        break
       +end
       +
       +
       +#
       +# Look for voice mail by detecting the 1000hz BEEP
       +# If the call length was too short to catch the beep,
       +# this signature can fail. For non-US numbers, the beep
       +# is often a different frequency entirely.
       +#
       +f_1000 = 0
       +pks.each{|f| f_1000 += 1 if(f[0] > 990 and f[0] < 1010) }
       +if(f_1000 > 0)
       +        line_type = 'voicemail'
       +        break                                
       +end
       +
       +
       +#
       +# To use additional signatures, add new scripts to this directory
       +# named XX.myscript.rb, where XX is a two digit number less than
       +# 99 and greater than 01.
       +#
       +#
 (DIR) diff --git a/etc/sigs/99.default.rb b/etc/sigs/99.default.rb
       @@ -0,0 +1,10 @@
       +#
       +# WarVOX Fallback Signatures
       +#
       +
       +#
       +# Fall back to 'voice' if nothing else has been matched
       +# This should be last signature file processed 
       +#
       +
       +line_type = 'voice'
 (DIR) diff --git a/etc/warvox.conf b/etc/warvox.conf
       @@ -38,3 +38,8 @@ analysis_threads: 2
        # Configure the dial blacklist location
        #
        blacklist: %BASE%/etc/blacklist.txt
       +
       +#
       +# Configure the signature directory
       +#
       +signatures: %BASE%/etc/sigs
 (DIR) diff --git a/lib/warvox/config.rb b/lib/warvox/config.rb
       @@ -73,6 +73,29 @@ module Config
                        
                end
        
       +        def self.signatures_path
       +                info = YAML.load_file(WarVOX::Conf)
       +                return nil if not info
       +                return nil if not info['signatures']
       +                File.expand_path(info['signatures'].gsub('%BASE%', WarVOX::Base))
       +        end
       +        
       +        def self.signatures_load
       +                path = signatures_path
       +                sigs = []
       +                return sigs if not path
       +
       +                Dir.new(path).entries.sort{ |a,b| 
       +                        a.to_i <=> b.to_i 
       +                }.map{ |ent| 
       +                        File.join(path, ent) 
       +                }.each do |ent|
       +                        sigs << ent if File.file?(ent)
       +                end
       +                
       +                sigs
       +        end
       +        
                # This method searches the PATH environment variable for
                # a fully qualified path to the supplied file name.
                # Stolen from Rex
 (DIR) diff --git a/lib/warvox/jobs/analysis.rb b/lib/warvox/jobs/analysis.rb
       @@ -170,8 +170,10 @@ class Analysis < Base
                        # Calculate average frequency and peaks over time
                        avg = {}
                        pks = []
       +                pkz = []
                        fft.each do |slot|
                                pks << slot.sort{|a,b| a[1] <=> b[1] }.reverse[0]
       +                        pkz << slot.sort{|a,b| a[1] <=> b[1] }.reverse[0..9]
                                slot.each do |freq|
                                        avg[ freq[0] ] ||= 0
                                        avg[ freq[0] ] +=  freq[1]
       @@ -188,64 +190,20 @@ class Analysis < Base
                        end
                        frefile.flush
        
       -                #
       -                # XXX: store significant frequencies somewhere (tones)
       -                #
       -
                        # Make a guess as to what kind of phone number we found
                        line_type = nil
       -                while(not line_type)
       -
       -                        # Look for silence
       -                        if(flow.split(/\s+/).grep(/^H,/).length == 0)
       -                                line_type = 'silence'
       -                                break
       -                        end
       -
       -                        # Look for modems by detecting 2250hz tones
       -                        f_2250 = 0
       -                        pks.each{|f| f_2250 += 1 if(f[0] > 2240 and f[0] < 2260) }
       -                        if(f_2250 > 2)
       -                                line_type = 'modem'
       -                                break                                
       -                        end
        
       -                        # Look for the 1000hz voicemail BEEP
       -                        if(res[:peak_freq] > 990 and res[:peak_freq] < 1010)
       -                                line_type = 'voicemail'
       -                                break
       -                        end
       -
       -                        # Most faxes have at least two of the following tones
       -                        f_1625 = f_1660 = f_1825 = f_2100 = false
       -                        pks.each do |f|
       -                                # $stderr.puts "#{r.number} #{f.inspect}"
       -                                f_1625 = true if(f[0] > 1620 and f[0] < 1630)
       -                                f_1660 = true if(f[0] > 1655 and f[0] < 1665)
       -                                f_1825 = true if(f[0] > 1820 and f[0] < 1830)
       -                                f_2100 = true if(f[0] > 2090 and f[0] < 2110)                                                                                
       -                        end
       -                        if([ f_1625, f_1660, f_1825, f_2100 ].grep(true).length >= 2)
       -                                line_type = 'fax'
       -                                break
       -                        end                        
       -
       -                        # Dial tone detection
       -                        f_440 = false
       -                        f_350 = false
       -                        pks.each do |f|
       -                                f_440 = true if(f[0] > 435 and f[0] < 445)
       -                                f_345 = true if(f[0] > 345 and f[0] < 355)
       -                        end
       -                        if(f_440 and f_350)
       -                                line_type = 'dialtone'
       -                                break
       +                WarVOX::Config.signatures_load.each do |sigfile|
       +                        begin
       +                                str = File.read(sigfile, File.size(sigfile))
       +                                while(true)
       +                                        eval(str, binding)
       +                                        break
       +                                end
       +                        rescue ::Exception => e
       +                                $stderr.puts "DEBUG: Caught exception in #{sigfile}: #{e} #{e.backtrace}"
                                end
       -
       -                        # Detect humans based on long pauses
       -
       -                        # Default to voice
       -                        line_type = 'voice'
       +                        break if line_type
                        end
        
                        # Save the guessed line type