1. 程式人生 > 其它 >Linux(kali)實用libpcap抓包並轉發資料包

Linux(kali)實用libpcap抓包並轉發資料包

Linux(kali)實用libpcap抓包並轉發資料包

本文連結:https://www.cnblogs.com/muphy/p/14922039.html

安裝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

執行時需要設定抓發地址、監聽埠和網絡卡,程式會將網絡卡設定位混雜模式以便抓取區域網內的所有資料包