Linux(kali)使用libpcap抓包并在不影响原有通信基础上转发数据包
Linux(kali)使用libpcap抓包并在不影响原有通信基础上转发数据包
本文链接:https://www.cnblogs.com/muphy/p/14922039.html
也可以直接通过内核抓包而不需要安装libpcap:linux或者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
可能需要先依次安装flex和bsion,安装方式同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端口建立通信
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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 加持,客户体验更智能