Reupload after previous removal. - projectvoip - VoIP honeypot similar to ssh honeypot, using asterisk as the backend.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 94772bd4e5c9fa0bb421346c9b8724a08706b972
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Wed,  5 May 2021 20:40:30 +0100
       
       Reupload after previous removal.
       
       Diffstat:
         A README                              |      36 +++++++++++++++++++++++++++++++
         A crontab                             |       3 +++
         A extensions.conf                     |      24 ++++++++++++++++++++++++
         A project-voip.rb                     |     242 +++++++++++++++++++++++++++++++
         A sip.conf                            |      21 +++++++++++++++++++++
         A voip.sql                            |      49 +++++++++++++++++++++++++++++++
       
       6 files changed, 375 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -0,0 +1,36 @@
       +
       + __   __   __        ___  __  ___       __     __  
       +|__) |__) /  \    | |__  /  `  |  \  / /  \ | |__) 
       +|    |  \ \__/ \__/ |___ \__,  |   \/  \__/ | |    
       +                                                   
       +
       +Project VOIP was meant to be a VOIP honeypot, but I haven't had much
       +time to develop it, so I am uploading everything I have so far. Project
       +VOIP is based on phorensix v1.0 by J. Oquendo / sil @ infiltrated dot
       +net.
       +
       +Phorensix was scripted in bash and logged all information to a series of
       +files. Project VOIP is coded in Ruby has been updated to work with the
       +latest version of asterisk and also logs all information to a MySQL
       +database.
       +
       +* Logs the following information to a mysql database:
       +  * IP Address information
       +  * Peer(s) AS Number
       +  * Netblock AS Number
       +  * Netblock Prefix
       +  * AS Name
       +  * AS Country
       +  * AS Domain name
       +  * ISP Name
       +* Number called
       +* SIP Agent
       +* SIP channel used
       +* Traceroute of the IP Address
       +* Packet capture of the session (.cap file)
       +* Recording of the call  (.wav)
       +
       +usage:
       +
       +        $ apt-get install tshark rubygems mysql-client libmysqlclient-dev
       +        $ gem install mysql
 (DIR) diff --git a/crontab b/crontab
       @@ -0,0 +1,3 @@
       +# Dump the .cap and  .wav every 18 mins - dirty hack
       +
       +*/18 * * * * /usr/bin/ruby -w /home/jay/project-voip.rb -d 1 2>&1
 (DIR) diff --git a/extensions.conf b/extensions.conf
       @@ -0,0 +1,24 @@
       +[general] 
       +
       +static=yes 
       +writeprotect=no 
       +clearglobalvars=yes 
       +autofallthrough=yes
       +
       +[project-voip]
       + 
       +exten => _X.,1,Set(CTIME=${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)})
       +exten => _X.,n,system(/usr/bin/ruby /home/jay/project-voip.rb -i ${SIPCHANINFO(peerip)} -w /opt/project-voip/wav/${CTIME}.wav -c ${CHANNEL} -e ${EXTEN} -u '${SIPCHANINFO(useragent)}' &)
       +exten => _X.,n,Answer
       +exten => _X.,n,Wait(1)
       +exten => _X.,n,Playtones(ring)
       +exten => _X.,n,Wait(5)
       +exten => _X.,n,StopPlaytones
       +exten => _X.,n,Playback(press-pound-to-login-star-to-hangup)
       +exten => _X.,n,Record(/opt/project-voip/wav/${CTIME}:wav,,,qk)
       +exten => _X.,n,Wait(1)
       +exten => _X.,n,Hangup
       +
       +[default]
       +
       +include => project-voip
 (DIR) diff --git a/project-voip.rb b/project-voip.rb
       @@ -0,0 +1,242 @@
       +#!/usr/bin/ruby
       +
       +=begin
       +
       +Project VOIP
       +=============
       +
       +
       +Project VOIP was meant to be a VOIP honeypot but I havent had much time to
       +develop it so I am uploading everything I have so far here :-) 
       +
       +Project VOIP is based on phorensix v.1 by J. Oquendo / sil @ infiltrated dot net.
       +
       +Phorensix was scripted in bash and logged all information to a series of files. 
       +Project VOIP is coded in Ruby has been updated to work with the latest version of
       +asterisk and also logs all information to a MySQL database. 
       +
       +Jay Scott <jay@jayscott.co.uk>
       +
       +
       +What it does
       +------------
       +
       +-> Logs the following information to a mysql database: 
       + -> IP Address information
       +   -> Peer(s) AS Number
       +   -> Netblock AS Number
       +   -> Netblock Prefix
       +   -> AS Name
       +   -> AS Country
       +   -> AS Domain name
       +   -> ISP Name
       + -> Number called
       + -> SIP Agent
       + -> SIP Channel used.
       + -> Traceroute of the IP Address
       + -> Packet capture of the session (.cap file)
       + -> Recording of the call  (.wav)
       +
       +Installing
       +----------
       +
       +Install Tshark and ruby gems if not installed already
       +
       + - apt-get install tshark rubygems mysql-client libmysqlclient-dev
       +
       +Install the ruby gem files for mysql
       +
       +  gem install mysql
       +
       +Use the configs below as a template, changing the values as appropriate
       +
       +
       +Make sure and update the Mysql information!.
       + 
       +=end
       +
       +require 'rubygems'
       +require 'optparse'
       +require 'mysql'
       +
       +BASE_DATA     = "/opt/project-voip/data"
       +CRON_FILE     = "/opt/project-voip/data/cron"
       +MYSQL_HOST    = ""
       +MYSQL_USER    = ""
       +MYSQL_PASS    = ""
       +MYSQL_TABLE   = ""
       +HONEYPOT_ID   = "1"
       +
       +options = {}
       + 
       +op = OptionParser.new do|opts|
       +
       +  opts.banner = "Usage: ruby #{File.basename($0)} "
       +  options[:ipaddress] = nil
       +  options[:data] = nil
       +  options[:useragent] = "Unknown"
       +  options[:exten] = "Unknown"
       +  options[:channel] = "Unknown"
       +
       +  opts.on( '-i', '--ipaddress [IPADDRESS]', 'IP Address' ) do|i|
       +    options[:ipaddress] = i
       +  end
       +
       +  opts.on( '-e', '--exten [EXTEN]', 'Phone number called ' ) do|e|
       +    options[:exten] = e 
       +  end
       +
       +  opts.on( '-c', '--channel [CHANNEL]', 'Channel passed by Asterisk' ) do|c|
       +    options[:channel] = c 
       +  end
       +  
       +  opts.on( '-u', '--useragent [USERAGENT]', 'Callers user-agent' ) do|u|
       +    options[:useragent] = u
       +  end
       +  
       +  opts.on( '-w', '--wav [WAV FILE]', 'WAV file location' ) do|w|
       +    options[:wav] = w
       +  end
       +  
       +  opts.on( '-d', '--data', 'Upload Data Files to MySQL.' ) do
       +    options[:data] = true
       +  end
       +
       +  opts.on( '-h', '--help', 'Display this screen' ) do
       +    puts opts
       +    exit
       +  end
       +
       +  opts.on("--version", "Show version") do
       +    puts OptionParser::Version.join('.')
       +    exit
       +  end
       +end
       + 
       +op.parse!
       +
       +# Get the options passed
       +ip_address      = options[:ipaddress]
       +data_update     = options[:data]
       +useragent       = options[:useragent]
       +called_exten    = options[:exten]
       +caller_channel  = options[:channel]
       +wav_file        = options[:wav]
       +
       +# No IP.. somethings wrong, exit :p
       +if !data_update.nil?
       +
       +  File.open("#{CRON_FILE}").each_line{ |s|
       +    arrayData = s.split(':')
       +    file_id = arrayData[0]
       +    file_cap = arrayData[1].strip
       +    file_wav = arrayData[2].strip
       +    
       +    cf = File.new(file_cap, 'rb')
       +    wf = File.new(file_wav, 'rb')
       +    
       +    cap_data = Mysql.escape_string(cf.sysread(cf.stat.size))
       +    wav_data = Mysql.escape_string(wf.sysread(wf.stat.size))
       +    
       +    begin
       +      con_info = Mysql.real_connect("#{MYSQL_HOST}", "#{MYSQL_USER}", "#{MYSQL_PASS}", "#{MYSQL_TABLE}")
       +    rescue Mysql::Error => e
       +         puts "Error code: #{e.errno}"
       +         puts "Error message: #{e.error}"
       +         puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
       +    end
       +    
       +    con_info.query("UPDATE caller SET capture=\"#{cap_data}\", recording=\"#{wav_data}\" WHERE id='#{file_id}'")
       +    
       +    con_info.close
       +  }
       +  
       +  puts "Updated"
       +  File.delete("#{CRON_FILE}")
       +  File.new("#{CRON_FILE}", "w")
       +  exit(1)
       +  
       +end
       +
       +# No IP.. somethings wrong, exit :p
       +if ip_address.nil?
       +  exit(-1)
       +end
       +
       +# Set the dates we want
       +date = Time.new
       +current_date  = date.strftime("%Y%m%d")
       +current_time  = date.strftime("%H%M%S")
       +mysql_date    = date.strftime("%H%M%S")
       +
       +cap_file  =  "#{BASE_DATA}/#{ip_address}-#{mysql_date}.cap"
       +
       +whois_info = Array.new
       +whois_data = `whois -h whois.pwhois.org #{ip_address}`
       +whois_info = whois_data.split("\n")
       +
       +# ip_address, origin_as, prefix, as_path, as_org_name, org_name, net_name, cache_date, lat, long, city, region, country
       +whois_info = whois_info.map do |x| 
       +  x.split(':')[1].strip
       +end
       +
       +traceroute_output = `traceroute -w 1 -m 25 -n #{ip_address} &`
       +packet_capture = `tshark -q -R \"ip.addr == #{ip_address}\" -w #{cap_file} -a duration:20 &`
       +
       +# Connect to MySQL DB. 
       +begin
       +  con_info = Mysql.real_connect("#{MYSQL_HOST}", "#{MYSQL_USER}", "#{MYSQL_PASS}", "#{MYSQL_TABLE}")
       +rescue Mysql::Error => e
       +     puts "Error code: #{e.errno}"
       +     puts "Error message: #{e.error}"
       +     puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
       +end
       +
       +rs_check = con_info.query("SELECT * from information WHERE ip_address='#{ip_address}'")
       +
       +# If the IP is unique then create a new record for it. 
       +if rs_check.num_rows == 0
       +  con_info.query("INSERT INTO information 
       +                (ip_address, asn, prefix, as_path, as_org_name, org_name, net_name, lat, lon, city, region, country, traceroute) 
       +                VALUES 
       +                ('#{ip_address}', '#{whois_info[1]}', '#{whois_info[2]}', '#{whois_info[3]}', '#{whois_info[4]}', '#{whois_info[5]}', '#{whois_info[6]}', '#{whois_info[8]}', '#{whois_info[9]}', '#{whois_info[10]}', '#{whois_info[11]}', '#{whois_info[12]}', '#{traceroute_output}')")
       +end
       +
       +d = DateTime.now
       +
       +# Insert the call information
       +con_info.query("INSERT INTO caller 
       +                (uid, number, agent, channel, timestamp, honeypot) 
       +                VALUES 
       +                ('#{ip_address}','#{called_exten}','#{useragent}','#{caller_channel}', '#{d.to_s}', '#{HONEYPOT_ID}')")
       +
       +
       +# This section dumps the wav and cap file information to a file to be read by 
       +# cron. We cant upload the wav and cap file at the same time because you dont
       +# know if the call has finished so the wav and cap are still in progress.
       +#
       +# Asterisk cant reliably detect if a call has terminated, if it did we could
       +# call function to kill tshark and then update the DB with the file data then. 
       +#
       +# PROBLEM: The cron could run just after this information has been saved or not
       +# finished processing and chop the data anyway 
       +# 
       +# meh.... need to ditch asterisk and just create my own sip server.
       +
       +# Get the ID of the record we just inserted.
       +
       +rs_id = con_info.query("SELECT MAX(id) AS MAXID FROM caller")
       +
       +while row = rs_id.fetch_row do
       +    last_id = row[0]
       +end
       +
       +con_info.close
       +
       +if !File::file?(CRON_FILE)
       +  cronFile = File.new("#{CRON_FILE }", "w")
       +end
       +
       +File.open("#{CRON_FILE}", "a") do |f|
       +  f.puts "#{last_id}:#{cap_file}:#{wav_file}"
       +end
 (DIR) diff --git a/sip.conf b/sip.conf
       @@ -0,0 +1,21 @@
       +[general]
       +context=project-voip            ; Default context for incoming calls
       +allowoverlap=no                 ; Disable overlap dialing support. (Default is yes)
       +udpbindaddr=0.0.0.0             ; IP address to bind UDP listen socket to (0.0.0.0 binds to all)
       +tcpenable=yes                   ; Enable server for incoming TCP connections (default is no)
       +tcpbindaddr=0.0.0.0             ; IP address for TCP server to bind to (0.0.0.0 binds to all interfaces)
       +srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
       +alwaysauthreject=no
       +allowguest=yes
       +
       +
       +[100]
       +username=100
       +secret=100
       +context=project-voip
       +type=friend
       +canreinvite=no
       +host=dynamic
       +qualify=1000
       +mailbox=100
       +allow=all
 (DIR) diff --git a/voip.sql b/voip.sql
       @@ -0,0 +1,49 @@
       +
       +
       +DROP TABLE IF EXISTS `caller`;
       +CREATE TABLE IF NOT EXISTS `caller` (
       +  `id` int(15) NOT NULL AUTO_INCREMENT,
       +  `uid` varchar(15) NOT NULL,
       +  `number` varchar(100) DEFAULT NULL,
       +  `agent` varchar(100) DEFAULT NULL,
       +  `channel` varchar(100) DEFAULT NULL,
       +  `capture` longblob NOT NULL,
       +  `recording` longblob NOT NULL,
       +  `timestamp` datetime NOT NULL,
       +  `dumped` int(1) NOT NULL DEFAULT '0',
       +  `honeypot` int(11) NOT NULL,
       +  PRIMARY KEY (`id`),
       +  KEY `uid` (`uid`)
       +) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
       +
       +DROP TABLE IF EXISTS `information`;
       +CREATE TABLE IF NOT EXISTS `information` (
       +  `id` int(15) NOT NULL AUTO_INCREMENT,
       +  `ip_address` varchar(15) NOT NULL,
       +  `asn` varchar(100) DEFAULT NULL,
       +  `as_path` varchar(100) DEFAULT NULL,
       +  `prefix` varchar(100) DEFAULT NULL,
       +  `as_org_name` varchar(100) DEFAULT NULL,
       +  `org_name` varchar(100) DEFAULT NULL,
       +  `country` varchar(100) DEFAULT NULL,
       +  `net_name` varchar(100) DEFAULT NULL,
       +  `lon` float(10,6) DEFAULT NULL,
       +  `lat` float(10,6) DEFAULT NULL,
       +  `city` varchar(100) DEFAULT NULL,
       +  `region` varchar(100) DEFAULT NULL,
       +  `traceroute` varchar(400) DEFAULT NULL,
       +  `reported` int(1) NOT NULL DEFAULT '0',
       +  PRIMARY KEY (`id`),
       +  KEY `ip_address` (`ip_address`)
       +) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
       +
       +DROP TABLE IF EXISTS `report`;
       +CREATE TABLE IF NOT EXISTS `report` (
       +  `id` int(15) NOT NULL AUTO_INCREMENT,
       +  `uid` varchar(15) NOT NULL,
       +  `email` varchar(200) DEFAULT NULL,
       +  `last_contact` datetime DEFAULT NULL,
       +  `total_contact` int(2) DEFAULT NULL,
       +  `reply` text,
       +  PRIMARY KEY (`id`)
       +) ENGINE=MyISAM  DEFAULT CHARSET=latin1;