Technology Sharing | A Complete Guide to Uninstallable Kernel Modules in Linux Systems (Part 1)

640?wxfrom=5&wx_lazy=1&retryload=1


Introduction

           Using the Linux operating system for servers is becoming more and more common these days. Therefore, hacking Linux is becoming more and more interesting today. The best technique for attacking Linux is to modify the kernel code. Due to a method called Loadable


           KernelModules (LKMs)), it is possible to write code that runs at the kernel level, and this code can allow us to touch very sensitive parts of the operating system. There are some good texts or documents about LKM knowledge in the past , they introduce some new ideas, methods, and complete LKMs that a Hacker could only dream of. And there are also some interesting public discussions (on newsgroups, mailing lists).


           Yet why am I rewriting this stuff about LKMs? Here are some of my reasons:

           In the past textbooks often did not provide good explanations for those beginners. And this textbook has a large part of the basic chapters. This is to help those beginners understand the concepts. I have seen many people using the system's flaws or Listeners however have no idea how they work. I've included a lot of annotated source code in this post just to help beginners who think hacking is just a game of tools!


           Each published tutorial only focuses on a specific topic. There is no complete guide for Hackers who care about LKMs. This article will cover almost everything about LKMs (even viruses).


           This article is discussed from a hacker or virus perspective, but system administrators or kernel developers can also refer to it and learn a lot from it.


           Previous articles have introduced some advantages or methods of using LKMs for intrusion, but there are always things that we have never heard of in the past. This article will introduce some new ideas to everyone. (Not all new materials , just something to help us)


           This article will introduce some simple ways to prevent LKM attacks, and also how to counter these defenses by using some methods like Runtime Kernel Patching.


           Keep in mind that these new ideas are only implemented by utilizing some special modules. To actually use them in reality, they still need to be improved. The main purpose of this article is to give you a general direction on the whole LKM In Appendix A, I'll give you some practical LKMs, with some brief notes (for those who are new to them), and how to use them.


           The entire article (except for part 5) is based on a Linux 2.0.x 80x86 machine. I tested all programs and code snippets. In order to work with most of the code provided here, your Linux system must have LKM support .Only in the fourth part, I will give you some source code that does not need LKM support. Most of the ideas in this article can be implemented on Linux 2.2.x (maybe you will need some small changes).


           This article will have a special section to help sysadmins with system security. You (as a Hacker) must read those sections too. You must know everything sysadmins know, and more. You also You will find a lot of good ideas here. It will also help you develop advanced LKMs for hacking systems.


Part 1. Basics


1.1

What are LKMs?


           LKMs are Loadable Kernel  Modules. These modules were originally used by the Linux system to extend his functions. The advantage of using LKMs is that they can be loaded dynamically without recompiling the kernel. Because of these advantages, they are often used by special devices (or file systems), such as sound cards.

Each LKM consists of at least two basic functions:


int init_module(void) /* used to initialize all data */

{

...

}

void cleanup_module(void) /* used to clean up data to have a safe exit */

{

...

}

The command to load a module (often restricted to root access) is:

# insmod module.o

This command makes the system do the following:

Load the executable object file (in this case module.o)

Call the create_module system call (as to what a system call is, see 1.2) to allocate memory.

Unresolved references are looked up by the system call get_kernel_syms.

在此之后系统调用init_module将会被调用用来初始化LKM->执行 int inti_module(void) 等等

(内核符号将会在1.3节中内核符号表中解释)

OK,到目前为止,我想我们可以写出我们第一个小的LKM来演示一下这些基本的功能是如何工作的了.

#define MODULE

#include

int init_module(void)

{

printk("<1>Hello World\n");

return 0;

}

void cleanup_module(void)

{

printk("<1>Bye, Bye");

}


           你可能会奇怪为什么在这里我用printk(....)而不是printf(.....).在这里你要明白内核编程是完全不同于普通的用户环境下的编程的.你只能使用很有限的一些函数(见1.6)仅使用这些函数你是干不了什么的.因此,你将会学会如何使用你在用户级别中用的那么多函数来帮助你入侵内核.耐心一些,在此之前我们必须做一点其他的.....


上面的那个例子可以很容易的被编译:

# gcc -c -O3 helloworld.c

# insmod helloworld.o


           OK,现在我们的模块已经被加载了并且给我们打印出了那句很经典的话.现在你可以通过下面这个命令来确认你的LKM确实运行在内核级别中:

# lsmod

Module     Pages  Used by

helloworld     1    0


           这个命令读取在 /proc/modules 的信息来告诉你当前那个模块正被加载.'Pages'

显示的是内存的信息(这个模块占了多少内存页面).'Used by'显示了这个模块被系统使用的次数(引用计数).这个模块只有当这个计数为0时才可以被除去.在检查过这个以后,你可以用下面的命令卸载这个模块

# rmmod helloworld


           OK, this is just a small step towards LKMs. I often compare these LKMs to old DOS TSR programs, (yes, I know there are a lot of differences between them), and those TSRs can often resides in memory and intercepts the interrupts we want. Microsoft's Win9x has something similar called VxD. The most interesting thing about these programs is that they can hook into some system function, which in Linux we call these functions system call.


1.2

What is a system call?


           What is a system call ? I hope you can understand. Each operating system has some basic functions in the kernel to call other operations of the system. In the Linux system, these functions are called system calls. They represent There is a conversion from user level to kernel level. Opening a file at the user level is implemented at the kernel level through the sys_open system call. There is a complete list of system calls in /usr/include/sys/syscall.h . The list below is my syscall.h

#ifndef _SYS_SYSCALL_H

#define _SYS_SYSCALL_H

#define SYS_setup 0

/* Only used by init, used to start the system */

#define SYS_exit 1

#define SYS_fork 2

#define SYS_read 3

#define SYS_write 4

#define SYS_open 5

#define SYS_close 6

#define SYS_waitpid 7

#define SYS_creat 8

#define SYS_link 9

#define SYS_unlink 10

#define SYS_execve 11

#define SYS_chdir 12

#define SYS_time 13

#define SYS_prev_mknod 14

#define SYS_chmod 15

#define SYS_chown 16

#define SYS_break 17

#define SYS_oldstat 18

#define SYS_lseek 19

#define SYS_getpid 20

#define SYS_mount 21

#define SYS_umount 22

#define SYS_setuid 23

#define SYS_getuid 24

#define SYS_stime 25

#define SYS_ptrace 26

#define SYS_alarm 27

#define SYS_oldfstat 28

#define SYS_pause 29

#define SYS_utime 30

#define SYS_stty 31

#define SYS_gtty 32

#define SYS_access 33

#define SYS_nice 34

#define SYS_ftime 35

#define SYS_sync 36

#define SYS_kill 37

#define SYS_rename 38

#define SYS_mkdir 39

#define SYS_rmdir 40

#define SYS_dup 41

#define SYS_pipe 42

#define SYS_times 43

#define SYS_prof 44

#define SYS_brk 45

#define SYS_setgid 46

#define SYS_getgid 47

#define SYS_signal 48

#define SYS_geteuid 49

#define SYS_getegid 50

#define SYS_acct 51

#define SYS_phys 52

#define SYS_lock 53

#define SYS_ioctl 54

#define SYS_fcntl 55

#define SYS_mpx 56

#define SYS_setpgid 57

#define SYS_ulimit 58

#define SYS_oldolduname 59

#define SYS_umask 60

#define SYS_chroot 61

#define SYS_prev_ustat 62

#define SYS_dup2 63

#define SYS_getppid 64

#define SYS_getpgrp 65

#define SYS_setsid 66

#define SYS_sigaction 67

#define SYS_siggetmask 68

#define SYS_sigsetmask 69

#define SYS_setreuid 70

#define SYS_setregid 71

#define SYS_sigsuspend 72

#define SYS_sigpending 73

#define SYS_sethostname 74

#define SYS_setrlimit 75

#define SYS_getrlimit 76

#define SYS_getrusage 77

#define SYS_gettimeofday 78

#define SYS_settimeofday 79

#define SYS_getgroups 80

#define SYS_setgroups 81

#define SYS_select 82

#define SYS_symlink 83

#define SYS_oldlstat 84

#define SYS_readlink 85

#define SYS_uselib 86

#define SYS_swapon 87

#define SYS_reboot 88

#define SYS_readdir 89

#define SYS_mmap 90

#define SYS_munmap 91

#define SYS_truncate 92

#define SYS_ftruncate 93

#define SYS_fchmod 94

#define SYS_fchown 95

#define SYS_getpriority 96

#define SYS_setpriority 97

#define SYS_profil 98

#define SYS_statfs 99

#define SYS_fstatfs 100

#define SYS_ioperm 101

#define SYS_socketcall 102

#define SYS_klog 103

#define SYS_setitimer 104

#define SYS_getitimer 105

#define SYS_prev_stat 106

#define SYS_prev_lstat 107

#define SYS_prev_fstat 108

#define SYS_olduname 109

#define SYS_iopl 110

#define SYS_vhangup 111

#define SYS_idle 112

#define SYS_vm86old 113

#define SYS_wait4 114

#define SYS_swapoff 115

#define SYS_sysinfo 116

#define SYS_ipc 117

#define SYS_fsync 118

#define SYS_sigreturn 119

#define SYS_clone 120

#define SYS_setdomainname 121

#define SYS_uname 122

#define SYS_modify_ldt 123

#define SYS_adjtimex 124

#define SYS_mprotect 125

#define SYS_sigprocmask 126

#define SYS_create_module 127

#define SYS_init_module 128

#define SYS_delete_module 129

#define SYS_get_kernel_syms 130

#define SYS_quotactl 131

#define SYS_getpgid 132

#define SYS_fchdir 133

#define SYS_bdflush 134

#define SYS_sysfs 135

#define SYS_personality 136

#define SYS_afs_syscall 137

#define SYS_setfsuid 138

#define SYS_setfsgid 139

#define SYS__llseek 140

#define SYS_getdents 141

#define SYS__newselect 142

#define SYS_flock 143

#define SYS_syscall_flock SYS_flock

#define SYS_msync 144

#define SYS_readv 145

#define SYS_syscall_readv SYS_readv

#define SYS_writev 146

#define SYS_syscall_writev SYS_writev

#define SYS_getsid 147

#define SYS_fdatasync 148

#define SYS__sysctl 149

#define SYS_mlock 150

#define SYS_munlock 151

#define SYS_mlockall 152

#define SYS_munlockall 153

#define SYS_sched_setparam 154

#define SYS_sched_getparam 155

#define SYS_sched_setscheduler 156

#define SYS_sched_getscheduler 157

#define SYS_sched_yield 158

#define SYS_sched_get_priority_max 159

#define SYS_sched_get_priority_min 160

#define SYS_sched_rr_get_interval 161

#define SYS_nanosleep 162

#define SYS_mremap 163

#define SYS_setresuid 164

#define SYS_getresuid 165

#define SYS_vm86 166

#define SYS_query_module 167

#define SYS_poll 168

#define SYS_syscall_poll SYS_poll

#endif /* */


           每个系统调用都有一个预定义的数字(见上表),那实际上是用来进行这些调用的.内核通过中断0x80来控制每一个系统调用.这些系统调用的数字以及任何参数都将被放入某些寄存器(eax用来放那些代表系统调用的数字)


           那些系统调用的数字是一个被称之为sys_call_table[]的内核中的数组结构的索引值.这个结构把系统调用的数字映射到实际使用的函数.


           OK,这些是继续阅读所必须的足够知识了.下面的表列出了那些最有意思的系统调用以及一些简短的注释.相信我,为了你能够真正的写出有用的LKM你必须确实懂得那些系统调用是如何工作的.


系统调用列表:

int sys_brk(unsigned long new_brk);

改变DS(数据段)的大小->这个系统调用会在1.4中讨论

int sys_fork(struct pt_regs regs);

著名的fork()所用的系统调用

int sys_getuid ()

int sys_setuid (uid_t uid)

用于管理UID等等的系统调用

int sys_get_kernel_sysms(struct kernel_sym *table)

用于存取系统函数表的系统调用(->1.3)

int sys_sethostname (char *name, int len);

int sys_gethostname (char *name, int len);

sys_sethostname是用来设置主机名(hostname)的,sys_gethostname是用来取的

int sys_chdir (const char *path);

int sys_fchdir (unsigned int fd);

两个函数都是用于设置当前的目录的(cd ...)

int sys_chmod (const char *filename, mode_t mode);

int sys_chown (const char *filename, mode_t mode);

int sys_fchmod (unsigned int fildes, mode_t mode);

int sys_fchown (unsigned int fildes, mode_t mode);

用于管理权限的函数

int sys_chroot (const char *filename);

用于设置运行进程的根目录的

int sys_execve (struct pt_regs regs);

非常重要的系统调用->用于执行一个可执行文件的(pt_regs是堆栈寄存器)

long sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg);

改变fd(打开文件描述符)的属性的

int sym_link (const char *oldname, const char *newname);

int sys_unlink (const char *name);

用于管理硬/软链接的函数

int sys_rename (const char *oldname, const char *newname);

用于改变文件名

int sys_rmdir (const char* name);

int sys_mkdir (const *char filename, int mode);

用于新建已经删除目录

int sys_open (const char *filename, int mode);

int sys_close (unsigned int fd);

所有和打开文件(包括新建)有关的操作,还有关闭文件的.

int sys_read (unsigned int fd, char *buf, unsigned int count);

int sys_write (unsigned int fd, char *buf, unsigned int count);

读写文件的系统调用

int sys_getdents (unsigned int fd, struct dirent *dirent, unsigned int count);

用于取得文件列表的系统调用(ls...命令)

int sys_readlink (const char *path, char *buf, int bufsize);

读符号链接的系统调用

int sys_selectt (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);

多路复用I/O操作

sys_socketcall (int call, unsigned long args);

socket 函数

unsigned long sys_create_module (char *name, unsigned long size);

int sys_delete_module (char *name);

int sys_query_module (const char *name, int which, void *buf, size_t bufsize,

size_t *ret);

用于模块的加载/卸载和查询.


           These are the syscalls that I think would be of interest to an intruder. Of course you may need some special syscalls if you want to gain root access to the system, but as a hacker he will probably have a basic list from the above. In the second part you will know how to use these system calls for your own purposes.


Linux cloud computing free courses are hotly launched , the last 2 days of free courses are the first to listen, the operation and maintenance dry goods content is free to listen , and you can listen to the operation and maintenance courses for free by clicking "read the original text" at the end of the article ! Hurry up ~~~~

PS: Remember to check the free gift package that Xiaobian sent you~

Welfare | More than 10,000 sets of PPT templates are waiting for you for free! Get it unconditionally!

Free delivery | More than 1000 sets of resume templates are free to get, with a resume making tutorial!

Get it for free | The e-book "100 Cases of Shell Scripts" is free, and it is necessary for operation and maintenance~

640? 640?wx_fmt=jpeg

▼▼Click [ read the original text ] to listen to the 5-day Linux operation and maintenance dry goods sharing class for free , the hot lecture is in progress, come and grab it!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326362862&siteId=291194637