题目: 网络嗅探器的设计与实现: 基本要求捕获本网段的数据包,将报文结构显示出来.进一步要求进行数据包协议分析,可以按报头进行统计,提取部分关键信息,如捕获登陆信息,破解登陆密码等。
本程序实现功能:
1.能对局域网内广播数据包和自己的数据包进行捕获;
2.能将报文从DLC到TCP(UDP)分层显示出来;
3.支持一个关键字的,从数据包中相关信息捕获;
程序运行结果如下(命令行的):
Net: 192.168.1.0
Mask: 255.255.255.0
/*--------------------input values--------------------*/
Please set the follow values
key: (the key word you want to get)
num : (how many packets you want to grab,
filter: (the packet filter,such as ip)
such as -1,which means infinite.
-------------------------------------------------------
Find keyword: name
num of packets: 10
Filter: tcp and port 80
Packet number: 1
--DLC:
Ether_shost = 0:4:61:7a:c6:eb
Ether_dhost = 0:8:5c:e:96:d2
Ether_type = IP
----IP:
Version = 4, header length = 20 bytes
Type of service = 0
Total length = 60
Identification = 55082
Flags = 16384
Time to live = 16384
Protocol = TCP
Checksum = 27740
From = 192.168.1.11
To = 72.14.253.99
----TCP:
Src port = 52328
Dst port = 80
Sequence number = 65068
Acknowledgement = 0
Data offset = 160
Flags = 2
.......0 = FIN
......1. = SYN
.....0.. = RST
....0... = PUSH
...0.... = ACK
..0..... = URG
.0...... = ECE
0....... = CWR
Windows num = 5840
Checksum = 17890
Urgent pointer = 0
Payload length: 40 bytes:
00000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
00016 00 00 00 00 0a 00 00 00 00 00 00 00 ff ff ff ff ................
00032 ff ff ff ff ff ff ff ff ........
程序:
libpcap是c语言写的,但由于个人比较了c++的面向对象思维。对在main()函数里弄一大堆函数,这个函数调用那个,那个调用这个,感到很反感。最后实在弄不下去了,除了将各个协议头重新写成类的形式(在protocol.h中),并添加display()方法来显示之外,重新把整个嗅探器实现封装成了一个Sniffer类:
//部分函数直接copy www.tcpdum.org的示例。
#ifndef SNIFFER_H
#define SNIFFER_H
extern " C " ... {
#include <pcap.h>
}
#include < iostream >
#include < cstdlib >
#include < string >
#include < vector >
#define EXP_LEN 20
class Sniffer
... {
private:
char* dev;
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 net;
bpf_u_int32 mask;
pcap_t* handle;
struct bpf_program fp;
void display_net();
static void display_ether(const u_char*);
static void display_arp(const u_char*);
static void display_ip(const u_char*);
static void display_tcp(const u_char*,int offset);
static void display_udp(const u_char*,int offset);
static void display_payload(const u_char*,int);
static void print_hex_ascii_line(const u_char*,int,int);
void get_input();
std::vector<std::string> slip_str(std::string);
public:
static std::string str_key;
int num_packets;
std::string filter_exp;
public:
Sniffer();
void init();
void run();
void err(const char* msg)
...{
std::cerr<<msg<<std::endl;
exit(1);
}
static void getpacket(u_char* args,
const struct pcap_pkthdr* header,
const u_char* packet);
} ;
#endif // sinffer.h
4 .嗅探器实现,sniffer.cpp
#include " sniffer.h "
#include " protocol.h "
#include < sys / socket.h >
#include < arpa / inet.h > // for inet_ntoa(),inet_aton()
#include < netinet / in .h > // for htons()
#include < netinet / if_ether.h >
#include < netinet / ether.h > // for ether_header
#include < cstdio >
#include < cstring >
#include < fstream >
using namespace std;
const int SIZE_ETHER = 14 ;
const int CW = 25 ;
const int SNAP_LEN = 1518 ;
ofstream out( " find.txt " );
// vector<string> keywords;
string Sniffer::str_key = " name " ;
Sniffer::Sniffer():net( 0 ),mask( 0 )
... {
filter_exp="ip";
num_packets=-1;
}
void Sniffer::display_net()
... {
struct in_addr a1;
// struct in_addr a2;
a1.s_addr=net;
//a2.s_addr=mask;
cout<<" Net device: "<<dev<<endl
<<" Net: "<<inet_ntoa(a1)<<endl;
a1.s_addr