分享
 
 
 

使用pcap编写自己的sniffer(2)

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

<续>

怎样使用(处理)packet指针变量呢?一个packet指针所指的结构包含了很多属性,它并不是一个真正的字符串,而是多个结构组成的集合(比如:一个TCP/IP数据包包括以太网头、IP包头、TCP头和数据包中有效的数据负载)。首先需要定义这些结构:

/* Ethernet header */

struct sniff_ethernet {

u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */

u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */

u_short ether_type; /* IP? ARP? RARP? etc */

};

/* IP header */

struct sniff_ip {

#if BYTE_ORDER == LITTLE_ENDIAN

u_int ip_hl:4, /* header length */

ip_v:4; /* version */

#if BYTE_ORDER == BIG_ENDIAN

u_int ip_v:4, /* version */

ip_hl:4; /* header length */

#endif

#endif /* not _IP_VHL */

u_char ip_tos; /* type of service */

u_short ip_len; /* total length */

u_short ip_id; /* identification */

u_short ip_off; /* fragment offset field */

#define IP_RF 0x8000 /* reserved fragment flag */

#define IP_DF 0x4000 /* dont fragment flag */

#define IP_MF 0x2000 /* more fragments flag */

#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */

u_char ip_ttl; /* time to live */

u_char ip_p; /* protocol */

u_short ip_sum; /* checksum */

struct in_addr ip_src,ip_dst; /* source and dest address */

};

/* TCP header */

struct sniff_tcp {

u_short th_sport; /* source port */

u_short th_dport; /* destination port */

tcp_seq th_seq; /* sequence number */

tcp_seq th_ack; /* acknowledgement number */

#if BYTE_ORDER == LITTLE_ENDIAN

u_int th_x2:4, /* (unused) */

th_off:4; /* data offset */

#endif

#if BYTE_ORDER == BIG_ENDIAN

u_int th_off:4, /* data offset */

th_x2:4; /* (unused) */

#endif

u_char th_flags;

#define TH_FIN 0x01

#define TH_SYN 0x02

#define TH_RST 0x04

#define TH_PUSH 0x08

#define TH_ACK 0x10

#define TH_URG 0x20

#define TH_ECE 0x40

#define TH_CWR 0x80

#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)

u_short th_win; /* window */

u_short th_sum; /* checksum */

u_short th_urp; /* urgent pointer */

};

注:这些结构定义在不同的系统实现中可能存在差异,请查阅相关文档。

另:搞不懂作者什么意思,为什么非要自己定义这些结构,干嘛不用系统自己定义的实现呢?

省略了原作者关于定义这些结构的描述…

假设我们通过以太网处理TCP/IP数据包(其他的物理网络类似),如下代码将packet指针所指的结构分解为不同的结构体:

const struct sniff_ethernet *ethernet; /* The ethernet header */

const struct sniff_ip *ip; /* The IP header */

const struct sniff_tcp *tcp; /* The TCP header */

const char *payload; /* Packet payload */

/* For readability, we'll make variables for the sizes of each of the structures */

int size_ethernet = sizeof(struct sniff_ethernet);

int size_ip = sizeof(struct sniff_ip);

int size_tcp = sizeof(struct sniff_tcp);

And now we do our magical typecasting:

ethernet = (struct sniff_ethernet*)(packet);

ip = (struct sniff_ip*)(packet + size_ethernet);

tcp = (struct sniff_tcp*)(packet + size_ethernet + size_ip);

payload = (u_char *)(packet + size_ethernet + size_ip + size_tcp);

如果packet值(该指针变量所指的地址)为X,则上面所述的结构在内存中的布局如下所示:

Variable

Location (in bytes)

sniff_ethernet

X

sniff_ip

X + 14

sniff_tcp

X + 14 + 20

payload

X + 14 + 20 + 20

Wrapping up

到此为止,我们已经可以用pcap编写一个sniffer应用程序了。我们已经了解了pcap编程的基础知识,包括打开一个pcap会话句柄,处理pcap会话句柄的属性,监听数据包,应用过滤规则,并使用回调函数定义我们自己的处理过程。随原文提供的示例程序:sniffer.c

This document is Copyright 2002 Tim Carstens. All rights reserved. Redistribution and use, with or without modification, are permitted provided that the following conditions are met: 1. Redistribution must retain the above copyright notice and this list of conditions. 2. The name of Tim Carstens may not be used to endorse or promote products derived from this document without specific prior written permission.

/* Insert 'wh00t' for the BSD license here */

附录:例用pcap编写的示例程序

/*

编译:gcc –Wall –o testpcap testpcap.c -lpcap

*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <pcap.h>

#include <sys/types.h>

#include <netinet/ip.h>

#include <netinet/ether.h>

#include <net/ethernet.h>

#include <netinet/udp.h>

#include <netinet/tcp.h>

#include <netinet/in.h>

#include <arpa/inet.h>

/* MACRO to print debug info */

//#define DEBUG 1

#ifdef DEBUG

#define debug(stderr, msg) fprintf(stderr, msg)

#define _ ,

#else /* if no define DEBUG */

#define debug(stderr, msg)

#endif /* end of BEBUG */

#define LOOKUPDEV_ERR -1

#define OPEN_LIVE_ERR -2

#define COMPILE_ERR -3

/* protocol ID's */

#define IPPRO 8 /* IP protocol */

/* call back function invoke by pcap_loop, major process for ourselves */

void

got_packet(u_char *args, const struct pcap_pkthdr *header,

const u_char *packet);

/* handle ethernet header */

u_int16_t

handle_ethernet(u_char *args,const struct pcap_pkthdr* pkthdr,

const u_char* packet);

/* handle IP header */

void

handle_IP(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet);

int

main(int argc, char *argv[])

{

char *dev = NULL; /* device to sniff on */

char errbuf[PCAP_ERRBUF_SIZE]; /* buffer to store error msg */

pcap_t *handle = NULL; /* pcap session handle */

struct bpf_program filter; //compiled filter expression

char filter_app[] = "port 23"; /* filter ruler for sniffing */

bpf_u_int32 mask; //netmask of our sniffing device

bpf_u_int32 net; //the ip of our sniffing device

int num = 0; /* number of packets captured */

/* variables for getopt */

long total = -1; /* total packets to sniff */

char *flter = filter_app; /* filter ruler for sniffing */

int c; /* temprory char variable */

while ((c = getopt(argc, argv, "n:f:")) != -1) {

switch(c) {

case 'n':

total = atoi(optarg);

break;

case 'f':

flter = optarg;

break;

case '?':

fprintf(stderr, "Usage: %s -n <num> -f <filter string>\n", argv[0]);

exit(1);

default:

fprintf(stdout, "Using fitler: port 23 and sniffing util interrupt by console!\n");

}

}

if (NULL == (dev = pcap_lookupdev(errbuf))) {

fprintf(stderr, "pcap_lookupdev() error: %s\n", errbuf);

exit(LOOKUPDEV_ERR);

}

fprintf(stdout, "Sniffing on device: %s\n\n", dev);

pcap_lookupnet(dev, &net, &mask, errbuf);

/* open a new pcap session */

if (NULL == (handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf))) {

fprintf(stderr, "pcap_open_live() error: %s\n", errbuf);

exit(OPEN_LIVE_ERR);

}

/* compile capture rule */

if (-1 == pcap_compile(handle, &filter, flter, 1, net)) {

fprintf(stderr, "pcap_compile() error!\n");

exit(COMPILE_ERR);

}

pcap_setfilter(handle, &filter);

/* using while + pcap_next instead of pcap_loop or pcap_dispatch */

/* while (1) {

debug(stderr, "in pcap_next while\n");

packet = pcap_next(handle, &header);

printf("Captured a packet with lengthen of [%d]\n", header.len);

debug(stderr, "The packet captured: %s\n" _ packet + header.caplen);

}

*/

num = pcap_loop(handle, total, got_packet, NULL);

if (-1 == num) {

pcap_perror(handle, "pcap_loop error: ");

}

if (-2 == num) {

pcap_perror(handle, "pcap_loop break by pcap_breakloop: ");

}

pcap_close(handle);

return 0;

}

void

got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)

{

u_int16_t type;

type = handle_ethernet(args, header, packet);

debug(stderr, "protocol type: %i\n" _ type);

switch(type) {

case IPPRO:

debug(stderr, "protocol type: IP\n");

handle_IP(args, header, packet);

break;

case ETHERTYPE_ARP:

/* handle arp protocol */

break;

case ETHERTYPE_REVARP:

/* handle rarp protocol */

break;

default:

fprintf(stdout, "Protocol is ignored\n");

}

fprintf(stdout,"\n");

return;

} //end of got_packet

u_int16_t

handle_ethernet(u_char *args,const struct pcap_pkthdr* pkthdr,

const u_char* packet)

{

struct ether_header *eptr; /* net/ethernet.h */

/* lets start with the ether header... */

eptr = (struct ether_header *) packet;

fprintf(stdout,"ETH: %s --> "

,ether_ntoa((struct ether_addr *)(eptr->ether_shost)));

fprintf(stdout,"%s "

,ether_ntoa((struct ether_addr *)(eptr->ether_dhost)));

/* check to see if we have an ip packet */

if (ntohs (eptr->ether_type) == ETHERTYPE_IP)

{

fprintf(stdout,"(IP)");

}else if (ntohs (eptr->ether_type) == ETHERTYPE_ARP)

{

fprintf(stdout,"(ARP)");

}else if (ntohs (eptr->ether_type) == ETHERTYPE_REVARP)

{

fprintf(stdout,"(RARP)");

}else {

fprintf(stdout,"(?)");

exit(1);

}

return eptr->ether_type;

} //end of handle_ethernet

void

handle_IP(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet)

{

const struct iphdr *ip = (const struct iphdr *)(packet + sizeof(struct ether_header));

u_int length = pkthdr->len;

u_int hlen,off,version;

int len;

struct in_addr in;

debug(stderr, "total pcap pkt length: %i\n" _ length);

debug(stderr, "total pcap pkt header length: %i\n" _ pkthdr->caplen);

/* jump pass the ethernet header */

length =- sizeof(struct ether_header);

/* check to see we have a packet of valid length */

if (length < sizeof(struct iphdr))

{

printf("truncated ip %d",length);

return;

}

len = ntohs(ip->tot_len);

debug(stderr, "total ip pkt length: %i\n" _ len);

hlen = ip->ihl; /* header length */

debug(stderr, "ip header length: %i\n" _ hlen);

version = ip->version;/* ip version */

debug(stderr, "ip version: %i\n" _ version);

/* check version */

if(version != 4)

{

fprintf(stdout,"Unknown version %d\n",version);

return ;

}

/* check header length */

if(hlen < 5 )

{

fprintf(stdout,"bad-hlen %d \n",hlen);

}

/* see if we have as much packet as we should */

if(length < len)

printf("\ntruncated IP - %d bytes missing\n",len - length);

/* Check to see if we have the first fragment */

off = ntohs(ip->frag_off);

if((off & 0x1fff) == 0 )/* aka no 1's in first 13 bits */

{/* print SOURCE DESTINATION hlen version len offset */

fprintf(stdout,"\nIP: ");

in.s_addr = ip->saddr;

fprintf(stdout,"%s ",inet_ntoa(in));

in.s_addr = ip->daddr;

fprintf(stdout,"%s %d %d %d %d\n",

inet_ntoa(in),

hlen,version,len,off);

}

return;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有