C/PCAP:ARP数据包值均为0
我正在努力提高我的C/网络知识,用Pcap库实现ARP欺骗工具 我一直在嗅探arp数据包。我可以在Ethernet帧的ethertype字段中检测ARP类型。但当我“读取”ARP数据包时,所有值都是0(null),但硬件地址(MAC)和协议地址(ip)是非常奇怪的8字节重复数(如20e54ef12:20e54ef12:20e54ef12…)。我就是搞不懂。 以下是我迄今为止所做的工作: 数据包结构.h(用于eth、arp、ip的不同结构…) 这部分是错误的:C/PCAP:ARP数据包值均为0,c,pcap,arp,C,Pcap,Arp,我正在努力提高我的C/网络知识,用Pcap库实现ARP欺骗工具 我一直在嗅探arp数据包。我可以在Ethernet帧的ethertype字段中检测ARP类型。但当我“读取”ARP数据包时,所有值都是0(null),但硬件地址(MAC)和协议地址(ip)是非常奇怪的8字节重复数(如20e54ef12:20e54ef12:20e54ef12…)。我就是搞不懂。 以下是我迄今为止所做的工作: 数据包结构.h(用于eth、arp、ip的不同结构…) 这部分是错误的: void handleARP(con
void handleARP(const struct pkt_eth * eth) {
const struct pkt_arp * arp = (const struct pkt_arp *) (eth + ETH_SIZE);
这里您将传入一个struct pkt\u eth*
,您将eth\u SIZE
添加到该结构中。指针算术前进到下一个元素,而不是下一个字节。实际上,您正在查找传递的指针后面的sizeof(struct pkt_eth)*eth_SIZE
字节
你应该这么做
const struct pkt_arp * arp = (const struct pkt_arp *) (eth + 1);
(或者传入一个已从您要解码的层开始的未签名字符*)我已经完全重构了我的代码,并且可以正常工作,不过还是要感谢(正确的)答案;)
#include<stdio.h>
#include<stdlib.h>
#include<netinet/in.h> // for addresses translation
#include<errno.h>
// for ntohs etc
// can also be necessary to include netinet/in
#include <arpa/inet.h>
#include "packet_struct.h"
#include <pcap.h>
#define SNAP_LEN 1518
int packet_count = 0;
void handleARP(const struct pkt_eth * eth) {
const struct pkt_arp * arp = (const struct pkt_arp *) (eth + ETH_SIZE);
print_pkt_arp(arp);
if(ntohs(arp->htype) != 1) {
fprintf(stderr, "Error : ARP packet does not contain a Hardware type Ethernet -> %d\n",ntohs(arp->htype));
return;
}
// check protocol type
if(ntohs(arp->ptype) != 0x800) {
fprintf(stderr,"Error : ARP packet does not contain a IPv4 type\n");
return;
}
}
void sniff_callback(u_char * user, const struct pcap_pkthdr * h,const u_char * bytes) {
int i = 0;
for(i=0; i < 25; i++) { printf("-"); }; printf("\n");
printf("Received packet number %d ==> %d\n",packet_count++,h->len);
const struct pkt_eth * eth;
unsigned short eth_type;
unsigned int captureLength = h->caplen;
unsigned int packetLength = h->len;
if(captureLength != packetLength) {
fprintf(stderr,"Error : received packet with %d available instead of %d \n",captureLength,packetLength);
return;
}
if(captureLength < ETH_SIZE) {
fprintf(stderr,"Error : received too small packet , %d bytes",captureLength);
return;
}
eth = (struct pkt_eth*)(bytes);
// print the packet
print_pkt_eth(eth);
eth_type = ntohs(eth->type);
if(eth_type == ETHERTYPE_ARP) {
handleARP(eth);
}
for(i=0; i < 25; i++) { printf("-"); }; printf("\n");
return;
}
/* returns 0 if everything went well */
int set_options(pcap_t * handle) {
int ret = 0;
ret = pcap_set_promisc(handle,1);
if(ret != 0) {
fprintf(stderr,"Error setting promiscuous mode\n");
return ret;
}
ret = pcap_set_snaplen(handle,SNAP_LEN);
if(ret != 0) {
fprintf(stderr,"Error setting snapshot length\n");
return ret;
}
ret = pcap_set_timeout(handle,1000);
if(ret != 0) {
fprintf(stderr,"Error setting timeout\n");
return ret;
}
return ret;
}
int activate(pcap_t * handle) {
int ret = pcap_activate(handle);
switch(ret) {
case 0:
fprintf(stdout,"Activation complete\n");
break;
case PCAP_WARNING_PROMISC_NOTSUP:
fprintf(stderr,"Promiscuous mode not supported\n");
return ret;
case PCAP_ERROR_PERM_DENIED:
fprintf(stderr,"Not have the permission required\n");
return ret;
case PCAP_ERROR_PROMISC_PERM_DENIED:
fprintf(stderr,"Not have the permission required for promiscuous\n");
return ret;
default:
fprintf(stderr,"Error occured during activation, see code\n");
return ret;
}
return ret;
}
/* Will activate device , filter & call the sniffing loop */
int sniffing_method(char * interface, char * filter,int packet_count) {
char err[PCAP_ERRBUF_SIZE]; //error buffer
pcap_t * handle; // handler of the interface by pcap
struct bpf_program bpf;
bpf_u_int32 mask; // network mask
bpf_u_int32 ip; // network ip
struct in_addr addr; // network number
int ret;
/* get mask & ip */
if(pcap_lookupnet(interface, &ip, &mask, err) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",interface,err);
exit(EXIT_FAILURE);
}
handle = pcap_create(interface,err);
if (handle == NULL) {
fprintf(stderr,"Error pcap_create() : %s \n",err);
exit(EXIT_FAILURE);
}
if(set_options(handle) != 0) {
fprintf(stderr,"Exiting\n");
exit(EXIT_FAILURE);
}
if (activate(handle) != 0) {
fprintf(stderr,"Exiting\n");
exit(EXIT_FAILURE);
}
/* FILTER PART */
if(filter != NULL) {
if(pcap_compile(handle,&bpf,filter,0,ip) == -1){
fprintf(stderr,"Couldn't compile filter expr %s : %s\n",filter,pcap_geterr(handle));
exit(EXIT_FAILURE);
}
if(pcap_setfilter(handle, &bpf) == -1) {
fprintf(stderr,"Couldn't install filter %s : %s\n",filter,pcap_geterr(handle));
exit(EXIT_FAILURE);
}
}
/* SNIFF starts */
printf("Sniffing starting on %s ...\n",interface);
pcap_loop(handle,packet_count,sniff_callback,NULL);
pcap_freecode(&bpf);
pcap_close(handle);
return EXIT_SUCCESS;
}
void usage() {
printf("sniff interface [filter] [count]");
printf("interface is the interface you want to listen on. It will try to put it in monitor mode");
printf("filter can be a filter for libpcap to apply for packets it reads");
}
int main(int argc, char * argv[])
{
int i = 0; // counter
int ret;
char * default_filter = "ip";
char * filter;
int pcount = -1; //take all packet by defaults
char * interface;
if(argc < 2) {
fprintf(stderr, "No interfaces specified in arguments\n");
usage();
exit(EXIT_FAILURE);
}
// take command line filter
if(argc > 2) {
filter = argv[2];
} else {
filter = default_filter;
}
// take command line packet count limit
if(argc > 3) {
pcount = atoi(argv[3]);
}
fprintf(stdout,"Args : ");
for(i = 0; i < argc; i++) {
fprintf(stdout,"\t%s",argv[i]);
}
printf("\n");
interface = argv[1];
sniffing_method(interface,filter,pcount);
}
Received packet number 2 ==> 42
Ethernet Layer
Source: 00:ee:bd:aa:f4:98:
Dest: FF:FF:FF:FF:FF:FF:
Type: ARP
ARP Layer
Hardware type: 00
Protocol type: 00
Hardware addresses length: 0
Protocol addresses length: 0
Operation code: 0
Hardware sender: 20e9a152:20e9a152:20e9a152:20e9a152:20e9a152:20e9a152:
Software sender: 20e9a158:20e9a158:20e9a158:20e9a158:
Error : ARP packet does not contain a Hardware type Ethernet -> 0
-------------------------
-------------------------
Received packet number 3 ==> 42
Ethernet Layer
Source: 00:ee:bd:aa:f4:98:
Dest: FF:FF:FF:FF:FF:FF:
Type: ARP
ARP Layer
Hardware type: 00
Protocol type: 00
Hardware addresses length: 0
Protocol addresses length: 0
Operation code: 0
Hardware sender: 20e5a152:20e5a152:20e5a152:20e5a152:20e5a152:20e5a152:
Software sender: 20e5a158:20e5a158:20e5a158:20e5a158:
void handleARP(const struct pkt_eth * eth) {
const struct pkt_arp * arp = (const struct pkt_arp *) (eth + ETH_SIZE);
const struct pkt_arp * arp = (const struct pkt_arp *) (eth + 1);