基于socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)),写抓包软件,C++代码
时间: 2024-03-14 17:48:23 浏览: 183
以下是基于socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))的抓包软件的C++代码示例:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#define ETH_HDRLEN 14
using namespace std;
int main(int argc, char* argv[]) {
int sock_fd;
struct ifreq ifr;
char iface[] = "eth0"; // 设备名称
char buffer[ETH_FRAME_LEN];
struct sockaddr_in source, dest;
struct ethhdr* eth_hdr;
struct iphdr* ip_hdr;
struct tcphdr* tcp_hdr;
int data_len;
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd < 0) {
perror("Error creating socket");
return 1;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)-1);
if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) < 0) {
perror("Error getting interface index");
return 1;
}
struct sockaddr_ll socket_address;
memset(&socket_address, 0, sizeof(socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_ifindex = ifr.ifr_ifindex;
socket_address.sll_protocol = htons(ETH_P_IP);
bind(sock_fd, (struct sockaddr*)&socket_address, sizeof(socket_address));
while (true) {
data_len = recvfrom(sock_fd, buffer, ETH_FRAME_LEN, 0, NULL, NULL);
if (data_len < 0) {
perror("Error receiving packet");
break;
}
eth_hdr = (struct ethhdr*)buffer;
if (ntohs(eth_hdr->h_proto) != ETH_P_IP) {
continue;
}
ip_hdr = (struct iphdr*)(buffer + ETH_HDRLEN);
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = ip_hdr->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = ip_hdr->daddr;
if (ip_hdr->protocol == IPPROTO_TCP) {
tcp_hdr = (struct tcphdr*)(buffer + ETH_HDRLEN + (ip_hdr->ihl * 4));
cout << inet_ntoa(source.sin_addr) << ":" << ntohs(tcp_hdr->source)
<< " -> " << inet_ntoa(dest.sin_addr) << ":" << ntohs(tcp_hdr->dest) << endl;
}
}
close(sock_fd);
return 0;
}
该程序使用了Linux下的socket API,创建了一个PF_PACKET类型的原始套接字,可以接收所有的以太网帧。程序首先指定了需要监听的设备名称(iface),然后通过ioctl函数获取设备的索引号,最后通过bind函数将socket与设备绑定。在while循环中,程序通过recvfrom函数从socket中接收数据包,然后根据以太网帧头和IP头的协议类型进行过滤,最后根据TCP头的源IP、目的IP、源端口、目的端口等信息进行输出。
相关推荐












