libnet Introduction and Analysis
Currently, socket-based network programming has become an irreplaceable programming method, which treats network communication as a file descriptor and abstracts the operation of this "network file" (that is, socket socket) into a file-like operation. From the implementation details, this way of working is based on the TCP/IP network communication model, encapsulating a series of implementations, so that we only need to use a specified parameter, we can implement the data based on the required protocol to send and receive.
However, if we are interested in the work that the system automatically gives us, and want to make "face to head" contact with the data sent,libnet will be a good choice.
Libnet is an important library for the development of network security tools on the same platform in Unix systems, which, together with Libpcap andLibnids, provides the developers of network security tools with a rich and complete set of weapons, making it easy to write strong and robust structures. , portability and high-character procedures.
Libnet provides a series of interface functions to implement and encapsulate the construction and delivery of packets. It can be used to construct the header of each layer protocol from the application layer to the link layer, and send the packets together in an orderly manner with valid data. Of course, it is also based on the TCP/IP protocol family model.
The current version of Libnet is 1.1.2, which has a relatively large change relative to the 1.0.* version.
All source code consists of 18,000 lines of code,109 export functions, including 67 package functions. This allows it to support all protocols of the existing TCP/IP family. In addition, it supports multi-platform,Windows,os x,bsd,linux, Solaris,hpux can be used.
is the protocol it supports:
The Libnet library can be divided into 4 functional parts: memory management, address resolution, packet processing, and other support functions.
★ Memory Management functions
Single packet Memory initialization and environment setup:
libnet_t *libnet_init (int injection_type, char *device, char *err_buf);
Resource release:
void Libnet_destroy (libnet_t *l);
★ Address Resolution function
Address Resolution:
Char *libnet_addr2name4 (u_int32_t in, u_int8_t use_name);
LIBNET_NAME2ADDR4 (libnet_t *l, Char *host_name, u_int8_t use_name);
struct LIBNET_IN6_ADDR libnet_name2addr6 (libnet_t *l, Char *host_name, u_int8_t use_name);
void Libnet_addr2name6_r (struct libnet_in6_addr addr, u_int8_t use_name,
char *host_name, int host_name_len);
Get the interface Device IP address:
u_int32_t LIBNET_GET_IPADDR4 (libnet_t *l);
struct LIBNET_IN6_ADDR libnet_get_ipaddr6 (libnet_t *l);
Get the interface Device hardware address:
struct LIBNET_ETHER_ADDR *libnet_get_hwaddr (libnet_t *l);
★ Packet Constructor
(This part of the function is more, all appear in the form of libnet_build_* (), this is skipped)
★ Packet Sending function
int Libnet_write (libnet_t *l);
★ Related support functions
Random number Seed Generator:
int Libnet_seed_prand (libnet_t *l);
Get random Number:
u_int32_t libnet_get_prand (int mod);
Port list Chain initialization:
int Libnet_plist_chain_new (libnet_t *l, libnet_plist_t **plist, Char *token_list);
Gets the next item (port range ) of the port list chain:
int Libnet_plist_chain_next_pair (libnet_plist_t *plist, u_int16_t *bport,
u_int16_t *eport);
The port list chain output shows:
int Libnet_plist_chain_dump (libnet_plist_t *plist);
Get the port list chain:
Char *libnet_plist_chain_dump_string (libnet_plist_t *plist);
Port list chain Memory release:
int Libnet_plist_chain_free (libnet_plist_t *plist);
It's also very easy to use, as long as you know what you're going to do and where you should put the parameters. the basic steps for developing an application using the Libnet library are simple:
1, the memory initialization of the packet;
2, the construction of data packets;
3, send data;
4. Release of resources;
Example: Libnet's release package provides a number of sample programs, where /libnet/sample/tcp1.c if you omit some parameter settings and error handling, the program is simplified to:
#if (H***e_config_h)
#i nclude ". /include/config.h "
#endif
#i nclude "Libnet_test.h"
#ifdef __win32__
#i nclude ". /include/win32/getopt.h "
#endif
Int
Main (int argc, char *argv[])
{
.......
L = Libnet_init (
Libnet_link,/* Injection type */
NULL,/* Network interface */
ERRBUF); /* ERROR Buffer */
......
t = libnet_build_tcp_options (
"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000",
20,
L
0);
......
t = libnet_build_tcp (SRC_PRT, Dst_prt, 0x01010101, 0x02020202, Th_syn, 32767, 0, 10,
Libnet_tcp_h + + payload_s, payload, payload_s, L, 0);
t = Libnet_build_ipv4 (libnet_ipv4_h + libnet_tcp_h + payload_s, 0, 242, 0, 64,
IPPROTO_TCP, 0, Src_ip, dst_ip, NULL, 0, L, 0);
t = libnet_build_ethernet (ENET_DST, ENET_SRC, Ethertype_ip, NULL, 0, L, 0);
c = Libnet_write (L);
Libnet_destroy (l);
return (exit_success);
Bad
Libnet_destroy (l);
return (exit_failure);
}
#if defined (__win32__)
#i nclude < ... /include/win32/getopt.h>
#i nclude <winsock2.h>
#i nclude <ws2tcpip.h>
#endif/* __win32__ */
/* EOF */
Analysis of the source code of Libnet
★ Overall Design Ideas
For each packet to be sent,Libnet maintains a libnet_t structure, which is the key to understanding the entire libnet and the key to Libnet's ability to achieve its power. Let us start with it, from the whole to the details to uncover the veil of libnet. The figure below is an example of the structure of libnet_t.
One of theFD is the data packet that will be used to sendSocket socket,Injection_type will be set tolibnet_init (), that is, the way you choose to send, is a link-layer packet based on the link_layer? Or is it based on ip layer raw packets? The latter case is divided into ip4 and ip6 two kinds. protocol_blocks and protocol_end are pointers, pointing to a libnet custom libnet_pblock_t structure, thus managing a libnet_pblock_t linked list. and libnet_pblock_t to express the various protocols, to maintain the various protocols to the data packets sent to the data block, its specific options are described below. link_type represents the type of the link layer, link_offset points to the link layer, which is the offset address of the lowest protocol header. aligner is set to maintain the word alignment of the last packet, the string pointer device points to the device used for the communication, such as ptag_state, records some of the information about the package during its establishment process. label is a character array. Whenever an error occurs, the errbuf array is used to log the error message. The entire packet length is stored in the total_size.
From the libnet_t has probably been able to see libnet design ideas: The programmer determines some parameters, and through the function call parameters to the relevant data to the Libnet.libnet creates a libnet_pblock_t structure for the programmer to save the data for each request to purchase a protocol header, and the structure into the linked list. When all the preparation work is done, the programmer commanded, libnet the protocolblock chain ( starting with protocol_blocks, finally Pblock_end) in the packet header and the data into a compliant package, sent through the hardware. If any of the steps go awry, the programmer can get error messages from the ERRBUF. Finally,Libnet took an instruction from the programmer to do all the work.
The header of each protocol will be implemented as a libnet_pblock_t structure in the early stages . libnet defines the corresponding data structures for the protocols it supports, such as the TCP header definition:
struct LIBNET_TCP_HDR
{
u_int16_t Th_sport; /* Source Port */
u_int16_t Th_dport; /* Destination Port * *
u_int32_t Th_seq; /* Sequence Number */
u_int32_t Th_ack; /* Acknowledgement number */
#if (Libnet_lil_endian)
u_int8_t Th_x2:4,/* (unused) */
Th_off:4; /* Data offset */
#endif
#if (Libnet_big_endian)
u_int8_t Th_off:4,/* Data offset */
Th_x2:4; /* (Unused) */
#endif
u_int8_t Th_flags; /* Control flags */
.......
u_int16_t Th_win; /* Window */
u_int16_t th_sum; /* CHECKSUM */
u_int16_t th_urp; /* Urgent pointer */
};
The length of it is:
#define LIBNET_TCP_H 0x14/**< TCP header:20 bytes */
When the programmer calls libnet_built_tcp () to build a TCP header,Libnet allocates a structure and fills in the fields of the structure as the programmer wishes. and generates a libnet_pblock_t structure, which points its buf pointer to the header structure and saves the length of the header (20 bytes) with B_len. Other related fields of this libnet_pblock_t will be populated by rules. The libnet_pblock_t will then be added to the appropriate location of the Protocol block chain maintained by the libnet_t structure. The so-called "niche" will be explained later. is a possible scenario in the process:
The realization of libnet is not difficult for the benefit of this ingenious overall structure,and our understanding of it also benefits. What's left is just a few details that need to be grasped, which is obviously more appropriate to read the code yourself.
The following is the approximate processing flow.
Before you begin, you need to insert a note:Libnet uses conditional compilation to eliminate differences between platforms, resulting in a number of functions with the same name (which are, of course, internally called), such as Libnet_open_link (five). Which call the program chooses at run time depends on the platform you are using or the precompiled option you impose on the compiler.
In general, things start from libnet_init (). Libnet_init () first turns on the network function of the system: under Linux, it verifies that it has superuser privileges (which means that low-privileged users cannot use success), and if it is under windows, it calls the famous The WSAStartup () function. A memory area is then allocated to establish the libnet_t structure. After the simple initialization, according to the programmer incoming send type parameter, the corresponding operation: if is based on the link layer sends the method (libnet_link,libnet_link_adv), will request the device to the operating system, and turns on the underlying Socket service. If it is based on the way the IP layer is sent, the socket service for that layer is turned on .
After preparing for the work, transfer to the direct construction of the package work , the actual performance of the work is to build a series of protocol Baotou. Programmers need to build the protocol header in top-down order, and the body data to be sent is often loaded as the "Payload (payload)" of the first packet header. In addition, some protocols may have optional data items, this part is Libnet Independent, is responsible for a separate libnet_pblock_t,libnet also provide the corresponding function function, the name is designated as libnet_ Build_*_options (). In this case,libnet automatically adjusts the position of these protocol blocks in the linked list so that the payload data block is in front, the options block in the middle, followed by the fixed header of the layer protocol.
At the right time,Libnet will perform the tedious work of calculating checksums gracefully, and you won't even feel like it's done for you.
Thus, as long as the programmer's use is correct, the data and the packet header are listed sequentially in the list, which is very useful for simplifying the work behind it. In the libnet_write () process, the data in the linked list is copied sequentially into a large buffer. Although the copy is in the order from the high-level protocol to the lower protocol, it is copied from the back of the buffer, and from here we can see the idea of the "protocol stack" flashing.
When everything is done, the programmer simply calls the Libnet_destroy () function, shuts down the network communication device used, and frees up the memory consumed. The programmer's job is so simple: he even just needs to pass a parameter to this short function.
In addition to doing some of the most direct work,Libnet offers a rich set of useful features. It provides an address resolution feature that enables the conversion of IP addresses between network byte order, domain name, and point form, and it also provides a complete set of random number generation schemes for you to use, and so on. These features make it possible to leap from a simple library to a complete system.
(the image used in the text originated from Mike Schiffman 's PPT on RSA conference in 2004)