PK!dllpyreaver/__init__.py"""pyreaver. Reaver python bindings """ from .reaver import Reaver # noqa from .wash import Wash # noqa PK!ppyreaver/executor.py"""Pyrcrack-ng Executor helper.""" import abc import asyncio import functools import itertools import logging import subprocess import tempfile import uuid import docopt import stringcase logging.basicConfig(level=logging.INFO) class Option: """Represents a single option (e.g, -e).""" def __init__(self, usage, word=None, value=None, logger=None): """Set option parameters.""" self.usage = usage self.word = word self.logger = logger self.value = value keys = usage.keys() self.is_short = Option.short(word) in keys self.is_long = Option.long(word) in keys self.expects_args = bool(usage[self.formatted]) self.logger.debug("Parsing option %s:%s", self.word, self.value) @property @functools.lru_cache() def formatted(self): """Format given option acording to definition.""" result = (Option.short(self.word) if self.is_short else Option.long(self.word)) if self.usage.get(result): return result sword = self.word.replace('_', '-') return Option.short(sword) if self.is_short else Option.long(sword) @staticmethod def long(word): """Extract long format option.""" return "--{}".format(word) @staticmethod def short(word): """Extract short format option.""" return "-{}".format(word) @property def parsed(self): """Returns key, value if value is required.""" if self.expects_args: return (self.formatted, str(self.value)) return (self.formatted, ) def __repr__(self): return f"Option(<{self.parsed}>, {self.is_short}, {self.expects_args})" class ExecutorHelper: """Abstract class interface to a shell command.""" def __init__(self): """Set docstring.""" if not self.__doc__: self.__doc__ = self.helpstr self.uuid = uuid.uuid4().hex self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(logging.DEBUG) self.proc = None self.meta = {} if self.requires_tempfile: self.tempfile = tempfile.NamedTemporaryFile() elif self.requires_tempdir: self.tempdir = tempfile.TemporaryDirectory() @abc.abstractproperty def requires_tempfile(self): """Synchronous mode.""" @abc.abstractproperty def requires_tempdir(self): """Synchronous mode.""" @abc.abstractproperty def command(self): """Specify command to execute.""" @property @functools.lru_cache() def helpstr(self): """Extract help string for current command.""" helpcmd = '{} 2>&1; echo'.format(self.command) return subprocess.check_output(helpcmd, shell=True).decode() @property @functools.lru_cache() def usage(self): """Extract usage from a specified command. This is useful if usage not defined in subclass, but it is recommended to define them there. """ opt = docopt.parse_defaults(self.__doc__) return dict({a.short or a.long: bool(a.argcount) for a in opt}) def _run(self, *args, **kwargs): """Check command usage and execute it. If self.sync is defined, it will return process call output, and launch it blockingly. Otherwise it will call asyncio.create_subprocess_exec() """ self.logger.debug("Parsing options: %s", kwargs) options = list( (Option(self.usage, a, v, self.logger) for a, v in kwargs.items())) self.logger.debug("Got options: %s", options) opts = [self.command] + list(args) + list( itertools.chain(*(o.parsed for o in options))) self.logger.debug("Running command: %s", opts) return opts async def run(self, *args, **kwargs): """Run (as a coroutine).""" opts = self._run(*args, **kwargs) self.proc = await asyncio.create_subprocess_exec( *opts, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return self.proc async def __aexit__(self, *args, **kwargs): """Clean up conext manager.""" if self.requires_tempfile: self.tempfile.__exit__(*args, **kwargs) elif self.requires_tempdir: self.tempdir.__exit__(*args, **kwargs) async def __aenter__(self): """Create temporary directories and files if required.""" if self.requires_tempfile: self.tempfile.__enter__() elif self.requires_tempdir: self.tempdir.__enter__() return self def stc(command): """Convert snake case to camelcase in class format.""" return stringcase.pascalcase(command.replace('-', '_')) PK!7s^^pyreaver/models.py"""Models.""" from dataclasses import dataclass @dataclass class AccessPoint: """Represents an AP, as outputted by wash.""" bssid: str essid: str channel: str rssi: str vendor_oui: str wps_version: str wps_state: str wps_locked: str wps_manufacturer: str wps_model_name: str wps_model_number: str wps_device_name: str wps_serial: str wps_uuid: str wps_response_type: str wps_primary_device_type: str wps_config_methods: str wps_rf_bands: str = None dummy: str = None wps_selected_registrar: str = None @property def score(self): """**Kinda-hackability** orientative score. TODO: add wps version, state etc here. """ power_score = -float(self.rssi) / 100 total_score = power_score return round((total_score / 1) * 100) PK!7 pyreaver/reaver.py"""Airdecap-ng.""" from .executor import ExecutorHelper import asyncio class Reaver(ExecutorHelper): """Reaver v1.6.5-git-21-gf8847d4 WiFi Protected Setup Attack Tool Copyright (c) 2011, Tactical Network Solutions, Craig Heffner Options: --interface= Name of the monitor-mode interface to use --bssid= BSSID of the target AP --mac= MAC of the host system --essid= ESSID of the target AP --channel= Set the 802.11 channel for the interface (implies -f) --session= Restore a previous session file --exec= Execute the supplied command upon successful pin recovery --fixed Disable channel hopping --5ghz Use 5GHz 802.11 channels --verbose Display non-critical warnings (-vv or -vvv for more) --quiet Only display critical messages --help Show help --pin= Use the specified pin (may be arbitrary string or 4/8 digit WPS pin) --delay= Set the delay between pin attempts [1] --lock-delay= Set the time to wait if the AP locks WPS pin attempts [60] --max-attempts= Quit after num pin attempts --fail-wait= Set the time to sleep after 10 unexpected failures [0] --recurring-delay= Sleep for y seconds every x pin attempts --timeout= Set the receive timeout period [10] --m57-timeout= Set the M5/M7 timeout period [0.40] --no-associate Do not associate with the AP (association must be done by another application) --no-nacks Do not send NACK messages when out of order packets are received --dh-small Use small DH keys to improve crack speed --ignore-locks Ignore locked state reported by the target AP --eap-terminate Terminate each WPS session with an EAP FAIL packet --timeout-is-nack Treat timeout as NACK (DIR-300/320) --ignore-fcs Ignore frame checksum errors --win7 Mimic a Windows 7 registrar [False] --pixie-dust Run pixiedust attack --output-file= Write packets of interest into pcap file """ # noqa command = 'reaver' sync = False requires_tempfile = False requires_tempdir = False async def run(self, *args, **kwargs): """Run async and update results""" asyncio.create_task(self.result_updater()) return await super().run(*args, **kwargs) async def result_updater(self): """Set result on local object.""" self.meta['result'] = {'lines': []} while not self.proc: await asyncio.sleep(1) while self.proc.returncode is None: line = (await self.proc.stdout.readline()).decode() self.meta['result']['lines'].append(line) PK!дpyreaver/wash.py"""Walsh.""" from contextlib import suppress import asyncio import json from .executor import ExecutorHelper from .models import AccessPoint class Wash(ExecutorHelper): """ Wash v1.6.5-git-21-gf8847d4 WiFi Protected Setup Scan Tool Copyright (c) 2011, Tactical Network Solutions, Craig Heffner Options: --interface= Interface to capture packets on --file [FILE1 FILE2 FILE3 ...] Read packets from capture files --channel= Channel to listen on [auto] --probes= Maximum number of probes to send --ignore-fcs Ignore frame checksum errors --2ghz Use 2.4GHz 802.11 channels --5ghz Use 5GHz 802.11 channels --scan Use scan mode --survey Use survey mode [default] --all Show all APs, even those without --json print extended WPS info as json --utf8 Show UTF8 ESSID --progress Show percentage of crack progress --help Show help """ command = 'wash' sync = False requires_tempfile = False requires_tempdir = False async def run(self, *args, **kwargs): """Run async, with json mode""" if not ('json' in kwargs or 'j' in kwargs): kwargs.pop('j', None) kwargs['json'] = True asyncio.create_task(self.result_updater()) return await super().run(*args, **kwargs) async def result_updater(self): """Set result on local object.""" while not self.proc: await asyncio.sleep(1) self.meta['result'] = {'aps': []} while self.proc.returncode is None: with suppress(json.JSONDecodeError): self.meta['result']['aps'].append( AccessPoint( **json.loads(await self.proc.stdout.readline()))) def sorted_aps(self): """Return sorted aps by score.""" return sorted( self.meta['result']['aps'], key=lambda x: x.score, reverse=True) PK!HڽTUpyreaver-0.1.3.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!HRM!pyreaver-0.1.3.dist-info/METADATA_K0|<*B؆YC}w5$&ۛV"{-Nr0@ $k@$}BTl$gw`Css<6lZ+͑+8XW")jGTb`O56CE%Bf\G`_beʧxEJ 9,h.~6Nɧ)e'KQ湨O Q$T >PڨPK!HGpyreaver-0.1.3.dist-info/RECORDu9r@@gidhY PZb'Ҙ^vq4= :Ю`H#Ȱ걾A*Bz|\YRh%dNl@[';K j), ]SսNuLxgn"p$@rQ^,) Y}Y%3*{q%h[a?ҿ k~])ѡ^'IE@АM-ѐ k2`hZgw_2KbF9?D@n0Y}o޽,/v꼍70Q^ƃTU,?;,{N*|fғWT?H#O0jn-ɂI)^ D;h9oPK!dllpyreaver/__init__.pyPK!ppyreaver/executor.pyPK!7s^^pyreaver/models.pyPK!7 Opyreaver/reaver.pyPK!д$pyreaver/wash.pyPK!HڽTU.-pyreaver-0.1.3.dist-info/WHEELPK!HRM!-pyreaver-0.1.3.dist-info/METADATAPK!HG.pyreaver-0.1.3.dist-info/RECORDPK*0