Supported Targets | ESP32 | ESP32-C6 | ESP32S2 | ESP32S3 |
---|---|---|---|---|
Wireless (802.11) | Yes | Yes | Yes | No(t Yet) |
Bluetooth | Yes | Not Yet | No | No(t Yet) |
BTLE | Yes | Maybe? | No | No(t Yet) |
ZigBee/Thread | No | Yes | No | No(t Yet) |
(802.15.4) |
Flipper WiFi Dev Board uses ESP32S2
This project contains an evolving collection of wireless utilities for use on the ESP32. Initial development focused on implementing a core set of 802.11 exploratory tools, which is gradually being expanded to include Bluetooth and Bluetooth Low Energy (BLE), with 802.15.4 (ZigBee/Thread) and general-purpose 2.4GHz radio hopefully not too far behind.
If you have a Flipper Zero there is a Flipper Zero companion app to Gravity. This is being developed alongside ESP32-Gravity and should be in feature parity most of the time.
https://github.com/chris-bc/Flipper-Gravity
Please note the comments below about compiling ESP32-Gravity for the Flipper Zero.
This project was originally intending to target the ESP32-C6 due in particular to its Thread & ZigBee support. Unfortunately, when I began looking beyond the WiFi libraries, I found that the (then) latest beta didn't yet support many Bluetooth features for the ESP32-C6.
This prompted a shift back to the base ESP32 chipset. Testing with the Flipper Zero WiFi Dev Board shows that its ESP32S2 lacks Bluetooth. Given the popularity of that board Gravity will customise the build based on the selected chipset (you don't need to do anything other than select the chipset), including Bluetooth features only if Bluetooth is available.
I recently got a ESP32S3 and, excited by its larger memory footprint, began thinking about the best way to include an OUI database in Gravity while flashing Gravity to the device. Strangely, it froze during the initialisation process. And does this reliably. That's unfortunate, but it looks like it's failing during WiFi initialisation so hopefully will be an easy fix in the near future.
Since Gravity has been included with RogueMaster Firmware I thought I should make a couple of changes to make it easy for people other than me to know which esp32-Gravity is compatible with which Flipper-Gravity.
(major).(minor).(release)
;1.2.1
;1.2.1
and 1.2.9
) will always be compatible with each other, although the addition or significant modification of some features may result in a small number of features not working;1.2.1
and 1.3.1
, are unlikely to be compatible. A change in minor version represents a noteable change to the platform or a breaking change to the platform;1.4.9
to 2.0.0
, represent substantial changes to the application and how it runs. Different major versions will not be compatible with each other.Use idf.py
menuconfig to configure global options. The section 'Gravity Configuration' contains these options, which include the following:
FLIPPER
: Reduce console output as much as possible while retaining utility, to accommodate the Flipper Zero's smaller displayDEBUG
: Enable additional logging to isolate issuesDEBUG_VERBOSE
: Enable way too much loggingThe following configuration options are also required in order for Gravity to use Bluetooth and fit within ESP32's smaller memory footprint:
Place FreeRTOS functions into Flash
(enable)Place non-ISR ringbuf functions into Flash
(enable)Place ISR ringbuf functions into Flash
(enable)Bluetooth
Classic Bluetooth
A2DP
SPP
Bluetooth Low Energy
Enable BLE multi-connections
Use Dynamic memory allocation in BT/BLE stack
All you need to do to build, flash and run Gravity is:
. /path/to/esp-idf/export.sh
(note the initial 'dot space')idf.py set-target <chipset>
("esp32", "esp32s2", "esp32c6", etc.)idf.py menuconfig
idf.py build flash
To open a console to Gravity:
idf.py monitor
A number of different binary packages are available with each release.
Download and extract the appropriate archive, preferably on a Linux
VM. On a Linux host the packaged executables will work so the flash
script won't require updating - simply run flash.sh
and the device should flash.
If it isn't already installed you may need to python3 -m pip install esptool
.
For Windows and MacOS users you'll just need to take an extra couple of steps:
Python
if it is not already installed. Ensure PIP
is also installed (in most cases either PIP is installed by default or a bootstrap is provided to easily install it).esptool
using python3 -m pip install esptool
esptool.py
should now be in your path. If not, run esptool.py from the binary package.esptool.py
directly from the path rather than calling a standalone version via python.esptool.py
in the script.This should have resulted in you flashing three binary files to your esp32: esp-wireless-tools.bin
, bootloader.bin
and partition-table.bin
.
To provide a nice, large output screen Gravity was first designed to run as a command-line application. Simply connect your favourite console - screen, minicom, netcat, putty - to the device's COM port on your computer and explore away!
A Flipper Zero application for Gravity has also been developed, providing a more portable and discreet - if teensy-screened - way of using Gravity. ESP32-Gravity (when in Flipper mode - see 'Configuration' above) has been heavily customised to make best use of Flipper's small screen, so you don't lose any functionality on Flipper. https://github.com/chris-bc/Flipper-Gravity Alternatively you can download a compiled Flipper binary file (FAP) from here:
To connect your Flipper Zero and your ESP32, simply connect RX to TX, TX to RX, GND to GND and 3V3 to 3V3.
Flash the app as normal using one of the above methods, ensuring you either download the Flipper binaries or
enable Flipper Zero output in idf.py menuconfig
before building it.
Once your microcontroller has been flashed with a compatible version of ESP32-Gravity::
I've been told to avoid powering the ESP32 from Flipper's 3V3 pin, purportedly because it does not support hot plugging.
I have no idea whether that's true or not, or what it would mean if it were true, but consider yoursef warned. (I use the 3V3 pin myself).
Work on Gravity continues on a few fronts, depending on the mood I'm in at the time:
The remainder of this document describes Gravity's features from the perspective of somebody using Gravity's serial console UI. If your only interaction with Gravity is through the Flipper Zero application please don't feel this documentation won't be useful for you.
While you won't be interested in command syntax when using the Flipper app, it will save you a lot of trial and error by explaining what commands do, and what other configuration items or commands they're dependent on.
I also encourage you to put their Flipper to the side for an afternoon and connect Gravity to your laptop while in a populated area. With the substantially-improved screen real-estate you can get so much more information over a console. The Flipper Zero is wonderful for discreet exploration, or targeting a small number of known devices.
This documentation has been completely reviewed and updated for Gravity v0.5.0 (20230907).
Gravity provides a number of exploratory, offensive and defensive wireless features that you may find useful for testing the robustness of your wireless devices and networks. Gravity currently supports 3 varieties of wireless device - 802.11 (WiFi) and 802.15.1 (Bluetooth Classic and Bluetooth Low Energy) - with the intention to expand into 802.15.4 (ZigBee/Thread) after consolidating existing functionality.
Some features do not require any configuration and can be started immediately, for
example the random, infinite and rickroll Beacon Spam. Most features require one or more
targets to be selected. Depending on the feature, the targets may be real APs, real STAs, real
Bluetooth devices (BT/BLE) or user-specified SSIDs. Real BT, BLE, APs and STAs are
identified using scan
; user-specified SSIDs are managed using target-ssids
.
Settings that affect the behaviour of Gravity are controlled using get
, set
, and
hop
. One of the most important of these for WiFi is hop
, which determines whether
channel hopping is enabled. If this has not been explicitly set Gravity will use the
default channel hop setting for command you run, starting and stopping hopping if necessary
when features are started and stopped.
All commands accept a variety of parameters. See the Help section for information on
using Gravity's help system to obtain syntax and usage information for commands.
The AP
option in particular confuses some people; try to remember that when
specifying target stations as an argument using the AP
option Gravity will
target all clients of the selected access points.
Gravity uses Espressif's console component, providing tab-completion, command hints and
a built-in help system. To use the built-in help, which provides a list of available
commands and their function, and includes several device-specific commands, run help
.
Once you're sick of that wall of text, commands
will provide a list of Gravity
commands and their syntax, and info <command>
will provide more detailed information
about that command.
Tab completion works as expected (but only for commands, not parameters I'm afraid), and if you pause after typing a command its syntax will be displayed on the current line.
All command documentation will begin with a line identifying which technologies the command applies to. For example:
Applies To: WiFi, BT, BLE
Applies To: WiFi
target-ssids
is used to manage user-specified (i.e. fake) SSIDs. These can be used
by features such as Beacon Spam and Probe Flood as the SSIDs broadcast by
Gravity.
Syntax: target-ssids [ ( ADD | REMOVE ) <ssidName> ]
As a simple list of strings its use is straightforward:
target-ssids
with no arguments displays the list of current targetstarget-ssids add <ssidName>
adds <ssidName>
to the listtarget-ssids remove <ssidName>
removed <ssidName>
from the listApplies To: WiFi, BT, BLE
scan
controls whether different types of scanning are currently active. Scanning
parses several types of wireless protocol packets to identify nearby stations (WiFi
devices), access points (WiFi routers), bluetooth devices (Phones, Cars, etc.) and
Bluetooth Low Energy devices (tokens, beacons, etc.).
Syntax: scan [ ( [ <ssidName> ] WIFI ) | BT | BLE [ PURGE ( RSSI | AGE | UNNAMED | UNSELECTED | NONE )+ ] | OFF ]
If debug
has been enabled in idf.py menuconfig
you will receive a notification
every time a new device or AP is discovered. BLE devices are too prevalent to display a notification every time one is seen.
scan
returns the current status of scanningscan wifi
activates 802.11 Wireless scanningscan bt
activates Bluetooth Classic scanningscan ble
activates Bluetooth Low Energy scanningscan off
deactivates scanningOnce Gravity has discovered devices and access points by scanning, you can select
one or more of those objects as targets for your commands. If you leave scan
running
while you run other commands it will continue to discover new APs and devices in the
background.
scan <ssidName>
will activate scanning, but only for APs advertising
the specified <ssidName>
, and STAs that are associated with APs
advertising the specified <ssidName>
.
This feature works by first identifying the MAC of the AP advertising
the specified SSID. Because this requires the AP to send a beacon or
probe response it may take some time before you see any output from
this feature. Rest assured that relevant data is being captured from
packets while this is happening. Because of this, if you scan
an SSID
that hasn't previously been discovered by scan
you will typically have
a short delay until a suitable packet is found, followed by a lot of
output from cached data that suddenly becomes relevant once the AP's
MAC is known.
Because Bluetooth Low-Energy devices are so prevalent it is quite easy to fill all of ESP32's memory with cached BLE device information. To assist with this Gravity can automatically remove devices from its cache to make memory available for new BLE devices if it runs out of memory. In order to do this you need to provide Gravity with a Purge Strategy, informing it how it should prioritise BLE devices in order to select the best ones to delete.
Future enhancements are planned to implement automatic purging for WiFi and Bluetooth Classic devices.
See documentation for the command PURGE for information on this.
TODO Add a link here
Applies To: WiFi, BT, BLE
view
, you guessed it, allows you to view the devices discovered by scan
.
Syntax: view ( ( AP [ selectedSTA ] ) | ( STA [ selectedAP ] ) | BT | SORT ( AGE | RSSI | SSID ) )+
view ap
lists access points discovered during scanning. The following information is provided
for each AP:
select ap 3
. An asterisk (*) displayed before the ID indicates that the AP has been selected.view sta
lists stations discovered during scanning. The following information is provided for each STA:
select sta 7
. An asterisk (*) displayed before the ID indicates that the STA has been selected.view bt
Lists Bluetooth and Bluetooth Low-Energy devices discovered during scanning. The following information is provided for each device:
select bt 13
. As asterisk (*) displayed before the ID indicates that the device has been selected.If one or more stations or access points have been selected additional options can be used to filter your results based on the selected items.
view ap selectedSTA
lists access points discovered during scanning that are access points of the currently-selected
stations.
view sta selectedAP
lists stations discovered during scanning that are clients of the currently-selected
access points.
Display options can be combined in any way you like, for example view ap selectedsta ap sta sta selectedap
.
Syntax: clear AP | STA | BT | ALL
Clears scan
results of the specified type. scan
results are kept until the ESP32 is
switched off, with subsequent scans adding to, rather than replacing, results.
If you wish to remove these results and start afresh you can run:
clear ap
clears cached access pointsclear sta
clears cached stationsclear bt
clears cached Bluetooth devices (both Classic and Low-Energy)clear all
clears access points, stations and Bluetooth devicesSelects and deselects devices discovered during scanning. Rather
than specifying whether you want to select or deselect something, select
will
simply toggle the item's selected status, selecting specified items if they are
not selected and deselecting them if they are selected.
Syntax: select ( AP | STA | BT ) <id>+
<id>
refers to the identifiers displayed by view ap
. Multiple IDs can be specified by
separating them with either a space or a ^
(for Flipper Zero compatibility).
For example select ap 1 2 3
. If AP 2 had already been selected before running this
command then, after running, APs 1 and 3 will be selected and AP 2 no longer selected.
select sta <id>+
and select bt <id>+
operate in exactly the same way, except for stations
rather than access points.
Syntax: selected [ AP | STA | BT ]+
Displays only selected devices. These are displayed in the same format as view
.
selected ap
displays selected access pointsselected sta
displays selected stationsselected bt
displays selected Bluetooth devicesselected
, selected bt ap sta
and variations display all three device typesIn addition to the configuration options described under Configuration a number of
settings can be changed while Gravity is running to change its behaviour. These are
controlled using the commends get
, set
and hop
.
These commands are described together because they complement each other, with get
displaying the current value of a setting and set
updating that setting to have the
specified value.
Their use is also very similar,
Syntax:
get <variable>
set <variable> <value>
<variable>
can be one of the following settings.
The current wireless channel. This will not disable channel hopping if it is active, so while setting this will change the wireless channel in that situation, it will continue to hop to other channels.
TODO: Information on channels supported by the ESP32 and ESP32-C6
The physical identifier for the ESP32. This is displayed, and when setting must be provided, in the standard colon-separated six octet format, e.g. e0:0a:f6:0f:ca:fe.
The first three octets are referred to as the Organisationally Unique Identifier and identify a specific manufacturer. I hope to be able to add a feature to Gravity to display manufacturer information for discovered devices, although could have issues fitting an OUI database on the ESP32.
MAC Randomisation. Specifies whether Gravity will change its MAC address after every packet that is sent.
Valid values to set
MAC Randomisation are on
and off
.
This is not currently operational
The time (in minutes) since a station or access point was last seen when Gravity will stop including it in operations and results.
Decimal values can be used for this setting if a minute isn't granular-enough control.
The length of time for Gravity to wait between sending packets. A value of 0
disables
this delay. The default value for this setting is defined under Gravity Configuration
in esp.py menuconfig
.
This setting was introduced because some firewalls will identify a sudden burst of packets as an attack.
This setting can override the value set in idf.py menuconfig
. Several features,
at the time of writing beacon
and fuzz
, can generate random SSID names as part
of their functionality.
This setting can be enabled with the value on
, yes
or true
and disabled
with the value off
, no
or false
.
When this setting is disabled (default), SSIDs will be generated by selecting a random SSID length between SSID_LEN_MIN and SSID_LEN_MAX, and then selecting words at random from a dictionary of 1,000 words, selecting additional words until the desired length is reached.
When this setting is enabled SSIDs will be generated by selecting a random SSID length between SSID_LEN_MIN and SSID_LEN_MAX, and then selecting characters at random until the desired length is reached.
If you'd like to change the contents of the dictionary it is defined in words.c
.
If you change the number of items in the dictionary you will need to update the value
of gravityWordCount
, also defined in words.c
.
If you'd like to change the characters that are used when this setting is enable
they are held in the array ssid_chars
, defined in beacon.h
.
The minimum acceptable length for an SSID that is generated by Gravity. This can
be a value between 0
and the system constant MAX_SSID_LEN
. MAX_SSID_LEN
should
always have a value of 32
. It also must not be greater than SSID_LEN_MAX
.
The maximum acceptable length for an SSID that is generated by Gravity. This can
be a value between 0
and the system constant MAX_SSID_LEN
. MAX_SSID_LEN
should
always have a value of 32
. It also must not be less than SSID_LEN_MEN
.
The default number of SSIDs to generate for features that generate random SSIDs.
Currently this is only used by beacon random
(where count
is not specified).
The Purge Strategy - The set of Purge Methods to apply. This is a bitwise composition of BLE_PURGE_RSSI (1), BLE_PURGE_AGE (2), BLE_PURGE_UNNAMED (4), BLE_PURGE_UNSELECTED (8), and BLE_PURGE_NONE (16)
The minimum age that will be purged by purge
. Age purging will be considered complete
when no more devices exist with an age greater than BLE_PURGE_MIN_AGE
.
The maximum RSSI that will be purged by purge
. RSSI purging will be considered complete
when no more devices exist with an RSSI less than BLE_PURGE_MAX_RSSI
.
Applies To: WiFi
Channel hopping is a background process that we sometimes want and sometimes don't.
Because of that it has its own command to turn it on and off, but Gravity attempts
to be a little more helpful; if hop
has not been explicitly turned on or off
and you use a feature that is configured to use channel hopping by default, Gravity
will automatically turn hopping on when the feature is started and off when it is
stopped.
This setting controls the state of Gravity's channel hopping. This can be one of
three values, OFF
, ON
and DEFAULT
. When channel hopping is in the ON
or
OFF
state it will remain in that state until you manually change it or the ESP32
is restarted.
Syntax: hop [<millis>] [ ON | OFF | DEFAULT | KILL ] [ SEQUENTIAL | RANDOM ]
<millis>
is provided Gravity will pause on each channel for that number of milliseconds before changing to the next channel;KILL
will terminate the process that controls channel hopping. Normally this remains active once channel hopping has been started for the first time, but this may provide marginally better energy usage through a slight reduction in memory usage and processing when channel hopping is not running;ON
and OFF
give you manual control of channel hopping; it will remain in that state until you set it again, ignoring features' channel hopping defaults;DEFAULT
channel hopping is not active, but will automatically start if a function is run that is configured to use channel hopping by default. When this occurs channel hopping will also automatically stop when no more functions are using it by default.SEQUENTIAL
and RANDOM
specify whether channel hopping should occur progressively through the channels, or move around randomly. RANDOM
hopping can be helpful if trying to evade detection, but SEQUENTIAL
is the default and typically the best choice.If you wish to change the default hop
state for any feature, they are defined in
a case
statement in the function app_main
in gravity.c
. Default values for dwell
time (see below) are also specified in this location.
The usage description above states that, when <millis>
is specified, Gravity will
pause on each wireless channel for that number of milliseconds before changing to
another channel. This may be called the hop interval
, hop frequency
or dwell time
.
If hop
has been explicitly enabled you are in 'full control' of channel hopping
features; if you want it to hop at a different frequency you need to change it yourself.
If channel hopping is started without providing a dwell time Gravity will determine
the longest dwell time required by each enabled feature and use that value.
To set the dwell time to 1,000 (1,000ms == 1 second) use hop 1000
.
If hop
is in its default mode default values will be used for the dwell time.
Currently all features use one of two dwell times, although this is readily extensible.
These default values are specified in idf.py menuconfig
by the settings labelled
default dwell time for most features
and default dwell time for larger features
.
The latter value is used for all variations of the Mana attack, with all other features
(so far) using the smaller value. The allocation of functions to dwell times occurs in
the function app_main
in gravity.c
, where hop_millis_defaults[]
is populated.
NOTE: While many Gravity features will change the dwell time based on their own defaults, they will not change this back to its original value.
The only reason any of the functionality described above even exists is to provide the context needed to run the features described in this section (and those coming soon!) - So with all the above information out of the way let's get into it.
Applies To: WiFi
Broadcast forged beacon frames, simulating the presence of fake wireless networks.
This function on its own has limited potential beyond practical jokes, although has some use verifying the absence of buffer overflows when developing modules that scan for wireless networks.
Syntax: beacon [ RICKROLL | RANDOM [COUNT] | INFINITE | TARGET-SSIDs | APs | OFF ] [ AUTH ( OPEN | WPA )+ ]
Run beacon
with no parameters to display the current status.
AUTH ( OPEN | WPA )+
This optional sub-command specifies the type(s) of authentication Gravity should advertise
the APs as having. Functionally, a beacon only advertises whether or not an AP has privacy
enabled, meaning that there is no need to differentiate between WEP
and WPA
; both
have the same effect - causing the beacon to advertise itself as secure rather than open.
Multiple authentication types can be specified by joining them together - auth open wpa
. In
this case Gravity will send two beacon frames for every one that it would otherwise have
sent - one beacon frame advertising an open network and one advertising a secured network.
As soon as I can come up with a clever way to specify a list of authentication types on the command line we can allow specifying a different authentication type per AP, but that's a nut I'm yet to crack.
RICKROLL
Broadcasts 8 new SSIDs named with lines from a song we all know and love.
RANDOM [ COUNT ]
Generates random SSID names and broadcasts those. If count
is specified this is
the number of SSIDs that are broadcast; if not specified the value of
DEFAULT_SSID_COUNT
is used as the number of SSIDs. If this value has not been set
its default value, defined in idf.py menuconfig
, is used.
INFINITE
Instead of repeatedly broadcasting frames advertising the same set of SSIDs, this mode broadcasts a different frame, advertising a different SSID, every time. This was an effective way to find and remove buffer overflows in one of my wireless applications.
TARGET-SSIDs
This mode should probably be higher up the list because it's probably the most popular of this class of attack; broadcast SSID names that you specify yourself.
Use the target-ssids
command to build a list of SSIDs, and then run
beacon target-ssids
to begin broadcasting the SSIDs you have defined.
APs
Broadcast beacon frames for the SSIDs used by the selected access points. Access
Points must have been scan
ned and select
ed prior to starting this mode.
Applies To: WiFi
Broadcast forged probe request frames, sending requests for specified SSIDs.
Probe requests are the mechanism that allows a station (like a phone) to automatically connect to an access point (like a wifi router) when they are in range and powered on. Stations periodically send probe requests, which may signal nearby access points to send a response to the station with information about their SSIDs. A probe request may either be a wildcard request, asking all access points to respond with their SSID information, or it could be a directed request, asking nearby access points if they provide a specific SSID.
Syntax: probe [ ANY | TARGET-SSIDs | APs | OFF ]
Run probe
with no parameters to display its current status.
ANY
transmits wildcard probe requests.
TARGET-SSIDs
sends probe requests for the SSIDs specified by target-ssids
.
APs
sends probe requests for the SSIDs of the selected access points.
Applies To: WiFi
Deauthentication frames are a valid part of the wireless protocol which, for a variety of reasons, alert a connected station that it is being deauthenticated from its access point. This provides the station with an opportunity to stop what it's doing and disconnect from the access point of its own accord.
This is clearly a feature that could be disruptive if misused, and in the distant past it was indeed possible to send a broadcast deauthentication packet and have most stations disconnect from a network. Things are a little more robust these days and you won't often be able to disconnect stations with a broadcast packet. Target them individually, however, and your success rate will be high.
Syntax: deauth [<millis>] [ FRAME | DEVICE | SPOOF ] [ STA | AP | BROADCAST | OFF ]
<millis>
provides an optional way to set ATTACK_MILLIS
while starting deauth
; specifies the time between deauthentication packets.
[ FRAME | DEVICE | SPOOF ]
Specifies what, if any, MAC spoofing occurs.
FRAME
modifies the sender MAC in the wireless frame that is transmitted, but does not change the device's MAC. The sender MAC address that is used, except in BROADCAST
mode, is the MAC address of the AP the target STA is associated with.DEVICE
replaces the sender MAC address in the frame template with the ESP32's MAC address.SPOOF
modifies the sender MAC address in the same way as FRAME
, and also modifies the ESP32's MAC address to match the address of the target STA's AP.[ STA | AP | BROADCAST | OFF ]
Specifies the target(s) of the deauthentication attack.
While a broadcast packet is widest-reaching, it's also least effective and only causes disassociation on a small number of modern devices.
Broadcast mode uses the broadcast address (FF:FF:FF:FF:FF:FF) as the destination and the device's MAC as the sender.
The deauthentication attack targets selected stations (i.e. stations select
ed
after scan
ning).
The AP
deauth mode targets all stations that are associated with selected
access points. In other words, after you scan
and select
some access points,
this mode will target stations connected to those access points.
Applies To: WiFi
Syntax: mana ( CLEAR | ( [ VERBOSE ] [ ON | OFF ] ) | ( AUTH [ NONE | WEP | WPA ] ) | ( LOUD [ ON | OFF ] ) )
Mana is a neat little trick you can use to make almost any wireless device connect to your access point.
Home WiFi
Home WiFi
That's called the Karma attack
. If only life were that simple! It used to be, until manufacturers closed that loophole by requiring APs to have previously responded to
a wildcard probe request.
Home WiFi
Home WiFi
with your phone's MAC address, and sends a probe response claiming to be Home WiFi
(although it won't do anything unless your phone is vulnerable to Karma)Home WiFi
is associated with your phone's MAC and sends a probe response claimining to be Home WiFi
Home WiFi
Home WiFi
Home WiFi
in response to a wildcard probe request, so it's OK to trust GravityThis variation is the Mana attack
. Gravity starts an access point using
Open Authentication (i.e. no password) on launch, which handles the final
piece of a simple Mana-based attack chain:
A STA will, over timee, send a directed probe request for every network in its Preferred Network List (PNL).
In practice this means that, for a consumer device such as a phone, tablet or laptop, if that device has ever connected to an open wireless network before - as is often found at coffee shops, restaurants, airports, etc. - and the device hasn't been told to forget that network, then it can be tricked into connecting to our rogue AP.
Until I'm able to include bridging to the Internet there's limited use to this - most phones will quickly disconnect once they decide they can't get an Internet connection - but I think it's a very interesting technique nonetheless.
A connected device will send all network requests to Gravity - For example if it tries to open the web page http://google.com it will first ask Gravity for the IP of google.com. Unfortunately it will stop there at the moment because Gravity is not Internet-connected. However, if you set that aside as a problem to be solved, once it is Gravity will see everything that the victim sends over the network. While most communication is encrypted today some is not, and some that is will fall back to unencrypted if Gravity refuses to connect the victim to encrypted ports.
Loud Mana
is a variation on the Mana
attack that attempts to successfully
target devices that are not broadcasting probe requests for open networks
(for whatever reason) by sending them probe responses for networks we think
they may have seen.
Johnsons Home WiFi
;My Cafe Free WiFi
, an open network;My Cafe Free WiFi
to device A has a high likelihood of succeeding; if the devices are owned by family members they are likely to both have used the free WiFi at the same cafe.Because this potentially results in Gravity sending a probe response for a
large number of SSIDs it generates much more network traffic than a regular
Mana
attack, hence Loud Mana.
NOTE: Because Mana's purpose is to have STAs connect to your rogue AP
it is important that channel hopping and MAC randomisation both be disabled
when running Mana
.
Syntax: mana ( CLEAR | ( [ VERBOSE ] [ ON | OFF ] ) | ( AUTH [ NONE | WEP | WPA ] ) | ( LOUD [ ON | OFF ] ) )
mana clear
Because Mana
compiles Preferred Network Lists for all stations it observes, you may like to clear out the cached PNLs. That's what mana clear
does.
mana [ VERBOSE ] [ ON | OFF ]
This is the primary command that turns Mana on or Off. Running mana
with no parameters displays its current status. Starting mana using
mana verbose on
will generate more console output - there's a lot
of useful information to monitor while this is in development. Once
everything is ironed out and there's a clever way to bridge victims
to the Internet this can become a simple pwn [ ON | OFF ]
feature
with everything automated, but for now extra information is good.
mana auth [ NONE | WEP | WPA ]
Configure the authentication type advertised by Mana
in probe responses.
The default authentication type is NONE
because I don't believe the
other types offer any value in the Mana
attack - In order to establish
an encrypted connection with a STA the AP also needs to know the encryption
key. And if we know the key it would probably be easier to just connect to
the network and find your way into the device, rather than convincing it
to connect to you.
At least, I hope that would be easier, because right now changing the built-in AP's authentication type and password requires a recompile.
mana loud [ ON | OFF ]
Enable or disable Loud Mana
, described above. If Mana
is not running when
mana loud on
is run it will be automatically started.
Applies To: WiFi
Sends a variety of invalid packets to see how different devices respond to different types of invalid packets.
This feature can currently operate on beacon frames, probe requests and probe responses. Two models of invalid packet have been developed so far:
Syntax: fuzz OFF | ( ( BEACON | REQ | RESP )+ ( OVERFLOW | MALFORMED ) )
( BEACON | REQ | RESP )+
The type of packet to send. Multiple packet types can be specified, although thinking about it that has never been tested so ... you know.
BEACON
will send a beacon frameREQ
will send a probe requestRESP
will send a probe responsescan
results)OVERFLOW
In this mode the transmitted wireless packets are well-formed - they would be correct, except that their SSID is longer than an SSID is allowed to be.
This mode will begin by sending packets with length MAX_SSID_LEN + 1
. MAX_SSID_LEN
is (theoretically) platform-specific, but is 32. So we start with an SSID length
of 33. Then increase it to 34, then 35, and so on until the function is stopped.
MALFORMED
In this mode the packets are not well-formed - The SSID is either longer or shorter than specified by SSID_LEN. This function alters SSID_LEN in invalid ways (without changing the length of the SSID) to see what happens.
This function begins by generating a valid SSID with a length as specified by the
MALFORMED_FROM
setting in idf.py menuconfig
(default 16). If the default value
of 16 is used as the (real) SSID length, this function will transmit a packet
specifying an SSID_LEN of 17, then 15, 18, 14, 19, 13, 20, 12, etc.
Applies To: WiFi
sniff
doesn't offer any really compelling functionality and started life as a
debugging flag during the very early stages of Gravity's development, when I
was learning how to parse wireless frames.
The intent of sniff
is to display information about interesting packets that are
observed. The sheer volume of packets, coupled with limitations of a serial console,
make finding the balance where enough packets are displayed to be useful, but not so many as to make them incomprehensible.
All that is by way of saying that sniff
's functionality may vary considerably over
time. What won't change, however, is its principle - sniff
displays interested
information about interesting packets to the screen. It doesn't store them or do
anything else with them, so in a lot of ways it is a less capable version of scan
.
Syntax: sniff [ ON | AFF ]
Applies To: WiFi, BT, BLE
This is a sort of homing feature, allowing you to follow selected devices to their source using their RSSIs. In the future a more considered implementation will be developed, generating a single, composite score.
Applies To: WiFi
This feature is intended to simulate a denial-of-service (DOS) attack on the selected AP(s) by
AP-DOS
operates on selectedAPs
- that is, the Access Points that were
identified using scan
and selected using select ap
.
Syntax: ap-dos [ ON | OFF ]
Applies To: WiFi
This feature is intended to simulate a 'clone-and-takeover' attack on the selected
AP. At a general level you could say that it combines AP-DOS
's deauthentication
and disassociation
messages, beacon
's forged beacon frames, and Mana
's
ability to sneak its way into a station's Preferred Network List (PNL). The
hoped-for result is to trick stations to disconnect from their existing access
point and, not necessarily connect to Gravity, but NOT reconnect to their original AP.
AP-CLONE
operates on selectedAPs
- that is, the Access Points that were
identified using scan
and selected using select ap
.
Any number of authentication types can be specified. Where multiple authentication types are provided Gravity will send a packet for each authentication type. This may be detected by some routers as an attack.
Syntax: ap-clone [ ( ON | OFF ) ( OPEN | WEP | WPA )+ ]
Applies To: BLE
This feature allows memory to be recovered by removing devices from Gravity's cache.
Syntax: purge [ WIFI | BT | BLE ]+ [ RSSI | AGE | UNNAMED | UNSELECTED | NONE ]+
Specify the device types to purge. As of v 0.5.0 BLE is the only implemented device type. If no device type is specified all device types are selected.
Specify the methods used to select devices for purging.
RSSI
Delete devices with the lowest RSSI, repeating until there are no devices with an RSSI below BLE_PURGE_MAX_RSSI.
AGE
Delete devices with the greatest age, repeating until there are no devices with an age greater than BLE_PURGE_MIN_AGE.
UNNAMED
Delete devices without a name.
UNSELECTED
Delete devices that are not selected.
NONE
Do not delete any devices. If memory runs out halt scanning.
NOT YET IMPLEMENTED.
This is a placeholder for the standard handshake/pmkid capture that all wireless software needs to have as a feature.
Actually though, given how many new features have been added to ESP32 Marauder
over the past six months, I think I might leave it as my scanning and
handshake-capturing tool of choice while I focus on different kinds of features
like Mana
, Fuzz
and AP-DOS
/AP-CLONE
.
At least in the short term, then, this feature probably won't be built.
TODO
Debugging statements written during development have not been removed from the code; they've been put behind #ifdef directives and can be enabled by adding #define DEBUG to one of the header files to enable them.
Gravity is written using Espressif's ESP-IDF development platform. Building & installation follows the same paradigm as other ESP-IDF projects, using idf.py build flash monitor to build the application, flash a chip, and start a serial connection with the device.
Gravity currently uses a serial console as its user interface, with text-based commands and feedback. Tools such as Putty, Screen, Minicom and the Arduino IDE can be used to establish a serial connection over USB to interact with the device. Since it will already be installed for building the application, I suggest using ESP-IDF as your serial monitor. To start the ESP-IDF serial monitor and have it connect to a device run idf.py monitor. This can be combined alongside building and flashing with the command "idf.py build flash monitor".
Finding the serial port used by Gravity varies depending on operating system: