new: implemented channel hopping for wifi.recon module ( ref #53 )

This commit is contained in:
evilsocket 2018-02-17 02:41:10 +01:00
parent e1e2e33f57
commit a66f5fabbb
4 changed files with 87 additions and 2 deletions

View file

@ -11,6 +11,7 @@ import (
"github.com/evilsocket/bettercap-ng/core" "github.com/evilsocket/bettercap-ng/core"
"github.com/evilsocket/bettercap-ng/log" "github.com/evilsocket/bettercap-ng/log"
"github.com/evilsocket/bettercap-ng/network"
"github.com/evilsocket/bettercap-ng/packets" "github.com/evilsocket/bettercap-ng/packets"
"github.com/evilsocket/bettercap-ng/session" "github.com/evilsocket/bettercap-ng/session"
@ -28,6 +29,7 @@ type WiFiRecon struct {
wifi *WiFi wifi *WiFi
stats *WiFiStats stats *WiFiStats
handle *pcap.Handle handle *pcap.Handle
channel int
client net.HardwareAddr client net.HardwareAddr
accessPoint net.HardwareAddr accessPoint net.HardwareAddr
} }
@ -36,6 +38,7 @@ func NewWiFiRecon(s *session.Session) *WiFiRecon {
w := &WiFiRecon{ w := &WiFiRecon{
SessionModule: session.NewSessionModule("wifi.recon", s), SessionModule: session.NewSessionModule("wifi.recon", s),
stats: NewWiFiStats(), stats: NewWiFiStats(),
channel: 0,
client: make([]byte, 0), client: make([]byte, 0),
accessPoint: make([]byte, 0), accessPoint: make([]byte, 0),
} }
@ -97,9 +100,13 @@ func NewWiFiRecon(s *session.Session) *WiFiRecon {
w.AddHandler(session.NewModuleHandler("wifi.show", "", w.AddHandler(session.NewModuleHandler("wifi.show", "",
"Show current wireless stations list (default sorting by essid).", "Show current wireless stations list (default sorting by essid).",
func(args []string) error { func(args []string) error {
return w.Show("essid") return w.Show("channel")
})) }))
w.AddParam(session.NewIntParameter("wifi.recon.channel",
"",
"WiFi channel or empty for channel hopping."))
return w return w
} }
@ -177,6 +184,17 @@ func mhz2chan(freq int) int {
return 0 return 0
} }
type ByChannelSorter []*WiFiStation
func (a ByChannelSorter) Len() int { return len(a) }
func (a ByChannelSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByChannelSorter) Less(i, j int) bool {
if a[i].Channel == a[j].Channel {
return a[i].HwAddress < a[j].HwAddress
}
return a[i].Channel < a[j].Channel
}
type ByEssidSorter []*WiFiStation type ByEssidSorter []*WiFiStation
func (a ByEssidSorter) Len() int { return len(a) } func (a ByEssidSorter) Len() int { return len(a) }
@ -221,8 +239,10 @@ func (w *WiFiRecon) Show(by string) error {
stations := w.wifi.List() stations := w.wifi.List()
if by == "seen" { if by == "seen" {
sort.Sort(BywifiSeenSorter(stations)) sort.Sort(BywifiSeenSorter(stations))
} else { } else if by == "essid" {
sort.Sort(ByEssidSorter(stations)) sort.Sort(ByEssidSorter(stations))
} else {
sort.Sort(ByChannelSorter(stations))
} }
rows := make([][]string, 0) rows := make([][]string, 0)
@ -259,6 +279,20 @@ func (w *WiFiRecon) Configure() error {
return err return err
} else if w.handle, err = ihandle.Activate(); err != nil { } else if w.handle, err = ihandle.Activate(); err != nil {
return err return err
} else if err, w.channel = w.IntParam("wifi.recon.channel"); err == nil {
if err = network.SetInterfaceChannel(w.Session.Interface.Name(), w.channel); err != nil {
return err
}
log.Info("WiFi recon active on channel %d.", w.channel)
} else {
w.channel = 0
// we need to start somewhere, this is just to check if
// this OS support switching channel programmatically.
if err = network.SetInterfaceChannel(w.Session.Interface.Name(), 1); err != nil {
return err
}
log.Info("WiFi recon active with channel hopping.")
} }
w.wifi = NewWiFi(w.Session, w.Session.Interface) w.wifi = NewWiFi(w.Session, w.Session.Interface)
@ -368,6 +402,25 @@ func (w *WiFiRecon) Start() error {
} }
w.SetRunning(true, func() { w.SetRunning(true, func() {
// start channel hopper if needed
if w.channel == 0 {
go func() {
log.Info("Channel hopper started.")
for w.Running() == true {
for channel := 1; channel < 15; channel++ {
if err := network.SetInterfaceChannel(w.Session.Interface.Name(), channel); err != nil {
log.Warning("Error while hopping to channel %d: %s", channel, err)
}
// this is the default for airodump-ng, good for them, good for us.
time.Sleep(250 * time.Millisecond)
if w.Running() == false {
return
}
}
}
}()
}
defer w.handle.Close() defer w.handle.Close()
src := gopacket.NewPacketSource(w.handle, w.handle.LinkType()) src := gopacket.NewPacketSource(w.handle, w.handle.LinkType())
for packet := range src.Packets() { for packet := range src.Packets() {

View file

@ -3,8 +3,12 @@ package network
import ( import (
"net" "net"
"regexp" "regexp"
"github.com/evilsocket/bettercap-ng/core"
) )
const airPortPath = "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport"
var IPv4RouteParser = regexp.MustCompile("^([a-z]+)+\\s+(\\d+\\.+\\d+.\\d.+\\d)+\\s+([a-zA-z]+)+\\s+(\\d+)+\\s+(\\d+)+\\s+([a-zA-Z]+\\d+)$") var IPv4RouteParser = regexp.MustCompile("^([a-z]+)+\\s+(\\d+\\.+\\d+.\\d.+\\d)+\\s+([a-zA-z]+)+\\s+(\\d+)+\\s+(\\d+)+\\s+([a-zA-Z]+\\d+)$")
var IPv4RouteTokens = 7 var IPv4RouteTokens = 7
var IPv4RouteCmd = "netstat" var IPv4RouteCmd = "netstat"
@ -26,3 +30,13 @@ func IPv4RouteIsGateway(ifname string, tokens []string, f func(gateway string) (
func getInterfaceName(iface net.Interface) string { func getInterfaceName(iface net.Interface) string {
return iface.Name return iface.Name
} }
func SetInterfaceChannel(iface string, channel int) error {
out, err := core.Exec(airPortPath, []string{iface, "--channel", fmt.Sprintf("%d", channel)})
if err != nil {
return err
} else if out != "" {
return fmt.Errorf("Unexpected output while setting interface %s to channel %d: %s", iface, channel, out)
}
return nil
}

View file

@ -1,8 +1,11 @@
package network package network
import ( import (
"fmt"
"net" "net"
"regexp" "regexp"
"github.com/evilsocket/bettercap-ng/core"
) )
// only matches gateway lines // only matches gateway lines
@ -26,3 +29,13 @@ func IPv4RouteIsGateway(ifname string, tokens []string, f func(gateway string) (
func getInterfaceName(iface net.Interface) string { func getInterfaceName(iface net.Interface) string {
return iface.Name return iface.Name
} }
func SetInterfaceChannel(iface string, channel int) error {
out, err := core.Exec("iwconfig", []string{iface, "channel", fmt.Sprintf("%d", channel)})
if err != nil {
return err
} else if out != "" {
return fmt.Errorf("Unexpected output while setting interface %s to channel %d: %s", iface, channel, out)
}
return nil
}

View file

@ -1,6 +1,7 @@
package network package network
import ( import (
"fmt"
"net" "net"
"regexp" "regexp"
"strings" "strings"
@ -57,3 +58,7 @@ func getInterfaceName(iface net.Interface) string {
return iface.Name return iface.Name
} }
func SetInterfaceChannel(iface string, channel int) error {
return fmt.Errorf("Windows does not support WiFi channel hopping.")
}