2018年8月3日 星期五

Exploit Scapy to Generate WIFI Probe Request Packets on x86 Linux Distribution and OpenWRT


      Thought there are discussing threads and posts about how to use scapy library to generate probe request packets, but based on my searching, all of those are not organized and detail. This post would like to fill the gap.

   I assume you have install the python and scapy in your linux, if you have not done that, please refer to those:

Python: http://ubuntuhandbook.org/index.php/2017/07/install-python-3-6-1-in-ubuntu-16-04-lts/
Anaconda :  https://conda.io/docs/user-guide/install/linux.html  (optional)
Scapy : https://scapy.readthedocs.io/en/latest/installation.html#installing-scapy-v2-x

一. Broadcasting the probe-request in the x86-based Linux distribution:

below is the python code, named as broadcastproberequest.py,  to call scapy for generating probe-request:

#!/usr/bin/python
#coding:utf-8

import time
from scapy.all import *


def KeepBroadcastingProbeRequest(interface="wlan0", interval=0.1, \
        duration=30, ssid="譖路由器"):
    
    count = duration/interval

    packet = RadioTap()/Dot11(type=0, subtype=4, \
    addr1="ff:ff:ff:ff:ff:ff", addr2="00:11:22:33:44:55" ,addr3="ff:ff:ff:ff:ff:ff") \
    /Dot11Elt(ID="SSID", info=ssid)

    sendp(packet,  iface= iface, inter=interval, count=count)


if __name__ == '__main__':

    iface = 'wlan0'
    interval = 0.1
    duration = 30
    ssid = "開源路由器"
    try:
        opts, args = getopt.getopt(sys.argv[1:],"i:t:s:d:")
    except getopt.GetoptError as e:
        print("-i <iface>  -t <interval> -s <SSID> -d <duration>")
        sys.exit(-1)

    for opt, arg in opts:
        if opt == '-i':
            iface = arg
        elif opt == '-t':
            interval = float(arg)
        elif opt == '-s':
            ssid = arg   
        elif opt == '-d':
            duration = int(arg)
        elif opt == '-h':
            print("-i <iface>  -t <interval> -s <SSID> -d <duration>")
            sys.exit(1)

    print( "iface=%s, interval=%1.3f, duration=%d, SSID=%s" \
        %(iface, interval, duration, ssid))

    KeepBroadcastingProbeRequest(interface=iface, interval=interval, ssid=ssid, duration=duration)

Before you run your code,  if you currently use this wifi-interface (network card) online,  YOU SHOULD DISCONNECT IT AND SET THIS INTERFACE AS MINOTORING MODE :

Inquiry the network-interfaces statue:
gaiger@i5-3210M:~$ ifconfig
:
wlp3s0    Link encap:Ethernet  HWaddr 60:67:20:a5:44:ae  
          inet addr:192.168.1.140  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fd80:d8b6:da22:0:69c3:1d2c:cf5:ce18/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:818b:1644:e8b:d756/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:a068:21d:dfe8:f717/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:2cae:5b7f:d19e:1280/64 Scope:Global
          inet6 addr: fd80:d8b6:da22::a34/128 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:3b50:b57d:b0c8:4a68/64 Scope:Global
          inet6 addr: fd80:d8b6:da22:0:99e4:c8ee:ea9a:bfe8/64 Scope:Global
          inet6 addr: fe80::f19c:8dd9:2058:c699/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1337204 errors:0 dropped:555386 overruns:0 frame:0
          TX packets:543649 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:528846681 (504.3 MiB)  TX bytes:79969190 (76.2 MiB)


Inquiry the wireless interface statue:
gaiger@i5-3210M:~$ iwconfig
wlp3s0    IEEE 802.11abgn  ESSID:"Tenda 3270 "  
          Mode:Managed  Frequency:2.437 GHz  Access Point: C8:3A:35:78:2D:98   
          Bit Rate=72.2 Mb/s   Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          Link Quality=70/70  Signal level=-35 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:13   Missed beacon:0
:


The WIFI-interface in this computer is named as wlp3s0. I DISCONNECT IT FROM ROUTER and set it as monitoring mode in channel 1( 2.412 GHz):
gaiger@i5-3210M:~$ sudo ifconfig wlp3s0 down
gaiger@i5-3210M:~$ sudo iwconfig wlp3s0 mode monitor
gaiger@i5-3210M:~$ sudo iwconfig wlp3s0 channel 1
gaiger@i5-3210M:~$ sudo ifconfig wlp3s0 up
gaiger@i5-3210M:~$ sudo iwconfig wlp3s0
wlp3s0    IEEE 802.11abgn  Mode:Monitor  Frequency:2.412 GHz  Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on


Of course, I could set the other channels, below is the result I set it as channel 6.
wlp3s0    IEEE 802.11abgn  Mode:Monitor  Frequency:2.437 GHz  Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on

Now the code is able to be workable:
gaiger@i5-3210M:~/sandbox/python-spider$ sudo python broadcastproberequest.py -i mon0 -t 0.02 -s 偽測探 -d 300


  I use the other device(ESP8266), to achieve the sniffing purpose, it is the sniffed result:


About the arguments :

-i <iface> -t <interval> -s <SSID> -d <duration>
 iface : interface name, default is wlan0
interval :  broadcasting interval, in unit of second, default is 0.1.
SSID : the fake ssid you would like to broadcast, it supports UTF-8 for international purpose. Default is 開源路由器
duration : how long would the broadcasting last, in unit of second. default is 30 seconds.


二. Run the code in OpenWRT.

  甲. Check there is over 7.5 MB storage space available on your OpenWRT device :

root@JoySince:~# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                   12.3M      2.7M      9.6M  22% /
:

If your space is not adequate, you could try to adopt extroof skill.

 乙. Install those package, libffi, python-mini and python:
root@JoySince:~#opkg update
root@JoySince:~#opkg install libffi
root@JoySince:~#opkg install python-mini
root@JoySince:~#opkg install python


丙. install scapy.

   Before install scapy, you need to install tcpdump and unzip.
root@JoySince:~#opkg install python tcpdump unzip

After the installation has done, download the scapy from here and move the downloaded scapy.XXX.tar.gz file to your OpenWRT.

install the scapy.XXX.tar.gz file (mine is scapy-2.4.0.tar.gz), I assume the scapy.XXX.tar.gz is located in /tmp folder:

root@JoySince:/tmp~#tar -zxvf scapy-2.4.0.tar.gz
root@JoySince:/tmp~#cd scapy-2.4.0
root@JoySince:/tmp~#python setup.py install

After the installation has been done, you could remove the tar.gz file and the unzip scapy folder.


丁.  Set the WIFI interface on OpenWRT in monitor mode.

Modify the file /etc/config/wireless as :
config wifi-device 'radio0'
        option type 'mac80211'
#       option channel '8'
        option channel '1' ##
        option hwmode '11g'
        option path 'platform/ar933x_wmac'
        option htmode 'HT40'
        option txpower '30'
        option country 'US'

config wifi-iface
        option device 'radio0'
        option mode monitor ##
#       option mode 'ap'
#       option ssid 'JoySince'
        option network 'lan'
        option encryption 'psk'
        option key '12345678'

The lines begins from # are what I commented out, the lines end in ## are what I added.
After the modification has been done, set this configuration applied:
root@JoySince:/tmp# wifi
root@JoySince:/tmp# iw wlan0 info
Interface wlan0
        ifindex 6
        wdev 0x2
        addr 00:ca:01:06:0d:da
        type monitor
        wiphy 0
        channel 1 (2412 MHz), width: 20 MHz (no HT), center1: 2412 MHz

If it does not work, reboot your OpenWRT.


丁. Move the code broadcastproberequest.py to your OpenWRT,  and run the code.

root@JoySince:~# python broadcastproberequest.py -d 300  -t 0.05 -s 白羅剎


Result :


※ You could adopt the other OpenWRT with the same configuration of file /etc/config/wireless to monitor the broadcasted probe-request packets :

root@JoySince:~# tcpdump -i wlan0 -e -s 1024 type mgt subtype probe-req -vv

But you could not use ONLY ONE openWRT to broadcast and monitor probe-request  at the same time.