Open-source project
wiire-a/pixiewps avatar
wiire-a/pixiewps

pixiewps: computing the WPS PIN offline from a captured handshake

An offline Wi-Fi Protected Setup brute-force utility

1,756 stars322 forksCNOASSERTION

At a glance

What is it?
pixiewps is a C tool that recovers a WPS PIN by brute forcing it locally against the authentication session key from a captured exchange, exploiting the low entropy of some access point implementations, and since version 1.4 it can also recover a WPA-PSK from a passive capture.
Who is it for?
pixiewps fits a security researcher auditing the WPS implementation of an access point they own, since the whole computation is local and offline, taking seconds instead of the hours an online attack needs.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the attack actually exploits

Pixiewps is a tool written in C used to bruteforce offline the WPS PIN, exploiting the low or non-existing entropy of some software implementations, which is the so-called pixie-dust attack discovered by Dominique Bongard in summer 2014. The project states it is meant for educational purposes only.

The distinction from the usual approach is the important one. Traditional online brute-force attacks, implemented in tools like Reaver or Bully, aim to recover the PIN in a few hours by talking to the access point over the air. This method can get the PIN in a matter of seconds or minutes, depending on the target, if vulnerable.

The reason is that WPS PINs are not random. They are derived from a fixed algorithm, so the value space is much smaller than eight digits, and the weakness is in implementations that generate them with low or no entropy. An offline attack computes candidates locally against a value derived from the handshake, rather than making network requests to test each one. That is why the same attack that takes hours online takes seconds here, and why the tool needs a captured session rather than a live radio conversation.

The tool came out of the community, and the README links the two Kali forum threads where the work happened, one announcing the tool and one describing the offline WPS attack.

The project is licensed under GPL v3 or later, with a LICENSE.md file. The primary language is C, the last push was on 2026-04-17, and the releases are v1.4.2 from 2018-01-25, v1.4.1 from 2017-12-04 and v1.4 from 2017-12-04.

Building it, and the OpenSSL trade-off

The build needs a compiler toolchain and, depending on the version, a threading library.

bash
apt-get -y install build-essential

The requirements section explains the history. Prior versions of 1.2 require libssl-dev, and versions 1.4 and later make use of multi-threading and require libpthread, POSIX threads. OpenSSL has also been re-introduced as optional to achieve better speeds, which is the point of the Build section.

The source is obtained by cloning, or by downloading and unzipping the archive:

bash
git clone https://github.com/wiire/pixiewps
bash
wget https://github.com/wiire/pixiewps/archive/master.zip && unzip master.zip

Then the build is a plain make:

bash
cd pixiewps*/
make

and you can optionally turn on the faster path:

bash
make OPENSSL=1

which uses the faster OpenSSL SHA-256 functions. The install is:

bash
sudo make install

The Makefile shows what is happening underneath. The compiler flags are -O3 with an internal -std=c99, and the OpenSSL branch adds -lcrypto and a -DUSE_OPENSSL define. The crypto is vendored: the source includes src/crypto/tfm, a TFM implementation, and src/crypto/tc, a twofish implementation, with the AES sources in aes_cbc.c and aes.c. So the default build has no OpenSSL dependency at all, which is why libssl-dev is not in the requirements for the current versions, and the OpenSSL build is purely a speed optimisation.

The library is linked with -lpthread, and the install target copies the binary to /usr/local/bin and the man page pixiewps.1 to /usr/local/share/man/man1.

The six required arguments, and what they represent

The usage screen is a complete specification of the tool's interface, and the required arguments are the values from the captured exchange.

code
Usage: pixiewps <arguments>

Required arguments:

  -e, --pke         : Enrollee public key
  -r, --pkr         : Registrar public key
  -s, --e-hash1     : Enrollee hash 1
  -z, --e-hash2     : Enrollee hash 2
  -a, --authkey     : Authentication session key
  -n, --e-nonce     : Enrollee nonce

The naming maps directly onto the WPS exchange. The enrollee and the registrar are the two parties in the protocol, the enrollee hash 1 and hash 2 are the values the enrollee commits to, the authentication session key is the shared secret the two sides derived, and the enrollee nonce is the random value in the exchange.

The optional arguments add the registrar nonce, the enrollee BSSID, a verbosity level from 1 to 3 where 1 is the quietest, an output file, and a jobs count for parallel threads, defaulting to auto.

Then there are the mode selection flags, which are comma separated and default to auto, and a set of mode-3 only options: a starting date and an ending date, a force flag, and the two recovery options for encrypted settings.

The tool has a man page and a verbose help screen with more usage examples, and the common invocation is simply:

code
pixiewps --pke ... --pkr ... --e-hash1 ... --e-hash2 ... --authkey ... --e-nonce ...

The documentation is direct about where the values come from. It requires a modified version of Reaver or Bully which prints the Authentication Session key, given as the --authkey option, and the recommended version is reaver-wps-fork-t6x.

Mode 3, and recovering a WPA-PSK from a passive capture

Since version 1.4 the tool can also recover the WPA-PSK from a complete passive capture, M1 through M7, for some devices, and those devices currently only work with --mode 3.

The two mode-3-only options in the usage screen are -7, --m7-enc, recover encrypted settings from M7, and -5, --m5-enc, recover secret nonce from M5.

The -7 option requires the encrypted settings attribute found in M7, which is where the Registrar proved knowledge of the PIN and the Access Points, the Enrollee, sent its current network configuration. The documentation says this feature can be used to crack the WPA-PSK, and the WPS PIN, from a passive packet capture such as sniffing a PBC session. That is a meaningful extension, because a passive capture of a PBC session is something a monitoring adapter can collect without any interaction with the access point at all.

The date options support that mode. --start [mm/]yyyy and --end [mm/]yyyy, only for mode 3, default to a plus and minus one day, and they bound the search over the PIN derivation. The -f, --force option, also mode 3 only, starts bruteforcing from the current time and goes back all the way to 0, and is conceptually identical to using --end 01/1970, since the two are interchangeable.

There is also a feature inherited from Reaver 1.3, the -S, --dh-small option, and the documentation is clear that it should not be used. It works by choosing the private key as 1, which results in the public key --pkr being 2, and that speeds the cracking because the access point does less work to compute the Diffie-Hellman shared secret later used to derive the session keys that encrypt the transaction. Some routers are buggy and do not function correctly with it, and some will not even be able to validate the correct PIN, so the transaction fails after M4. For this reason the feature is deprecated and should never be used in Reaver.

One more edge case is documented, the empty PIN denoted as <empty>, which can be tested with -p "" in Reaver 1.6.1 and later. It comes from a misconfiguration of the PIN method on some access points which have the PIN variable set to NULL or the empty string.

Notes for wrappers, platforms, and versioning

There is a short section aimed at people writing scripts around the tool, and it is the part that tells you how to integrate it.

The data in the input can be formatted with one of the following byte separators, a colon, a hyphen, a space, or without any. The most useful tags like WPS pin and WPA-PSK are denoted with [+] or [-] in case of failure, so a wrapper can tell a recovered PIN from a recovered PSK from a failure. Pixiewps returns 0 on a successful attempt. And an option that has been deprecated means it should not be used any more and may get removed in a later release.

Platform support is broad. On Windows it can be compiled with MinGW, and you need to have installed pthread support. Since version 1.4.1 it has been included in the OpenWrt and LEDE official repositories, which is how it reached the embedded router world where WPS PINs actually matter.

The versioning convention is 1.x.y, where x usually indicates a major release and y a minor release, typically bug fixing or other small changes. Every major release starts with y equal to 0 and should be considered unstable in the first hours of publishing, even if not marked as such. The CHANGELOG.md holds the list of changes between releases.

The source layout is small: a src directory, a Makefile, the man page, the CHANGELOG, the licence, and a .editorconfig. Inside src there are the crypto subdirectories, the headers for config, endianness, version, the main pixiewps header, utils and wps, and a pixiewrapper.c that builds a second binary, which is the wrapper target in the Makefile.

The contributing section notes that since the very first release pixiewps has improved a lot but it is hard to keep track of every device on the market, and the project decided to add an automatic message suggesting that they are interested in supporting a given device. That is a sensible way to collect coverage data from a tool that runs against hardware the maintainers do not own.

Editorial conclusion

pixiewps fits a security researcher auditing the WPS implementation of an access point they own, since the whole computation is local and offline, taking seconds instead of the hours an online attack needs. It is a poor fit for attacking a network you do not own, which is the whole capability of the tool and the reason to think twice before installing it, and it is a poor fit for an access point with a properly random PIN, since the attack depends on the implementation being weak. Before using it, check the CHANGELOG.md for the release history, build with make OPENSSL=1 for the faster SHA-256 path, and read the notes on wrapper scripts so your automation parses the output correctly.

Frequently asked questions

What is pixiewps and how is it different from Reaver?

It is a C tool that bruteforces offline the WPS PIN, exploiting the low or non-existing entropy of some access point implementations, the pixie-dust attack discovered by Dominique Bongard in summer 2014. Where tools like Reaver or Bully recover a PIN in a few hours by talking to the access point, pixiewps can do it in seconds or minutes if the target is vulnerable, because the work happens locally.

How do I build and install pixiewps?

Install build-essential, clone the repository or download and unzip the archive, then run make in the source directory, optionally with make OPENSSL=1 to use the faster OpenSSL SHA-256 functions, and finish with sudo make install. Versions 1.4 and later use multi-threading and require libpthread, and the default build has no OpenSSL dependency.

What arguments does pixiewps need?

Six are required: the enrollee public key, the registrar public key, the enrollee hash 1 and hash 2, the authentication session key, and the enrollee nonce. The authentication session key comes from a modified version of Reaver or Bully that prints it, with the recommended version being reaver-wps-fork-t6x. Optional arguments include the registrar nonce, the enrollee BSSID, a verbosity level, an output file and a parallel job count.

Can pixiewps recover a WPA-PSK from a passive capture?

Since version 1.4 it can, for some devices, and those work with --mode 3. The -7, --m7-enc option requires the encrypted settings attribute found in M7, and the feature can be used to crack the WPA-PSK and the WPS PIN from a passive packet capture such as a sniffed PBC session.

Official sources

  1. Issues
  2. README
  3. Releases
  4. wiire-a/pixiewps on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wiire-a-pixiewps.svg)](https://hysenlabs.com/projects/wiire-a-pixiewps)

Was this useful?