Reswizzle sigs -> classifiers, prep for real sigs - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 4c5d46d2470eff1c43a8a7d088975c191330f06f
(DIR) parent 917c87718c063533f4e01756585d8080ed2a4a5c
(HTM) Author: HD Moore <hd_moore@rapid7.com>
Date: Fri, 28 Dec 2012 20:04:10 -0600
Reswizzle sigs -> classifiers, prep for real sigs
Diffstat:
M app/views/home/about.html.erb | 14 +++-----------
A config/classifiers/.keep | 0
A config/classifiers/01.default.rb | 80 +++++++++++++++++++++++++++++++
A config/classifiers/99.default.rb | 36 +++++++++++++++++++++++++++++++
A config/signatures/.keep | 0
D config/sigs/01.default.rb | 97 ------------------------------
D config/sigs/99.default.rb | 56 -------------------------------
M config/warvox.conf | 21 ++++++++++-----------
M lib/warvox/config.rb | 18 +++++++++---------
M lib/warvox/jobs/analysis.rb | 13 +++++--------
10 files changed, 143 insertions(+), 192 deletions(-)
---
(DIR) diff --git a/app/views/home/about.html.erb b/app/views/home/about.html.erb
@@ -4,9 +4,9 @@
<h1 class='title'>About WarVOX</h1>
<b>WarVOX</b> is a product of <a href="http://www.rapid7.com/">Rapid7 Inc</a> and is provided as
-free software under the BSD license. WarVOX is intended for legal security assessment, asset inventory,
+free software. WarVOX is intended for legal security assessment, asset inventory,
and research purposes only. The latest version of WarVOX can be found at
-<a href="http://github.com/rapid7/warvox/">http://github.com/rapid7/warvox/</a>.
+<a href="https://github.com/rapid7/warvox/">https://github.com/rapid7/warvox/</a>.
</td><td valign='top' align='center'>
@@ -17,7 +17,7 @@ and research purposes only. The latest version of WarVOX can be found at
<tr>
<td valign="top" align="right" class="header_item">
- WarVOX Version:
+ Version:
</td>
<td><%= WarVOX::VERSION %></td>
</tr>
@@ -76,14 +76,6 @@ and research purposes only. The latest version of WarVOX can be found at
<td><%= WarVOX::Conf %></td>
</tr>
-
-<tr>
- <td valign="top" align="right" class="header_item" width='200'>
- Data Storage:
- </td>
- <td><%= WarVOX::Config.data_path %></td>
-</tr>
-
<tr>
<td valign="top" align="right" class="header_item" width='200'>
Admin User:
(DIR) diff --git a/config/classifiers/.keep b/config/classifiers/.keep
(DIR) diff --git a/config/classifiers/01.default.rb b/config/classifiers/01.default.rb
@@ -0,0 +1,80 @@
+#
+# WarVOX Classifiers
+#
+
+#
+# These lightweight signatures are used to determine the
+# line type, which is the top-level classification that
+# differentiates between modem, fax, voice, and other
+# common results.
+#
+
+
+#
+# If you want to force your checks to run first, add your
+# logic to a file starting with "00." and place it in
+# this directory. Signature files are processed numerically
+# from lowest to highest (like RC scripts)
+#
+
+
+#
+# Initialize some local variables out of data
+#
+freq = data[:freq]
+fcnt = data[:fcnt]
+maxf = data[:maxf]
+
+#
+# Look for modems by detecting a 2100hz answer + 2250hz tone
+#
+if( (fcnt[2100] > 1.0 or fcnt[2230] > 1.0) and fcnt[2250] > 0.5)
+ @line_type = 'modem'
+ raise Completed
+end
+
+#
+# Look for modems by detecting a peak frequency of 2250hz
+#
+if(fcnt[2100] > 1.0 and (maxf > 2245.0 and maxf < 2255.0))
+ @line_type = 'modem'
+ raise Completed
+end
+
+#
+# Look for modems by detecting a peak frequency of 3000hz
+#
+if(fcnt[2100] > 1.0 and (maxf > 2995.0 and maxf < 3005.0))
+ @line_type = 'modem'
+ raise Completed
+end
+
+#
+# Look for faxes by checking for a handful of tones (min two)
+#
+fax_sum = 0
+[
+ fcnt[1625], fcnt[1660], fcnt[1825], fcnt[2100],
+ fcnt[600], fcnt[1855], fcnt[1100], fcnt[2250],
+ fcnt[2230], fcnt[2220], fcnt[1800], fcnt[2095],
+ fcnt[2105]
+].map{|x| fax_sum += [x,1.0].min }
+if(fax_sum >= 2.0)
+ @line_type = 'fax'
+ raise Completed
+end
+
+#
+# Dial tone detection (440hz + 350hz)
+#
+if(fcnt[440] > 1.0 and fcnt[350] > 1.0)
+ @line_type = 'dialtone'
+ raise Completed
+end
+
+#
+# To use additional heuristics, 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/config/classifiers/99.default.rb b/config/classifiers/99.default.rb
@@ -0,0 +1,36 @@
+#
+# WarVOX Classifiers
+#
+#
+
+#
+# Initialize some local variables out of data
+#
+freq = data[:freq]
+fcnt = data[:fcnt]
+maxf = data[:maxf]
+
+# 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.
+if(fcnt[1000] >= 1.0)
+ @line_type = 'voicemail'
+ raise Completed
+end
+
+# Look for voicemail by detecting a peak frequency of
+# 1000hz. Not as accurate, but thats why this is in
+# the fallback script.
+if(maxf > 995 and maxf < 1005)
+ @line_type = 'voicemail'
+ raise Completed
+end
+
+
+#
+# Fall back to 'voice' if nothing else has been matched
+# This should be the last check processed
+#
+
+@line_type = 'voice'
(DIR) diff --git a/config/signatures/.keep b/config/signatures/.keep
(DIR) diff --git a/config/sigs/01.default.rb b/config/sigs/01.default.rb
@@ -1,97 +0,0 @@
-#
-# WarVOX Default Signatures
-#
-
-#
-# 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)
-#
-
-
-#
-# Initialize some local variables out of data
-#
-freq = data[:freq]
-fcnt = data[:fcnt]
-maxf = data[:maxf]
-
-#
-# Look for silence by checking for a strong frequency in each sample
-#
-scnt = 0
-ecnt = 0
-=begin
-freq.each do |fsec|
- scnt += 1
- if(fsec.length == 0)
- ecnt += 1
- next
- end
- sump = 0
- fsec.map {|x| sump += x[1] }
- savg = sump / fsec.length
- ecnt += 1 if (savg < 100)
-end
-=end
-
-# Store these into data for use later on
-data[:scnt] = scnt
-data[:ecnt] = ecnt
-
-#
-# Look for modems by detecting a 2100hz answer + 2250hz tone
-#
-if( (fcnt[2100] > 1.0 or fcnt[2230] > 1.0) and fcnt[2250] > 0.5)
- @line_type = 'modem'
- raise Completed
-end
-
-#
-# Look for modems by detecting a peak frequency of 2250hz
-#
-if(fcnt[2100] > 1.0 and (maxf > 2245.0 and maxf < 2255.0))
- @line_type = 'modem'
- raise Completed
-end
-
-#
-# Look for modems by detecting a peak frequency of 3000hz
-#
-if(fcnt[2100] > 1.0 and (maxf > 2995.0 and maxf < 3005.0))
- @line_type = 'modem'
- raise Completed
-end
-
-#
-# Look for faxes by checking for a handful of tones (min two)
-#
-fax_sum = 0
-[
- fcnt[1625], fcnt[1660], fcnt[1825], fcnt[2100],
- fcnt[600], fcnt[1855], fcnt[1100], fcnt[2250],
- fcnt[2230], fcnt[2220], fcnt[1800], fcnt[2095],
- fcnt[2105]
-].map{|x| fax_sum += [x,1.0].min }
-if(fax_sum >= 2.0)
- @line_type = 'fax'
- raise Completed
-end
-
-#
-# Dial tone detection (440hz + 350hz)
-#
-if(fcnt[440] > 1.0 and fcnt[350] > 1.0)
- @line_type = 'dialtone'
- raise Completed
-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/config/sigs/99.default.rb b/config/sigs/99.default.rb
@@ -1,56 +0,0 @@
-#
-# WarVOX Fallback Signatures
-#
-#
-
-#
-# Initialize some local variables out of data
-#
-freq = data[:freq]
-fcnt = data[:fcnt]
-maxf = data[:maxf]
-ecnt = data[:ecnt]
-scnt = data[:scnt]
-
-
-# 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.
-if(fcnt[1000] >= 1.0)
- @line_type = 'voicemail'
- raise Completed
-end
-
-# Look for voicemail by detecting a peak frequency of
-# 1000hz. Not as accurate, but thats why this is in
-# the fallback script.
-if(maxf > 995 and maxf < 1005)
- @line_type = 'voicemail'
- raise Completed
-end
-
-=begin
-
-#
-# Look for silence by checking the frequency signature
-#
-if(freq.map{|f| f.length}.inject(:+) == 0)
- @line_type = 'silence'
- raise Completed
-end
-
-
-if(ecnt == scnt)
- @line_type = 'silence'
- raise Completed
-end
-=end
-
-#
-# Fall back to 'voice' if nothing else has been matched
-# This should be the last signature file processed
-#
-
-@line_type = 'voice'
-
(DIR) diff --git a/config/warvox.conf b/config/warvox.conf
@@ -2,7 +2,6 @@
# WarVOX Configuration
#
-
#
# Configure the username and password for the WarVOX
# web interface. This password is sent in clear text
@@ -12,12 +11,6 @@ authentication:
pass: warvox
#
-# Configure the path to all saved data files
-# This requires ~500M of space per 10k prefix
-#
-data_path: "%BASE%/data/"
-
-#
# Configure filesystem paths to each required tool
#
tools:
@@ -26,9 +19,10 @@ tools:
iaxrecord: "%BASE%/bin/iaxrecord.rb"
#
-# Maximum processing jobs, normally this
-# is set to your processor core count,
-# but you can limit it further here.
+# Maximum processing jobs, normally this is set to your processor core count,
+# but you can limit it further here. Keep in mind that each analysis job also
+# requires at least 512Mb of RAM (based on audio capture length). A 300 second
+# audio capture could consume 3Gb of RAM per thread (the default is 53 seconds).
#
max_analysis_threads: 0
@@ -38,6 +32,11 @@ max_analysis_threads: 0
blacklist: "%BASE%/config/blacklist.txt"
#
+# Configure the classifier directory
+#
+classifiers: "%BASE%/config/classifiers"
+
+#
# Configure the signature directory
#
-signatures: "%BASE%/config/sigs"
+signatures: "%BASE%/config/signatures"
(DIR) diff --git a/lib/warvox/config.rb b/lib/warvox/config.rb
@@ -32,13 +32,6 @@ module Config
)
end
- def self.data_path
- info = YAML.load_file(WarVOX::Conf)
- return nil if not info
- return nil if not info['data_path']
- File.expand_path(info['data_path'].gsub('%BASE%', WarVOX::Base))
- end
-
def self.analysis_threads
core_count = File.read("/proc/cpuinfo").scan(/^processor\s+:/).length rescue 1
@@ -83,8 +76,15 @@ module Config
File.expand_path(info['signatures'].gsub('%BASE%', WarVOX::Base))
end
- def self.signatures_load
- path = signatures_path
+ def self.classifiers_path
+ info = YAML.load_file(WarVOX::Conf)
+ return nil if not info
+ return nil if not info['classifiers']
+ File.expand_path(info['classifiers'].gsub('%BASE%', WarVOX::Base))
+ end
+
+ def self.classifiers_load
+ path = classifiers_path
sigs = []
return sigs if not path
(DIR) diff --git a/lib/warvox/jobs/analysis.rb b/lib/warvox/jobs/analysis.rb
@@ -13,7 +13,7 @@ class Analysis < Base
rescue ::LoadError
end
- class SignalProcessor
+ class Classifier
class Completed < RuntimeError
end
@@ -106,7 +106,7 @@ class Analysis < Base
fd.write(mr.audio)
end
- pfd = IO.popen("#{bin} '#{tmp.path}' '#{ dr.number.gsub("'", '') }'")
+ pfd = IO.popen("#{bin} '#{tmp.path}' '#{ dr.number.gsub(/[^0-9a-zA-Z\-\+]+/, '') }'")
out = Marshal.load(pfd.read) rescue nil
pfd.close
@@ -231,10 +231,10 @@ class Analysis < Base
end
#
- # Signature processing
+ # Classifier processing
#
- sproc = SignalProcessor.new
+ sproc = Classifier.new
sproc.data =
{
:raw => raw,
@@ -247,7 +247,7 @@ class Analysis < Base
:maxp => maxp
}
- WarVOX::Config.signatures_load.each do |sigfile|
+ WarVOX::Config.classifiers_load.each do |sigfile|
begin
str = File.read(sigfile, File.size(sigfile))
sproc.proc(str)
@@ -260,9 +260,6 @@ class Analysis < Base
# Save the guessed line type
res[:line_type] = sproc.line_type
- # Save any matched signatures
- res[:signatures] = sproc.signatures.map{|s| "#{s[0]}:#{s[1]}:#{s[2]}" }.join("\n")
-
png_big = Tempfile.new("big")
png_big_dots = Tempfile.new("bigdots")
png_big_freq = Tempfile.new("bigfreq")