LINUX-BG Адрес : http://www.linux-bg.org |
(почти)Пълно ръководство за модулите в Linux ядрото [част 1] |
От: pragmatic / THC Публикувана на: 21-05-2001 Адрес на статията: http://www.linux-bg.org/cgi-bin/y/index.pl?page=article&id=advices&key=330146683 |
Преведено от: Андрю Иванов. Оригиналното ръководство може да откриете на този адреса> СЪДЪРЖАНИЕ ВъведениеI. Основи
ВъведениеПолзата от Linux в света на сървърите нараства всяка секунда. Така че да хакнеш Linux става все по-интересно с всеки изминал ден. Една от най-добрите техники за атака на Linux система е чрез използване на kernel код т.е. програмен код за ядрото на операционната система. Благодарение на функцията наречена "Loadable Kernel Modules" (Заредими Модули на Ядрото - LKM) е възможно да се напише код, работещ в рамките на ядрото, което ни позволява да достигнем много чувствителни части на операционната система. Преди време съществуваха някои текстове и файлове, засягащи LKM хакването (Phrack, например), които бяха доста добри. Те They представиха нови идеи, нови методи и завършени LKMs, правещи всичко за което един хакер някога е мечтал. Също така и някои публични дискусии през 1998 (новинарски групи, пощенски списъци) бяха много интересни.И така, защо да пиша отново за LKMs? Ами, има няколко причини:
Основната мотивация на този текст е да даде на всеки един голям текст, покриващ целия проблем LKM. В приложение A давам няколко съществуващи LKMs плюс кратко описание на тяхната работа (за начинаещи) и начини за тяхното използване. Целият текст (с изключение на част V) се базира на Linux 2.0.x машина (x86). Тествал съм всички програми и фрагменти код. Linux системата трябва да поддържа LKM, за да използвате повечето примерни кодове в този текст. Само част IV ще демонстрира някои сорсове, които работят без вградена поддръжка на LKM. Повечето исеи в този текст че работят и на 2.2.x системи (вероятно ще трябва да направите някои минимално корекции); но спомнете си, че ядро 2.2.x тъкмо беше излязло (1/99) и повечето linux дистрибуции все още използват 2.0.x (Redhat, SuSE, Caldera, ...). През април някои дистрибутори, като SuSE ще покажат техните версии с ядро 2.2.x; така че няма да имате нужда да знаете как да хакнете ядро 2.2.x към настоящия момент. Добрите администратори също ще изчакат няколко месеца, за да получат по-надеждно 2.2.x ядро. [Забележка : Повечето системи просто не се нуждаят от ядро 2.2.x, така че те ще продължат да използват 2.0.x]. Този текст има специален раздел, занимаващ се с LKMs, помагащи на администраторите да обезопасят системата. Вие (хакерите) трябва също да прочетете този раздел, вие трябва да знаете всичко, което админите знаят и дори повече. Ще получите някои добри идеи от този раздел, които могат да ви помогнат да разработите по-напреднали 'хекерски LKMs'. Просто прочетете целия текст ! И, моля ви, запомнете : Този текст беше написан единствено за учебни цели. Всяко противозаконно действие основано на този текст си е лично ваш проблем. I. Основи1. Какво представляват LKMLKM - това са Loadable Kernel Modules (Заредими Модули на Ядрото. Те се използват от Linux ядрото за повишаване на функционалността му. Ползите от LKM : Tе могат да се зареждат динамично; не се налага прекомпилиране на цялото ядро. Поради тези си свойства, LKM се използват често за драйвери за специфични устройства (или файлови системи), като например звукови карти и подобни.Всеки LKM се състои от две основни функции (минимум) : int init_module(void) /*използва се за всичко свързано с инициализацията*/ { ... } void cleanup_module(void) /*използва се за 'чисто' спиране на модула*/ { ... } Зареждане на модул - обикновено извършвано от root - става чрез командата: # insmod module.o Тази команда предизвиква извършването на следните действия от системата :
И така, струва ми се, че вече може да напишем първият си малък LKM, просто за да демонстрираме основните принципи на работа: #define MODULE #include <Linux/module.h> int init_module(void) { printk("<1>Hello World\n"); return 0; } void cleanup_module(void) { printk("<1>Bye, Bye"); } Може би се учудвате, че използвах printk(...), а не printf(...). Е добре, програмирането на ниво ядро е напълно различно от програмирането на потребителско ниво ! Разполагате с много ограничен набор от команди (виж I.6). С тези команди не можете да направите кой знае какво, така че ще се научите как да използвате много от функциите, които познавате от вашите потребителски програми; те ще ви помагат да хакнете ядрото. Само бъдете търпеливи, първо трябва да свършим още нещо... Примерният LKM, даден по-горе може лесно да бъде компилиран по следният начин: # gcc -c -O3 helloworld.c # insmod helloworld.o Добре, нашият модул е зареден и ни показа един известен текст. Сега можете да пробвате някои команди, които ще ви показат, че LKM-а наистина се разполага в рамките на ядрото. # lsmod Module Pages Used by helloworld 1 0 Тази команда изчита информацията в /proc/modules, за да ви покаже кои модули са заредени в момента. 'Страниците' (pages) дават информация за паметта (колко страници от паметта заема модула); Полето 'използван от' (used by) ни дава информация колко често модулът се използва от Системата (брой обръщения). Модулът може да бъде отстранен, само когато този брояч показва нула; след като проверите това, можете да премахнете модула със # rmmod helloworld Е, това беше нашата първа малка стъпка (наистина мъничка) към злоупотребите с LKMs. Винаги съм сравнявал тези LKMs със старите TSR програми под DOS (да, знам, съществуват много разлики), те бяха нашата вратичка за пребиваване в паметта и прихващане на всяко прекъсване, което пожелаем. Microsoftския WIN 9x има нещо наречено VxD, което също е много подобно на LKMs (и тук има много разлики). Най-интересното при тези резидентни програми е възможността да прихванеме системните функции, наричани 'системни повиквания' (systemcalls) в света на Linux 2. Какво представляват системните повиквания (systemcalls)Надявам се знаете, че всяка ОС има функции, вградени в ядрото й, които се използват за извършването на всяка една операция в тази система.Функциите, които Linux използва се наричат системни повиквания (systemcalls). Те представляват преход от потребителското пространство към ниво 'ядро'. Отварянето на фаил в потребителското пространство е представено от системно повикване sys_open на ниво ядро. За изчерпателен списък на системните повиквания (systemcalls), които са достъпни за вашата система погледнете в /usr/include/sys/syscall.h. Този списък представлява моят syscall.h #ifndef _SYS_SYSCALL_H #define _SYS_SYSCALL_H #define SYS_setup 0 /* Използва се само от init, за да се 'подкара' системата. */ #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 /* Syscall за файлова система Andrew */ #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 /* <sys/syscall.h> */ Всяко системно повикване има определен номер (погледни листинга по-горе), който реално се използва за системно повикване. Ядрото използва прекъсване 0x80 за обслужване на всяко системно повикване. Номерът на systemcall-а и всички необходими аргументи се преместват в някои регистри (eax за номер на systemcall, напр,). номера на системното повикване представлява номер в масив на структура на ядрото, наречен sys_call_table[]. Тази структура съпоставя номерата на системните повиквания и необходимите сервизни функции. Е, това знание трябва да е достатъчно, за да продължим с четенето. В следващата таблица е даден списък на най-интересните повиквания заедно с кратко описание. Повярвайте ми, трябва да знаете точното действие на тези повиквания, за да направите наистина полезни LKMи.
3. Какво представлява Kernel-Symbol-Table (таблица със символите на ядрото)символ - нещо (напр. графично изображение), което представлява/олицетворява обект/събект/нещо абстрактно т.е. всеки символ на ядрото представлява някаква негова функциябел. пр. Е, добре! Разбираме основната концепция за системните повиквания (systemcalls) и модулите. Но има още нещо, и то много важно, което трябва да разберем - Kernel Symbol Table (таблица със символите на ядрото. Погледнете /proc/ksyms. Всеки ред в този файл представлява експортиран (публичен) символ на ядрото, който е достъпен за нашият LKM. Огледайте добре този файл; ще откриете много интересни неща в него. Файлът е наистина интересен и може да ни помогне да разберем какво може да използва нашият LKM , но има един проблем. Всеки символ използван в нашият LKM (като функция) също се експортира в този "публичен регистър" т.е. появява се в този файл-списък. Така един опитен администратор би могъл да открие малкият ни LKM и да го отстрани (kill). Съществуват много методи, чрез които да не позволим на админите да видят нашият LKM, вижте раздел II. Матодите споменати в II могат да бъдат наречени 'хакове', но когато разгледате съдържанието на раздел II няма да откриете препратка към "Как да държиме LKM символите далеч от /proc/ksyms". Причината да не споменаваме този проблем в раздел II е следната : няма да се нуждаете от трик, за да не допуснете модули-символи си до /proc/ksyms. Разработчиците на LKM могат да използват следният отрязък "нормален" код, за да спрат експортираните символи от техният модул: static struct symbol_table module_syms= { /*дефинираме собствена таблица на символите !*/ #include <linux/symtab_begin.h> /*Символите които искаме да експортираме, а искаме ли ?*/ ... }; register_symtab(&module_syms); /*извършва истинското регистриране*/ Тъй като не искаме да изнасяме никакви символи на показ, използваме следната конструкция :register_symtab(NULL); Този ред трябва да бъде вмъкнат във функцията init_module(), запомнете го ! << (почти)Пълно ръководство за модулите в Linux ядрото [част 2] | Как да защитите вашият Linux (част 2) >> |
Авторите на сайта, както и техните сътрудници запазват авторските права върху собствените си материали публикувани тук,
но те са copyleft т.е. могат свободно да бъдат копирани и разпространявани с изискването изрично да се упоменава името на автора,
както и да се публикува на видно място, че те са взети от оригиналния им URL-адрес на този сървър (http://www.linux-bg.org). Авторските права на преводните материали принадлежат на техните автори. Ако с публикуването тук на някакъв материал неволно са нарушени нечии права - след констатирането на този факт материалът ще бъде свален.
All trademarks, logos and copyrights mentioned on this site are the property of their respective owners.
|