分类: LINUX
2010-05-08 21:49:45
ARP分组:
以太网帧:
说明1:这时ARP要查询的以太网地址,全部填0或者1都可以。
说明2:用自己的以太网地址代替。
复制过来,省得打字太麻烦,最关键的一句话就是这里了:目标硬件地址 FF FF FF FF FF FE。这个地址是个特殊的mac地址叫做为广播地址。他有这样的特点,不管在windows或者linux环境下,当网卡处于混杂模式的情况下,网卡的硬件过滤器不会过滤该分组,当然是废话了,混杂模式的网卡才不管你这个地址是什么了,他什么都不过滤,但是如果是普通模式的情况下,硬件过滤器会丢弃该数据帧。那么我们就不会收到arp响应了。接着假如带检测的机器网卡在混杂模式下,该数据帧就会进行下一步处理,也就是通过软件过滤器了。目前的软件过滤器实现一般只判断这个mac地址的第一个字节是不是FF,如果是FF,软件过滤器就把这个数据帧当作是广播处理,就是不过滤的意思了,这样就会交给内核正常的处理流程了,这样的话处于混杂模式的机器就会发送一个arp相应给我们了,那就ok了。反之如果不是FF,软件过滤器就会丢弃掉这个数据帧,这就是为什么我们要把这个目标硬件地址设置成FF FF FF FF FF FE的原因了。
代码:
[code]
#include
#include
#include
#include
#include
#include
#include
#include
#include
//arp frame header (14 bytes)
struct frame_hdr {
unsigned char dst_mac[6];
unsigned char src_mac[6];
unsigned short frm_type;
};
//arp frame header+body (14+8+20 bytes)
struct frame_ether {
struct frame_hdr fh;
struct arphdr ah;
unsigned char src_mac[6];
unsigned char src_ip[4];
unsigned char dst_mac[6];
unsigned char dst_ip[4];
};
int main(int argc, char **argv) {
int sockfd;
struct sockaddr_ll peer_addr;
//创建AF_PACKET类型socket
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if(sockfd == -1)perror("socket()");
//初始化struct sockaddr_ll 类型的socket地址结构
memset(&peer_addr, 0, sizeof(peer_addr));
peer_addr.sll_family = AF_PACKET;
struct ifreq req;
strcpy(req.ifr_name, "eth0");
if(ioctl(sockfd, SIOCGIFINDEX, &req) != 0)perror("ioctl()");
peer_addr.sll_ifindex = req.ifr_ifindex;
peer_addr.sll_protocol = htons(ETH_P_ARP);
//发送arp请求到要检测的机器ip
unsigned char bad_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}; //伪广播地址,混杂模式下,软件过滤层不会过滤该数据帧。就是说会有arp相应了
unsigned char my_ip[4] = {192, 168, 1, 99}; //本机的ip地址
unsigned char my_mac[6] = {0x00, 0x0c, 0x29, 0x5e, 0x01, 0xff}; //本机的mac地址
unsigned char dst_ip[4] = {192, 168, 1, 102}; //要检测是否处于混杂模式的机器ip
unsigned char dst_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//build arp frame
struct frame_ether frame;
memcpy(frame.fh.dst_mac, bad_mac, 6);
memcpy(frame.fh.src_mac, my_mac, 6);
frame.fh.frm_type = htons(ETH_P_ARP);
frame.ah.ar_hrd = htons(ARPHRD_ETHER);
frame.ah.ar_pro = htons(ETH_P_IP);
frame.ah.ar_hln = 6;
frame.ah.ar_pln = 4;
frame.ah.ar_op = htons(ARPOP_REQUEST);
memcpy(frame.src_mac, my_mac, 6);
memcpy(frame.src_ip, my_ip, 4);
memcpy(frame.dst_mac, dst_mac, 6);
memcpy(frame.dst_ip, dst_ip, 4);
int nbytes = sendto(sockfd, &frame, sizeof(frame), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr));
printf("nbytes = %d\n", nbytes);
return 0;
}