最近有几位网友谈到如何实现分析数据包,如何来捕捉数据等问题比较迷惑,我写了一个简单的程序帮助大家理解,这个程序并不能完全完成大家的问题,还需要阅读者自己根据自己的需要编写自己的代码。
本程序在Linux下编写的,主要实现捕捉数据包,分析eth头,arp,ip,udp,tcp头部分信息。
包括三个文件,Makefile,sniffer.c,sniffer.h
下面是程序的源代码
--------------------------------------------------------------------------------------------------------
Makefile
CC = gcc -Wall -O2
LIBS =
INCLUDE =
TARGET = sniffer
all:$(TARGET)
sniffer: sniffer.o
$(CC) -o sniffer sniffer.o $(LIBS)
.c.o:
$(CC) -c $(INCLUDE) $<
clean:
@rm *.o
@rm sniffer
---------------------------------------------------------------------------------------------------------
sniffer.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h> /* For ETH_P_ALL */
#include <net/if_arp.h>
#include "sniffer.h"
#define BUFSIZE 2048
static void hex_print(const u_char *buf, int len, int offset);
static int decode_eth(const u_char *buf);
static int decode_ip(const u_char *buf);
static int decode_arp(const u_char *buf);
static int decode_tcp(const u_char *buf);
static int decode_udp(const u_char *buf);
int main()
{
int listenfd;
int n;
char buf[BUFSIZE];
if ((listenfd = socket(PF_PACKET, SOCK_RAW,
htons(ETH_P_ALL))) < 0) {
perror("socket");
exit(1);
}
for (;;) {
if ((n = recv(listenfd, buf, BUFSIZE, 0)) > 0){
hex_print(buf, n, 0);
decode_eth(buf);
}
}
return 0;
}
static int decode_eth(const u_char *buf)
{
strUCt ethhdr *eth = (struct ethhdr *) buf;
printf("\nMAC header");
printf("\nDestination Address: %02X:%02X:%02X:%02X:%02X:%02X",
HWADDR(eth->h_dest));
printf("\nSource Address:%02X: %02X:%02X:%02X:%02X:%02X",
HWADDR(eth->h_source));
printf("\nType: %02X-%02X", PWord(eth->h_proto));
switch (ntohs(eth->h_proto)) {
case ETH_P_IP:
return decode_ip((u_char *)ð[1]);
case ETH_P_ARP:
return decode_arp((u_char *)ð[1]);
default:
return -1;
}
return 0;
}
static int decode_arp(const u_char *buf)
{
struct ether_arp *arph = (struct ether_arp *) buf;
printf("\nAddress Resolution Protocol");
printf("\nHardware Type: %d", ntohs(arph->arp_hrd));
printf("\nProtocol Type: %02X-%02X", PWORD(arph->arp_pro));
printf("\nLength of Hardware Address: %d", arph->arp_hln);
printf("\nLength of Protocol Address: %d", arph->arp_pln);
printf("\nOperation Code: %d", ntohs(arph->arp_op));
printf("\nSender`s Hardware Address: %02X:%02X:%02X:%02X:%02X:%02X",
HWADDR(arph->arp_sha));
printf("\nSender`s IP Address: %d.%d.%d.%d", NIPQUAD(arph->arp_spa));
printf("\nTarget`s Hardware Address: %02X:%02X:%02X:%02X:%02X:%02X",
HWADDR(arph->arp_tha));
printf("\nTarget`s IP Address: %d.%d.%d.%d", NIPQUAD(arph->arp_tpa));
return 0;
}
static int decode_ip(const u_char *buf)
{
struct iphdr *iph = (struct iphdr *) buf;
printf("\nIPv4 header");
printf("\nVersion: %d", iph->version);
printf("\nHeader length: %d (%d bytes)", iph->ihl, iph->ihl*4);
printf("\nType of service (TOS):0x%02X", iph->tos);
printf("\nTotal length: %d", ntohs(iph->tot_len));
printf("\nIdentification: %d", ntohs(iph->id));
printf("\nFlags: %02X %02X", PWORD(iph->frag_off));
printf("\nTime to Live (TTL): %d hops", iph->ttl);
printf("\nProtocol: %d", iph->protocol);
printf("\nChecksum: 0x%02X%02X", PWORD(iph->check));
printf("\nSource IP Address: %d.%d.%d.%d", NIPQUAD(iph->saddr));
printf("\nDestination IP Address: %d.%d.%d.%d", NIPQUAD(iph->daddr));
switch (iph->protocol) {
case IPPROTO_TCP:
return decode_tcp((u_char *)&iph[1]);
case IPPROTO_UDP:
return decode_udp((u_char *)&iph[1]);
default:
return -1;
}
return 0;
}
static int decode_tcp(const u_char *buf)
{
struct tcphdr *tcph = (struct tcphdr *) buf;
printf("\nTCP header");
printf("\nSource port: %d", ntohs(tcph->source));
printf("\nDestination port: %d", ntohs(tcph->dest));
printf("\nSequence number: %u", ntohl(tcph->seq));
printf("\nAcknowledegment number: %u", ntohl(tcph->ack_seq));
printf("\nHeader length: %d (%d bytes)", tcph->doff, tcph->doff*4);
printf("\nReserved: 0x%X", tcph->res1);
printf("\nFlags: r:%d,u:%d,a:%d,p:%d,r:%d,s:%d,f:%d",
tcph->res2, tcph->urg, tcph->ack, tcph->psh,
tcph->rst, tcph->syn, tcph->fin);
printf("\nWindow size: %d", ntohs(tcph->window));
printf("\nChecksum: 0x%02X%02X", PWORD(tcph->check));
printf("\nUrgent pointer: %d", ntohs(tcph->urg_ptr));
return 0;
}
static int decode_udp(const u_char *buf)
{
struct udphdr *udph = (struct udphdr *) buf;
printf("\nUDP header");
printf("\nSource Port: %d", ntohs(udph->source));
printf("\nDestination Port: %d", ntohs(udph->dest));
printf("\nLength: %d bytes", ntohs(udph->len));
printf("\nChecksum: 0x%X", udph->check);
return 0;
}
static void hex_print(const u_char *buf, int len, int offset)
{
u_int i, j, jm;
int c;
printf("\n");
for (i = 0; i < len; i += 0x10) {
printf(" %04x: ", (u_int)(i + offset));
jm = len - i;
jm = jm > 16 ? 16 : jm;
for (j = 0; j < jm; j++) {
if ((j % 2) == 1)
printf("%02x ", (u_int) buf[i+j]);
else printf("%02x", (u_int) buf[i+j]);
}
for (; j < 16; j++) {
if ((j % 2) == 1) printf(" ");
else printf(" ");
}
printf(" ");
for (j = 0; j < jm; j++) {
c = buf[i+j];
c = isprint(c) ? c : '.';
printf("%c", c);
}
printf("\n");
}
}
---------------------------------------------------------------------------------------------------
sniffer.h
#ifndef _SNIFFER_H
#define _SNIFFER_H
/*
* Display an MAC address in readable format.
*/
#define HWADDR(addr) ((unsigned char *)&addr)[0], ((unsigned char *)&addr)[1], ((unsigned char *)&addr)[2], ((unsigned char *)&addr)[3], ((unsigned char *)&addr)[4], ((unsigned char *)&addr)[5]
/*
* Display an IP address in readable format.
*/
#define NIPQUAD(addr) ((unsigned char *)&addr)[0], ((unsigned char *)&addr)[1], ((unsigned char *)&addr)[2], ((unsigned char *)&addr)[3]
#define HIPQUAD(addr) ((unsigned char *)&addr)[3], ((unsigned char *)&addr)[2], ((unsigned char *)&addr)[1], ((unsigned char *)&addr)[0]
#define PWORD(addr) ((unsigned char *)&addr)[0], ((unsigned char *)&addr)[1]
#endif
TCP数据包分析结果
0000: 00d0 b7b6 4b81 000e a6ab ba6a 0800 4500 ....K......j..E.
0010: 0028 602e 4000 4006 c474 0a01 0113 0a01 .(`.@.@..t......
0020: 0119 24fb 0017 bdf7 c047 8b42 c68a 5010 ..$......G.B..P.
0030: 3dd3 66b5 0000 0000 0000 0000 =.f.........
MAC header
Destination Address: 00:D0:B7:B6:4B:81
Source Address:00: 0E:A6:AB:BA:6A
Type: 08-00
IPv4 header
Version: 4
Header length: 5 (20 bytes)
Type of service (TOS):0x00
Total length: 40
Identification: 24622
Flags: 40 00
Time to Live (TTL): 64 hops
Protocol: 6
Checksum: 0xC474
Source IP Address: 10.1.1.19
Destination IP Address: 10.1.1.25
TCP header
Source port: 9467
Destination port: 23
Sequence number: 3187130439
Acknowledegment number: 2336409226
Header length: 5 (20 bytes)
Reserved: 0x0
Flags: r:0,u:0,a:1,p:0,r:0,s:0,f:0
Window size: 15827
Checksum: 0x66B5
Urgent pointer: 0
ARP数据包分析结果:
0000: ffff ffff ffff 0001 0292 0c96 0806 0001 ................
0010: 0800 0604 0001 0001 0292 0c96 0a01 01f3 ................
0020: 0000 0000 0000 0a01 0153 0000 0000 0000 .........S......
0030: 0000 0000 0000 0000 0000 0000 ............
MAC header
Destination Address: FF:FF:FF:FF:FF:FF
Source Address:00: 01:02:92:0C:96
Type: 08-06
Address Resolution Protocol
Hardware Type: 1
Protocol Type: 08-00
Length of Hardware Address: 6
Length of Protocol Address: 4
Operation Code: 1
Sender`s Hardware Address: 00:01:02:92:0C:96
Sender`s IP Address: 10.1.1.243
Target`s Hardware Address: 00:00:00:00:00:00
Target`s IP Address: 10.1.1.83