#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>
#include <netpacket/packet.h>
#define ETH_ARP 0x0806 // ARP协议以太网类型
#define ARP_REQUEST 1 // ARP请求操作码
#define ARP_REPLY 2 // ARP响应操作码
#define BUF_SIZE 1024
// ARP包头结构体 (RFC 826)
struct arp_header {
uint16_t htype; // 硬件类型
uint16_t ptype; // 协议类型
uint8_t hlen; // 硬件地址长度
uint8_t plen; // 协议地址长度
uint16_t oper; // 操作码
uint8_t sha[6]; // 发送方MAC
uint8_t spa[4]; // 发送方IP
uint8_t tha[6]; // 目标MAC
uint8_t tpa[4]; // 目标IP
};
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <bridge_interface> <start_ip> <end_ip>\n", argv[0]);
fprintf(stderr, "Example: %s br0 192.168.1.1 192.168.1.254\n");
exit(EXIT_FAILURE);
}
char *iface = argv[1]; // 桥接接口名,如br0
char *start_ip = argv[2]; // 起始IP
char *end_ip = argv[3]; // 结束IP
// 创建原始套接字 (AF_PACKET: 链路层访问)
int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// 绑定到桥接接口
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, iface, IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) {
perror("Bind to interface failed");
close(sock);
exit(EXIT_FAILURE);
}
// 构造以太网帧 + ARP请求
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 广播MAC
uint8_t local_mac[6];
struct ifreq mac_req;
strncpy(mac_req.ifr_name, iface, IFNAMSIZ);
if (ioctl(sock, SIOCGIFHWADDR, &mac_req) < 0) { // 获取本机MAC
perror("Get MAC failed");
close(sock);
exit(EXIT_FAILURE);
}
memcpy(local_mac, mac_req.ifr_hwaddr.sa_data, 6);
// 发送ARP请求到每个IP
struct sockaddr_ll sa;
memset(&sa, 0, sizeof(sa));
sa.sll_family = AF_PACKET;
sa.sll_ifindex = if_nametoindex(iface);
sa.sll_halen = ETH_ALEN;
memcpy(sa.sll_addr, broadcast_mac, 6); // 目标MAC=广播
for (uint32_t ip = ntohl(inet_addr(start_ip)); ip <= ntohl(inet_addr(end_ip)); ip++) {
uint8_t packet[BUF_SIZE];
struct ethhdr *eth = (struct ethhdr *)packet;
struct arp_header *arp = (struct arp_header *)(packet + sizeof(struct ethhdr));
// 填充以太网帧头
memcpy(eth->h_dest, broadcast_mac, 6);
memcpy(eth->h_source, local_mac, 6);
eth->h_proto = htons(ETH_ARP); // 类型=ARP
// 填充ARP包头
arp->htype = htons(1); // 以太网
arp->ptype = htons(ETH_P_IP); // IPv4
arp->hlen = 6; // MAC长度
arp->plen = 4; // IP长度
arp->oper = htons(ARP_REQUEST); // 操作码=请求
memcpy(arp->sha, local_mac, 6); // 发送方MAC(本机)
inet_pton(AF_INET, "0.0.0.0", arp->spa); // 发送方IP(通常设为0)
memset(arp->tha, 0, 6); // 目标MAC(未知)
uint32_t target_ip = htonl(ip);
memcpy(arp->tpa, &target_ip, 4); // 目标IP
// 发送数据包
if (sendto(sock, packet, sizeof(struct ethhdr) + sizeof(struct arp_header), 0,
(struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("Send ARP request failed");
}
usleep(1000); // 避免洪水攻击,延迟1ms
}
// 捕获ARP响应
printf("Scanning MAC addresses on %s...\n", iface);
printf("IP Address\t\tMAC Address\n");
printf("----------------------------------------\n");
while (1) {
uint8_t buffer[BUF_SIZE];
ssize_t len = recvfrom(sock, buffer, BUF_SIZE, 0, NULL, NULL);
if (len < 0) {
perror("Packet receive error");
break;
}
// 检查以太网类型是否为ARP
struct ethhdr *recv_eth = (struct ethhdr *)buffer;
if (ntohs(recv_eth->h_proto) != ETH_ARP) continue;
// 解析ARP包头
struct arp_header *recv_arp = (struct arp_header *)(buffer + sizeof(struct ethhdr));
if (ntohs(recv_arp->oper) != ARP_REPLY) continue; // 仅处理响应
// 打印IP和MAC
char ip_str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, recv_arp->spa, ip_str, INET_ADDRSTRLEN);
printf("%-15s\t\t%02X:%02X:%02X:%02X:%02X:%02X\n",
ip_str,
recv_arp->sha[0], recv_arp->sha[1], recv_arp->sha[2],
recv_arp->sha[3], recv_arp->sha[4], recv_arp->sha[5]);
}
close(sock);
return 0;
}
怎么修改
最新发布