Skip to main content

Using Scapy with RFMON mode on an Android phone

It used to be that you would have to carry around a laptop, and perhaps an additional wireless adapter, to enjoy wifi monitor mode while out and about. You may be able to replicate this with a much more pocket-friendly smartphone. But only certain phones have the necessary wireless chipset. For this to work, you will need a rooted phone with an appropriate Broadcom BCM 4330 or BCM 4329 wireless chipset. You may be able to find out if you have a supported device from 'Ctrl-F'ing the comments at http://bcmon.blogspot.co.uk/2013/07/monitor-mode-reloaded_14.html

bcmon, from the above link, is the app necessary for installing some patched firmware and enabling monitor mode on compatible phones.

As the authors of bcmon note:
please note that this code is experimental and you use it at your own risk and we are not responsible nor liable for any damage or loss of data. Sometimes unexpected things might go wrong and you might end up with a device that is no longer functional. Be warned and please take the responsibility yourself--it is your own risk and no one else can be held responsible.

Having said that, I have had no problems with this software, other than occasional crashes when disabling monitor mode again (after a reboot it works fine), and have not heard of anyone else having such a catastrophe. I am not even running Cyanogen, just stock Android 4.0, on a Galaxy S2.

Scapy is a library for packet manipulation written in Python; the one drawback is that Python is very slow as languages go. It really proves useful on smartphones as it is easy to roll your own packet manipulation tools, where popular programs like Wireshark or Kismet are not readily available for the Android platform.

Setting up bcmon
Be sure to first install up to date versions of Busybox (https://play.google.com/store/apps/details?id=stericson.busybox&hl=en_GB) and Terminal Emulator (https://play.google.com/store/apps/details?id=jackpal.androidterm&hl=en) on your device.

Get the bcmon app from https://code.google.com/p/bcmon/downloads/list - the .apk file carries patched firmware for both chipsets. You'll need to sideload it of course.
You will notice, after enabling monitor mode, that the app already comes with some wireless cracking tools. I haven't played with these myself. The app also comes bundled with tcpdump which is a very useful thing to have.

Setting up Python/Scapy
Scapy is a Python library so you will need to set up Python on your Android phone. First you need SL4A (Scripting Layer For Android) - go here and swipe the QR code https://code.google.com/p/android-scripting/ to download this app. Install and run the app, and from there (yes, inside the SL4A app itself) install Python. You'll notice that there are other languages supported too, so download any that take your fancy.

Now to install Scapy visit http://www.secdev.org/projects/scapy/
I just downloaded the tar.gz from here, unpacked it and copied over the scapy folder inside (the one that contains subfolders arch, asn1, crypto, etc.) to /sdcard/com.googlecode.pythonforandroid/extras/python/ on my phone. I could not get distutils to work on my phone for some reason, and simply copying the folder over did the trick.

As I recall, I had to also install PyCrypto from an Egg, which you can do easily from inside the Python For Android app. 

Setting up shell scripts for the environment
To set everything up for bcmon inside an arbitrary terminal window, have the following shell script available. I just put it on the root of my sdcard, and call it bc.sh to save on typing when using the phone's virtual keyboard. 

#! /system/bin/sh
export LD_LIBRARY_PATH=/data/data/com.bcmon.bcmon/files/libs
export LD_PRELOAD=/data/data/com.bcmon.bcmon/files/libs/libfake_driver.so
/data/data/com.bcmon.bcmon/files/tools/enable_bcmon


To set up Python so you can run it from a shell, make a shell script (from the comments in https://code.google.com/p/python-for-android/wiki/RunPythonFromShell)

#! /system/bin/sh
PW=`pwd`
export EXTERNAL_STORAGE=/mnt/sdcard
export LANG=en
export PYTHONPATH=/mnt/sdcard/com.googlecode.pythonforandroid/extras/python:/data/data/com.googlecode.pythonforandroid/files/python/lib/python2.6/lib-dynload:/data/data/com.googlecode.pythonforandroid/files/python/lib/python2.6
export TEMP=/mnt/sdcard/com.googlecode.pythonforandroid/extras/python/tmp
export PYTHON_EGG_CACHE=$TEMP
export PYTHONHOME=/data/data/com.googlecode.pythonforandroid/files/python
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/data/com.googlecode.pythonforandroid/files/python/lib:/data/data/com.googlecode.pythonforandroid/files/python/lib/python2.6/lib-dynload:/mnt/sdcard/com.googlecode.pythonforandroid/extras/python
cd $PW
/data/data/com.googlecode.pythonforandroid/files/python/bin/python "$@"


...and call that 'py.sh' or something. I just have this in /sdcard too.
Now, if you have a Python script that you have written, you can run that from the command line via:
sh py.sh [path-to-script]
...supposing your working directory is /sdcard.

Putting it together
Run the bcmon app and enable monitor mode. Come out of there and go to the Terminal Emulator app.

Open up a terminal and type
su
to run as root

Type
cd sdcard
to be in the same folder as the shell scripts you just made, assuming you placed them in the sdcard root like I did.

Type
sh bc.sh
to set up the environment for bcmon.

Optionally, run iwconfig to make sure everything is as it should be (wlan0 should show 'Mode: Monitor'). Make sure that you are on the right 802.11 channel for your purposes.

Type
sh py.sh
for the Python console.

When you get the Python prompt type:
from scapy.all import *
And you can just play around from there. Scapy documentation is here - http://www.secdev.org/projects/scapy/doc/ and there is an interactive demo at http://www.secdev.org/projects/scapy/demo.html.

Likewise, you can write Python scripts using the Scapy library, use bc.sh to set up the environment, and then run the scripts from the command line by appending the path of the script to the command sh py.sh.

Now you can work with OSI layer 2 packets in Scapy. Basically, you can craft your own data packets from the ground up, transmit them, and also monitor whatever is going on around you on the airwaves. However, there is one thing that I had to do to get sniffing to work properly.

Sniffing
I can only relate what I had to do for the Galaxy S2 here. I imagine it's the same for other phones though.
But you have to do something like this, in your scripts using Scapy, for every incoming packet:
   p = RadioTap(str(p))   # cast to a string then to a RadioTap packet

I don't know why, but Scapy does not recognise the (16-byte) radiotap header off the bat, instead seeing it as some kind of broken Ethernet header. This trips up the packet-dissection code. But when you process every incoming packet as above, it sees it as it should be.

Speaking of the radiotap header, there is a Scapy extension to parse it that is mentioned here: http://stackoverflow.com/a/20776878. Scapy itself does not do much in the way of parsing radiotap headers. With this extension, you can access the signal strength of incoming packets via the dBm_AntSignal property.

Injection
Packet injection works fine. You can make up any type of packet you like with Scapy, even completely wacky ones that don't correspond to anything in everyday use.

One tip for development is to also use a laptop with monitor mode enabled, running Wireshark, to catch what your phone is putting out there and see if it is what you intended.

You can, as the Scapy documentation shows, also craft and send packets on layer 3, without having to be in monitor mode, but you are more limited there with regards to what is possible.

Channel hopping
If you want to do channel hopping, open another terminal window and do it from there, as a lot of messages from bcmon will fly by. You can use another window to run other scripts. I use this simple Python script for channel hopping:

import os
import random
import time

while True:
 try:
  channel = random.randrange(1,13)
  os.system("iwconfig %s channel %d > /dev/null" % ("wlan0", channel))
  time.sleep(0.3)
 except KeyboardInterrupt:
  break


Cleanup
As I remarked earlier, disabling monitor mode in the bcmon app may cause the phone to crash. But I found it to be alright after a reboot. I have had to re-enable wifi myself when it reboots, and that's it, normal service resumed.