Monday, August 10, 2009

Trigger an event when someone (unknown) connects to the AP

To trigger an event when someone connects to my open AP, I had the following choices:

  • Get the output of hostapd. Indeed, when someone associates, hostapd outputs some stuff.
  • We can see the modifications in /proc/net/madwifi/athX/associated_sta

    > cat /proc/net/madwifi/ath0/associated_sta
    macaddr: <00:11:f1:51:e6:10>
    RSSI 30
    last_rx 0.013332
    ni_tstamp 0 ni_rtsf 3567813500
    macaddr: <00:11:77:ce:c1:13>
    RSSI 22
    last_rx 0.003333
    ni_tstamp 0 ni_rtsf 3567821275


  • We can modify the madwifi driver to trigger some special event.
Actually, I chose the 3rd option, because it was the cleanest one in my opinion. Since I don't have a big experience with kernel programming, I first googled a little and found this. That was exactly what I was looking for. Besides, it was even easier to what I was doing (playing with inotify...).

I just could not use his patch, because I am using madwifi-hal-0.10.5.6/ in the branch/, since I had big problems with stuck beacons. Basically, what you have to do, is find the function responsible for association (supposing you want to do something when a new association occurs). In the file madwifi-hal-0.10.5.6/ath/if_ath.c, you will find the ath_newassoc(...) function, that after patching will become:


static void
ath_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ath_softc *sc = netdev_priv(ic->ic_dev);

/* Kernel Object Event patch (dmr@c0nc3pt.com) */

struct kobject *kobj = &vap->iv_dev->dev.kobj;
char atd[12], mac[4+18], bss[4+18];
char *envp_ext[] = {
atd,
mac,
bss,
NULL
};


sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);

/* are we supporting compression? */
if (!(vap->iv_ath_cap & ni->ni_ath_flags & IEEE80211_NODE_COMP))
ni->ni_ath_flags &= ~IEEE80211_NODE_COMP;

/* disable compression for TKIP */
if ((ni->ni_ath_flags & IEEE80211_NODE_COMP) &&
(ni->ni_wpa_ie != NULL) &&
(ni->ni_rsn.rsn_ucastcipher == IEEE80211_CIPHER_TKIP))
ni->ni_ath_flags &= ~IEEE80211_NODE_COMP;

ath_setup_keycacheslot(sc, ni);
#ifdef ATH_SUPERG_XR
if (1) {
struct ath_node *an = ATH_NODE(ni);
if (ic->ic_ath_cap & an->an_node.ni_ath_flags & IEEE80211_ATHC_XR)
an->an_minffrate = ATH_MIN_FF_RATE;
else
an->an_minffrate = 0;
ath_grppoll_period_update(sc);
}
#endif
/* KOE: feel free to add whatever you want... :-) */

snprintf(atd, sizeof(atd), "ASSOCIATE=%c", isnew ? '1' : '0');

snprintf(mac, sizeof(mac), "MAC=%02x:%02x:%02x:%02x:%02x:%02x",
ni->ni_macaddr[0], ni->ni_macaddr[1],
ni->ni_macaddr[2], ni->ni_macaddr[3],
ni->ni_macaddr[4], ni->ni_macaddr[5]);

snprintf(bss, sizeof(bss), "BSS=%02x:%02x:%02x:%02x:%02x:%02x",
ni->ni_bssid[0], ni->ni_bssid[1],
ni->ni_bssid[2], ni->ni_bssid[3],
ni->ni_bssid[4], ni->ni_bssid[5]);
if (kobject_uevent_env(kobj, KOBJ_CHANGE, envp_ext) < 0) {
printk(KERN_ERR "madwifi-ng kobject trouble!\n");
}
}


I find the way the event is set up is very clear and easy to understand. Then, after that, you recompile your sources and load the module.

Here comes the interesting part: setting a udev rule to catch the event. I was pissed off because it didn't work the way the guy was describing. Actually, since there was a typo, udev didn't catch the event.
Let see how to build a udev event.

> udevadm monitor --kernel --environment
monitor will print the received events for:
KERNEL - the kernel uevent

KERNEL[1249918765.975675] change /devices/pci0000:00/0000:00:0e.0/net/ath0 (net)
UDEV_LOG=0
ACTION=change
DEVPATH=/devices/pci0000:00/0000:00:0e.0/net/ath0
SUBSYSTEM=net
ASSOCIATE=1
MAC=00:26:11:A1:71:11
BSS=06:C0:B3:A3:b5:d8
INTERFACE=ath0
IFINDEX=8
SEQNUM=942


Basically, udevadm gives us the fields to enter to make our rule.

> cat /etc/udev/rules.d/99-wlan-association.rules
SUBSYSTEM=="net", ACTION=="change", ASSOCIATE=="1", RUN+="/home/root/scripts/assoc.sh"

If you want to be more precise with the udev rule, just add a new field, like the INTERFACE for example. In my case, I found this as being just great. Upon even, the script assoc.sh is executed.

Let see what this script does (as an example):

#!/bin/bash
#!/bin/sh

set $*
FILE=/home/root/scripts/macaddr.txt


RESULT=`grep ${MAC} $FILE`
if [ ! $RESULT ]
then
sms myself "${MAC} associated with ${BSS} (${INTERFACE})"
fi

The file macaddr.txt contains known MAC addresses. If grep does not find the MAC address in this file, it means that we don't know the guy that connected and the box sends me a sms. Cool, isn't it ? Now we can do on-demand-MITM (or on-association-MITM).

Again, greetz to dmr who did the kevent stuff.

No comments:

Post a Comment