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 <sys/socket.h>
#include <netinet/ether.h>
#include <stdio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <string.h>
#include <zconf.h>
#include <sys/ioctl.h>

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 <sys/socket.h>
#include <netinet/ether.h>
#include <stdio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <string.h>
#include <zconf.h>
#include <sys/ioctl.h>

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抓包會找到此包,如下圖所示。

原始socket可以做很多事情,網上有篇文章講如何用原始socket竊取ftp明文的用戶名密碼用ping命令發回。我想到的最有意思的也就是去做各種偵聽僞造。哈哈哈。就像有一篇文章寫的這個是駭客初級知識。tcpdump的最基本原理其實已經懂了,後面其實想把重心放在ffmpeg上,但也真心不希望這個是libpcap/tcpdump的最後一篇文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章