黑客編程入門C語言網絡編程之arp協議的實現

編程語言 C語言 Python 黑客 GeekLearning 2017-05-07

C語言實現arp協議

之前兩篇文章<<黑客編程入門golang網絡編程之arp協議的實現>> <<黑客編程入門python網絡編程之arp協議的實現>> 分別用golang和python 編程語言實現了arp協議.

下面介紹用C語言來實現arp協議.

代碼如下:

#include <stdio.h>

#include <ctype.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <netdb.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <linux/if_ether.h>

#include <getopt.h>

#define ETH_HW_ADDR_LEN 6

#define IP_ADDR_LEN 4

#define ARP_FRAME_TYPE 0x0806

#define ETHER_HW_TYPE 1

#define IP_PROTO_TYPE 0x0800

#define DEBUG 1

char usage[] =

{

"sendarp: send an arp packet\n usage: sendarp [-?] [-v] [-t message_type] [-i interface]\n [-p sender_protocol_address] [-P target_protocol_address]\n [-h sender_hardware_address] [-H target_hardware_address] [-v]\n \n -? display this message\n -v verbose Default: not verbose\n Be verbose\n \n -t message type Default: 1\n Identifies the purpose for this ARP packet\n 1 ARP Request\n 2 ARP Response\n 3 Reverse ARP Request\n 4 Reverse ARP Response\n 8 Inverse ARP Request\n 9 Inverse ARP Response\n \n -i interface Default: eth0\n Select an interface (eth1, lo, ppp0, whatever...)\n \n -p sender protocol address Default: 0.0.0.0\n Identifies the ip address of the system issuing the ARP packet.\n \n -P target protocol address Default: 0.0.0.0\n Identifies the ip address of the ARP packet's destination.\n \n -h sender hardware address Default: 00:00:00:00:00:00\n Identifies the hardware address of the system issuing the ARP packet.\n \n -H target hardware address Default: 00:00:00:00:00:00\n Identifies the hardware address of the ARP packet's destination.\n \n" };

struct arp_packet {

u_char dst_hw_addr[ETH_HW_ADDR_LEN];

u_char src_hw_addr[ETH_HW_ADDR_LEN];

u_short frame_type;

u_short hw_type;

u_short prot_type;

u_char hw_addr_size;

u_char prot_addr_size;

u_short type;

u_char sndr_hw_addr[ETH_HW_ADDR_LEN];

u_char sndr_ip_addr[IP_ADDR_LEN];

u_char rcpt_hw_addr[ETH_HW_ADDR_LEN];

u_char rcpt_ip_addr[IP_ADDR_LEN];

u_char padding[18];

};

void send_arp(char *src_ip, char *src_hw_addr, char *dst_ip, char *dst_hw_addr,

char *interface, u_short type);

void die(char *);

void get_ip_addr(struct in_addr*, char*);

void get_hw_addr(char*, char*);

int main(int argc, char** argv) {

char src_hw_addr[32];

char dst_hw_addr[32];

char src_ip[32];

char dst_ip[32];

char interface[32];

u_short type = 1;

char *arg;

u_short verbose = 0;

int i = 1;

u_short help = 0;

strcpy(src_hw_addr, "00:00:00:00:00:00");

strcpy(dst_hw_addr, "00:00:00:00:00:00");

strcpy(src_ip, "0.0.0.0");

strcpy(dst_ip, "0.0.0.0");

strcpy(interface, "eth0");

if (argc <= 1)

help = 1;

while (arg = argv[i]) {

i++;

if (strcmp("-i", arg) == 0) {

strncpy(interface, argv[i++], 31);

} else if (strcmp("-p", arg) == 0) {

strncpy(src_ip, argv[i++], 31);

} else if (strcmp("-P", arg) == 0) {

strncpy(dst_ip, argv[i++], 31);

} else if (strcmp("-h", arg) == 0) {

strncpy(src_hw_addr, argv[i++], 31);

} else if (strcmp("-H", arg) == 0) {

strncpy(dst_hw_addr, argv[i++], 31);

} else if (strcmp("-v", arg) == 0) {

verbose = 1;

} else if (strcmp("-t", arg) == 0) {

arg = argv[i++];

if (strcmp("1", arg) == 0)

type = 1;

else if (strcmp("2", arg) == 0)

type = 2;

else if (strcmp("3", arg) == 0)

type = 3;

else if (strcmp("4", arg) == 0)

type = 4;

else if (strcmp("8", arg) == 0)

type = 8;

else if (strcmp("9", arg) == 0)

type = 9;

} else {

help = 1;

}

}

if (help)

printf("%s", usage);

while (1) {

send_arp(src_ip, src_hw_addr, dst_ip, dst_hw_addr, interface, type);

if (verbose) {

printf("Sending ARP Packet:\n");

printf(" Interface: %s\n", interface);

printf(" Message type: %d\n", type);

printf(" Sender hardware address: %s\n", src_hw_addr);

printf(" Sender protocol address: %s\n", src_ip);

printf(" Target hardware address: %s\n", dst_hw_addr);

printf(" Target protocol address: %s\n", dst_ip);

}

}

exit(0);

}

void send_arp(char *src_ip, char *src_hw_addr, char *dst_ip, char *dst_hw_addr,

char *interface, u_short type) {

struct in_addr src_in_addr, dst_in_addr;

struct arp_packet pkt;

struct sockaddr sa;

int sock;

sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ARP));

if (sock < 0) {

perror("socket");

exit(1);

}

pkt.frame_type = htons(ARP_FRAME_TYPE);

pkt.hw_type = htons(ETHER_HW_TYPE);

pkt.prot_type = htons(IP_PROTO_TYPE);

pkt.hw_addr_size = ETH_HW_ADDR_LEN;

pkt.prot_addr_size = IP_ADDR_LEN;

pkt.type = htons(type);

get_hw_addr(pkt.src_hw_addr, src_hw_addr);

get_hw_addr(pkt.dst_hw_addr, "ff:ff:ff:ff:ff:ff");

get_hw_addr(pkt.sndr_hw_addr, src_hw_addr);

get_hw_addr(pkt.rcpt_hw_addr, dst_hw_addr);

get_ip_addr(&src_in_addr, src_ip);

get_ip_addr(&dst_in_addr, dst_ip);

memcpy(pkt.sndr_ip_addr, &src_in_addr, IP_ADDR_LEN);

memcpy(pkt.rcpt_ip_addr, &dst_in_addr, IP_ADDR_LEN);

bzero(pkt.padding, 18);

strcpy(sa.sa_data, interface);

if (sendto(sock, &pkt, sizeof(pkt), 0, &sa, sizeof(sa)) < 0) {

perror("sendto");

exit(1);

}

exit(0);

}

void die(char* str) {

fprintf(stderr, "%s\n", str);

exit(1);

}

void get_ip_addr(struct in_addr* in_addr, char* str) {

struct hostent *hostp;

in_addr->s_addr = inet_addr(str);

if (in_addr->s_addr == -1) {

if ((hostp = gethostbyname(str)))

bcopy(hostp->h_addr,in_addr,hostp->h_length);

else {

fprintf(stderr,"send_arp: unknown host %s\n",str);

exit(1);

}

}

}

void get_hw_addr(char* buf, char* str) {

int i;

char c, val;

char hw_addr[64];

strcpy(hw_addr, str);

for (i = 0; i < ETH_HW_ADDR_LEN; i++) {

if (!(c = tolower(*str++))) {

char msg[64];

sprintf(msg, "Invalid hardware address: %s", hw_addr);

die(msg);

}

if (isdigit(c))

val = c - '0';

else if (c >= 'a' && c <= 'f')

val = c - 'a' + 10;

else {

char msg[64];

sprintf(msg, "Invalid hardware address: %s", hw_addr);

die(msg);

}

*buf = val << 4;

if (!(c = tolower(*str++)))

die("Invalid hardware address");

if (isdigit(c))

val = c - '0';

else if (c >= 'a' && c <= 'f')

val = c - 'a' + 10;

else {

char msg[64];

sprintf(msg, "Invalid hardware address: %s", hw_addr);

die(msg);

}

*buf++ |= val;

if (*str == ':')

str++;

}

}

以上代碼保存為sendarp.c

在linux系統下編譯 gcc -o sendarp sendarp.c

程序運行必須有root權限,可以如下運行程序

sudo ./sendarp -t 1 -i enp3s0 -P 192.168.1.2 -p 192.168.1.1 -h 'DA:32:4F:3E:33:22'

之後用wireshark抓包如下:

黑客編程入門C語言網絡編程之arp協議的實現

可以看到成功發送了arp請求

相關閱讀:

黑客編程入門python網絡編程之arp協議的實現

黑客編程入門golang網絡編程之arp協議的實現

相關推薦

推薦中...