Home arrow Papers arrow Papers (German) arrow Funktionshooking unter Linux 2: ptrace (German)

main

Home
Blog
IRC


Netgarage RSS Feed
Linux Powered
Hacker Emblem
Apache 2.0 Power
Valid XHTML








Funktionshooking unter Linux 2: ptrace (German)
Written by cr   
Wednesday, 16 May 2007
Ein etwas älterer Text der Möglichkeiten des Funktionshooking unter Linux beschreibt in 4 Teilen. Teil 2 bschreibt an einem einfachen Beispiel  ptrace.

Funktionshooking Teil 2: ptrace


#include <sys/ptrace.h>

long ptrace(enum __ptrace_request request, pid_t pid,

void *addr, void *data);


Der ptrace Systemcall ist ein Hilfsmittel der es einem Elternprozess erlaubt,

einen anderen Prozess auszuführen und diesen zu Überwachen. Gleichzeitig

erhalten wir dadurch die Möglichkeit Registervariablen auszulesen und zu

manipulieren.


Beispiel:

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.


-------------geteuid.c-----------------


#include <sys/types.h>

#include <stdio.h>

#include <stdlib.h>


int main(void)

{

char* env;

if((env=getenv("LD_PRELOAD"))!=NULL) {

exit(-1);

}

printf("EUID=%i\n",geteuid());

return 0;

}

 

-------------geteuid.c-----------------


cr@chronos:~$ gcc -o geteuid geteuid.c

cr@chronos:~$ ./geteuid

EUID=1000

cr@chronos:~$ ./seuid.sh

cr@chronos:~$


Wenn LD_PRELOAD gesetzt ist beendet sich das Programm einfach. In diesem Fall

zB. kommt ptrace ins Spiel. Ich werde hier nur einige Grundlagen nennen für

weitergehende Informationen unbedingt die man pages lesen!


Der Linuxkernel unterstüzt verschiedene sogenannte Systemcalls, aktuell im

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.


Der Plan ist erstmal recht simple wir überwachen mit ptrace die Systemcalls

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.


cr@chronos:~$ grep "geteuid" /usr/include/asm-i486/unistd.h

#define __NR_geteuid32 201


Der Systemcall geteuid hat die nummer 201.


-------------ptrace_euid.c-----------------


#include <sys/ptrace.h>

#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 main(void)

{

int status = 0;

int pid;

struct user_regs_struct uregs;


if ((pid=fork())==-1) {

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);


while (wait(&status) && !WIFEXITED(status)) {

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-----------------


Erklärungen zum Code:

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:~$ gcc -o ptrace_euid ptrace_euid.c

cr@chronos:~$ ./ptrace_euid

EUID=666

done.

cr@chronos:~$


Und wieder haben wir unsere euid korrigieren können :)


Info:

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 >