gpt4 book ai didi

C/PCAP : ARP packet values all 0

转载 作者:太空宇宙 更新时间:2023-11-04 03:43:05 25 4
gpt4 key购买 nike

我正在尝试通过使用 Pcap 库实现 ARP 欺骗工具来提高我的 C/网络知识。

我被嗅探 arp 数据包困住了。我可以在以太网帧的以太网类型字段中检测到 ARP 类型。但是当我“读取”ARP 数据包时,所有值都是 0(空)但是硬件地址(MAC)和协议(protocol)地址(ip)是非常奇怪的 8 字节重复数字(比如 20e54ef12:20e54ef12:20e54ef12...)。我只是想不通。这是我到目前为止所做的:

packet_struct.h(用于 eth、arp、ip...的不同结构)

#ifndef DEF_PACKET_STRUCT
#define DEF_PACKET_STRUCT
#include <sys/types.h>
#define BUFF_SIZE 1518
#define ETH_SIZE 14
#define ARP_SIZE 28
/* in bytes */
#define ETH_ADDR_SIZE 6
#define IP_ADDR_SIZE 4

typedef struct pkt_eth {
unsigned char dest[ETH_ADDR_SIZE];
unsigned char src[ETH_ADDR_SIZE];
unsigned short type;
} pkt_eth;

#define ETHERTYPE_ARP 0x0806
#define ARP_REQUEST 1
#define ARP_REPLY 2
typedef struct pkt_arp {
unsigned short htype;/* hardware type => ethernet , etc */
unsigned short ptype; /*protocol type => ipv4 or ipv6 */
unsigned char hard_addr_len; /* usually 6 bytes for ethernet */
unsigned char proto_addr_len; /*usually 8 bytes for ipv4 */
unsigned short opcode; /* type of arp */
unsigned char hard_addr_send[ETH_ADDR_SIZE];
unsigned char proto_addr_send[IP_ADDR_SIZE];
unsigned char hard_addr_dest[ETH_ADDR_SIZE];
unsigned char proto_addr_dest[IP_ADDR_SIZE];
} pkt_arp;

#define ETHERTYPE_IP 0x0800
typedef struct pkt_ip {
unsigned char vhl;
unsigned char tos;
unsigned short len;
unsigned short id;
unsigned short off;
unsigned char ttl;
unsigned char proto;
unsigned short crc;
unsigned int addr_src;
unsigned int addr_dest;
} pkt_ip;

#endif

packet_print.c(打印数据包信息的实用程序)

    #include "packet_struct.h"
#include <stdio.h>
#include <stdlib.h>

char * to_addr(unsigned char * addr, int length) {
int i = 0;
char string[length];
for(i=0; i< length; i++)
sprintf(string,"%02x:",addr[i]);
return string;
}
void print_pkt_eth(pkt_eth * eth) {
int i = 0;

fprintf(stdout,"Ethernet Layer \n");
fprintf(stdout,"\tSource:\t");
for(i=0;i<ETH_ADDR_SIZE;i++)
fprintf(stdout,"%02x:",eth->src[i]);
//fprintf(stdout,"%s",to_addr(eth->src,ETH_ADDR_SIZE));
fprintf(stdout,"\n\tDest:\t");
for(i=0;i<ETH_ADDR_SIZE;i++)
fprintf(stdout,"%02X:",eth->dest[i]);

if(ntohs(eth->type) == ETHERTYPE_IP)
fprintf(stdout,"\n\tType:\t IPv4");
else if(ntohs(eth->type) == ETHERTYPE_ARP)
fprintf(stdout,"\n\tType:\t ARP");
printf("\n");
}

void print_pkt_arp(pkt_arp * arp) {
int op = 0;
int i = 0;
printf("ARP Layer \n");
printf("\tHardware type:\t%02d\n",arp->htype);
printf("\tProtocol type:\t%02d\n",arp->ptype);
printf("\tHardware addresses length:\t%01d\n",arp->hard_addr_len);
printf("\tProtocol addresses length:\t%01d\n",arp->proto_addr_len);
op = ntohs(arp->opcode);
printf("\tOperation code:\t%01u\n",op);
printf("\tHardware sender:\t");
for(i=0;i<ETH_ADDR_SIZE;i++)
printf("%02x:",arp->hard_addr_send);
printf("\n\tSoftware sender:\t");
for(i=0;i<IP_ADDR_SIZE;i++)
printf("%02x:",arp->proto_addr_send);
printf("\n");

}

void print_pkt_ip(pkt_ip * ip) {
}

sniffer.c(工具本身)

#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);

这里您传递了一个 struct pkt_eth*,您向其添加了 ETH_SIZE。指针算法前进到下一个元素,而不是下一个字节。您实际上是在寻找传入指针之后的 sizeof(struct pkt_eth) * ETH_SIZE 个字节。

你应该这样做

 const struct pkt_arp * arp = (const struct pkt_arp *) (eth + 1);

(或者传入一个已经从您要解码的层开始的 unsigned char *。)

关于C/PCAP : ARP packet values all 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26962370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com