libpcap/tcpdump—5—捕获方式(AF_PACKET原始套接字)

pcap_loop调用pcap_read_linux_mmap_v3循环捕获数据,此时程序已经进入正常嗅探过程,而我们应该重点关注的点应该是在这之前的启动过程。

整体了解之后发现一切都是围绕着socket展开,这个socket和以往纯应用层tcp/udp的socket不一样,它将Ethernet、ip、tcp层的数据都暴露出来,被称作原始套接字。

libpcap/tcpdump就是用原始套接字来捕获网卡数据,围绕着原始套接字又做了丰富的功能。本文抛开libpcap/tcpdump,用原始套接字实现了一个收和一个发。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void printf_hex(char *data, int len, int count);

int main(int argc,char *argv[]) {

    int sock_raw_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if(sock_raw_fd < 0){
        perror("socket");
        return -1;
    }

    unsigned char buf[1024] = {0};
    int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);
    printf_hex(buf,len,16);

    return 0;
}

void printf_hex(char *data, int len, int count)
{
    printf("start data=%p _pDataLen=%d", data,len);
    int i = 0;

    printf("\n");
    for(i = 0; i < len; i++)
    {
        if(data[i] < 0x10) {
            printf("0x0%x, ", data[i]);
        } else {
            printf("0x%x, ", data[i]);
        }
        if((!((i + 1) %count)) && (i > 0))
        {
            printf("\n");
        }
    }
    printf("\n");
    printf("\n");
    printf("end _pData\n");

    return;
}

上面的代码编译执行后会抓一个数据包并打印出来,同时用wireshark进行抓包,可以在抓包中发现打印的数据,并且是从链路层开始打印的。如果想获取ip,端口和网卡等信息,直接读数据即可,很多系统调用可能也是利用原始socket开发。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void printf_hex(char *data, int len, int count);

int main(int argc,char *argv[]) {

    int sock_raw_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if(sock_raw_fd < 0){
        perror("socket");
        return -1;
    }

    unsigned char buf[14] = {0};//6+6+2
//    int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);
//    printf_hex(buf,len,16);

    struct sockaddr_ll sll;
    struct ifreq req;

    strncpy(req.ifr_name, "ens33", IFNAMSIZ);
    if(ioctl(sock_raw_fd, SIOCGIFINDEX, &req) == -1){
        perror("ioctl");
        close(sock_raw_fd);
        return -1;
    }

    bzero(&sll,sizeof(sll));
    sll.sll_ifindex = req.ifr_ifindex;

    buf[0]=0x00;
    buf[1]=0x0c;
    buf[2]=0x29;
    buf[3]=0xbf;
    buf[4]=0xfc;
    buf[5]=0xef;
    int len = sendto(sock_raw_fd, buf, sizeof(buf), 0, (struct sockaddr *)&sll, sizeof(sll));
    if(len == -1){
        perror("sendto");
        return -1;
    }

    return 0;
}

void printf_hex(char *data, int len, int count)
{
    printf("start data=%p _pDataLen=%d", data,len);
    int i = 0;

    printf("\n");
    for(i = 0; i < len; i++)
    {
        if(data[i] < 0x10) {
            printf("0x0%x, ", data[i]);
        } else {
            printf("0x%x, ", data[i]);
        }
        if((!((i + 1) %count)) && (i > 0))
        {
            printf("\n");
        }
    }
    printf("\n");
    printf("\n");
    printf("end _pData\n");

    return;
}

用tcpdump抓包会找到此包,如下图所示。

libpcap/tcpdump—5—捕获方式(AF_PACKET原始套接字)_第1张图片

原始socket可以做很多事情,网上有篇文章讲如何用原始socket窃取ftp明文的用户名密码用ping命令发回。我想到的最有意思的也就是去做各种侦听伪造。哈哈哈。就像有一篇文章写的这个是骇客初级知识。tcpdump的最基本原理其实已经懂了,后面其实想把重心放在ffmpeg上,但也真心不希望这个是libpcap/tcpdump的最后一篇文章。

你可能感兴趣的:(tcpdump,网络,linux)