Chinaunix首页 | 论坛 | 博客
  • 博客访问: 584540
  • 博文数量: 92
  • 博客积分: 5026
  • 博客等级: 大校
  • 技术积分: 1321
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-28 11:04
文章分类

全部博文(92)

文章存档

2011年(9)

2010年(17)

2009年(12)

2008年(54)

我的朋友

分类: LINUX

2010-05-08 21:49:45

目的:
    今天饱受局域网内的arp欺骗困挠,所以复习了一下相关的arp方面的知识。mark一下。
功能:
    检测局域网内的某台机器是否处于混杂模式状态。
原理:
    构造一个arp请求数据帧发送给带检测的机器。通过是收到arp响应判断带检测的机器是否处于混杂模式。首先构造出下面的数据帧。

ARP分组:

  • 目的以太网地址 00 00 00 00 00 00(说明1)
  • 发送方以太网地址 00 11 22 33 44 55(说明2)
  • 高层协议类型 08 00(IP)
  • 硬件类型 00 01(以太网)
  • 硬件地址长度 06(以太网地址长度)
  • IP地址长度 04
  • 发送方的IP地址 本机IP地址
  • 目标的IP地址 被检测主机的IP地址
  • ARP操作码 00 01(ARP请求01、ARP应答02)

  以太网帧:

  • 协议类型 08 06(ARP)
  • 发送方的硬件地址 本机以太网卡地址
  • 目标硬件地址 FF FF FF FF FF FE

 说明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;
}

[/code]
 
说明:
linux的2.6内核。
直接gcc编译。
然后执行。
 
同时打开一个窗口用tcpdump arp 观察是否收到了arp响应。
 
 
最后:
that's all!
阅读(3093) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~