摸索着用java抓包

Wireshark』是一款优秀的开源的网络数据包分析软件,如果你用过你就一定会懂的。然而wireshark虽然对网络数据包拥有强大的分析能力,但是对于要实时对数据包进行分析处理就不那么容易了,于是乎为了完成项目要求,起早摸黑的开始了Google探索网络数据分析之路。

Google了许久发现怎么离不开都离不开『ibpcap』一个神奇的lib,让对C一直充满敬意而又一窍不通的我来说,有种很想去尝试的冲动。最后在网上拷了段代码跑了下,感觉还是蛮爽的因为我没有用tcpdump,作为C的入门之作,我决定还是把代码贴出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//netpkghdr.h
#ifndef _NET_PKG_HDR_H_
#define _NET_PKG_HDR_H_
#define ETHERTYPE_IP 0x0008 // IP协议 (0x0800的网络序)
#define TCP_PROTOCAL 0x0006 // TCP协议 (0x0600的网络序)
#define BUFF_MAX_LEN 0x10000 // 最大包长
#pragma pack(push, 1)
// ethernet header
typedef struct ether_header
{
unsigned char dst[6]; // 目标MAC
unsigned char src[6]; // 源MAC
unsigned short type; // 上层协议标识
} eth_hdr;
// ipv4 address
typedef struct ip_address
{
unsigned char b1, b2, b3, b4;
} ip_addr;
// ipv4 header
typedef struct ip_header
{
unsigned char ver_ihl; // 版本信息(4)头长度(4)
unsigned char tos; // 服务类型
unsigned short len; // 数据包长度
unsigned short id; // 数据包标识
unsigned short slice; // 片偏移
unsigned char ttl; // ttl
unsigned char proto; // 协议
unsigned short sum; // 校验和
ip_addr saddr; // 源IP
ip_addr daddr; // 目标IP
} ip_hdr;
// tcp header
typedef struct tcp_header
{
unsigned short sport; // 源端口
unsigned short dport; // 目标端口
unsigned int seq; // 序列号
unsigned int ack; // 应答
unsigned short len_code; // TCP头长度(4)保留(6)标志(6)
unsigned short window; // 窗口大小
unsigned short sum; // 校验和
unsigned short urp; // 紧急数据偏移
} tcp_hdr;
// udp header
typedef struct udp_header
{
unsigned short sport; // 源端口
unsigned short dport; // 目标端口
unsigned short len; // 包长
unsigned short sum; // 校验和
} udp_hdr;
#pragma pack(pop)
#endif /* _NET_PKG_HDR_H_ */

capture.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include "netpkghdr.h"
unsigned char g_buffer[BUFF_MAX_LEN] = {0};
pcap_t* get_pcap( const char* name )
{
pcap_if_t* ifs;
pcap_if_t* d;
pcap_t* pcap;
char errbuff[PCAP_ERRBUF_SIZE];
char *device = "eth0";
char errbuf[1024];
if ((device = pcap_lookupdev(errbuf)) == NULL)
{
perror(errbuf);
return NULL;
}
else
printf("device: %s\n", device);
pcap = pcap_open_live( device, \
BUFF_MAX_LEN, \
0, \
3000, \
errbuff );
pcap_freealldevs( ifs );
if ( pcap == NULL )
{
fprintf( stderr, "pcap_open_live [%s]\n", errbuff );
return NULL;
}
return pcap;
}
int main()
{
int rc;
pcap_t* pcap;
struct bpf_program bpf;
struct pcap_pkthdr* header;
const unsigned char* pkt_data;
eth_hdr* eth;
ip_hdr* ip;
unsigned short ip_hdr_len;
tcp_hdr* tcp;
unsigned short tcp_hdr_len;
unsigned short tcp_data_len;
unsigned char* tcp_pkt_data;
if ( ( pcap = get_pcap( "eth0" ) ) == NULL )
{
return -1;
}
printf( "**********************************************\n\n" );
if ( pcap_compile( pcap, &bpf, "tcp", 1, 0 ) < 0 )
{
fprintf( stderr, "pcap_compile error\n" );
return -1;
}
if ( pcap_setfilter( pcap, &bpf ) < 0 )
{
fprintf( stderr, "pcap_setfilter\n" );
return -1;
}
while ( ( rc = pcap_next_ex( pcap, &header, &pkt_data ) ) >= 0 )
{
if ( rc == 0 )
{
continue;
}
eth = ( eth_hdr* )pkt_data;
ip = ( ip_hdr* )( eth + 1 );
ip_hdr_len = ( ( ip->ver_ihl & 0x0F ) << 2 );
tcp = ( tcp_hdr* )( pkt_data + sizeof( eth_hdr ) + ip_hdr_len );
tcp_hdr_len = ( ( tcp->len_code & 0x00F0 ) >> 2 );
tcp_data_len = header->len - sizeof( eth_hdr ) - ip_hdr_len - tcp_hdr_len;
tcp_pkt_data = ( unsigned char* )tcp + tcp_hdr_len;
/* if ( tcp_data_len < 3 || \
( strncmp( ( char* )tcp_pkt_data, "GET", 3 ) && \
strncmp( ( char* )tcp_pkt_data, "POST", 4 ) && \
strncmp( ( char* )tcp_pkt_data, "HTTP/1.1", 8 ) ) )
{
continue;
}*/
memcpy( g_buffer, tcp_pkt_data, tcp_data_len );
g_buffer[tcp_data_len] = 0;
printf(" MAC : %02X-%02X-%02X-%02X-%02X-%02X", eth->src[0], eth->src[1], eth->src[2], eth->src[3], eth->src[4], eth->src[5]);
printf(" --> %02X-%02X-%02X-%02X-%02X-%02X\n", eth->dst[0], eth->dst[1], eth->dst[2], eth->dst[3], eth->dst[4], eth->dst[5]);
printf(" IP : %d.%d.%d.%d:%d", ip->saddr.b1, ip->saddr.b2, ip->saddr.b3, ip->saddr.b4, ntohs(tcp->sport));
printf(" --> %d.%d.%d.%d:%d\n", ip->daddr.b1, ip->daddr.b2, ip->daddr.b3, ip->daddr.b4, ntohs(tcp->dport));
printf(" 长度: %d\n\n Hex:\n", header->len);
//显示数据帧内容
int i;
for (i = 0; i < (int)header->len; ++i) {
printf(" %02x", pkt_data[i]);
if ( (i + 1) % 16 == 0 )
printf("\n");
}
printf( "\n\n" );
printf( "%s\n", ( char* )g_buffer );
printf( "**********************************************\n\n" );
}
pcap_close( pcap );
return 0;
}

作为一个菜鸟看到程序跑起来,小激动还是少不了的。
但是我的C实在是连门都没入啊,后面你让我这个Java菜鸟怎么办!哭完之后,还是Google翻,Github搜,继续我的探索之旅,Jpcap,JNetpcap先后出现,定眼一看,零好几年的,而且许久没有维护了,没有办法,想用但有点瘆,只好安慰自己不要放弃,一个一个试,后来发现『Jpcap: A Java wrapper around libpcap』这个相对简单,但是貌似好多包都抓不到,继续哭。

泪是流不完的,事总是要做的。

Github作为全球最大的同性交友网站有一种神奇魔力,因为他总会给你惊喜,『pcap4j』就是我的新发现,日本人的作品,日语0级英语1级的我,不断告诫自己,要想上就得推到。

伙伴们,别打扰我,我在积蓄力量,上完了再和大家分享……