mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 21:13:18 -07:00
new: added native wifi handshakes capture from wifi.recon module
This commit is contained in:
parent
23f340d8eb
commit
a6cfb2413f
9 changed files with 273 additions and 30 deletions
|
@ -77,6 +77,19 @@ func (s *EventsStream) viewWiFiEvent(e session.Event) {
|
||||||
tui.Dim(desc),
|
tui.Dim(desc),
|
||||||
tui.Bold(probe.SSID),
|
tui.Bold(probe.SSID),
|
||||||
tui.Yellow(rssi))
|
tui.Yellow(rssi))
|
||||||
|
} else if e.Tag == "wifi.client.handshake" {
|
||||||
|
hand := e.Data.(WiFiHandshakeEvent)
|
||||||
|
ss := "s"
|
||||||
|
if hand.NewPackets == 1 {
|
||||||
|
ss = ""
|
||||||
|
}
|
||||||
|
fmt.Fprintf(s.output, "[%s] [%s] captured a full handshake for station %s and AP %s (saved %d new packet%s to %s)\n",
|
||||||
|
e.Time.Format(eventTimeFormat),
|
||||||
|
tui.Green(e.Tag),
|
||||||
|
hand.Station.String(),
|
||||||
|
hand.AP.String(),
|
||||||
|
hand.NewPackets, ss,
|
||||||
|
hand.File)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/google/gopacket/pcap"
|
"github.com/google/gopacket/pcap"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/fs"
|
||||||
"github.com/evilsocket/islazy/tui"
|
"github.com/evilsocket/islazy/tui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ type WiFiModule struct {
|
||||||
pktSourceChanClosed bool
|
pktSourceChanClosed bool
|
||||||
deauthSkip []net.HardwareAddr
|
deauthSkip []net.HardwareAddr
|
||||||
deauthSilent bool
|
deauthSilent bool
|
||||||
|
shakesFile string
|
||||||
apRunning bool
|
apRunning bool
|
||||||
apConfig packets.Dot11ApConfig
|
apConfig packets.Dot11ApConfig
|
||||||
writes *sync.WaitGroup
|
writes *sync.WaitGroup
|
||||||
|
@ -123,6 +125,11 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
w.AddParam(session.NewStringParameter("wifi.handshakes.file",
|
||||||
|
"~/bettercap-wifi-handshakes.pcap",
|
||||||
|
"",
|
||||||
|
"File path of the pcap file to save handshakes to."))
|
||||||
|
|
||||||
w.AddParam(session.NewStringParameter("wifi.ap.ssid",
|
w.AddParam(session.NewStringParameter("wifi.ap.ssid",
|
||||||
"FreeWiFi",
|
"FreeWiFi",
|
||||||
"",
|
"",
|
||||||
|
@ -221,6 +228,14 @@ func (w *WiFiModule) Configure() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err, w.shakesFile = w.StringParam("wifi.handshakes.file"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if w.shakesFile != "" {
|
||||||
|
if w.shakesFile, err = fs.Expand(w.shakesFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if w.source != "" {
|
if w.source != "" {
|
||||||
if w.handle, err = pcap.OpenOffline(w.source); err != nil {
|
if w.handle, err = pcap.OpenOffline(w.source); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -353,6 +368,7 @@ func (w *WiFiModule) Start() error {
|
||||||
w.discoverProbes(radiotap, dot11, packet)
|
w.discoverProbes(radiotap, dot11, packet)
|
||||||
w.discoverAccessPoints(radiotap, dot11, packet)
|
w.discoverAccessPoints(radiotap, dot11, packet)
|
||||||
w.discoverClients(radiotap, dot11, packet)
|
w.discoverClients(radiotap, dot11, packet)
|
||||||
|
w.discoverHandshakes(radiotap, dot11, packet)
|
||||||
w.updateInfo(dot11, packet)
|
w.updateInfo(dot11, packet)
|
||||||
w.updateStats(dot11, packet)
|
w.updateStats(dot11, packet)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
)
|
)
|
||||||
|
|
||||||
var maxStationTTL = 5 * time.Minute
|
var maxStationTTL = 5 * time.Minute
|
||||||
|
@ -23,6 +25,13 @@ type WiFiProbe struct {
|
||||||
RSSI int8
|
RSSI int8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WiFiHandshakeEvent struct {
|
||||||
|
File string
|
||||||
|
NewPackets int
|
||||||
|
AP net.HardwareAddr
|
||||||
|
Station net.HardwareAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (w *WiFiModule) stationPruner() {
|
func (w *WiFiModule) stationPruner() {
|
||||||
w.reads.Add(1)
|
w.reads.Add(1)
|
||||||
defer w.reads.Done()
|
defer w.reads.Done()
|
||||||
|
@ -121,3 +130,76 @@ func (w *WiFiModule) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Do
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func allZeros(s []byte) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if v != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
|
||||||
|
if keyLayer := packet.Layer(layers.LayerTypeEAPOLKey); keyLayer != nil {
|
||||||
|
if key := keyLayer.(*layers.EAPOLKey); key.KeyType == layers.EAPOLKeyTypePairwise {
|
||||||
|
staMac := net.HardwareAddr{}
|
||||||
|
apMac := net.HardwareAddr{}
|
||||||
|
if dot11.Flags.FromDS() {
|
||||||
|
staMac = dot11.Address1
|
||||||
|
apMac = dot11.Address2
|
||||||
|
} else if dot11.Flags.ToDS() {
|
||||||
|
staMac = dot11.Address2
|
||||||
|
apMac = dot11.Address1
|
||||||
|
}
|
||||||
|
|
||||||
|
if station, found := w.Session.WiFi.GetClient(staMac.String()); found {
|
||||||
|
// ref. https://wlan1nde.wordpress.com/2014/10/27/4-way-handshake/
|
||||||
|
if !key.Install && key.KeyACK && !key.KeyMIC {
|
||||||
|
// [1] (ACK) AP is sending ANonce to the client
|
||||||
|
log.Debug("[%s] got frame 1/4 of the %s <-> %s handshake (anonce:%x)",
|
||||||
|
tui.Green("wifi"),
|
||||||
|
apMac,
|
||||||
|
staMac,
|
||||||
|
key.Nonce)
|
||||||
|
station.Handshake.AddFrame(0, packet)
|
||||||
|
} else if !key.Install && !key.KeyACK && key.KeyMIC && !allZeros(key.Nonce) {
|
||||||
|
// [2] (MIC) client is sending SNonce+MIC to the API
|
||||||
|
log.Debug("[%s] got frame 2/4 of the %s <-> %s handshake (snonce:%x mic:%x)",
|
||||||
|
tui.Green("wifi"),
|
||||||
|
apMac,
|
||||||
|
staMac,
|
||||||
|
key.Nonce,
|
||||||
|
key.MIC)
|
||||||
|
station.Handshake.AddFrame(1, packet)
|
||||||
|
} else if key.Install && key.KeyACK && key.KeyMIC {
|
||||||
|
// [3]: (INSTALL+ACK+MIC) AP informs the client that the PTK is installed
|
||||||
|
log.Debug("[%s] got frame 3/4 of the %s <-> %s handshake (mic:%x)",
|
||||||
|
tui.Green("wifi"),
|
||||||
|
apMac,
|
||||||
|
staMac,
|
||||||
|
key.MIC)
|
||||||
|
station.Handshake.AddFrame(2, packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
numUnsaved := station.Handshake.NumUnsaved()
|
||||||
|
doSave := numUnsaved > 0
|
||||||
|
if doSave && w.shakesFile != "" {
|
||||||
|
log.Debug("saving handshake frames to %s", w.shakesFile)
|
||||||
|
if err := w.Session.WiFi.SaveHandshakesTo(w.shakesFile, w.handle.LinkType()); err != nil {
|
||||||
|
log.Error("error while saving handshake frames to %s: %s", w.shakesFile, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if doSave && station.Handshake.Complete() {
|
||||||
|
w.Session.Events.Add("wifi.client.handshake", WiFiHandshakeEvent{
|
||||||
|
File: w.shakesFile,
|
||||||
|
NewPackets: numUnsaved,
|
||||||
|
AP: apMac,
|
||||||
|
Station: staMac,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -48,11 +48,20 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
|
||||||
if len(station.Cipher) > 0 {
|
if len(station.Cipher) > 0 {
|
||||||
encryption = fmt.Sprintf("%s (%s, %s)", station.Encryption, station.Cipher, station.Authentication)
|
encryption = fmt.Sprintf("%s (%s, %s)", station.Encryption, station.Cipher, station.Authentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
if encryption == "OPEN" || encryption == "" {
|
if encryption == "OPEN" || encryption == "" {
|
||||||
encryption = tui.Green("OPEN")
|
encryption = tui.Green("OPEN")
|
||||||
ssid = tui.Green(ssid)
|
ssid = tui.Green(ssid)
|
||||||
bssid = tui.Green(bssid)
|
bssid = tui.Green(bssid)
|
||||||
|
} else {
|
||||||
|
// this is ugly, but necessary in order to have this
|
||||||
|
// method handle both access point and clients
|
||||||
|
// transparently
|
||||||
|
if ap, found := w.Session.WiFi.Get(station.HwAddress); found && ap.HasHandshakes() {
|
||||||
|
encryption = tui.Red(encryption)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sent := ""
|
sent := ""
|
||||||
if station.Sent > 0 {
|
if station.Sent > 0 {
|
||||||
sent = humanize.Bytes(station.Sent)
|
sent = humanize.Bytes(station.Sent)
|
||||||
|
@ -318,7 +327,7 @@ func (w *WiFiModule) ShowWPS(bssid string) (err error) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Printf("* %s (%s ch:%d):\n", tui.Bold(ssid), tui.Dim(station.BSSID()), station.Channel())
|
fmt.Printf("* %s (%s ch:%d):\n", tui.Bold(ssid), tui.Dim(station.BSSID()), station.Channel())
|
||||||
keys := []string{}
|
keys := []string{}
|
||||||
for name, _ := range station.WPS {
|
for name := range station.WPS {
|
||||||
keys = append(keys, name)
|
keys = append(keys, name)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
|
@ -2,9 +2,16 @@ package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcapgo"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Dot11Freq2Chan(freq int) int {
|
func Dot11Freq2Chan(freq int) int {
|
||||||
|
@ -174,3 +181,37 @@ func (w *WiFi) Clear() error {
|
||||||
w.aps = make(map[string]*AccessPoint)
|
w.aps = make(map[string]*AccessPoint)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *WiFi) SaveHandshakesTo(fileName string, linkType layers.LinkType) error {
|
||||||
|
w.Lock()
|
||||||
|
defer w.Unlock()
|
||||||
|
|
||||||
|
doHead := !fs.Exists(fileName)
|
||||||
|
|
||||||
|
fp, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fp.Close()
|
||||||
|
|
||||||
|
writer := pcapgo.NewWriter(fp)
|
||||||
|
|
||||||
|
if doHead {
|
||||||
|
if err = writer.WriteFileHeader(65536, linkType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ap := range w.aps {
|
||||||
|
for _, station := range ap.Clients() {
|
||||||
|
station.Handshake.EachUnsavedPacket(func(pkt gopacket.Packet) {
|
||||||
|
err = writer.WritePacket(pkt.Metadata().CaptureInfo, pkt.Data())
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -96,3 +96,16 @@ func (ap *AccessPoint) Clients() (list []*Station) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ap *AccessPoint) HasHandshakes() bool {
|
||||||
|
ap.Lock()
|
||||||
|
defer ap.Unlock()
|
||||||
|
|
||||||
|
for _, c := range ap.clients {
|
||||||
|
if c.Handshake.Complete() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
67
network/wifi_handshake.go
Normal file
67
network/wifi_handshake.go
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handshake struct {
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
|
Challenges []gopacket.Packet
|
||||||
|
Responses []gopacket.Packet
|
||||||
|
Confirmations []gopacket.Packet
|
||||||
|
unsaved []gopacket.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandshake() *Handshake {
|
||||||
|
return &Handshake{
|
||||||
|
Challenges: make([]gopacket.Packet, 0),
|
||||||
|
Responses: make([]gopacket.Packet, 0),
|
||||||
|
Confirmations: make([]gopacket.Packet, 0),
|
||||||
|
unsaved: make([]gopacket.Packet, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handshake) AddFrame(n int, pkt gopacket.Packet) {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
h.Challenges = append(h.Challenges, pkt)
|
||||||
|
case 1:
|
||||||
|
h.Responses = append(h.Responses, pkt)
|
||||||
|
case 2:
|
||||||
|
h.Confirmations = append(h.Confirmations, pkt)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.unsaved = append(h.unsaved, pkt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handshake) Complete() bool {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
|
||||||
|
nChal := len(h.Challenges)
|
||||||
|
nResp := len(h.Responses)
|
||||||
|
nConf := len(h.Confirmations)
|
||||||
|
|
||||||
|
return nChal > 0 && nResp > 0 && nConf > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handshake) NumUnsaved() int {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
return len(h.unsaved)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handshake) EachUnsavedPacket(cb func(gopacket.Packet)) {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
|
||||||
|
for _, pkt := range h.unsaved {
|
||||||
|
cb(pkt)
|
||||||
|
}
|
||||||
|
h.unsaved = make([]gopacket.Packet, 0)
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ type Station struct {
|
||||||
Cipher string `json:"cipher"`
|
Cipher string `json:"cipher"`
|
||||||
Authentication string `json:"authentication"`
|
Authentication string `json:"authentication"`
|
||||||
WPS map[string]string `json:"wps"`
|
WPS map[string]string `json:"wps"`
|
||||||
|
Handshake *Handshake `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanESSID(essid string) string {
|
func cleanESSID(essid string) string {
|
||||||
|
@ -35,6 +36,7 @@ func NewStation(essid, bssid string, frequency int, rssi int8) *Station {
|
||||||
Frequency: frequency,
|
Frequency: frequency,
|
||||||
RSSI: rssi,
|
RSSI: rssi,
|
||||||
WPS: make(map[string]string),
|
WPS: make(map[string]string),
|
||||||
|
Handshake: NewHandshake(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,83 +37,83 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
wpsDeviceTypes = map[uint16]wpsDevType{
|
wpsDeviceTypes = map[uint16]wpsDevType{
|
||||||
0x0001: wpsDevType{"Computer", map[uint16]string{
|
0x0001: {"Computer", map[uint16]string{
|
||||||
0x0001: "PC",
|
0x0001: "PC",
|
||||||
0x0002: "Server",
|
0x0002: "Server",
|
||||||
0x0003: "Media Center",
|
0x0003: "Media Center",
|
||||||
}},
|
}},
|
||||||
0x0002: wpsDevType{"Input Device", map[uint16]string{}},
|
0x0002: {"Input Device", map[uint16]string{}},
|
||||||
0x0003: wpsDevType{"Printers, Scanners, Faxes and Copiers", map[uint16]string{
|
0x0003: {"Printers, Scanners, Faxes and Copiers", map[uint16]string{
|
||||||
0x0001: "Printer",
|
0x0001: "Printer",
|
||||||
0x0002: "Scanner",
|
0x0002: "Scanner",
|
||||||
}},
|
}},
|
||||||
0x0004: wpsDevType{"Camera", map[uint16]string{
|
0x0004: {"Camera", map[uint16]string{
|
||||||
0x0001: "Digital Still Camera",
|
0x0001: "Digital Still Camera",
|
||||||
}},
|
}},
|
||||||
0x0005: wpsDevType{"Storage", map[uint16]string{
|
0x0005: {"Storage", map[uint16]string{
|
||||||
0x0001: "NAS",
|
0x0001: "NAS",
|
||||||
}},
|
}},
|
||||||
0x0006: wpsDevType{"Network Infra", map[uint16]string{
|
0x0006: {"Network Infra", map[uint16]string{
|
||||||
0x0001: "AP",
|
0x0001: "AP",
|
||||||
0x0002: "Router",
|
0x0002: "Router",
|
||||||
0x0003: "Switch",
|
0x0003: "Switch",
|
||||||
}},
|
}},
|
||||||
|
|
||||||
0x0007: wpsDevType{"Display", map[uint16]string{
|
0x0007: {"Display", map[uint16]string{
|
||||||
0x0001: "TV",
|
0x0001: "TV",
|
||||||
0x0002: "Electronic Picture Frame",
|
0x0002: "Electronic Picture Frame",
|
||||||
0x0003: "Projector",
|
0x0003: "Projector",
|
||||||
}},
|
}},
|
||||||
|
|
||||||
0x0008: wpsDevType{"Multimedia Device", map[uint16]string{
|
0x0008: {"Multimedia Device", map[uint16]string{
|
||||||
0x0001: "DAR",
|
0x0001: "DAR",
|
||||||
0x0002: "PVR",
|
0x0002: "PVR",
|
||||||
0x0003: "MCX",
|
0x0003: "MCX",
|
||||||
}},
|
}},
|
||||||
|
|
||||||
0x0009: wpsDevType{"Gaming Device", map[uint16]string{
|
0x0009: {"Gaming Device", map[uint16]string{
|
||||||
0x0001: "XBox",
|
0x0001: "XBox",
|
||||||
0x0002: "XBox360",
|
0x0002: "XBox360",
|
||||||
0x0003: "Playstation",
|
0x0003: "Playstation",
|
||||||
}},
|
}},
|
||||||
0x000F: wpsDevType{"Telephone", map[uint16]string{
|
0x000F: {"Telephone", map[uint16]string{
|
||||||
0x0001: "Windows Mobile",
|
0x0001: "Windows Mobile",
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
wpsAttributes = map[uint16]wpsAttr{
|
wpsAttributes = map[uint16]wpsAttr{
|
||||||
0x104A: wpsAttr{Name: "Version", Desc: wpsVersionDesc},
|
0x104A: {Name: "Version", Desc: wpsVersionDesc},
|
||||||
0x1044: wpsAttr{Name: "State", Desc: map[string]string{
|
0x1044: {Name: "State", Desc: map[string]string{
|
||||||
"01": "Not Configured",
|
"01": "Not Configured",
|
||||||
"02": "Configured",
|
"02": "Configured",
|
||||||
}},
|
}},
|
||||||
0x1012: wpsAttr{Name: "Device Password ID", Desc: map[string]string{
|
0x1012: {Name: "Device Password ID", Desc: map[string]string{
|
||||||
"0000": "Pin",
|
"0000": "Pin",
|
||||||
"0004": "PushButton",
|
"0004": "PushButton",
|
||||||
}},
|
}},
|
||||||
0x103B: wpsAttr{Name: "Response Type", Desc: map[string]string{
|
0x103B: {Name: "Response Type", Desc: map[string]string{
|
||||||
"00": "Enrollee Info",
|
"00": "Enrollee Info",
|
||||||
"01": "Enrollee",
|
"01": "Enrollee",
|
||||||
"02": "Registrar",
|
"02": "Registrar",
|
||||||
"03": "AP",
|
"03": "AP",
|
||||||
}},
|
}},
|
||||||
|
|
||||||
0x1054: wpsAttr{Name: "Primary Device Type", Func: dot11ParseWPSDeviceType},
|
0x1054: {Name: "Primary Device Type", Func: dot11ParseWPSDeviceType},
|
||||||
0x1049: wpsAttr{Name: "Vendor Extension", Func: dot11ParseWPSVendorExtension},
|
0x1049: {Name: "Vendor Extension", Func: dot11ParseWPSVendorExtension},
|
||||||
0x1053: wpsAttr{Name: "Selected Registrar Config Methods", Func: dot11ParseWPSConfigMethods},
|
0x1053: {Name: "Selected Registrar Config Methods", Func: dot11ParseWPSConfigMethods},
|
||||||
0x1008: wpsAttr{Name: "Config Methods", Func: dot11ParseWPSConfigMethods},
|
0x1008: {Name: "Config Methods", Func: dot11ParseWPSConfigMethods},
|
||||||
0x103C: wpsAttr{Name: "RF Bands", Func: dott11ParseWPSBands},
|
0x103C: {Name: "RF Bands", Func: dott11ParseWPSBands},
|
||||||
|
|
||||||
0x1057: wpsAttr{Name: "AP Setup Locked"},
|
0x1057: {Name: "AP Setup Locked"},
|
||||||
0x1041: wpsAttr{Name: "Selected Registrar"},
|
0x1041: {Name: "Selected Registrar"},
|
||||||
0x1047: wpsAttr{Name: "UUID-E"},
|
0x1047: {Name: "UUID-E"},
|
||||||
0x1021: wpsAttr{Name: "Manufacturer", Type: wpsStr},
|
0x1021: {Name: "Manufacturer", Type: wpsStr},
|
||||||
0x1023: wpsAttr{Name: "Model Name", Type: wpsStr},
|
0x1023: {Name: "Model Name", Type: wpsStr},
|
||||||
0x1024: wpsAttr{Name: "Model Number", Type: wpsStr},
|
0x1024: {Name: "Model Number", Type: wpsStr},
|
||||||
0x1042: wpsAttr{Name: "Serial Number", Type: wpsStr},
|
0x1042: {Name: "Serial Number", Type: wpsStr},
|
||||||
0x1011: wpsAttr{Name: "Device Name", Type: wpsStr},
|
0x1011: {Name: "Device Name", Type: wpsStr},
|
||||||
0x1045: wpsAttr{Name: "SSID", Type: wpsStr},
|
0x1045: {Name: "SSID", Type: wpsStr},
|
||||||
0x102D: wpsAttr{Name: "OS Version", Type: wpsStr},
|
0x102D: {Name: "OS Version", Type: wpsStr},
|
||||||
}
|
}
|
||||||
|
|
||||||
wpsConfigs = map[uint16]string{
|
wpsConfigs = map[uint16]string{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue