My Wardriving Setup

Felix Kohlhas
A wardriving setup based on a Raspberry Pi 4, low cost wifi modules and kismet

Raspberry Pi and a USB hub with WiFi modules in the windshield of a car

Wardriving is the act of searching for Wi-Fi wireless networks, usually from a moving vehicle, using a laptop or smartphone. [Wikipedia]

Hardware

Software

Base image

The RTL8188FU driver cannot be built on the current Raspberry Pi OS kernel (6.1), so the legacy image has to be used for now.

https://www.raspberrypi.com/software/operating-systems/

Raspberry Pi OS Lite (Legacy)
Release date: May 3rd 2023
System: 32-bit
Kernel version: 5.10
Debian version: 10 (buster)

RTL8188FU driver

In order to use the RTL8188FU modules in monitor mode, the drivers have to be compiled manually. This process is described in my post RTL8188FU Monitor Mode.

APT packages

apt-get install neovim jq gpsd kismet

gpsd

gpsd shoud automatically detect the USB GPS module. You can check on it using:

while read line; do jq '.' <<< $line; done < <( { sleep 3; echo -e '?WATCH={"enable":true,"json":true}\n' } | nc localhost 2947 )

RaspAP

curl -sL https://install.raspap.com | bash -s -- --minwrite

Configure at http://<device_ip>
User: admin, Pass: secret

Main script

Crontab

@reboot /root/run.sh >/root/run.log 2>&1

run.sh [file]

#!/bin/bash

# Wait 30 seconds for interfaces to be detected and come up etc.
sleep 30

# Change the working directory
mkdir -p /home/pi/kismet
cd /home/pi/kismet

# Create kismet_custom.conf using kismet_wardrive.conf as template
cp /etc/kismet/kismet_wardrive.conf /etc/kismet/kismet_custom.conf

# For each wireless interface
while read interface; do

    # Try to set interface to monitor mode
    # If successfull add the interface to kismet_custom.conf
    /usr/sbin/iw "$interface" set type monitor && echo "$interface" && \
        echo "source=$interface:name=$interface" >> /etc/kismet/kismet_custom.conf
        
done < <(find /sys/class/net -follow -maxdepth 2 -name wireless 2> /dev/null | cut -d '/' -f5)

# Start http server on port 8000
python3 -m http.server &

# Get data from gpsd
{
    sleep 3
    # Enable watch mode
    echo -e '?WATCH={"enable":true,"json":true}\n'
} | nc localhost 2947 | {
    while read -r line; do
        # Set the system time from gpsd output (UTC)
        date -u -s "$(echo "$line" | jq -r '.time')"
        # Continue if 3d fix aquired (mode == 3)
        echo "$line" | jq -r '.mode' | grep -q '3' && break
    done
}

# Start kismet with kismet_custom.conf as config
kismet --override custom > kismet.log &

Usage

Kismet will automatically start once the WiFi interfaces are in monitor mode and there’s a 3d GPS lock, so it really is plug-and-play.

Kismet can be checked on and configured by connecting to the AP and browsing to http://<device_ip>:2501. The Kismet-*.wiglecsv files can be downloaded at http://<device_ip>:8000 and uploaded to wigle.net without further processing.

To avoid SD card corruption the Raspberry Pi should be shutdown before removing power. This can be conveniently done in the RaspAP interface at http://<device_ip>.


Visualizing the data

Google Earth showing many markers with SSIDs
A small dataset visualized on Google Earth

To visualize the data before uploading it to wigle.net the following script can be used. It generates kml files from Kismet-*.wiglecsv files, which can then be imported and viewed in Google Earth.

Install requirements

pip3 install pandas simplekml

wiglecsv2kml.py [file]

from os import listdir
import simplekml
import pandas as pd

def write_pandas_to_kml(dataframe, output_file, title):
    # Create a KML object
    kml = simplekml.Kml(name=title)

    # Iterate over the rows in the DataFrame
    for index, row in dataframe.iterrows():
        # Extract the necessary data from the row
        latitude = row['CurrentLatitude']
        longitude = row['CurrentLongitude']
        description = '%s\n%s\n%s' % (row['MAC'], row['FirstSeen'], row['AuthMode'])

        # Create a KML point and add it to the KML object
        point = kml.newpoint()
        point.coords = [(longitude, latitude)]
        point.description = description
        point.name = '%s [%i]' % (row['SSID'], index)
        point.open = 1

    # Save the KML object to a file
    kml.save(output_file)

for filename in sorted(listdir('.')):
    if filename.endswith('.wiglecsv'):
        continue
    
    data = pd.read_csv(filename, skiprows=1)

    # Only show ~1000 points
    n_skip = int(len(data) / 1000) + 1
    
    print('%s [%i]' % (filename, len(data)))
    write_pandas_to_kml(data.iloc[::n_skip, :], filename + '.kml', filename)

Opening kml file in Google Earth

https://earth.google.com/web/

Projects > New Project > Import KML file from computer


Comments

This blog does not currently have a comment function. You can send me an email to [email protected] instead and I will add it here.