| Funktionshooking unter Linux 2: ptrace (German) |
| Written by cr | |
| Wednesday, 16 May 2007 | |
|
Funktionshooking Teil 2: ptrace
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
einen anderen Prozess auszuführen und diesen zu Überwachen. Gleichzeitig erhalten wir dadurch die Möglichkeit Registervariablen auszulesen und zu manipulieren.
Wie bereits bei LD_PRELOAD nehmen wir ein Programm namens geteuid welches über die Systemfunktion geteuid() die euid des Nutzers abfragt, dieses überprüft diesmal jedoch ob LD_PRELOAD gesetzt ist.
#include <stdio.h> #include <stdlib.h>
{ char* env; if((env=getenv("LD_PRELOAD"))!=NULL) { exit(-1); } printf("EUID=%i\n",geteuid()); return 0; }
-------------geteuid.c-----------------
cr@chronos:~$ ./geteuid EUID=1000 cr@chronos:~$ ./seuid.sh cr@chronos:~$
zB. kommt ptrace ins Spiel. Ich werde hier nur einige Grundlagen nennen für weitergehende Informationen unbedingt die man pages lesen!
2.6.17 Kernel gibt es davon 317. Die einzelnen Nummern zu den Systemcalls könnt ihr über /usr/include/asm-i486/unistd.h herausfinden oder /usr/include/sys/syscall.h, der genaue Pfad variert je nach verwendeter Distribution. Um einen dieser Systemcalls aufzurufen wird einfach dessen Nummer hexdezimal in das eax Register der CPU geschrieben und die jeweiligen Parameter in die CPU Register ebx, ecx, edx, esi und edi (x86). Zum Ausführen wird dann der Interrupt 0x80 aufgerufen. Für weiterführendes Wissen sollte man einfach mal ein paar Tutorials zu Linuxasm durcharbeiten.
während der Ausführung des geteuid Programms. Und sobald die Nummer für den geteuid Syscall im eax Register steht greifen wir korrigierend ein.
#define __NR_geteuid32 201
#include <signal.h> #include <linux/user.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h>
{ int status = 0; int pid; struct user_regs_struct uregs;
printf("fork() Fehler."); exit(-1); } else if (pid==0) { ptrace(PTRACE_TRACEME, 0, 0, 0); execl("./geteuid", "./geteuid", 0); } else { wait(&status); ptrace(PTRACE_SYSCALL, pid, 0, 0);
ptrace(PTRACE_GETREGS, pid, 0, &uregs); if (uregs.orig_eax == 201 && uregs.eax == 1000) { uregs.eax = 666; ptrace(PTRACE_SETREGS, pid, 0, &uregs); } ptrace(PTRACE_SYSCALL, pid, 0, 0); } } printf("done.\n"); return 0; }
-------------ptrace_euid.c-----------------
Status enthält den Rückgabewert des Kindprozesses und pid dessen pid. In uregs speichern wir die aktuellen Register die Definition von struct user_regs_struct uregs befindet sich in /user/include/linux/user.h. PTRACE_TRACEME sagt ptrace das der nachfolgende Prozess überwacht werden soll und den Kindprozess starten wir mit execl. In Der Schleife die solange läuft wie der Kindprozess, sichern wir die Register in uregs immer zum Zeitpunkt eines Systemcalls und prüfen ob der geteuid() Aufruf dabei ist, wenn ja korrigieren wir den Rückgabewert.
cr@chronos:~$ ./ptrace_euid EUID=666 done. cr@chronos:~$
Autor This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
|
|
| Last Updated ( Friday, 18 May 2007 ) |
| < Prev | Next > |
|---|