From 9990d6f947b13aa59dce6d7726c7e6b8a73cc1be Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 10 Mar 2014 22:33:24 +0100 Subject: [PATCH 01/14] fixed timestamp output (using field[3] instead of [2]) --- hoover.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoover.pl b/hoover.pl index aa37134..30a733c 100755 --- a/hoover.pl +++ b/hoover.pl @@ -177,7 +177,7 @@ sub dumpNetworks { } for $key ( keys %detectedSSID) { - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($detectedSSID{$key}[2]); + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($detectedSSID{$key}[3]); my $lastSeen = sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); print STDOUT sprintf("!! %-20s %-30s %10s %-20s\n", $detectedSSID{$key}[2], $detectedSSID{$key}[0], $detectedSSID{$key}[1], $lastSeen); From 5a4301b5ea2186ed841c3db20d73d2f7ba5894ba Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 10 Mar 2014 22:59:34 +0100 Subject: [PATCH 02/14] merge with hoover osx support from https://github.com/hermanbanken/hoover fork of hoover --- hoover.pl | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/hoover.pl b/hoover.pl index 30a733c..c4455be 100755 --- a/hoover.pl +++ b/hoover.pl @@ -56,8 +56,10 @@ my $verbose; my $interface; my $dumpFile; +my $osname = $^O; my $ifconfigPath = "/sbin/ifconfig"; my $iwconfigPath = "/sbin/iwconfig"; +my $airportPath = "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport"; my $tsharkPath = "/usr/local/bin/tshark"; my $options = GetOptions( "verbose" => \$verbose, @@ -71,7 +73,7 @@ if ($help) { print <<_HELP_; -Usage: $0 --interface=wlan0 [--help] [--verbose] [--iwconfig-path=/sbin/iwconfig] [--ipconfig-path=/sbin/ifconfig] +Usage: $0 --interface=en1_or_wlan0 [--help] [--verbose] [--iwconfig-path=/sbin/iwconfig] [--ipconfig-path=/sbin/ifconfig] [--dumpfile=result.txt] Where: --interface : Specify the wireless interface to use @@ -86,7 +88,7 @@ } # We must be run by root -(getlogin() ne "root") && die "$0 must be run by root!\n"; +($< != 0) && die "$0 must be run by root!\n"; # We must have an interface to listen to (!$interface) && die "No wireless interface speficied!\n"; @@ -95,7 +97,7 @@ ( ! -x $ifconfigPath) && die "ifconfig tool not found!\n"; # Check iwconfig availability -( ! -x $iwconfigPath) && die "iwconfig tool not found!\n"; +($osname ne 'darwin') && ( ! -x $iwconfigPath) && die "iwconfig tool not found!\n"; # Check tshark availability ( ! -x $tsharkPath) && die "tshark tool not available!\n"; @@ -104,7 +106,8 @@ (system("$ifconfigPath $interface up")) && "Cannot initialize interface $interface!\n"; # Set interface in monitor mode -(system("$iwconfigPath $interface mode monitor")) && die "Cannot set interface $interface in monitoring mode!\n"; +($osname ne 'darwin') && (system("$iwconfigPath $interface mode monitor")) && die "Cannot set interface $interface in monitoring mode!\n"; +($osname eq 'darwin') && (system("$airportPath $interface -z")) && die "Cannot disassociate interface $interface!\n"; # Create the child process to change wireless channels (!defined($pid = fork)) && die "Cannot fork child process!\n"; @@ -114,7 +117,7 @@ # Parent process: run the main loop # --------------------------------- ($verbose) && print "!! Running with PID: $$ (child: $pid)\n"; - open(TSHARK, "$tsharkPath -i $interface -n -l subtype probereq |") || die "Cannot spawn tshark process!\n"; + open(TSHARK, $osname ne 'darwin' ? "$tsharkPath -i $interface -n -l subtype probereq |" : "$tsharkPath -i $interface -n -l -y PPI -R \"wlan.fc.type_subtype==4\" |") || die "Cannot spawn tshark process!\n"; while () { chomp; my $line = $_; @@ -154,14 +157,22 @@ # Child process: Switch channels at regular interval # -------------------------------------------------- ($verbose) && print STDOUT "!! Switching wireless channel every 5\".\n"; + if ($osname ne 'darwin') { while (1) { for (my $channel = 1; $channel <= 12; $channel++) { (system("$iwconfigPath $interface channel $channel")) && die "Cannot set interface channel.\n"; sleep(5); } - } - + } } + else { + while (1) { + for (my $channel = 1; $channel <= 14; $channel++) { + (system("$airportPath $interface -c$channel")) && + die "Cannot set interface channel.\n"; + sleep(5); + } + } } } sub dumpNetworks { From dd0f37143b10b8489274cf6d626023376c85a5ec Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 10 Mar 2014 23:01:41 +0100 Subject: [PATCH 03/14] fixed command line param for tshark-path to match usage --- hoover.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoover.pl b/hoover.pl index c4455be..39ed8fc 100755 --- a/hoover.pl +++ b/hoover.pl @@ -67,7 +67,7 @@ "interface=s" => \$interface, "ifconfig-path=s" => \$ifconfigPath, "iwconfig-path=s" => \$iwconfigPath, - "tsharkPath=s" => \$tsharkPath, + "tshark-path=s" => \$tsharkPath, "dumpfile=s" => \$dumpFile, ); From cbc5ab28a8aaa42f5a3a7d6d95d70bf004445541 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 10 Mar 2014 23:09:10 +0100 Subject: [PATCH 04/14] new README file --- README | 202 ------------------------------------------------------ README.md | 44 ++++++++++++ 2 files changed, 44 insertions(+), 202 deletions(-) delete mode 100755 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100755 index aa37134..0000000 --- a/README +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/perl -# -# hoover.pl - Wi-Fi probe requests sniffer -# -# Original idea by David Nelissen (twitter.com/davidnelissen) -# Thank to him for allowing me to reuse the idea! -# -# This script scans for wireless probe requests and prints them out. -# Hereby you can see for which SSID's devices nearby are searching. -# -# Copyright (c) 2012 David Nelissen & Xavier Mertens -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of copyright holders nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# History -# ------- -# 2012/01/11 Created -# - -use strict; -use Getopt::Long; - -$SIG{USR1} = \&dumpNetworks; # Catch SIGINT to dump the detected networks -$SIG{INT} = \&cleanKill; -$SIG{KILL} = \&cleanKill; -$SIG{TERM} = \&cleanKill; - -my $uniqueSSID = 0; #uniq ssid counter -my %detectedSSID; # Detected network will be stored in a hash table - # SSID, Seen packets, Last timestamp -my $pid; -my $help; -my $verbose; -my $interface; -my $dumpFile; -my $ifconfigPath = "/sbin/ifconfig"; -my $iwconfigPath = "/sbin/iwconfig"; -my $tsharkPath = "/usr/local/bin/tshark"; -my $options = GetOptions( - "verbose" => \$verbose, - "help" => \$help, - "interface=s" => \$interface, - "ifconfig-path=s" => \$ifconfigPath, - "iwconfig-path=s" => \$iwconfigPath, - "tsharkPath=s" => \$tsharkPath, - "dumpfile=s" => \$dumpFile, -); - -if ($help) { - print <<_HELP_; -Usage: $0 --interface=wlan0 [--help] [--verbose] [--iwconfig-path=/sbin/iwconfig] [--ipconfig-path=/sbin/ifconfig] - [--dumpfile=result.txt] -Where: ---interface : Specify the wireless interface to use ---help : This help ---verbose : Verbose output to STDOUT ---ifconfig-path : Path to your ifconfig binary ---iwconfig-path : Path to your iwconfig binary ---tshark-path : Path to your tshark binary ---dumpfile : Save found SSID's/MAC addresses in a flat file (SIGUSR1) -_HELP_ - exit 0; -} - -# We must be run by root -(getlogin() ne "root") && die "$0 must be run by root!\n"; - -# We must have an interface to listen to -(!$interface) && die "No wireless interface speficied!\n"; - -# Check ifconfig availability -( ! -x $ifconfigPath) && die "ifconfig tool not found!\n"; - -# Check iwconfig availability -( ! -x $iwconfigPath) && die "iwconfig tool not found!\n"; - -# Check tshark availability -( ! -x $tsharkPath) && die "tshark tool not available!\n"; - -# Configure wireless interface -(system("$ifconfigPath $interface up")) && "Cannot initialize interface $interface!\n"; - -# Set interface in monitor mode -(system("$iwconfigPath $interface mode monitor")) && die "Cannot set interface $interface in monitoring mode!\n"; - -# Create the child process to change wireless channels -(!defined($pid = fork)) && die "Cannot fork child process!\n"; - -if ($pid) { - # --------------------------------- - # Parent process: run the main loop - # --------------------------------- - ($verbose) && print "!! Running with PID: $$ (child: $pid)\n"; - open(TSHARK, "$tsharkPath -i $interface -n -l subtype probereq |") || die "Cannot spawn tshark process!\n"; - while () { - chomp; - my $line = $_; - chomp($line = $_); - # Everything exept backslash (some probes contains the ssid in ascii, not usable) - #if($line = m/\d+\.\d+ ([a-zA-Z0-9:]+).+SSID=([a-zA-ZÀ-ÿ0-9"\s\!\@\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\,\.\?\>\<]+)/) { - if($line = m/\d+\.\d+ ([a-zA-Z0-9:_]+).+SSID=([a-zA-ZÀ-ÿ0-9"\s\!\@\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\,\.\?\>\<]+)/) { - if($2 ne "Broadcast") { # Ignore broadcasts - my $macAddress = $1; - my $newKey = $2; - print DEBUG "$macAddress : $newKey\n"; - if (! $detectedSSID{$newKey}) - { - # New network found! - my @newSSID = ( $newKey, # SSID - 1, # First packet - $macAddress, # MAC Address - time()); # Seen now - $detectedSSID{$newKey} = [ @newSSID ]; - $uniqueSSID++; - print "++ New probe request from $macAddress with SSID: $newKey [$uniqueSSID]\n"; - } - else - { - # Existing SSID found! - $detectedSSID{$newKey}[1]++; # Increase packets counter - $detectedSSID{$newKey}[2] = $macAddress; # MAC Address - $detectedSSID{$newKey}[3] = time(); # Now - ($verbose) && print "-- Probe seen before: $newKey [$uniqueSSID]\n"; - } - } - } - } -} -else { - # -------------------------------------------------- - # Child process: Switch channels at regular interval - # -------------------------------------------------- - ($verbose) && print STDOUT "!! Switching wireless channel every 5\".\n"; - while (1) { - for (my $channel = 1; $channel <= 12; $channel++) { - (system("$iwconfigPath $interface channel $channel")) && - die "Cannot set interface channel.\n"; - sleep(5); - } - } - -} - -sub dumpNetworks { - my $i; - my $key; - print STDOUT "!! Dumping detected networks:\n"; - print STDOUT "!! MAC Address SSID Count Last Seen\n"; - print STDOUT "!! -------------------- ------------------------------ ---------- -------------------\n"; - if ($dumpFile) { - open(DUMP, ">$dumpFile") || die "Cannot write to $dumpFile (Error: $?)"; - print DUMP "MAC Address SSID Count Last Seen\n"; - print DUMP "-------------------- ------------------------------ ---------- -------------------\n"; - } - for $key ( keys %detectedSSID) - { - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($detectedSSID{$key}[2]); - my $lastSeen = sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); - print STDOUT sprintf("!! %-20s %-30s %10s %-20s\n", $detectedSSID{$key}[2], - $detectedSSID{$key}[0], $detectedSSID{$key}[1], $lastSeen); - ($dumpFile) && print DUMP sprintf("%-20s %-30s %10s %-20s\n", - $detectedSSID{$key}[2], $detectedSSID{$key}[0], - $detectedSSID{$key}[1], $lastSeen); - } - print STDOUT "!! Total unique SSID: $uniqueSSID\n"; - ($dumpFile) && print DUMP "Total unique SSID: $uniqueSSID\n"; - close(DUMP); - return; -} - -sub cleanKill { - if ($pid) { - # Parent process: display information - print "!! Received kill signal!\n"; - kill 1, $pid; - dumpNetworks; - } - exit 0; -} diff --git a/README.md b/README.md new file mode 100644 index 0000000..805e26d --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# hoover.pl - Wi-Fi probe requests sniffer + +Original idea by David Nelissen (twitter.com/davidnelissen) +Thank to him for allowing me to reuse the idea! + +This script scans for wireless probe requests and prints them out. +Hereby you can see for which SSID's devices nearby are searching. + +Copyright (c) 2012 David Nelissen & Xavier Mertens +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +## History + +2012/01/11 Created +2014/03/10 Merged OSX fork and made minor fixes (timestamp) + +* Original source from https://github.com/xme/hoover +* OSX support from https://github.com/hermanbanken/hoover + + From bacd0f0375e28b1c0411f3aab9782123158588dd Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 10 Mar 2014 23:10:32 +0100 Subject: [PATCH 05/14] better layout for readme --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 805e26d..bb7e70c 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,9 @@ POSSIBILITY OF SUCH DAMAGE. ## History -2012/01/11 Created -2014/03/10 Merged OSX fork and made minor fixes (timestamp) - -* Original source from https://github.com/xme/hoover -* OSX support from https://github.com/hermanbanken/hoover +* 2012/01/11 Created +* 2014/03/10 Merged OSX fork and made minor fixes (timestamp) + * Original source from https://github.com/xme/hoover + * OSX support from https://github.com/hermanbanken/hoover From d3d77aef4659a6a72e2d37e5e16ff38f22ba6636 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Fri, 14 Mar 2014 23:50:06 +0100 Subject: [PATCH 06/14] changed creation of command line fortshark completely also record multiple MAC-addresses for same SSID --- hoover.pl | 68 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/hoover.pl b/hoover.pl index 39ed8fc..7bf1d60 100755 --- a/hoover.pl +++ b/hoover.pl @@ -50,7 +50,7 @@ my $uniqueSSID = 0; #uniq ssid counter my %detectedSSID; # Detected network will be stored in a hash table - # SSID, Seen packets, Last timestamp + # SSID, Seen packets, MAC, Last timestamp my $pid; my $help; my $verbose; @@ -117,46 +117,52 @@ # Parent process: run the main loop # --------------------------------- ($verbose) && print "!! Running with PID: $$ (child: $pid)\n"; - open(TSHARK, $osname ne 'darwin' ? "$tsharkPath -i $interface -n -l subtype probereq |" : "$tsharkPath -i $interface -n -l -y PPI -R \"wlan.fc.type_subtype==4\" |") || die "Cannot spawn tshark process!\n"; + + # only valid packets and non-empty SSIDs: + my $displayFilter = "wlan.fcs_good==1 and not wlan_mgt.ssid==\\\"\\\""; + my $fieldParams = "-T fields -e wlan.sa -e wlan_mgt.ssid -Eseparator=,"; + my $tsharkCommandLine = "$tsharkPath -i $interface -n -l $fieldParams"; + if ($osname ne 'darwin') { + $tsharkCommandLine .= " subtype probereq $fieldParams -2 -R \"$displayFilter\" |"; + } else { + $tsharkCommandLine .= " -y PPI -2 -R \"wlan.fc.type_subtype==4 and $displayFilter\" |" + } + ($verbose) && print "!! command: $tsharkCommandLine\n"; + + open(TSHARK, $tsharkCommandLine) || die "Cannot spawn tshark process!\n"; while () { chomp; my $line = $_; chomp($line = $_); - # Everything exept backslash (some probes contains the ssid in ascii, not usable) - #if($line = m/\d+\.\d+ ([a-zA-Z0-9:]+).+SSID=([a-zA-ZÀ-ÿ0-9"\s\!\@\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\,\.\?\>\<]+)/) { - if($line = m/\d+\.\d+ ([a-zA-Z0-9:_]+).+SSID=([a-zA-ZÀ-ÿ0-9"\s\!\@\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\,\.\?\>\<]+)/) { - if($2 ne "Broadcast") { # Ignore broadcasts - my $macAddress = $1; - my $newKey = $2; - print DEBUG "$macAddress : $newKey\n"; - if (! $detectedSSID{$newKey}) - { - # New network found! - my @newSSID = ( $newKey, # SSID - 1, # First packet - $macAddress, # MAC Address - time()); # Seen now - $detectedSSID{$newKey} = [ @newSSID ]; - $uniqueSSID++; - print "++ New probe request from $macAddress with SSID: $newKey [$uniqueSSID]\n"; - } - else - { - # Existing SSID found! - $detectedSSID{$newKey}[1]++; # Increase packets counter - $detectedSSID{$newKey}[2] = $macAddress; # MAC Address - $detectedSSID{$newKey}[3] = time(); # Now - ($verbose) && print "-- Probe seen before: $newKey [$uniqueSSID]\n"; - } - } - } + my ($macAddress, $ssid) = split(/,/, $line); + ($verbose) && print "!! found packet: mac=$macAddress, ssid=$ssid\n"; + my $hashKey = "$macAddress-$ssid"; + if (! $detectedSSID{$hashKey}) + { + # New network found! + my @newSSID = ( $ssid, # SSID + 1, # First packet + $macAddress, # MAC Address + time()); # Seen now + $detectedSSID{$hashKey} = [ @newSSID ]; + $uniqueSSID++; + print "++ New probe request from $macAddress with SSID: $ssid [$uniqueSSID]\n"; + } + else + { + # Existing SSID found! + $detectedSSID{$hashKey}[1]++; # Increase packets counter + $detectedSSID{$hashKey}[2] = $macAddress; # MAC Address + $detectedSSID{$hashKey}[3] = time(); # Now + ($verbose) && print "-- Probe seen before: $ssid [$uniqueSSID]\n"; + } } } else { # -------------------------------------------------- # Child process: Switch channels at regular interval # -------------------------------------------------- - ($verbose) && print STDOUT "!! Switching wireless channel every 5\".\n"; + ($verbose) && print STDOUT "!! Switching wireless channel every 5 seconds.\n"; if ($osname ne 'darwin') { while (1) { for (my $channel = 1; $channel <= 12; $channel++) { From 618073800478428109b97fef00deda75784f1f33 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Sat, 15 Mar 2014 00:05:38 +0100 Subject: [PATCH 07/14] added verbose info, fixed linux execution --- hoover.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hoover.pl b/hoover.pl index 7bf1d60..5560bf1 100755 --- a/hoover.pl +++ b/hoover.pl @@ -123,7 +123,7 @@ my $fieldParams = "-T fields -e wlan.sa -e wlan_mgt.ssid -Eseparator=,"; my $tsharkCommandLine = "$tsharkPath -i $interface -n -l $fieldParams"; if ($osname ne 'darwin') { - $tsharkCommandLine .= " subtype probereq $fieldParams -2 -R \"$displayFilter\" |"; + $tsharkCommandLine .= " subtype probereq -2 -R \"$displayFilter\" |"; } else { $tsharkCommandLine .= " -y PPI -2 -R \"wlan.fc.type_subtype==4 and $displayFilter\" |" } @@ -154,7 +154,7 @@ $detectedSSID{$hashKey}[1]++; # Increase packets counter $detectedSSID{$hashKey}[2] = $macAddress; # MAC Address $detectedSSID{$hashKey}[3] = time(); # Now - ($verbose) && print "-- Probe seen before: $ssid [$uniqueSSID]\n"; + ($verbose) && print "-- Probe seen before: $hashKey [$uniqueSSID]\n"; } } } @@ -166,6 +166,7 @@ if ($osname ne 'darwin') { while (1) { for (my $channel = 1; $channel <= 12; $channel++) { + ($verbose) && print STDOUT "!! Switching to channel $channel\n"; (system("$iwconfigPath $interface channel $channel")) && die "Cannot set interface channel.\n"; sleep(5); @@ -174,6 +175,7 @@ else { while (1) { for (my $channel = 1; $channel <= 14; $channel++) { + ($verbose) && print STDOUT "!! Switching to channel $channel\n"; (system("$airportPath $interface -c$channel")) && die "Cannot set interface channel.\n"; sleep(5); From 8be280396893e3a0a9f554c4488e06da96a6be6a Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 17 Mar 2014 10:36:23 +0100 Subject: [PATCH 08/14] fixed indentation --- hoover.pl | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/hoover.pl b/hoover.pl index 5560bf1..7ffa1c0 100755 --- a/hoover.pl +++ b/hoover.pl @@ -164,23 +164,25 @@ # -------------------------------------------------- ($verbose) && print STDOUT "!! Switching wireless channel every 5 seconds.\n"; if ($osname ne 'darwin') { - while (1) { - for (my $channel = 1; $channel <= 12; $channel++) { - ($verbose) && print STDOUT "!! Switching to channel $channel\n"; - (system("$iwconfigPath $interface channel $channel")) && - die "Cannot set interface channel.\n"; - sleep(5); - } - } } + while (1) { + for (my $channel = 1; $channel <= 12; $channel++) { + ($verbose) && print STDOUT "!! Switching to channel $channel\n"; + (system("$iwconfigPath $interface channel $channel")) && + die "Cannot set interface channel.\n"; + sleep(5); + } + } + } else { - while (1) { - for (my $channel = 1; $channel <= 14; $channel++) { - ($verbose) && print STDOUT "!! Switching to channel $channel\n"; - (system("$airportPath $interface -c$channel")) && - die "Cannot set interface channel.\n"; - sleep(5); - } - } } + while (1) { + for (my $channel = 1; $channel <= 14; $channel++) { + ($verbose) && print STDOUT "!! Switching to channel $channel\n"; + (system("$airportPath $interface -c$channel")) && + die "Cannot set interface channel.\n"; + sleep(5); + } + } + } } sub dumpNetworks { From 7727cdf7b66b80f410740f524e8fd83988cdf571 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 17 Mar 2014 19:47:22 +0100 Subject: [PATCH 09/14] first version of python --- hoover.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100755 hoover.py diff --git a/hoover.py b/hoover.py new file mode 100755 index 0000000..3cecd8e --- /dev/null +++ b/hoover.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import threading +import signal +import sys +import time +import subprocess +import os + +def signal_handler(signal, frame): + print 'You pressend CTRL+C, data is flushed into database/file...' + switchThread.running = False + switchThread.join() + sys.exit(0) + + +class switchChannelThread (threading.Thread): + def __init__(self, threadID, name, switchCommand, maxChannel, delayInSeconds): + threading.Thread.__init__(self) + self.threadID = threadID + self.name = name + self.switchCommand = switchCommand + self.maxChannel = maxChannel + self.delayInSeconds = delayInSeconds + self.running = True + def run(self): + print 'Starting switch channel thread using a dely of %d seconds' % self.delayInSeconds + while self.running: + for channel in range (1, self.maxChannel): + print 'Switching to channel %d' % (channel) + time.sleep(self.delayInSeconds) + if not self.running: + return + + +# create switch thread +#switchThread = switchChannelThread(1, 'SwitchChannel', 'airbase', 14, 5) +#switchThread.start() + +osname = os.uname()[0] + +tsharkPath = '/usr/local/bin/tshark' + +displayFilter = "wlan.fcs_good==1 and not wlan_mgt.ssid==\\\"\\\""; +fieldParams = "-T fields -e wlan.sa -e wlan_mgt.ssid -Eseparator=,"; +tsharkCommandLine = "{0} -i en1 -n -l {1}" + +if (osname == 'Darwin'): + tsharkCommandLine += " subtype probereq -2 -R \"{2}\"" +else: + tsharkCommandLine += " -y PPI -2 -R \"wlan.fc.type_subtype==4 and {2}\"" + +tsharkCommandLine = tsharkCommandLine.format(tsharkPath, fieldParams, displayFilter) + +print 'tshark command: %s' % tsharkCommandLine, + +popen = subprocess.Popen(tsharkCommandLine, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +for line in iter(popen.stdout.readline, ''): + print 'line: %s' % (line,) + +signal.signal(signal.SIGINT, signal_handler) +print 'press CTRL+C' +signal.pause() \ No newline at end of file From b849fe09c8222d58e37c9c8b43bd312bbc321e83 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Mon, 17 Mar 2014 22:51:05 +0100 Subject: [PATCH 10/14] added tshark command line and arguments --- hoover.py | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/hoover.py b/hoover.py index 3cecd8e..4fbe821 100755 --- a/hoover.py +++ b/hoover.py @@ -6,6 +6,8 @@ import time import subprocess import os +import argparse + def signal_handler(signal, frame): print 'You pressend CTRL+C, data is flushed into database/file...' @@ -31,33 +33,52 @@ def run(self): time.sleep(self.delayInSeconds) if not self.running: return - - + + +# command line parsing: +parser = argparse.ArgumentParser(description='Show and collect wlan request probes') +parser.add_argument('--interface', default='en1', + help='the interface used for monitoring') +parser.add_argument('--tsharkPath', default='/usr/local/bin/tshark', + help='path to tshark binary') +parser.add_argument('--verbose', action='store_true', help='verbose information') +args = parser.parse_args() + +tsharkPath = args.tsharkPath +interface = args.interface +verbose = args.verbose + # create switch thread #switchThread = switchChannelThread(1, 'SwitchChannel', 'airbase', 14, 5) #switchThread.start() osname = os.uname()[0] -tsharkPath = '/usr/local/bin/tshark' - displayFilter = "wlan.fcs_good==1 and not wlan_mgt.ssid==\\\"\\\""; fieldParams = "-T fields -e wlan.sa -e wlan_mgt.ssid -Eseparator=,"; -tsharkCommandLine = "{0} -i en1 -n -l {1}" +tsharkCommandLine = "{0} -i {1} -n -l {2}" -if (osname == 'Darwin'): - tsharkCommandLine += " subtype probereq -2 -R \"{2}\"" +if (osname != 'Darwin'): + tsharkCommandLine += " subtype probereq -2 -R \"{3}\"" else: - tsharkCommandLine += " -y PPI -2 -R \"wlan.fc.type_subtype==4 and {2}\"" + tsharkCommandLine += " -y PPI -2 -R \"wlan.fc.type_subtype==4 and {3}\"" + +tsharkCommandLine = tsharkCommandLine.format(tsharkPath, interface, fieldParams, displayFilter) -tsharkCommandLine = tsharkCommandLine.format(tsharkPath, fieldParams, displayFilter) +if verbose: + print 'tshark command: %s\n' % tsharkCommandLine, -print 'tshark command: %s' % tsharkCommandLine, +DEVNULL = open(os.devnull, 'w') +popen = subprocess.Popen(tsharkCommandLine, shell=True, stdout=subprocess.PIPE, stderr=DEVNULL) -popen = subprocess.Popen(tsharkCommandLine, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) -for line in iter(popen.stdout.readline, ''): - print 'line: %s' % (line,) +for line in iter(popen.stdout.readline, ''): + line = line.rstrip() + if verbose: + print 'line: "%s"' % (line,) + if line.find(',') > 0: + mac, ssid = line.split(',', 1) + print "mac: '{0}', ssid: '{1}'".format(mac,ssid) signal.signal(signal.SIGINT, signal_handler) print 'press CTRL+C' -signal.pause() \ No newline at end of file +signal.pause() From 128d52cb4bd35ff0105515f22456d5ec93aa5745 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Tue, 18 Mar 2014 23:09:45 +0100 Subject: [PATCH 11/14] scanning and switching channels now --- hoover.py | 85 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/hoover.py b/hoover.py index 4fbe821..cbb4be8 100755 --- a/hoover.py +++ b/hoover.py @@ -6,6 +6,7 @@ import time import subprocess import os +import os.path import argparse @@ -17,43 +18,100 @@ def signal_handler(signal, frame): class switchChannelThread (threading.Thread): - def __init__(self, threadID, name, switchCommand, maxChannel, delayInSeconds): + def __init__(self, threadID, name, delayInSeconds): threading.Thread.__init__(self) self.threadID = threadID self.name = name - self.switchCommand = switchCommand - self.maxChannel = maxChannel + if osname != "Darwin": + self.maxChannel = 12 + else: + self.maxChannel = 14 self.delayInSeconds = delayInSeconds self.running = True def run(self): print 'Starting switch channel thread using a dely of %d seconds' % self.delayInSeconds while self.running: - for channel in range (1, self.maxChannel): - print 'Switching to channel %d' % (channel) + for channel in range (1, self.maxChannel + 1): + if verbose: + print 'Switching to channel %d' % (channel) + if osname != "Darwin": + if subprocess.call([iwconfigPath, interface, "channel", channel]) != 0: + self.running = False + sys.exit(4) + else: + if subprocess.call([airportPath, interface, "-c%d" % channel]) != 0: + self.running = False + sys.exit(4) + time.sleep(self.delayInSeconds) if not self.running: return +osname = os.uname()[0] +if osname != "Darwin": + defaultInterface = "wlan0" +else: + defaultInterface = "en1" # command line parsing: parser = argparse.ArgumentParser(description='Show and collect wlan request probes') -parser.add_argument('--interface', default='en1', +parser.add_argument('--interface', default=defaultInterface, help='the interface used for monitoring') parser.add_argument('--tsharkPath', default='/usr/local/bin/tshark', help='path to tshark binary') +parser.add_argument('--ifconfigPath', default='/sbin/ifconfig', + help='path to ifconfig') +parser.add_argument('--iwconfigPath', default='/sbin/iwconfig', + help='path to iwconfig') parser.add_argument('--verbose', action='store_true', help='verbose information') args = parser.parse_args() tsharkPath = args.tsharkPath +ifconfigPath = args.ifconfigPath +iwconfigPath = args.iwconfigPath interface = args.interface verbose = args.verbose -# create switch thread -#switchThread = switchChannelThread(1, 'SwitchChannel', 'airbase', 14, 5) -#switchThread.start() +# only on osx: +airportPath = "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport"; + +# check all params +if not os.path.isfile(tsharkPath): + print "tshark not found at path {0}".format(tsharkPath) + sys.exit(1) +if not os.path.isfile(ifconfigPath): + print "ifconfig not found at path {0}".format(ifconfigPath) + sys.exit(1) +if osname != "Darwin": + if not os.path.isfile(iwconfigPath): + print "iwconfig not found at path {0}".format(iwconfigPath) + sys.exit(1) + +# start interface +if subprocess.call([ifconfigPath, interface, 'up']) != 0: + print "cannot start interface: {0}".format(interface) + sys.exit(2) + +# Set interface in monitor mode +retVal = 0 +if osname != 'Darwin': + retVal = subprocess.call([iwconfigPath, interface, "mode", "monitor"]) +else: + retVal = subprocess.call([airportPath, interface, "-z"]) -osname = os.uname()[0] +if retVal != 0: + print "cannot set interface to monitor mode: {0}".format(interface) + sys.exit(3) +# start thread that switches channels +switchThread = switchChannelThread(1, 'SwitchChannel', 5) +switchThread.start() + +signal.signal(signal.SIGINT, signal_handler) +print 'press CTRL+C to exit' +# signal.pause() + +# start tshark and read the results displayFilter = "wlan.fcs_good==1 and not wlan_mgt.ssid==\\\"\\\""; fieldParams = "-T fields -e wlan.sa -e wlan_mgt.ssid -Eseparator=,"; tsharkCommandLine = "{0} -i {1} -n -l {2}" @@ -73,12 +131,9 @@ def run(self): for line in iter(popen.stdout.readline, ''): line = line.rstrip() - if verbose: - print 'line: "%s"' % (line,) +# if verbose: +# print 'line: "%s"' % (line,) if line.find(',') > 0: mac, ssid = line.split(',', 1) print "mac: '{0}', ssid: '{1}'".format(mac,ssid) -signal.signal(signal.SIGINT, signal_handler) -print 'press CTRL+C' -signal.pause() From 4bf1022a52da0b172bae894ac8c954632d8985cb Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Thu, 20 Mar 2014 00:03:23 +0100 Subject: [PATCH 12/14] added collection of found mac/ssids and print them at the end --- hoover.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/hoover.py b/hoover.py index cbb4be8..4050fa2 100755 --- a/hoover.py +++ b/hoover.py @@ -10,10 +10,15 @@ import argparse + def signal_handler(signal, frame): print 'You pressend CTRL+C, data is flushed into database/file...' switchThread.running = False switchThread.join() + formatString = "{0: <18} {1: <20} {2: <18}" + print formatString.format("mac", "ssid", "last seen") + for key, value in entries.iteritems(): + print formatString.format(value.mac, value.ssid, time.strftime("%Y%m%d-%H:%M:%S", value.timeLastSeen)) sys.exit(0) @@ -47,6 +52,13 @@ def run(self): if not self.running: return +class Entry (object): + def __init__(self, mac, ssid, time): + self.mac = mac + self.ssid = ssid + self.timeLastSeen = time + + osname = os.uname()[0] if osname != "Darwin": defaultInterface = "wlan0" @@ -106,7 +118,6 @@ def run(self): # start thread that switches channels switchThread = switchChannelThread(1, 'SwitchChannel', 5) switchThread.start() - signal.signal(signal.SIGINT, signal_handler) print 'press CTRL+C to exit' # signal.pause() @@ -129,11 +140,20 @@ def run(self): DEVNULL = open(os.devnull, 'w') popen = subprocess.Popen(tsharkCommandLine, shell=True, stdout=subprocess.PIPE, stderr=DEVNULL) +# collect all Entry objects in entries +entries = {} + for line in iter(popen.stdout.readline, ''): line = line.rstrip() # if verbose: # print 'line: "%s"' % (line,) if line.find(',') > 0: mac, ssid = line.split(',', 1) - print "mac: '{0}', ssid: '{1}'".format(mac,ssid) - + if line in entries: + if verbose: + print "entry found (seen before): mac: '{0}', ssid: '{1}'".format(mac,ssid) + entry = entries[line] + entry.timeLastSeen = time.localtime() + else: + print "new entry found: mac: '{0}', ssid: '{1}'".format(mac,ssid) + entries[line] = Entry(mac, ssid, time.localtime()) From f6ec15d2df8c65995c60bb5872da7a96ac52aa68 Mon Sep 17 00:00:00 2001 From: Christof Dallermassl Date: Thu, 20 Mar 2014 00:05:31 +0100 Subject: [PATCH 13/14] added python version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb7e70c..bf2ff80 100644 --- a/README.md +++ b/README.md @@ -39,5 +39,5 @@ POSSIBILITY OF SUCH DAMAGE. * 2014/03/10 Merged OSX fork and made minor fixes (timestamp) * Original source from https://github.com/xme/hoover * OSX support from https://github.com/hermanbanken/hoover - +* 2014/03/18 finished python version (same functionality as perl version) From ee45878cddeb0957f0e891addcecfcd9eeb663b6 Mon Sep 17 00:00:00 2001 From: Roberto Salgado Date: Sat, 1 Nov 2014 19:21:40 -0700 Subject: [PATCH 14/14] Bug fix Change to cast channel variable to a string when called by subprocess.call() to avoid error. --- hoover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoover.py b/hoover.py index 4050fa2..cf7ea44 100755 --- a/hoover.py +++ b/hoover.py @@ -40,7 +40,7 @@ def run(self): if verbose: print 'Switching to channel %d' % (channel) if osname != "Darwin": - if subprocess.call([iwconfigPath, interface, "channel", channel]) != 0: + if subprocess.call([iwconfigPath, interface, "channel", str(channel)]) != 0: self.running = False sys.exit(4) else: