diff --git a/modules/events_view_wifi.go b/modules/events_view_wifi.go index a8fabefb..23acef58 100644 --- a/modules/events_view_wifi.go +++ b/modules/events_view_wifi.go @@ -77,6 +77,10 @@ func (s *EventsStream) viewWiFiHandshakeEvent(e session.Event) { what = fmt.Sprintf("%s handshake", ap.Encryption) } + if hand.PMKID != nil { + what = fmt.Sprintf("PMKID (%x)", hand.PMKID) + } + fmt.Fprintf(s.output, "[%s] [%s] captured %s -> %s %s to %s\n", e.Time.Format(eventTimeFormat), tui.Green(e.Tag), diff --git a/modules/wifi_events.go b/modules/wifi_events.go index 44138eb6..fdf327f9 100644 --- a/modules/wifi_events.go +++ b/modules/wifi_events.go @@ -24,4 +24,5 @@ type WiFiHandshakeEvent struct { NewPackets int AP net.HardwareAddr Station net.HardwareAddr + PMKID []byte } diff --git a/modules/wifi_recon.go b/modules/wifi_recon.go index 1d485c78..80c45304 100644 --- a/modules/wifi_recon.go +++ b/modules/wifi_recon.go @@ -157,6 +157,9 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers } if station, found := w.Session.WiFi.GetClient(staMac.String()); found { + // ref. https://hashcat.net/forum/thread-7717.html + rawPMKID := []byte(nil) + // 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 @@ -165,7 +168,7 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers apMac, staMac, key.Nonce) - station.Handshake.AddFrame(0, packet) + rawPMKID = station.Handshake.AddAndGetPMKID(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)", @@ -194,14 +197,17 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers } } - if doSave && station.Handshake.Complete() { + if doSave && (rawPMKID != nil || station.Handshake.Complete()) { w.Session.Events.Add("wifi.client.handshake", WiFiHandshakeEvent{ File: w.shakesFile, NewPackets: numUnsaved, AP: apMac, Station: staMac, + PMKID: rawPMKID, }) } + } else { + log.Warning("EAPOL captured for unknown station %s", staMac.String()) } } } diff --git a/network/wifi_handshake.go b/network/wifi_handshake.go index 9c42aa63..e641b1fe 100644 --- a/network/wifi_handshake.go +++ b/network/wifi_handshake.go @@ -1,8 +1,10 @@ package network import ( - "github.com/google/gopacket" "sync" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" ) type Handshake struct { @@ -34,6 +36,29 @@ func (h *Handshake) SetBeacon(pkt gopacket.Packet) { } } +func (h *Handshake) AddAndGetPMKID(pkt gopacket.Packet) []byte { + h.AddFrame(0, pkt) + + prevWasKey := false + for _, layer := range pkt.Layers() { + if layer.LayerType() == layers.LayerTypeEAPOLKey { + prevWasKey = true + continue + } + + if prevWasKey && layer.LayerType() == layers.LayerTypeDot11InformationElement { + info := layer.(*layers.Dot11InformationElement) + if info.ID == layers.Dot11InformationElementIDVendor && info.Length == 20 { + return info.Info + } + } + + prevWasKey = false + } + + return nil +} + func (h *Handshake) AddFrame(n int, pkt gopacket.Packet) { h.Lock() defer h.Unlock()