Chinaunix首页 | 论坛 | 博客
  • 博客访问: 832388
  • 博文数量: 330
  • 博客积分: 9641
  • 博客等级: 中将
  • 技术积分: 3181
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
文章分类

全部博文(330)

文章存档

2012年(17)

2011年(135)

2010年(85)

2009年(57)

2008年(36)

我的朋友

分类: 网络与安全

2011-02-28 23:52:51

1.根据man 7 packet 写出的抓包程序
有两种将网卡设置为promiscuous的方法,注释掉一种。

C语言Codee#17292
/* 
*  Low level network programming in Linux using PF_PACKET
*  Need root privileges
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include  //#include //#include
#include

#define RED "\e[31m\e[1m"
#define GREEN "\E[32m\E[1m"
#define YELLOW "\E[33m\E[1m"
#define BLUE "\E[34m\E[1m"  
#define NORMAL "\e[m"

int get_nic_index(int fd, const char* nic_name)
{
    struct ifreq ifr;
    if (nic_name == NULL)
           return -1;
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, nic_name, IFNAMSIZ);
    if (ioctl(fd, SIOCGIFINDEX, &ifr== -1{
        perror(GREEN"SIOCGIFINDEX ioctl error"NORMAL);
        return -1;
    }
    return ifr.ifr_ifindex;
}

int set_Nic_promisc(int fd, int dev_id)
{
    struct packet_mreq mr;
    memset(&mr, 0, sizeof(mr));
    mr.mr_ifindex = dev_id;
    mr.mr_type = PACKET_MR_PROMISC;
    if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,&mr,sizeof(mr))==-1{
        return -1;
    }
    return 0;
}

int set_nic_promisc(int sockfd, const char *nic_name)
{
    struct ifreq ethreq;
    strncpy(ethreq.ifr_name, nic_name, IFNAMSIZ);
    ioctl(sockfd, SIOCGIFFLAGS, &ethreq);
    ethreq.ifr_flags |= IFF_PROMISC;
    ioctl(sockfd, SIOCSIFFLAGS, &ethreq);
    return 0;
}

int main(int argc, char **argv)
{
    if (argc != 3{
        printf("usage: ./a.out \n");
        exit(1);
    }

    int pktfd;
    int maxpak = 0, ipak = 0;
    int fromlen;
    char buffer[BUFSIZ];
    struct iphdr *iph;
    struct sockaddr_ll sll;

    /* Low level socket */
    pktfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (pktfd == -1{
        perror(RED"Unable to create low level socket"NORMAL);
        return -1;
    }

    memset(&sll, 0, sizeof(sll));
    sll.sll_family = AF_PACKET;
    sll.sll_protocol = htons(ETH_P_ALL);
    sll.sll_ifindex = get_nic_index(pktfd, argv[1]);


    if (bind(pktfd, (struct sockaddr *&sll, sizeof(sll)) != 0{
        perror(YELLOW"bind error"NORMAL);
        goto FAIL;
    }
    set_nic_promisc(pktfd, argv[1]);

    //if (set_Nic_promisc(pktfd, sll.sll_ifindex) == -1) {
    //    fprintf(stderr, BLUE"set promisc failed! \n"NORMAL);
    //    goto FAIL;
    //}

    maxpak = atoi(argv[2]);
    while (!maxpak || ipak < maxpak{
        fromlen = recv(pktfd, buffer, BUFSIZ, MSG_TRUNC);
        printf("Buffer Length: %d bytes\n", fromlen);
        struct ethhdr *ethdr = (struct ethhdr *buffer;
        if ( ethdr->h_proto == htons(ETH_P_IP) ) {
            iph = (struct iphdr *) (buffer + sizeof(struct ethhdr));
            printf("IP Packet from: %s\n", inet_ntoa(*(struct in_addr*)&iph->saddr));
            printf("IP Packet To: %s\n", inet_ntoa(*(struct in_addr*)&iph->daddr));
            printf("IP Protocol: %#x\n", iph->protocol);
            printf("Buffer Content: %s\n\n", buffer);
            ipak++;
        }
    }

    return 0;

FAIL:
    close(pktfd);
    return -1;
}

测试中发现在家的pppoe拨号上网抓到的包格式解析错误,而放在虚拟机里面却正确。用wireshark听报文发现PPPoE的报文格式不同于普通报文。
pppoe拨号的报文在网络层的Type: PPPoE Session (0x8864),网络层到IP层之间还有2层
PPP-over-Ethernet Session (6 bytes)
Point-to-Point Protocol (2 bytes) Protocol: IP (0x0021)


2.AF_PACKET 获得网卡信息
没有获得Unix/Linux系统中的IP、MAC地址等信息的方法好,只能获得指定网卡的少量信息。
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/errno.h>
  4. #include <stdlib.h>
  5. #include <sys/socket.h>
  6. #include <arpa/inet.h>
  7. #include <sys/ioctl.h>
  8. #include <linux/if_arp.h> //#include //#include
  9. #include <linux/sockios.h>
  10. #include <unistd.h>

  11. int main(int argc, char **argv)
  12. {
  13.     if (argc != 2) {
  14.         printf("usage: ./a.out nic_name");
  15.         exit(1);
  16.     }

  17.     int i, sockfd;
  18.     static struct ifreq ethreq;
  19.     struct sockaddr_ll inside_address;

  20.     /* Low level socket */
  21.     sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
  22.     if (sockfd == -1) {
  23.         perror("Unable to create low level socket");
  24.         return -1;
  25.     }

  26.     strncpy(ethreq.ifr_name, argv[1], IFNAMSIZ);
  27.     memset(&inside_address, 0, sizeof(inside_address));
  28.     inside_address.sll_family = AF_PACKET;
  29.     inside_address.sll_protocol = htons(ETH_P_ALL);
  30.     inside_address.sll_hatype = ARPOP_REQUEST;
  31.     inside_address.sll_pkttype = PACKET_BROADCAST;
  32.     inside_address.sll_halen = ETH_ALEN;

  33.     ioctl(sockfd, SIOCGIFINDEX, &ethreq);
  34.     inside_address.sll_ifindex = ethreq.ifr_ifindex;
  35.     printf("%X, %X\n", inside_address.sll_ifindex, AF_INET);
  36.     ioctl(sockfd, SIOCGIFHWADDR, &ethreq);

  37.     if (bind(sockfd, (struct sockaddr *) &inside_address,
  38.              sizeof(inside_address)) != 0) {
  39.         perror("bind error");
  40.         return -1;
  41.     }

  42.     for (i = 0; i < 6; i++)
  43.         inside_address.sll_addr[i] = (unsigned char) ethreq.ifr_hwaddr.sa_data[i];

  44.     for (i = 0; i < 5; i++)
  45.         printf("%02X:", inside_address.sll_addr[i]);
  46.     printf("%02X\n", inside_address.sll_addr[i]);

  47.     close(sockfd);
  48.     return 0;
  49. }
阅读(1406) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~