diff --git a/modules/wifi/wifi_bruteforce.go b/modules/wifi/wifi_bruteforce.go index 44da5394..c52e1c19 100644 --- a/modules/wifi/wifi_bruteforce.go +++ b/modules/wifi/wifi_bruteforce.go @@ -60,7 +60,7 @@ func NewBruteForceConfig() *bruteforceConfig { workers: 1, wide: false, stop_at_first: true, - timeout: 10, + timeout: 15, queue: nil, done: atomic.Uint64{}, todo: 0, @@ -196,7 +196,7 @@ func (mod *WiFiModule) startBruteforce() (err error) { return fmt.Errorf("could not find interface %s", ifName) } - mod.Info("using interface %s (%s)", ifName, mod.iface.HwAddress) + mod.Info("using interface %s", ifName) mod.bruteforce.todo = uint64(len(mod.bruteforce.passwords) * len(mod.bruteforce.targets)) mod.bruteforce.done.Store(0) @@ -243,6 +243,8 @@ func (mod *WiFiModule) startBruteforce() (err error) { mod.showBruteforceProgress() } + mod.bruteforce.running.Store(false) + if mod.bruteforce.done.Load() == mod.bruteforce.todo { mod.Info("bruteforcing completed") } else { diff --git a/modules/wifi/wifi_bruteforce_darwin.go b/modules/wifi/wifi_bruteforce_darwin.go index ab1655ae..650dbe93 100644 --- a/modules/wifi/wifi_bruteforce_darwin.go +++ b/modules/wifi/wifi_bruteforce_darwin.go @@ -9,7 +9,6 @@ import ( "github.com/evilsocket/islazy/async" ) -// networksetup -setairportnetwork interface 'network name' 'password' func wifiBruteforce(mod *WiFiModule, job bruteforceJob) (bool, error) { networksetup, err := exec.LookPath("networksetup") if err != nil { diff --git a/modules/wifi/wifi_bruteforce_linux.go b/modules/wifi/wifi_bruteforce_linux.go index f9b93f25..41fdc5e7 100644 --- a/modules/wifi/wifi_bruteforce_linux.go +++ b/modules/wifi/wifi_bruteforce_linux.go @@ -1,7 +1,97 @@ package wifi -import "errors" +import ( + "bufio" + "errors" + "fmt" + "os" + "os/exec" + "strconv" + "strings" + "time" + + "github.com/evilsocket/islazy/str" + "github.com/evilsocket/islazy/tui" +) func wifiBruteforce(mod *WiFiModule, job bruteforceJob) (bool, error) { - return false, errors.New("TODO") + wpa_supplicant, err := exec.LookPath("wpa_supplicant") + if err != nil { + return false, errors.New("could not find wpa_supplicant in $PATH") + } + + config := fmt.Sprintf(`network={ + ssid="%s" + psk="%s" + }`, strconv.Quote(job.essid), strconv.Quote(job.password)) + + file, err := os.CreateTemp("", "bettercap-wpa-config") + if err != nil { + return false, fmt.Errorf("could not create temporary configuration file: %v", err) + } + defer os.Remove(file.Name()) + + if _, err := file.WriteString(config); err != nil { + return false, fmt.Errorf("could not write temporary configuration file: %v", err) + } + + mod.Debug("using %s ...", file.Name()) + + args := []string{ + "-i", + job.iface, + "-c", + file.Name(), + } + cmd := exec.Command(wpa_supplicant, args...) + cmdReader, err := cmd.StdoutPipe() + if err != nil { + return false, err + } + + scanner := bufio.NewScanner(cmdReader) + done := make(chan bool) + go func() { + auth := false + for scanner.Scan() { + line := strings.ToLower(str.Trim(scanner.Text())) + if strings.Contains(line, "handshake failed") { + mod.Debug("%s", tui.Red(line)) + break + } else if strings.Contains(line, "key negotiation completed") { + mod.Debug("%s", tui.Bold(tui.Green(line))) + auth = true + break + } else { + mod.Debug("%s", tui.Dim(line)) + } + } + if auth { + mod.Debug("success: %v", job) + } + done <- auth + }() + + if err := cmd.Start(); err != nil { + return false, err + } + + timeout := time.After(job.timeout) + doneInTime := make(chan bool) + go func() { + doneInTime <- <-done + }() + + select { + case <-timeout: + mod.Debug("%s timeout", job.password) + // make sure the process is killed + cmd.Process.Kill() + return false, nil + case res := <-doneInTime: + mod.Debug("%s=%v", job.password, res) + // make sure the process is killed + cmd.Process.Kill() + return res, nil + } }