Skip to content

Commit

Permalink
Code optimization ++++
Browse files Browse the repository at this point in the history
  • Loading branch information
kimocoder committed Aug 18, 2023
1 parent 2b24c8c commit 2f53243
Show file tree
Hide file tree
Showing 19 changed files with 224 additions and 241 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ chardet==5.2.0
pytest==7.4.0
scapy==2.5.0
argparse==1.4.0
setuptools==68.1.0
setuptools==68.1.2
124 changes: 60 additions & 64 deletions wifite/attack/wep.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# -*- coding: utf-8 -*-

import time

from ..config import Configuration
from ..model.attack import Attack
from ..model.wep_result import CrackResultWEP
Expand All @@ -13,15 +12,15 @@
from ..util.color import Color


class AttackWEP(Attack):
class AttackWEP:
"""
Contains logic for attacking a WEP-encrypted access point.
"""

fakeauth_wait = 5 # TODO: Configuration?

def __init__(self, target):
super(AttackWEP, self).__init__(target)
super().__init__(target)
self.crack_result = None
self.success = False

Expand Down Expand Up @@ -53,11 +52,11 @@ def run(self):
try:
# Start Airodump process
with Airodump(channel=self.target.channel,
target_bssid=self.target.bssid,
ivs_only=True, # Only capture IVs packets
skip_wps=True, # Don't check for WPS-compatibility
output_file_prefix='wep',
delete_existing_files=not keep_ivs) as airodump:
target_bssid=self.target.bssid,
ivs_only=True, # Only capture IVs packets
skip_wps=True, # Don't check for WPS-compatibility
output_file_prefix='wep',
delete_existing_files=not keep_ivs) as airodump:

Color.clear_line()
Color.p('\r{+} {O}waiting{W} for target to appear...')
Expand Down Expand Up @@ -107,7 +106,7 @@ def run(self):
current_ivs = airodump_target.ivs
total_ivs = previous_ivs + current_ivs

status = '%d/{C}%d{W} IVs' % (total_ivs, Configuration.wep_crack_at_ivs)
status = f'{total_ivs:d}/{{C}}{Configuration.wep_crack_at_ivs:d}{{W}} IVs'
if fakeauth_proc:
status += ', {G}fakeauth{W}' if fakeauth_proc.status else ', {R}no-auth{W}'
if aireplay.status is not None:
Expand All @@ -117,26 +116,9 @@ def run(self):

# Check if we cracked it.
if aircrack and aircrack.is_cracked():
(hex_key, ascii_key) = aircrack.get_key_hex_ascii()
# bssid = airodump_target.bssid
# if airodump_target.essid_known:
# essid = airodump_target.essid
# else:
# essid = None
Color.pl('\n{+} {C}%s{W} WEP attack {G}successful{W}\n' % attack_name)
if aireplay:
aireplay.stop()
if fakeauth_proc:
fakeauth_proc.stop()

self.crack_result = CrackResultWEP(self.target.bssid, self.target.essid, hex_key, ascii_key)
self.crack_result.dump()

Airodump.delete_airodump_temp_files('wep')

self.success = True
return self.success

return self._extracted_from_run_93(
aircrack, attack_name, aireplay, fakeauth_proc
)
if aircrack and aircrack.is_running():
# Aircrack is running in the background.
Color.p('and {C}cracking{W}')
Expand Down Expand Up @@ -173,10 +155,10 @@ def run(self):
xor_file = Aireplay.get_xor()
if not xor_file:
# If .xor is not there, the process failed.
Color.pl('\n{!} {O}%s attack{R} did not generate a .xor file' % attack_name)
Color.pl(f'\n{{!}} {{O}}{attack_name} attack{{R}} did not generate a .xor file')
# XXX: For debugging
Color.pl('{?} {O}Command: {R}%s{W}' % ' '.join(aireplay.cmd))
Color.pl('{?} {O}Output:\n{R}%s{W}' % aireplay.get_output())
Color.pl(f'{{?}} {{O}}Command: {{R}}{" ".join(aireplay.cmd)}{{W}}')
Color.pl(f'{{?}} {{O}}Output:\n{{R}}{aireplay.get_output()}{{W}}')
break

# If .xor exists, run packetforge-ng to create .cap
Expand All @@ -199,16 +181,16 @@ def run(self):
continue
else:
Color.pl('\n{!} {O}aireplay-ng exited unexpectedly{W}')
Color.pl('{?} {O}Command: {R}%s{W}' % ' '.join(aireplay.cmd))
Color.pl('{?} {O}Output:\n{R}%s{W}' % aireplay.get_output())
Color.pl(f'{{?}} {{O}}Command: {{R}}{" ".join(aireplay.cmd)}{{W}}')
Color.pl(f'{{?}} {{O}}Output:\n{{R}}{aireplay.get_output()}{{W}}')
break # Continue to other attacks

# Check if IVs stopped flowing (same for > N seconds)
if airodump_target.ivs > last_ivs_count:
time_unchanged_ivs = time.time()
elif Configuration.wep_restart_stale_ivs > 0 and \
attack_name != 'chopchop' and \
attack_name != 'fragment':
attack_name != 'chopchop' and \
attack_name != 'fragment':
stale_seconds = time.time() - time_unchanged_ivs
if stale_seconds > Configuration.wep_restart_stale_ivs:
# No new IVs within threshold, restart aireplay
Expand All @@ -224,31 +206,45 @@ def run(self):

time.sleep(1)
continue
# End of big while loop
# End of with-airodump
# End of big while loop
# End of with-airodump
except KeyboardInterrupt:
if fakeauth_proc:
fakeauth_proc.stop()
if not attacks_remaining:
if keep_ivs:
Airodump.delete_airodump_temp_files('wep')

self.success = False
return self.success

return self._extracted_from_run_206(keep_ivs)
if self.user_wants_to_stop(attack_name, attacks_remaining, airodump_target):
if keep_ivs:
Airodump.delete_airodump_temp_files('wep')

self.success = False
return self.success

return self._extracted_from_run_206(keep_ivs)
except Exception as e:
Color.pexception(e)
continue
# End of big try-catch
# End of for-each-attack-type loop
return self._extracted_from_run_206(keep_ivs)

# TODO Rename this here and in `run`
def _extracted_from_run_93(self, aircrack, attack_name, aireplay, fakeauth_proc):
(hex_key, ascii_key) = aircrack.get_key_hex_ascii()
# bssid = airodump_target.bssid
# if airodump_target.essid_known:
# essid = airodump_target.essid
# else:
# essid = None
Color.pl(f'\n{{+}} {{C}}{attack_name}{{W}} WEP attack {{G}}successful{{W}}\n')
if aireplay:
aireplay.stop()
if fakeauth_proc:
fakeauth_proc.stop()

self.crack_result = CrackResultWEP(self.target.bssid, self.target.essid, hex_key, ascii_key)
self.crack_result.dump()

Airodump.delete_airodump_temp_files('wep')

self.success = True
return self.success

# TODO Rename this here and in `run`
def _extracted_from_run_206(self, keep_ivs):
if keep_ivs:
Airodump.delete_airodump_temp_files('wep')

Expand All @@ -271,23 +267,23 @@ def user_wants_to_stop(current_attack, attacks_remaining, target):

# Deauth clients & retry
attack_index = 1
Color.pl(' {G}1{W}: {O}Deauth clients{W} and {G}retry{W} {C}%s attack{W} against {G}%s{W}' % (
current_attack, target_name))
Color.pl(
f' {{G}}1{{W}}: {{O}}Deauth clients{{W}} and {{G}}retry{{W}} {{C}}{current_attack} attack{{W}} against {{G}}{target_name}{{W}}')

# Move onto a different WEP attack
for attack_name in attacks_remaining:
attack_index += 1
Color.pl(
' {G}%d{W}: Start new {C}%s attack{W} against {G}%s{W}' % (attack_index, attack_name, target_name))
f' {{G}}{attack_index:d}{{W}}: Start new {{C}}{attack_name} attack{{W}} against {{G}}{target_name}{{W}}')

# Stop attacking entirely
attack_index += 1
Color.pl(' {G}%d{W}: {R}Stop attacking, {O}Move onto next target{W}' % attack_index)
Color.pl(f' {{G}}{attack_index:d}{{W}}: {{R}}Stop attacking, {{O}}Move onto next target{{W}}')
while True:
Color.p('{?} Select an option ({G}1-%d{W}): ' % attack_index)
Color.p(f'{{?}} Select an option ({{G}}1-{attack_index:d}{{W}}): ')
answer = input()
if not answer.isdigit() or int(answer) < 1 or int(answer) > attack_index:
Color.pl('{!} {R}Invalid input: {O}Must enter a number between {G}1-%d{W}' % attack_index)
Color.pl(f'{{!}} {{R}}Invalid input: {{O}}Must enter a number between {{G}}1-{attack_index:d}{{W}}')
continue
answer = int(answer)
break
Expand All @@ -306,20 +302,20 @@ def user_wants_to_stop(current_attack, attacks_remaining, target):
continue # Don't deauth ourselves.

Color.clear_entire_line()
Color.p('\r{+} {O}Deauthenticating client {C}%s{W}...' % client.station)
Color.p(f'\r{{+}} {{O}}Deauthenticating client {{C}}{client.station}{{W}}...')

Aireplay.deauth(target.bssid, client_mac=client.station, essid=target.essid)
deauth_count += 1

Color.clear_entire_line()
Color.pl('\r{+} Sent {C}%d {O}deauths{W}' % deauth_count)
Color.pl(f'\r{{+}} Sent {{C}}{deauth_count:d} {{O}}deauths{{W}}')

# Re-insert current attack to top of list of attacks remaining
attacks_remaining.insert(0, current_attack)
return False # Don't stop
elif answer == attack_index:
if answer == attack_index:
return True # Stop attacking
elif answer > 1:
if answer > 1:
# User selected specific attack: Re-order attacks based on desired next-step
attacks_remaining.insert(0, attacks_remaining.pop(answer - 2))
return False # Don't stop
Expand All @@ -329,17 +325,17 @@ def fake_auth(self):
Attempts to fake-authenticate with target.
Returns: True if successful, False is unsuccessful.
"""
Color.p('\r{+} attempting {G}fake-authentication{W} with {C}%s{W}...' % self.target.bssid)
Color.p(f'\r{{+}} attempting {{G}}fake-authentication{{W}} with {{C}}{self.target.bssid}{{W}}...')
fakeauth = Aireplay.fakeauth(self.target, timeout=AttackWEP.fakeauth_wait)
if fakeauth:
Color.pl(' {G}success{W}')
else:
Color.pl(' {R}failed{W}')
if Configuration.require_fakeauth:
# Fakeauth is required, fail
raise Exception('Fake-authenticate did not complete within %d seconds' % AttackWEP.fakeauth_wait)
raise Exception(f'Fake-authenticate did not complete within {AttackWEP.fakeauth_wait:d} seconds')
# Warn that fakeauth failed
Color.pl('{!} {O} unable to fake-authenticate with target (%s){W}' % self.target.bssid)
Color.pl(f'{{!}} {{O}} unable to fake-authenticate with target ({self.target.bssid}){{W}}')
Color.pl('{!} continuing attacks because {G}--require-fakeauth{W} was not set')
return fakeauth

Expand Down
4 changes: 2 additions & 2 deletions wifite/attack/wpa.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

class AttackWPA(Attack):
def __init__(self, target):
super(AttackWPA, self).__init__(target)
super().__init__(target)
self.clients = []
self.crack_result = None
self.success = False
Expand Down Expand Up @@ -225,7 +225,7 @@ def save_handshake(handshake):
os.makedirs(Configuration.wpa_handshake_dir)

# Generate filesystem-safe filename from bssid, essid and date
if handshake.essid and type(handshake.essid) is str:
if handshake.essid and isinstance(type, handshake.essid) is str:
essid_safe = re.sub('[^a-zA-Z0-9]', '', handshake.essid)
else:
essid_safe = 'UnknownEssid'
Expand Down
17 changes: 8 additions & 9 deletions wifite/attack/wps.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def can_attack_wps():
return Reaver.exists() or Bully.exists()

def __init__(self, target, pixie_dust=False, null_pin=False):
super(AttackWPS, self).__init__(target)
super().__init__(target)
self.success = False
self.crack_result = None
self.pixie_dust = pixie_dust
Expand Down Expand Up @@ -49,25 +49,24 @@ def run(self):
if not Reaver.exists() and Bully.exists():
# Use bully if reaver isn't available
return self.run_bully()
elif self.pixie_dust and not Reaver.is_pixiedust_supported() and Bully.exists():
if self.pixie_dust and not Reaver.is_pixiedust_supported() and Bully.exists():
# Use bully if reaver can't do pixie-dust
return self.run_bully()
elif Configuration.use_bully:
if Configuration.use_bully:
# Use bully if asked by user
return self.run_bully()
elif not Reaver.exists():
if not Reaver.exists():
# Print error if reaver isn't found (bully not available)
if self.pixie_dust:
Color.pl('\r{!} {R}Skipping WPS Pixie-Dust attack: {O}reaver{R} not found.{W}')
else:
Color.pl('\r{!} {R}Skipping WPS PIN attack: {O}reaver{R} not found.{W}')
return False
elif self.pixie_dust and not Reaver.is_pixiedust_supported():
# Print error if reaver can't support pixie-dust (bully not available)
Color.pl('\r{!} {R}Skipping WPS attack: {O}reaver{R} does not support {O}--pixie-dust{W}')
return False
else:
if not self.pixie_dust or Reaver.is_pixiedust_supported():
return self.run_reaver()
# Print error if reaver can't support pixie-dust (bully not available)
Color.pl('\r{!} {R}Skipping WPS attack: {O}reaver{R} does not support {O}--pixie-dust{W}')
return False

# TODO Rename this here and in `run`
def _extracted_from_run_14(self, arg0):
Expand Down
14 changes: 7 additions & 7 deletions wifite/model/wpa_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@ def __init__(self, bssid, essid, handshake_file, key):
self.essid = essid
self.handshake_file = handshake_file
self.key = key
super(CrackResultWPA, self).__init__()
super().__init__()

def dump(self):
if self.essid:
Color.pl(f'{{+}} {"Access Point Name".rjust(19)}: {{C}}{self.essid}{{W}}')
if self.bssid:
Color.pl(f'{{+}} {"Access Point BSSID".rjust(19)}: {{C}}{self.bssid}{{W}}')
Color.pl('{+} %s: {C}%s{W}' % ('Encryption'.rjust(19), self.result_type))
Color.pl(f'{{+}} {"Encryption".rjust(19)}: {{C}}{self.result_type}{{W}}')
if self.handshake_file:
Color.pl('{+} %s: {C}%s{W}' % ('Handshake File'.rjust(19), self.handshake_file))
Color.pl(f'{{+}} {"Handshake File".rjust(19)}: {{C}}{self.handshake_file}{{W}}')
if self.key:
Color.pl('{+} %s: {G}%s{W}' % ('PSK (password)'.rjust(19), self.key))
Color.pl(f'{{+}} {"PSK (password)".rjust(19)}: {{G}}{self.key}{{W}}')
else:
Color.pl('{!} %s {O}key unknown{W}' % ''.rjust(19))
Color.pl(f'{{!}} {"".rjust(19)} {{O}}key unknown{{W}}')

def print_single_line(self, longest_essid):
self.print_single_line_prefix(longest_essid)
Color.p('{G}%s{W}' % 'WPA'.ljust(5))
Color.p(f'{{G}}{"WPA".ljust(5)}{{W}}')
Color.p(' ')
Color.p('Key: {G}%s{W}' % self.key)
Color.p(f'Key: {{G}}{self.key}{{W}}')
Color.pl('')

def to_dict(self):
Expand Down
2 changes: 1 addition & 1 deletion wifite/tools/aircrack.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def __del__(self):
def crack_handshake(handshake, show_command=False):
from ..util.color import Color
from ..util.timer import Timer
f'Tries to crack a handshake. Returns WPA key if found, otherwise None.'
'Tries to crack a handshake. Returns WPA key if found, otherwise None.'

key_file = Configuration.temp('wpakey.txt')
command = [
Expand Down
1 change: 0 additions & 1 deletion wifite/tools/airmon.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import os
import re
import signal

from .dependency import Dependency
from .ip import Ip
from .iw import Iw
Expand Down
2 changes: 1 addition & 1 deletion wifite/tools/airodump.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import time
from .dependency import Dependency
from .tshark import Tshark
#from .wash import Wash
from .wash import Wash
from ..util.process import Process
from ..config import Configuration
from ..model.target import Target, WPSState
Expand Down
Loading

0 comments on commit 2f53243

Please sign in to comment.