I. Basics
1. What=20
are LKMs
2. What=20
are Syscalls
3. What=20
is the Kernel-Symbol-Table
4. How=20
to transform Kernel to User Space Memory
5. Ways=20
to use user space like functions
6. List=20
of daily needed Kernelspace Functions
7. What=20
is the Kernel-Daemon
8.=20
Creating your own Devices
II. Fun & Profit
1. How=20
to intercept Syscalls
2.=20
Interesting Syscalls to Intercept
III. Soltutions (for admins)
1. LKM=20
Detector Theory & Ideas
IV. Some Better Ideas (for hackers)
1.=20
Tricks to beat admin LKMs
2.=20
Patching the whole kernel - or creating the Hacker-OS
V. The near future : Kernel 2.2
1. Main=20
Difference for LKM writer's
VI. Last Words
1. The=20
'LKM story' or 'how to make a system plug & hack =
compatible'
2.=20
Links to other Resources
Appendix
A - Source Codes
The use of Linux in server environments is growing from second to =
second. So=20
hacking Linux becomes more interesting every day. One of the best =
techniques to=20
attack a Linux system is using kernel code. Due to its feature called =
Loadable=20
Kernel Modules (LKMs) it is possible to write code running in kernel =
space,=20
which allows us to access very sensitive parts of the OS. There were =
some texts=20
and files concerning LKM hacking before (Phrack, for example) which were =
very=20
good. They introduced new ideas, new methodes and complete LKMs doing =
anything a=20
hacker ever dreamed of. Also some public discussion (Newsgroups, =
Mailinglists)=20
in 1998 were very interesting.
So why do I write again a text about =
LKMs.=20
Well there are several reasons :=20
systemcall | description |
---|---|
int sys_brk(unsigned long new_brk); | changes the size of used DS (data segment) ->this systemcall = will=20 be discussed in I.4 |
int sys_fork(struct pt_regs regs); | systemcall for the well-know fork() function in user = space |
int sys_getuid () int sys_setuid (uid_t uid) ... |
systemcalls for managing UID etc. |
int sys_get_kernel_sysms(struct kernel_sym *table) | systemcall for accessing the kernel system table (-> = I.3) |
int sys_sethostname (char *name, int len); int = sys_gethostname=20 (char *name, int len); |
sys_sethostname is responsible for setting the hostname, and=20 sys_gethostname for retrieving it |
int sys_chdir (const char *path); int sys_fchdir (unsigned = int=20 fd); |
both function are used for setting the current directory (cd=20 ...) |
int sys_chmod (const char *filename, mode_t mode); int = sys_chown=20 (const char *filename, mode_t mode); int sys_fchmod (unsigned = int=20 fildes, mode_t mode); int sys_fchown (unsigned int fildes, = mode_t=20 mode); |
functions for managing permissions and so on |
int sys_chroot (const char *filename); | sets root directory for calling process |
int sys_execve (struct pt_regs regs); | important systemcall -> it is responsible for executing file=20 (pt_regs is the register stack) |
long sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long = arg); | changing characteristics of fd (opened file descr.) |
int sys_link (const char *oldname, const char *newname); int=20 sym_link (const char *oldname, const char *newname); int = sys_unlink=20 (const char *name); |
systemcalls for hard- / softlinks management |
int sys_rename (const char *oldname, const char *newname); | file renaming |
int sys_rmdir (const char* name); int sys_mkdir (const *char=20 filename, int mode); |
creating & removing directories |
int sys_open (const char *filename, int mode); int sys_close=20 (unsigned int fd); |
everything concering opening files (also creation), and also = closing=20 them |
int sys_read (unsigned int fd, char *buf, unsigned int =
count); int=20 sys_write (unsigned int fd, char *buf, unsigned int = count); |
systemcalls for writing & reading from Files |
int sys_getdents (unsigned int fd, struct dirent *dirent, = unsigned int=20 count); | systemcall which retrievs file listing (ls ... command) = |
int sys_readlink (const char *path, char *buf, int = bufsize); | reading symbolic links |
int sys_selectt (int n, fd_set *inp, fd_set *outp, fd_set *exp, = struct=20 timeval *tvp); | multiplexing of I/O operations |
sys_socketcall (int call, unsigned long args); | socket functions |
unsigned long sys_create_module (char *name, unsigned long=20
size); int sys_delete_module (char *name); int = sys_query_module=20 (const char *name, int which, void *buf, size_t bufsize, size_t=20 *ret); |
used for loading / unloading LKMs and = querying |
function/macro | description |
---|---|
int sprintf (char *buf, const char *fmt, ...); int vsprintf = (char=20 *buf, const char *fmt, va_list args); |
functions for packing data into strings |
printk (...) | the same as printf in user space |
void *memset (void *s, char c, size_t count); void *memcpy = (void=20 *dest, const void *src, size_t count); char *bcopy (const char = *src,=20 char *dest, int count); void *memmove (void *dest, const void = *src,=20 size_t count); int memcmp (const void *cs, const void *ct, = size_t=20 count); void *memscan (void *addr, unsigned char c, size_t=20 size); |
memory functions |
int register_symtab (struct symbol_table *intab); | see I.1 |
char *strcpy (char *dest, const char *src); char *strncpy = (char=20 *dest, const char *src, size_t count); char *strcat (char = *dest, const=20 char *src); char *strncat (char *dest, const char *src, size_t=20 count); int strcmp (const char *cs, const char *ct); int = strncmp=20 (const char *cs,const char *ct, size_t count); char *strchr = (const char=20 *s, char c); size_t strlen (const char *s); size_t strnlen = (const=20 char *s, size_t count); size_t strspn (const char *s, const = char=20 *accept); char *strpbrk (const char *cs, const char = *ct); char=20 *strtok (char *s, const char *ct); |
string compare functions etc. |
unsigned long simple_strtoul (const char *cp, char **endp, = unsigned=20 int base); | converting strings to number |
get_user_byte (addr); put_user_byte (x, = addr); get_user_word=20 (addr); put_user_word (x, addr); get_user_long=20 (addr); put_user_long (x, addr); |
functions for accessing user memory |
suser(); fsuser(); |
checking for SuperUser rights |
int register_chrdev (unsigned int major, const char *name, =
struct=20
file_o perations *fops); int unregister_chrdev (unsigned int = major,=20 const char *name); int register_blkdev (unsigned int major, = const char=20 *name, struct file_o perations *fops); int unregister_blkdev = (unsigned=20 int major, const char *name); |
functions which register device driver ..._chrdev -> = character=20 devices ..._blkdev -> block = devices |
function | description | |
---|---|---|
int sprintf (char *buf, const char *fmt, ...); int vsprintf = (char=20 *buf, const char *fmt, va_list args); |
functions for packing data into strings | |
int request_module (const char *name); | says kerneld that the kernel requires a certain module (given a = name=20 or gerneric ID / name) | |
int release_module (const char* name, int waitflag); | unload a module | |
int delayed_release_module (const char *name); | delayed unload | |
int cancel_release_module (const char *name); | cancels a call of delayed_release_module | |
"This patch isn't really much of a patch. It simply bumps = the=20 securelevel up, to 1 from 0. This freezes the immutable and = append-only bits=20 on files, keeping anyone from changing them (from the normal chattr=20 interface). Before turning this on, you should of course make certain = key=20 files immutable, and logfiles append-only. It is still possible to = open the=20 raw disk device, however. Your average cut and paste hacker will = probably not=20 know how to do this."Ok this one is really easy to = implement as a=20 LKM. We are lucky because the symbol responsible for the securelevel is = public=20 (see /proc/ksyms) so we can easily change it. I won't present an example = for=20 this bit of code, just import secure level and set it in the module's = init=20 function.=20
macro | description |
---|---|
EXPORT_NO_SYMBOLS; | this one is equal to register_symtab(NULL) for older kernel=20 versions |
EXPORT_SYMTAB; | this one must be defined before linux/module.h if you want to = export=20 some symbols |
EXPORT_SYMBOL(name); | export the symbol named 'name' |
EXPORT_SYMBOL_NOVERS (name); | export without version information |
function | description |
---|---|
int access_ok (int type, unsigned long addr, unsigned long = size); | this function checks whether the current process is allowed to = access=20 addr |
unsigned long copy_from_user (unsigned long to, unsigned long = from,=20 unsigned long len); | this is the 'new' memcpy_tofs function |
unsigned long copy_to_user (unsigned long to, unsigned long = from,=20 unsigned long len); | this is the counterpart of = copy_from_user(...) |
[Books]
Linux-Kernel-Programming (Addison Wesley)
A =
very good=20
book. I read the german version but I think there is also an english =
version.=20
Linux Device Drivers (O'Reilly)
A bit off topic, but also very=20
interesting. The focus is more on writing LKMs as device drivers.=20
Thanks for sources / ideas fly to :=20
plaguez, Solar Designer, halflife, Michal Zalewski, Runar Jensen, = Aleph1,=20 Stealthf0rk/SVAT, FLoW/HISPAHACK, route, Andrew Tridgell, Silvio Cesare, = daemon9, Nergal, van Hauser (especially for showing me some bugs) and = those=20 nameless individuals providing us with their ideas (there are so many) ! =
personal :
background music groups (helping me to concentrate on writing=20
:):
Neuroactive, Image Transmission, Panic on the Titanic, =
Dracul=20
A - Appendix
Here you will find some sources.If the author of the LKM also =
published some=20
notes / texts which are interesting, they will also be printed.
![]() ![]() |