Linux(kali)使用libpcap抓包并在不影响原有通信基础上转发数据包

Linux(kali)使用libpcap抓包并在不影响原有通信基础上转发数据包

本文链接:https://www.cnblogs.com/muphy/p/14922039.html

也可以直接通过内核抓包而不需要安装libpcaplinux或者Android使用内核ioctl抓包

安装libpacp

sudo apt-get install libpcap

或者

复制代码
#下载
wget http://www.tcpdump.org/release/libpcap-1.10.1.tar.gz
#解压
tar -zxvf libpcap-1.10.1.tar.gz
cd libpcap-1.10.1
#安装
./configure
make
make install
复制代码

可能需要先依次安装flexbsion,安装方式同libpcap

编写抓包及转发代码

百度收索的使用方式基本上是翻译自文档,强烈推荐直接看文档,https://eecs.wsu.edu/~sshaikot/docs/lbpcap/libpcap-tutorial.pdf

 

 下面是抓包兼抓发代码,ruphy.c

复制代码
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//链路层数据包格式
typedef struct {
    u_char DestMac[6];
    u_char SrcMac[6];
    u_char Etype[2];
} ETHHEADER;

//IP层数据包格式
typedef struct {
    int header_len:4;
    int version:4;
    u_char tos:8;
    int total_len:16;
    int ident:16;
    int flags:16;
    u_char ttl:8;
    u_char proto:8;
    int checksum:16;
    u_char sourceIP[4];
    u_char destIP[4];
} IPHEADER;

//协议映射表
char *Proto[]={
    "Reserved","ICMP","IGMP","GGP","IP","ST","TCP"
};

/*
 强调:当客户端连接服务器时,服务器会产生一个新的文件描述符(套接字)与客户端交互,这个新的套接字不是服务器端的监听套接字
 套接字是全双工的,在一个网络管道中的两端,每端都可以进行读写操作。
 */
typedef struct _recvmodel
{
    int sockfd;
    struct sockaddr_in * addr;
} RecvModel;

RecvModel model;
char dev[20];
char filter_port[100];

//send message
void send_msg(const u_char *msg, int len)
{
    if (send(model.sockfd, msg, len, 0) == -1)
    {
        printf("send failed ! error message %s\n", strerror(errno));
    }
}

//recv message
void * recv_thread()
{
    int flag = 0;
    char buf[1024] = { 0 };
    while (1)
    {
        flag = recv(model.sockfd, buf, sizeof(buf), 0);
        if (flag == 0)
        {
            printf("对方已经关闭连接!\n");
            return NULL;
        } else if (flag == -1) {
            printf("recv failed ! error message : %s\n", strerror(errno));
            return NULL;
        }
        printf("%s:%s", inet_ntoa(model.addr->sin_addr), buf);
        memset(buf, 0, sizeof(buf));
    }
    return NULL;
}

//回调函数
void pcap_handle(u_char* user,const struct pcap_pkthdr* header,const u_char* pkt_data)
{
    ETHHEADER *eth_header=(ETHHEADER*)pkt_data;
    printf("---------------Begin Analysis: %d -----------------\n", user);
    printf("Packet length: %d \n",header->len);
    //解析数据包IP头部
    if(header->len>=14){
        IPHEADER *ip_header=(IPHEADER*)(pkt_data+14);
        //解析协议类型
        char strType[100];
        if(ip_header->proto>7)
            strcpy(strType,"IP/UNKNWN");
        else
            strcpy(strType,Proto[ip_header->proto]);
        printf("Source MAC : %02X-%02X-%02X-%02X-%02X-%02X==>",eth_header->SrcMac[0],eth_header->SrcMac[1],eth_header->SrcMac[2],eth_header->SrcMac[3],eth_header->SrcMac[4],eth_header->SrcMac[5]);
        printf("Dest   MAC : %02X-%02X-%02X-%02X-%02X-%02X\n",eth_header->DestMac[0],eth_header->DestMac[1],eth_header->DestMac[2],eth_header->DestMac[3],eth_header->DestMac[4],eth_header->DestMac[5]);
        printf("Source IP : %d.%d.%d.%d==>",ip_header->sourceIP[0],ip_header->sourceIP[1],ip_header->sourceIP[2],ip_header->sourceIP[3]);
        printf("Dest   IP : %d.%d.%d.%d\n",ip_header->destIP[0],ip_header->destIP[1],ip_header->destIP[2],ip_header->destIP[3]);
        printf("Protocol : %s\n",strType);
        //显示数据帧内容
        int i, len;
        len = (int)header->len;
        for(i=0; i<len; ++i)  {
            printf(" %02x", pkt_data[i]);
            if( (i + 1) % 16 == 0 )
                printf("\n");
        }
        printf("\n");
send_msg(pkt_data, len); printf(
"\n\n"); } } void * listen_thread(void *arg) { pcap_t *handle; /* Session handle */ //char dev[] = "eth0"; /* Device to sniff on */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ struct bpf_program fp; /* The compiled filter expression */ char filter_exp[100] = "port "; // (char *)arg; /* The filter expression */ bpf_u_int32 mask; /* The netmask of our sniffing device */ bpf_u_int32 net; /* The IP of our sniffing device */ printf("000 %s", filter_exp); if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { fprintf(stderr, "Can't get netmask for device %s\n", dev); net = 0; mask = 0; } handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); if (handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); goto END; } printf("111 %s", filter_exp); strcat(filter_exp, filter_port); printf("222 %s", filter_exp); if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle)); goto END; } if (pcap_setfilter(handle, &fp) == -1) { fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle)); goto END; } /* wait loop forever */ int id = 0; if( pcap_loop(handle, 10, pcap_handle, (u_char*)&id) < 0){ fprintf(stderr, "cap error!"); } END: pcap_close(handle); printf("333 %s", filter_exp); return NULL; } int main() { //打开socket int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("open socket failed! error message:%s\n", strerror(errno)); return -1; } //定义IP地址结构 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); //设置TCP/IP连接 addr.sin_family=AF_INET; //设置端口号 int port; printf("设置转发端口号:"); scanf("%d", &port); addr.sin_port = htons(port); //设置允许连接地址 char ip[20]; do { printf("设置转发IP:"); scanf("%s", ip); printf("ip:%s, port: %d\n", ip, port); } while(ip[0] == '\0'); addr.sin_addr.s_addr = inet_addr(ip); do { printf("设置TCP抓包过滤端口:"); scanf("%s", filter_port); }while(filter_port[0] == '\0'); printf("TCP抓包过滤端口:%s\n", filter_port); //设置允许连接地址 do { printf("设置监听网卡(如:eth0):"); scanf("%s", dev); }while(dev[0] == '\0'); printf("监听网卡:%s\n", dev); //connect server int numx = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)); if (numx == -1) { printf("connect server failed ! error message :%s\n", strerror(errno)); goto END; } model.sockfd = sockfd; model.addr = &addr; printf("connect server ok ! \n"); pthread_t thr1, thr2; if (pthread_create(&thr1, NULL, listen_thread, NULL) != 0) { printf("create thread failed ! \n"); goto END; } printf("create listen_thread thread ok ! \n"); if (pthread_create(&thr2, NULL, recv_thread, NULL) != 0) { printf("create thread failed ! \n"); goto END; } printf("create recv_thread thread ok ! \n"); pthread_join(thr1, NULL); pthread_join(thr2, NULL); END: close(sockfd); return 0; }
复制代码

 

编译及运行

采用gcc静态编译将依赖一起编译成一个文件ruphy.o

gcc ruphy.c -static -lpcap -lpthread -o ruphy.o

运行

chmod 777 ruphy.o
./ruphy.o

运行时需要设置抓发地址、监听端口和网卡,程序会将网卡设置位混杂模式以便抓取局域网内的所有数据包

kali ip:192.168.2.100   8888端口用来接收抓发的数据  502端口用来开启TCP服务通信

win10 ip:192.168.2.83  连接kali 502端口建立通信

 

 

posted @   明月心~  阅读(1597)  评论(2编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示