|
Packit |
03b34a |
===============================================================================
|
|
Packit |
03b34a |
$Id: PACKET_BUILDING,v 1.3 2004/04/13 17:32:28 mike Exp $
|
|
Packit |
03b34a |
LIBNET 1.1 (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
|
|
Packit |
03b34a |
http://www.packetfactory.net/libnet
|
|
Packit |
03b34a |
===============================================================================
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
ADDING A NEW PACKET BUILDER, STATIC HEADER SIZE
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
Adding a new packet building module to libnet is usually pretty simple. The
|
|
Packit |
03b34a |
following short document details how to add a packet builder to libnet for a
|
|
Packit |
03b34a |
protocol that has a static header size. We'll use the Sebek protocol as an
|
|
Packit |
03b34a |
example to walk through the process.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
1) Make sure you have a good reference for the protocol in question. Be it an
|
|
Packit |
03b34a |
RFC or an official release doc from the author or vendor, you'll need
|
|
Packit |
03b34a |
something comprehensive. For Sebek, the comprehensive reference is here:
|
|
Packit |
03b34a |
http://project.honeynet.org.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
2) Figure out how big the header is and add it to the top of libnet-headers.h:
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
#define LIBNET_SEBEK_H 0x30 /* sebek header: 48 bytes */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
3) Create the protocol header structure and add it to the end of
|
|
Packit |
03b34a |
libnet-headers.h. Take care to use POSIX datatypes to define all of your
|
|
Packit |
03b34a |
values. Structure naming conventions are more or less up to you. Since
|
|
Packit |
03b34a |
they're never exported to the user, it's not a big deal, but try to keep
|
|
Packit |
03b34a |
them short and descriptive. Convention is to add the symbolic constant
|
|
Packit |
03b34a |
#defines above the structure members they apply to.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Sebek header
|
|
Packit |
03b34a |
* Static header size: 48 bytes
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
struct libnet_sebek_hdr
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
u_int32_t magic; /* identify packets that should be hidden */
|
|
Packit |
03b34a |
u_int16_t version; /* protocol version, currently 1 */
|
|
Packit |
03b34a |
#define SEBEK_PROTO_VERSION 1
|
|
Packit |
03b34a |
u_int16_t type; /* type of record */
|
|
Packit |
03b34a |
#define SEBEK_TYPE_READ 0 /* currently, only read is supported */
|
|
Packit |
03b34a |
#define SEBEK_TYPE_WRITE 1
|
|
Packit |
03b34a |
u_int32_t counter; /* PDU counter */
|
|
Packit |
03b34a |
u_int32_t time_sec; /* EPOCH timer */
|
|
Packit |
03b34a |
u_int32_t time_usec; /* residual microseconds */
|
|
Packit |
03b34a |
u_int32_t pid; /* PID */
|
|
Packit |
03b34a |
u_int32_t uid; /* UID */
|
|
Packit |
03b34a |
u_int32_t fd; /* FD */
|
|
Packit |
03b34a |
#define SEBEK_CMD_LENGTH 12
|
|
Packit |
03b34a |
u_int8_t cmd[SEBEK_CMD_LENGTH]; /* 12 first characters of the command */
|
|
Packit |
03b34a |
u_int32_t length; /* PDU length */
|
|
Packit |
03b34a |
};
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
3) Append a pblock identifier to the end of the list in libnet-structures.h.
|
|
Packit |
03b34a |
The ID number is not imporant as long as it is UNIQUE. As such, just find
|
|
Packit |
03b34a |
the last entry, append the new entry after it, and increase the pblock ID
|
|
Packit |
03b34a |
by one:
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
#define LIBNET_PBLOCK_SEBEK_H 0x3f /* Sebek header */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
4) Create your new builder file in src/. Adhere to the "libnet_build_PROTOCOL.c"
|
|
Packit |
03b34a |
convention. I recommend copying one of the existing builder modules and
|
|
Packit |
03b34a |
modifying it as you go.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
4a)
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
#if (HAVE_CONFIG_H)
|
|
Packit |
03b34a |
#include "../include/config.h"
|
|
Packit |
03b34a |
#endif
|
|
Packit |
03b34a |
#if (!(_WIN32) || (__CYGWIN__))
|
|
Packit |
03b34a |
#include "../include/libnet.h"
|
|
Packit |
03b34a |
#else
|
|
Packit |
03b34a |
#include "../include/win32/libnet.h"
|
|
Packit |
03b34a |
#endif
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_sebek(u_int32_t magic, u_int16_t version, u_int16_t type,
|
|
Packit |
03b34a |
u_int32_t counter, u_int32_t time_sec, u_int32_t time_usec, u_int32_t pid,
|
|
Packit |
03b34a |
u_int32_t uid, u_int32_t fd, u_int8_t cmd[SEBEK_CMD_LENGTH], u_int32_t length,
|
|
Packit |
03b34a |
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_XXX(u_char arg1, u_short arg2, u_long arg3, u_char *payload,
|
|
Packit |
03b34a |
u_long payload_s, libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* n is the size of the protocol unit. This is usually the header size
|
|
Packit |
03b34a |
* plus the payload size. This is also how many bytes are allocated on
|
|
Packit |
03b34a |
* the heap to hold this protocol unit.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
u_long n;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* h is used inside the pblock structure to let libnet know how big
|
|
Packit |
03b34a |
* much data to checksum. This is different for different protocols.
|
|
Packit |
03b34a |
* The IPv4 checksum covers the IP header only, while TCP and UDP
|
|
Packit |
03b34a |
* checksums cover header and data.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
u_short h;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* p will be used to refer to the protocol block that will either be
|
|
Packit |
03b34a |
* allocated if the function's pt argument is 0, or located if ptag refers
|
|
Packit |
03b34a |
* to a previously created protocol unit.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* XXX_hdr is the header structure that will be overlaid onto the
|
|
Packit |
03b34a |
* allocated memory by way of a memcpy.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
struct libnet_XXX_hdr XXX_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Here we sanity check to make sure we have a live l.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = LIBNET_XXX_H + payload_s;
|
|
Packit |
03b34a |
h = 0; /* no checksum by default */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, pt, n, LIBNET_PBLOCK_XXX_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Build your packet here. Be sure to call appropriate endian conversion
|
|
Packit |
03b34a |
* routines.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
XXX_hdr.field1 = arg1;
|
|
Packit |
03b34a |
XXX_hdr.field2 = htons(arg2);
|
|
Packit |
03b34a |
XXX_hdr.field3 = htonl(arg3);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Appened the protocol unit to the list.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (u_char *)&XXX_hdr, LIBNET_XXX_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Sanity check the payload arguments.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
if ((payload && !payload_s) || (!payload && payload_s))
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
sprintf(l->err_buf, "%s(): payload inconsistency\n", __FUNCTION__);
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Append the payload to the list if it exists.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
if (payload && payload_s)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, payload, payload_s);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* If this packet header has a checksum field, you'll add this
|
|
Packit |
03b34a |
* and you'll have to edit libnet_checksum.c to add it to the switch
|
|
Packit |
03b34a |
* table. You might have to define the protocol number too.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
if (sum == 0 && l->injection_type != LIBNET_RAW4)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* If checksum is zero, by default libnet will compute a checksum
|
|
Packit |
03b34a |
* for the user. The programmer can override this by calling
|
|
Packit |
03b34a |
* libnet_toggle_checksum(l, ptag, 1);
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Update the protocol block's meta information and return the protocol
|
|
Packit |
03b34a |
* tag id of this pblock. This tag will be used to locate the pblock
|
|
Packit |
03b34a |
* in order to modify the protocol header in subsequent calls.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
return (pt ? pt : libnet_pblock_update(l, p, h, LIBNET_PBLOCK_XXX_H));
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
4) Add it to src/Makefile.am and then automake from the TLD.
|
|
Packit |
03b34a |
5) Test the shit out of it.
|
|
Packit |
03b34a |
6) Send it over to mike@infonexus.com.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
EOF
|