|
ot pragmatic / THC(21-05-2001)
reiting (6)
[ dobre ]
[ zle ]
Variant za otpechatvane
(nearly) Complete Linux Loadable Kernel
Modules
-the definitive guide for hackers, virus coders and system
administrators-
Prevedeno ot: Andryu
Ivanov. Originalnoto rukovodstvo mozhe da otkriete na
tozi adres
SUDURZHANIE
Vuvedenie
I. Osnovi
1. Kakvo predstavliavat LKM
2. Kakvo predstavliavat sistemnite
povikvaniia (systemcalls)
3. Kakvo predstavliava
Kernel-Symbol-Table (tablitsa
sus simvolite na iadroto)
Vuvedenie
Polzata ot Linux v sveta na survurite narastva vsiaka
sekunda. Taka che da
haknesh Linux stava vse po-interesno s vseki izminal den.
Edna ot nai-dobrite
tehniki za ataka na Linux sistema e chrez izpolzvane na
kernel kod t.e.
programen kod za iadroto na operatsionnata sistema.
Blagodarenie na funktsiiata
narechena "Loadable Kernel Modules" (Zaredimi Moduli na
Qdroto - LKM) e
vuzmozhno da se napishe kod, rabotesht v ramkite na iadroto,
koeto ni pozvoliava
da dostignem mnogo chuvstvitelni chasti na operatsionnata
sistema. Predi vreme
sushtestvuvaha niakoi tekstove i failove, zasiagashti LKM
hakvaneto (Phrack,
naprimer), koito biaha dosta dobri. Te They predstaviha novi
idei, novi
metodi i zavursheni LKMs, praveshti vsichko za koeto edin haker
niakoga e mechtal.
Sushto taka i niakoi publichni diskusii prez 1998 (novinarski
grupi, poshtenski
spisutsi) biaha mnogo interesni.
I taka, zashto da pisha otnovo za LKMs? Ami, ima niakolko
prichini:
-
predishnite tekstove, poniakoga, ne davaha dobri obiasneniia za
nachinaeshtite;
tozi tekst ima mnogo obshirna chast posvetena na osnovite,
pomagashta na nachinaeshtite
da razberat osnovnite kontseptsii. Sreshtal sum mnogo hora,
izpolzvashti dobri
snifuri i tiam podobni bez dori da razbirat kak tezi
"igrachki" rabotiat.
Vklyuchih mnogo sors kod v tozi fail s mnogo komentari,
prosto za da pomogna
na nachinaeshtite, koito znaiat, che hakerstvoto e neshto poveche
ot tova da opustoshavash
niakakvi si mrezhi !
-
vseki publikuvan tekst se kontsentrirashe vurhu opredelena
tema, ne sushtestvuvashe
zavursheno rukovodstvo za hakeri, koeto da zasiaga LKMs. Tozi
tekst shte zasegne
pochti vsichki aspekti ot zloupotrebata s iadroto (dori
virusite)
-
tozi tekst beshe napisan ot glednata tochka na haker /
suzdatel na virusi,
no shte e ot polza i za administratorite i obiknovenite
razrabotchitsi, zanimavashti
se s iadroto
-
predishnite tekstove demonstriraha nai-vazhnite izgodi i
metodi na zloupotreba
s LKMs, no sushtestvuvat neshta, za koito vse oshte ne sme i
chuvali. Tozi tekst
shte demonstrira niakoi novi idei (nishto iztsialo novo, no vse
pak niashta, koito
mogat da ni pomognat)
-
tozi tekst shte pokazhe niakoi idei za prost nachin za
predpazvane ot LKM ataki
-
tozi tekst shte demonstrira i kak da budat preodoliani LKM
zashtitite chrez izpolzvane
na metodi kato Runtime Kernel Patching ("zakurpvane" na
iadroto v realno
vreme)
Molia, zapomnete, che novite idei za izpulneni pod formata na
moduli-prototipi
(samo za demonstratsionni tseli), koito triabva da budat
podobreni, za da
budat izpolzvani v realnostta.
Osnovnata motivatsiia na tozi tekst e da dade na vseki
edin goliam
tekst, pokrivasht tseliia problem LKM. V prilozhenie A davam
niakolko sushtestvuvashti
LKMs plyus kratko opisanie na tiahnata rabota (za nachinaeshti)
i nachini za
tiahnoto izpolzvane.
TSeliiat tekst (s izklyuchenie na chast V) se bazira na
Linux 2.0.x mashina
(x86). Testval sum vsichki programi i fragmenti kod. Linux
sistemata triabva
da poddurzha LKM, za da izpolzvate povecheto primerni kodove
v tozi tekst.
Samo chast IV shte demonstrira niakoi sorsove, koito rabotiat
bez vgradena poddruzhka
na LKM. Povecheto isei v tozi tekst che rabotiat i na 2.2.x
sistemi (veroiatno
shte triabva da napravite niakoi minimalno korektsii); no
spomnete si, che iadro
2.2.x tukmo beshe izliazlo (1/99) i povecheto linux
distributsii vse oshte izpolzvat
2.0.x (Redhat, SuSE, Caldera, ...). Prez april niakoi
distributori, kato
SuSE shte pokazhat tehnite versii s iadro 2.2.x; taka che niama
da imate nuzhda
da znaete kak da haknete iadro 2.2.x kum nastoiashtiia moment.
Dobrite administratori
sushto shte izchakat niakolko mesetsa, za da poluchat po-nadezhdno
2.2.x iadro. [Zabelezhka
: Povecheto sistemi prosto ne se nuzhdaiat ot iadro 2.2.x, taka
che te shte produlzhat
da izpolzvat 2.0.x].
Tozi tekst ima spetsialen razdel, zanimavasht se s LKMs,
pomagashti na administratorite
da obezopasiat sistemata. Vie (hakerite) triabva sushto da
prochetete tozi razdel,
vie triabva da znaete vsichko, koeto adminite znaiat i
dori poveche.
SHTe poluchite niakoi dobri idei ot tozi razdel, koito mogat da
vi pomognat
da razrabotite po-naprednali 'hekerski LKMs'. Prosto
prochetete tseliia tekst
!
I, molia vi, zapomnete : Tozi tekst beshe
napisan edinstveno
za uchebni tseli. Vsiako protivozakonno deistvie osnovano na
tozi tekst si
e lichno vash problem.
I. Osnovi
1. Kakvo predstavliavat LKM
LKM - tova sa Loadable Kernel Modules (Zaredimi Moduli na
Qdroto. Te se
izpolzvat ot Linux iadroto za povishavane na funktsionalnostta
mu. Polzite
ot LKM : Te mogat da se zarezhdat dinamichno; ne se
nalaga prekompilirane
na tsialoto iadro. Poradi tezi si svoistva, LKM se izpolzvat
chesto za draiveri
za spetsifichni ustroistva (ili failovi sistemi), kato
naprimer zvukovi karti
i podobni.
Vseki LKM se sustoi ot dve osnovni funktsii (minimum) :
int init_module(void) /*izpolzva se za vsichko svurzano
s initsializatsiiata*/
{
...
}
void cleanup_module(void) /*izpolzva se za 'chisto' spirane
na modula*/
{
...
}
Zarezhdane na modul - obiknoveno izvurshvano ot root - stava
chrez komandata:
# insmod module.o
Tazi komanda predizvikva izvurshvaneto na slednite deistviia
ot sistemata :
-
Zarezhdane na obektniia fail (v sluchaia module.o)
-
Izvikva sistemno povikvane create_module (za sistemni
povikvaniia -> vizh
I.2) za prezarezhdane na pametta
-
neutochnenite prepratki (references) se prevrushtat v
Kernel-Symbol-i chrez
sistemno povikvane get_kernel_syms
-
sled tova se izpolzva sistemno povikvane init_module za
instalirane na
LKM-a -> izpulniavaiki int init_module(void) i t.n.
Kernel-Symbol-ite sa obiasneni v I.3 (Kernel-Symbol-Table).
I taka, struva mi se, che veche mozhe da napishem purviiat
si maluk LKM,
prosto za da demonstrirame osnovnite printsipi na rabota:
#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");
}
Mozhe bi se uchudvate, che izpolzvah printk(...), a ne
printf(...). E dobre,
programiraneto na nivo iadro
e napulno razlichno ot programiraneto na
potrebitelsko nivo !
Razpolagate s mnogo ogranichen nabor ot komandi (vizh I.6). S
tezi komandi
ne mozhete da napravite koi znae kakvo, taka che shte se
nauchite kak da izpolzvate mnogo ot
funktsiite, koito poznavate ot vashite potrebitelski
programi; te shte vi pomagat da haknete iadroto.
Samo budete turpelivi, purvo triabva da svurshim oshte neshto...
Primerniiat LKM, daden po-gore mozhe lesno da bude kompiliran
po sledniiat nachin:
# gcc -c -O3 helloworld.c
# insmod helloworld.o
Dobre, nashiiat modul e zareden i ni pokaza edin izvesten
tekst. Sega mozhete da probvate niakoi
komandi, koito shte vi pokazat, che LKM-a naistina se
razpolaga v ramkite na iadroto.
# lsmod
Module
Pages Used by
helloworld
1 0
Tazi komanda izchita informatsiiata v /proc/modules, za da vi
pokazhe koi
moduli sa zaredeni v momenta. 'Stranitsite' (pages) davat
informatsiia za pametta (kolko stranitsi
ot pametta zaema modula); Poleto 'izpolzvan ot' (used by)
ni dava informatsiia kolko chesto modulut
se izpolzva ot Sistemata (broi obrushteniia). Modulut mozhe da
bude otstranen, samo kogato
tozi broiach pokazva nula; sled kato proverite tova, mozhete
da premahnete modula sus
# rmmod helloworld
E, tova beshe nashata purva malka stupka (naistina munichka)
kum zloupotrebite s LKMs. Vinagi
sum sravniaval tezi LKMs sus starite TSR programi pod DOS
(da, znam, sushtestvuvat mnogo razliki),
te biaha nashata vratichka za prebivavane v pametta i
prihvashtane na vsiako prekusvane, koeto
pozhelaem. Microsoftskiia WIN 9x ima neshto narecheno VxD, koeto
sushto e mnogo podobno na
LKMs (i tuk ima mnogo razliki). Nai-interesnoto pri tezi
rezidentni programi
e vuzmozhnostta da prihvaneme sistemnite funktsii, narichani
'sistemni povikvaniia' (systemcalls)
v sveta na Linux
2. Kakvo predstavliavat sistemnite
povikvaniia (systemcalls)
Nadiavam se znaete, che vsiaka OS ima funktsii, vgradeni v
iadroto i, koito
se izpolzvat za izvurshvaneto na vsiaka edna operatsiia v tazi
sistema.
Funktsiite, koito Linux izpolzva se narichat sistemni
povikvaniia (systemcalls).
Te predstavliavat prehod ot potrebitelskoto prostranstvo kum
nivo 'iadro'.
Otvarianeto na fail v potrebitelskoto prostranstvo e
predstaveno ot sistemno
povikvane sys_open na nivo iadro. Za izcherpatelen spisuk na
sistemnite povikvaniia
(systemcalls), koito sa dostupni za vashata sistema
poglednete v /usr/include/sys/syscall.h.
Tozi spisuk predstavliava moiat syscall.h
#ifndef _SYS_SYSCALL_H
#define _SYS_SYSCALL_H
#define
SYS_setup
0 /* Izpolzva se samo ot init, za da se 'podkara' sistemata.
*/
#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 za failova sistema 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> */
Vsiako sistemno povikvane ima opredelen nomer (pogledni
listinga po-gore), koito realno se
izpolzva za sistemno povikvane.
Qdroto izpolzva prekusvane 0x80 za obsluzhvane na vsiako
sistemno povikvane. Nomerut na
systemcall-a i vsichki neobhodimi argumenti se premestvat v
niakoi registri (eax za nomer na systemcall,
napr,).
nomera na sistemnoto povikvane predstavliava nomer v masiv
na struktura na iadroto, narechen
sys_call_table[]. Tazi struktura supostavia nomerata na
sistemnite povikvaniia i neobhodimite
servizni funktsii.
E, tova znanie triabva da e dostatuchno, za da produlzhim s
cheteneto. V sledvashtata tablitsa e
daden spisuk na nai-interesnite povikvaniia zaedno s kratko
opisanie.
Poviarvaite mi, triabva da znaete tochnoto deistvie na tezi
povikvaniia, za da
napravite naistina polezni LKMi.
sistemno povikvane |
opisanie |
int sys_brk(unsigned long new_brk); |
promenia razmera na izpolzvaniia DS (segment za danni)
->tova povikvane
shte bude diskutirano v I.4 |
int sys_fork(struct pt_regs regs); |
systemcall otgovariasht na dobre poznatata v
potrebitelskoto prostranstvo
funktsiia fork() |
int sys_getuid ()
int sys_setuid (uid_t uid)
... |
povikvaniia za upravlenie na UID i pod. |
int sys_get_kernel_sysms(struct kernel_sym *table) |
systemcall za dostup do sistemnata tablitsa na iadroto
(kernel system
table) (-> I.3) |
int sys_sethostname (char *name, int len);
int sys_gethostname (char *name, int len); |
sys_sethostname otgovaria za ustanoviavaneto na hostname,
a sys_gethostname
- za poluchavaneto mu(?) |
int sys_chdir (const char *path);
int sys_fchdir (unsigned int fd); |
i dvete funktsii se izpolzvat za ustanoviavane na
tekushtata direktoriia
(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); |
funktsii za upravlenie na pravata i pod. |
int sys_chroot (const char *filename); |
nastroiva osnovnata (root) direktoriia za izvikvashtiia
protses |
int sys_execve (struct pt_regs regs); |
Mnogo vazhen systemcall -> otgovaria za izpulnenieto na
failove (pt_regs
e registrov stek) |
long sys_fcntl (unsigned int fd, unsigned int cmd,
unsigned long arg); |
promenia harakteristikite na fd (opened file
descr.) |
int sys_link (const char *oldname, const char
*newname);
int sym_link (const char *oldname, const char
*newname);
int sys_unlink (const char *name); |
sistemno povikvane za upravlenie na tvurdi (hardlinks)
ili "meki" (softlinks)
vruzki |
int sys_rename (const char *oldname, const char
*newname); |
preimenuva failove |
int sys_rmdir (const char* name);
int sys_mkdir (const *char filename, int mode); |
suzdava i premahva direktorii |
int sys_open (const char *filename, int mode);
int sys_close (unsigned int fd); |
za vsichko svurzano s otvarianeto na failove (vklyuchitelno
suzdavaneto
im), a sushto i zatvarianeto im |
int sys_read (unsigned int fd, char *buf, unsigned int
count);
int sys_write (unsigned int fd, char *buf, unsigned int
count); |
sistemni povikvaniia za zapis i chetene ot failove |
int sys_getdents (unsigned int fd, struct dirent
*dirent, unsigned
int count); |
systemcall, chrez koito se izvlicha spisuk na failove
(komandata ls ...) |
int sys_readlink (const char *path, char *buf, int
bufsize); |
chete simvolichni vruzki |
int sys_selectt (int n, fd_set *inp, fd_set *outp,
fd_set *exp, struct
timeval *tvp); |
multiplexing na I/O operatsiite |
sys_socketcall (int call, unsigned long args); |
socket funktsii |
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); |
izpolzva se za zarezhdane / otstraniavane na LKMi i za
zapitvaniia |
Po moe mnenie, tova sa nai-interesnite sistemni povikvaniia
za imashtite hakerski
namereniia, razbira se, vuzmozhno e da se nuzhdaete ot neshto
spetsialno na sistemata
v koiato turshuvate, no obiknovenniiat haker ima izobilie ot
vuzmozhnosti sus
spisuka daden po-gore. V chast II shte se nauchite kak da
izpolzvate sistemnite
povikvaniia v svoia polza.
3. Kakvo predstavliava
Kernel-Symbol-Table (tablitsa sus
simvolite na iadroto)
simvol - neshto (napr. grafichno
izobrazhenie), koeto predstavliava/olitsetvoriava
obekt/subekt/neshto abstraktno t.e. vseki simvol na iadroto
predstavliava niakakva
negova funktsiia
bel. pr.
E, dobre! Razbirame osnovnata kontseptsiia za sistemnite
povikvaniia (systemcalls)
i modulite. No ima oshte neshto, i to mnogo vazhno, koeto triabva
da razberem
- Kernel Symbol Table (tablitsa sus simvolite na iadroto.
Poglednete /proc/ksyms.
Vseki red v tozi fail predstavliava eksportiran (publichen)
simvol na iadroto,
koito e dostupen za nashiiat LKM. Ogledaite dobre tozi fail;
shte otkriete
mnogo interesni neshta v nego.
Failut e naistina interesen i mozhe da ni pomogne da
razberem kakvo
mozhe da izpolzva nashiiat LKM , no ima edin problem. Vseki
simvol izpolzvan
v nashiiat LKM (kato funktsiia) sushto se eksportira v tozi
"publichen registur"
t.e. poiaviava se v tozi fail-spisuk. Taka edin opiten
administrator bi mogul
da otkrie malkiiat ni LKM i da go otstrani (kill).
Sushtestvuvat mnogo metodi, chrez koito da ne pozvolim na
adminite da
vidiat nashiiat LKM, vizhte razdel II.
Matodite spomenati v II mogat da budat narecheni
'hakove', no kogato
razgledate sudurzhanieto na razdel II niama da otkriete
prepratka kum "Kak
da durzhime LKM simvolite dalech ot /proc/ksyms". Prichinata
da ne spomenavame
tozi problem v razdel II e slednata :
niama da se nuzhdaete ot trik, za da ne dopusnete
moduli-simvoli si do
/proc/ksyms. Razrabotchitsite na LKM mogat da izpolzvat
sledniiat otriazuk
"normalen" kod, za da sprat eksportiranite simvoli ot
tehniiat modul:
static struct symbol_table module_syms= { /*definirame
sobstvena tablitsa na simvolite !*/
#include
<linux/symtab_begin.h>
/*Simvolite koito iskame da eksportirame, a iskame li ?*/
...
};
register_symtab(&module_syms);
/*izvurshva istinskoto registrirane*/
Tui kato ne iskame da iznasiame nikakvi simvoli na pokaz,
izpolzvame
slednata konstruktsiia :
register_symtab(NULL);
Tozi red triabva da bude vmuknat vuv funktsiiata
init_module(), zapomnete
go !
<< (pochti)Pulno rukovodstvo za modulite v Linux iadroto [chast 2] | Kak da zashtitite vashiiat Linux (chast 2) >>
|
|