Created
November 7, 2022 12:43
-
-
Save AtieP/52a0b502763d01a6e8fa9a8b493e693b to your computer and use it in GitHub Desktop.
ARP scanner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <linux/if_packet.h> | |
#include <net/ethernet.h> | |
#include <stdio.h> | |
#include <arpa/inet.h> | |
#include <sys/ioctl.h> | |
#include <net/if.h> | |
#include <string.h> | |
#include <netinet/in.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <linux/if_arp.h> | |
#include <unistd.h> | |
int sfd; | |
int our_ifindex; | |
char our_mac[6]; | |
in_addr_t our_ip; | |
char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
#define ARP_REQUEST 1 | |
#define ARP_REPLY 2 | |
struct arp_ip { | |
uint16_t htype; | |
uint16_t ptype; | |
uint8_t hlen; | |
uint8_t plen; | |
uint16_t op; | |
char srcmac[6]; | |
in_addr_t srcip; | |
char destmac[6]; | |
in_addr_t destip; | |
} __attribute__((packed)); | |
static void | |
print_mac(char *buf) | |
{ | |
for (int i = 0; i < 6; i++) { | |
printf("%hhx%s", buf[i], i != 5 ? ":" : ""); | |
} | |
} | |
static void | |
print_ip(in_addr_t ip) | |
{ | |
ip = ntohl(ip); | |
printf("%hhu.%hhu.%hhu.%hhu", (uint8_t) (ip >> 24), (uint8_t) (ip >> 16), (uint8_t) (ip >> 8), (uint8_t) ip); | |
} | |
static void | |
retrieve_interface_index(const char *ifname) | |
{ | |
struct ifreq req; | |
memset(&req, 0, sizeof(req)); | |
strncpy(req.ifr_name, ifname, IFNAMSIZ); | |
if (ioctl(sfd, SIOCGIFINDEX, &req) < 0) { | |
perror("ioctl(SIOCGIFINDEX)"); | |
exit(1); | |
} | |
our_ifindex = req.ifr_ifindex; | |
} | |
static void | |
retrieve_interface_mac(const char *ifname) | |
{ | |
struct ifreq req; | |
memset(&req, 0, sizeof(req)); | |
strncpy(req.ifr_name, ifname, IFNAMSIZ); | |
if (ioctl(sfd, SIOCGIFHWADDR, &req) < 0) { | |
perror("ioctl(SIOCGIFHWADDR)"); | |
exit(1); | |
} | |
assert(req.ifr_hwaddr.sa_family == ARPHRD_ETHER); | |
memcpy(our_mac, req.ifr_hwaddr.sa_data, 6); | |
} | |
static void | |
retrieve_interface_ip(const char *ifname) | |
{ | |
struct ifreq req; | |
memset(&req, 0, sizeof(req)); | |
strncpy(req.ifr_name, ifname, IFNAMSIZ); | |
if (ioctl(sfd, SIOCGIFADDR, &req) < 0) { | |
perror("ioctl(SIOCGIFADDR)"); | |
exit(1); | |
} | |
assert(req.ifr_addr.sa_family == AF_INET); | |
memcpy(&our_ip, req.ifr_addr.sa_data + sizeof(in_port_t), 4); | |
} | |
static void | |
print_arp(struct arp_ip *arp) | |
{ | |
printf("htype %hu ptype %hu hlen %hhu plen %hhu op %s", | |
ntohs(arp->htype), ntohs(arp->ptype), arp->hlen, | |
arp->plen, ntohs(arp->op) == ARP_REQUEST ? "ARP_REQUEST" : | |
(ntohs(arp->op) == ARP_REPLY ? "ARP_REPLY" : "??")); | |
if (arp->htype == htons(ARPHRD_ETHER) && arp->ptype == 8) { | |
printf(" source mac "); | |
print_mac(arp->srcmac); | |
printf(" source ip "); | |
print_ip(arp->srcip); | |
printf(" destination mac "); | |
print_mac(arp->destmac); | |
printf(" destination ip "); | |
print_ip(arp->destip); | |
printf("\n"); | |
} else | |
printf("\n"); | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
char *ifname; | |
struct arp_ip arp; | |
struct sockaddr_ll sll; | |
memset(&arp, 0, sizeof(arp)); | |
memset(&sll, 0, sizeof(sll)); | |
if (argc < 2) { | |
printf("expected interface name\n"); | |
return 1; | |
} | |
ifname = argv[1]; | |
/* create packet socket */ | |
sfd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)); | |
if (sfd < 0) { | |
perror("socket"); | |
return 1; | |
} | |
retrieve_interface_index(ifname); | |
retrieve_interface_mac(ifname); | |
retrieve_interface_ip(ifname); | |
printf("%s: idx %d mac ", ifname, our_ifindex); | |
print_mac(our_mac); | |
printf(" ip "); | |
print_ip(our_ip); | |
printf("\n"); | |
/* tell linux where to send */ | |
sll.sll_family = AF_PACKET; | |
sll.sll_protocol = htons(ETH_P_ARP); | |
sll.sll_ifindex = our_ifindex; | |
sll.sll_hatype = ARPHRD_ETHER; | |
sll.sll_halen = 6; | |
for (int i = 0; i < 6; i++) | |
sll.sll_addr[i] = broadcast[i]; | |
/* craft the arp packet */ | |
arp.htype = htons(ARPHRD_ETHER); | |
arp.ptype = htons(ETH_P_IP); | |
arp.hlen = 6; | |
arp.plen = 4; | |
arp.op = htons(ARP_REQUEST); | |
for (int i = 0; i < 6; i++) | |
arp.srcmac[i] = our_mac[i]; | |
arp.srcip = our_ip; | |
for (int i = 0; i < 6; i++) | |
arp.destmac[i] = 0; | |
arp.destip = htonl((192 << 24) | (168 << 16) | (1 << 8) | 1); | |
print_arp(&arp); | |
printf("sending ARP request for 192.168.1.1 ...\n"); | |
if (sendto(sfd, &arp, sizeof(arp), 0, (struct sockaddr *) &sll, sizeof(sll)) != sizeof(arp)) { | |
perror("write"); | |
return 1; | |
} | |
if (read(sfd, &arp, sizeof(arp)) != sizeof(arp)) { | |
perror("read"); | |
return 1; | |
} | |
print_arp(&arp); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment