mirror of
https://github.com/bettercap/bettercap
synced 2025-07-15 09:33:40 -07:00
new: implemented channel hopping for wifi.recon module ( ref #53 )
This commit is contained in:
parent
e1e2e33f57
commit
a66f5fabbb
4 changed files with 87 additions and 2 deletions
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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.")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue