📄 lib0022.html
字号:
<p class="para">An LKM is really just an ELF object file that is dynamically linked with the kernel. You can create an LKM simply by compiling with the <span class="fixed">-c</span> option that prevents the linker from being invoked. For example, if you have an LKM source file named <span class="fixed">1 km. c</span>, you can compile it into an object file with:</p>
<div class="informalexample">
<pre class="literallayout">
[root@localhost root]# gcc -c -Wall lkm.c
</pre>
</div>
<table border="0" cellspacing="0" cellpadding="0" class="note">
<tr>
<td valign="top" class="admon-check"></td><td valign="top" class="admon-title">Note </td><td valign="top" class="admon-body">
<p class="first-para">The Executable and Linkable Format (ELF) was originally designed by the UNIX System Laboratories (USL) before it was bought by Novell. The ELF specification was a part of the Application Binary Interface (ABI) effort. ELF is a binary format like COFF or Microsoft's PE format. In 1995, the Tool Interface Standard (TIS) group came out with version 1.2 of the ELF specification.</p>
</td>
</tr>
</table>
<p class="para">LKMs can be loaded/inserted into the kernel at run time with the following command:</p>
<div class="informalexample">
<pre class="literallayout">
[root@localhost root]# insmod lkm.o<a name="211"></a><a name="IDX-85"></a>
</pre>
</div>
<p class="para">The <span class="fixed">insmod</span> program invokes the <span class="fixed">sys_init_module ()</span> system call, which the kernel uses to register the LKM. If you look at this system call in <span class="fixed">/usr/src/linux/kernel/module . c</span>, you will see that it invokes a similarly named function in the LKM — <span class="fixed">init_module()</span>. Try not to get confused by all the various <span class="fixed">init_module()</span> functions.</p>
<p class="para">To verify that the module is loaded, you can issue the <span class="fixed">lsmod</span> command:</p>
<div class="informalexample">
<pre class="literallayout">
[root@localhost root]# lsmod
Module Size Used by
lkm 880 0 (unused)
ide-cd 27072 0 (autoclean)
cdrom 28512 0 (autoclean) [ide-cd]
soundcore 4464 0 (autoclean)
binfmt_misc 6416 1
tulip 39232 1
ds 7056 2
yenta_socket 9488 2
pcmcia_core 41600 0 [ds yenta_socket]
autofs 11520 0 (autoclean) (unused)
appletalk 20912 0 (autoclean)
ipx 16448 0 (autoclean)
mousedev 4448 1
hid 19024 0 (unused)
input 3840 0 [mousedev hid]
usb-uhci 21536 0 (unused)
usbcore 51712 1 [hid usb-uhci]
ext3 64624 1
jbd 40992 1 [ext3]
</pre>
</div>
<p class="para">Equivalent results can be obtained via:</p>
<div class="informalexample">
<pre class="literallayout">
[root@localhost root]# cat /proc/modules.
</pre>
</div>
<p class="para">This will provide you with a list of currently loaded modules. Naturally, some modules can be written so that they modify the kernel and are not listed (just a thought). Ba ha ha ha (Neumann laugh).</p>
<p class="para">To remove an LKM from the kernel's image, you can use the <span class="fixed">rmmod</span> command:</p>
<div class="informalexample">
<pre class="literallayout">
[root@localhost root]# rmmod lkm
</pre>
</div>
<p class="para">Note how I did not include the <span class="fixed">. o</span> suffix as I did with <span class="fixed">insmod</span>. The <span class="fixed">rmmod</span> command will cause the LKM's <span class="fixed">cleanup_module ()</span> function to be invoked. You should use this as an opportunity to restore the system to its previous state.</p>
<a name="212"></a><a name="IDX-86"></a>
<table border="0" cellspacing="0" cellpadding="0" class="note">
<tr>
<td valign="top" class="admon-check"></td><td valign="top" class="admon-title">Note </td><td valign="top" class="admon-body">
<p class="first-para">The <span class="fixed">init_module ()</span> and <span class="fixed">cleanup_module ()</span> are the only functions that are required in order for an object file to serve as an LKM.</p>
</td>
</tr>
</table>
<p class="para">In the following code, I use an LKM to intercept the <span class="fixed">sys_chdir</span> system call. This is reminiscent of the DOS example where I stole the keyboard interrupt. I basically take my own version of <span class="fixed">sys_chdir</span> and use it to wrap a call to the actual system call. This allows me to piggyback the system call code with my own instructions.</p>
<p class="para">The key to system call swapping is the <span class="fixed">sys_call_table</span> array, which is an array of pointers to system call functions in the kernel. It is analogous to the real mode interrupt vector table. We can change which address gets jumped to for a given system call by switching an entry in the <span class="fixed">sys_call_table</span> pointer array. In my example code, I make sure to save the old function address so that I can restore the <span class="fixed">sys_call_table</span> when I am done.</p>
<div class="informalexample">
<pre class="literallayout">
<span style="background-color:d9d9d9">/* --lkmod.c-- */</span>
<span style="background-color:d9d9d9">#define __KERNEL__ /*instructions are in kernel*/</span>
<span style="background-color:d9d9d9">#define MODULE /*type of kernel code is module code*/</span>
<span style="background-color:d9d9d9">#define LINUX /*keep it portable*/</span>
<span style="background-color:d9d9d9">#include<linux/kernel.h> /*standard LKM include*/</span>
<span style="background-color:d9d9d9">#include<linux/module.h> /*standard LKM include*/</span>
<span style="background-color:d9d9d9">#include<stdio.h> /*need for sprintf ()*/</span>
<span style="background-color:d9d9d9">#include <sys/syscall.h> /*need for __NR_chdir*/</span>
<span style="background-color:d9d9d9">#include <linux/sched.h> /*need for "current" pointer in</span>
<span style="background-color:d9d9d9">printStr*/</span>
<span style="background-color:d9d9d9">#include <linux/tty.h> /*need for tty_struct*/</span>
<span style="background-color:d9d9d9">extern void sys_call_table[]; /*array of function pointers*/</span>
<span style="background-color:d9d9d9">void printStr(char *str)</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">struct tty_struct *my_tty;</span>
<span style="background-color:d9d9d9">my_tty = current->tty;</span>
<span style="background-color:d9d9d9">if (my_tty != NULL)</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">(*(my_tty->driver).write)(my_tty,0,str,strlen(str));</span>
<span style="background-color:d9d9d9">(*(my_tty->driver).write)(my_tty,0,"\015\012",2);</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">asmlinkage int (*getuid_call)();</span><a name="213"></a><a name="IDX-87"></a>
<span style="background-color:d9d9d9">asmlinkage int (*saved_call)(const char *);</span>
<span style="background-color:d9d9d9">asmlinkage int my_call(const char *dir)</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">char *uid_str[8];</span>
<span style="background-color:d9d9d9">int uid;</span>
<span style="background-color:d9d9d9">uid = getuid_call();</span>
<span style="background-color:d9d9d9">sprintf((const char*)uid_str,"%d",uid);</span>
<span style="background-color:d9d9d9">printStr((const char*)uid_str);</span>
<span style="background-color:d9d9d9">printStr(dir);</span>
<span style="background-color:d9d9d9">return saved_call(dir);</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">int init_module()</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">printStr("init_module()-start");</span>
<span style="background-color:d9d9d9">saved_call = sys_call_table[__NR_chdir];</span>
<span style="background-color:d9d9d9">sys_call_table[__NR_chdir] = my_call;</span>
<span style="background-color:d9d9d9">getuid_call = sys_call_table[__NR_getuid];</span>
<span style="background-color:d9d9d9">printStr("init_module()-end");</span>
<span style="background-color:d9d9d9">return(0);</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">void cleanup_module()</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">printStr("cleanup()-start");</span>
<span style="background-color:d9d9d9">sys_call_table[__NR_chdir] = saved_call;</span>
<span style="background-color:d9d9d9">printStr("cleanup()-end");</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}</span>
</pre>
</div>
<a></a>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="214"></a><a name="ch02lev2sec20"></a>Example: Siege Warfare, More Treachery</h3>
<p class="first-para">We have waged a lengthy siege against Linux and have tried a number of tactics to defeat memory protection. Of the three approaches that I have presented, starving the enemy into submission is the path of least resistance. Then again, you never really get inside the castle walls (i.e., the kernel) with the wait-them-out tactic; you merely get to watch your quarry inside the castle spasm in their death throes. Memory leaks provide only a hollow victory in that they don't allow you to get past the protective walls of the operating system.</p>
<a name="215"></a><a name="IDX-88"></a>
<p class="para">Brute force attacks are glaringly fruitless, seeing as how the Pentium and Linux were explicitly designed to protect against such overt methods. Trying to barge into the kernel's linear address space is akin to banging your head against an anvil — the anvil wins every time.</p>
<p class="para">LKMs are a cunning solution, but you need to have root privileges to execute programs such as <span class="fixed">insmod</span> (ah ha! there's a catch!). Most people who obtain root don't need LKMs once they achieve that vaunted status anyway.</p>
<p class="para">An ingenious and more sophisticated approach is needed.</p>
<p class="para">One of the most devious tactics that I can think of is the buffer overflow attack. In the medieval days, a buffer overflow attack would be implemented by poisoning the besieged army's supply of food and water. They would consume the bad provisions and start acting confused and irrational.</p>
<p class="para">Buffer overflow techniques were made famous by Aleph One's article in issue 49 of <i class="emphasis">Phrack</i> magazine. They rely on a function that uses a call like <span class="fixed">strcpy()</span> to copy an argument to a local buffer. If a large enough argument is fed to the function, you can overflow the local buffer so that the function's activation record is corrupted. This allows skillful attackers to place their own return addresses and executable code on the activation record and literally hijack the processor's path of execution.</p>
<p class="para">Here is a fairly simple example:</p>
<div class="informalexample">
<pre class="literallayout">
<span style="background-color:d9d9d9">/* --bufferFlow.c-- */</span>
<span style="background-color:d9d9d9">#include<stdio.h></span>
<span style="background-color:d9d9d9">#include<stdlib.h></span>
<span style="background-color:d9d9d9">#include<string.h></span>
<span style="background-color:d9d9d9">void overflow(char *str)</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">char buffer[4];</span>
<span style="background-color:d9d9d9">strcpy(buffer,str);</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">void hijacked()</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">printf("\tYou've been hijacked!\n");</span>
<span style="background-color:d9d9d9">exit (0);</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">void main()</span>
<span style="background-color:d9d9d9">{</span><a name="216"></a><a name="IDX-89"></a>
<span style="background-color:d9d9d9">char bigbuff[]={'a','b','c','d', /*buffer*/</span>
<span style="background-color:d9d9d9">'e','f','g','h', /* ebp */</span>
<span style="background-color:d9d9d9">'\x0','\x0','\x0','\x0'}; /*IP*/</span>
<span style="background-color:d9d9d9">void *fptr;</span>
<span style="background-color:d9d9d9">unsigned long *lptr;</span>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -