fun and profit Injection de code sous GNU/Linux Nicolas Bareil [email protected] EADS Corporate Research Center - DCR/STI/C SSI Lab SSTIC 2006 Nicolas Bareil Playing with ptrace() for fun and profit
fois. . . Sous UNIX, ptrace() est le seul moyen de debuggage. User-space, Interface rigide et minimaliste, Privil` ege root non n´ ecessaire, ´ El´ eguant ; D’apr` es la page de manuel de SunOS ptrace() est unique et myst´ erieux. Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Plan 1 ptrace() 2 Injection de code 3 Applications pratiques Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage man ptrace Prototype #include <sys / ptrace . h> long ptrace (enum ptrace request request , pid t pid , void ∗addr , void ∗data ) ; Trois modes de tra¸ cage : Mode pas ` a pas, Par appel syst` eme, Tra¸ cage passif ; Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Actions classiques, document´ ees Requˆ ete Signification PTRACE_TRACEME PTRACE_ATTACH Attachement ` a un processus PTRACE_DETACH PTRACE_PEEKTEXT PTRACE_PEEKDATA Lecture m´ emoire PTRACE_PEEKUSR PTRACE_POKETEXT PTRACE_POKEDATA ´ Ecriture m´ emoire PTRACE_POKEUSR PTRACE_GETREGS Lecture des registres PTRACE_SETREGS ´ Ecriture des registres Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Manipulation des signaux Signaux & ptrace() Un processus trac´ e est stopp´ e ` a la r´ eception de chaque signal. Pour le tra¸ ceur, l’arrˆ et semble ˆ etre dˆ u ` a un SIGTRAP. L’option PTRACE_GETSIGINFO permet d’en connaˆ ıtre plus sur la raison de la notification. typedef struct siginfo { int si_signo ; /* num´ ero de signal */ int si_errno ; int si_code ; /* provenance : user ? kernel ?*/ ... } siginfo_t ; Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Manipulation des signaux Signaux & ptrace() Un processus trac´ e est stopp´ e ` a la r´ eception de chaque signal. Pour le tra¸ ceur, l’arrˆ et semble ˆ etre dˆ u ` a un SIGTRAP. L’option PTRACE_GETSIGINFO permet d’en connaˆ ıtre plus sur la raison de la notification. typedef struct siginfo { int si_signo ; /* num´ ero de signal */ int si_errno ; int si_code ; /* provenance : user ? kernel ?*/ ... } siginfo_t ; Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Manipulation des signaux Signaux & ptrace() Un processus trac´ e est stopp´ e ` a la r´ eception de chaque signal. Pour le tra¸ ceur, l’arrˆ et semble ˆ etre dˆ u ` a un SIGTRAP. L’option PTRACE_GETSIGINFO permet d’en connaˆ ıtre plus sur la raison de la notification. typedef struct siginfo { int si_signo ; /* num´ ero de signal */ int si_errno ; int si_code ; /* provenance : user ? kernel ?*/ ... } siginfo_t ; Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Protection anti-ptrace() int s tayal i ve ; void trapcatch ( int i ) { s tayal i ve = 1; } int main( void ) { . . . s tayal i ve = 1; signal (SIGTRAP, trapcatch ) ; while ( s tayal i ve ) { s tayal i ve = 0; k i l l ( getpid () , SIGTRAP) ; do the work ( ) ; } . . . Anti-ptrace() Protection bas´ ee sur le fait qu’un debugger classique ne peut pas diff´ erencier les signaux envoy´ es par le noyau ou par l’utilisateur. Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Anti-anti-ptrace() Deux moyens de d´ eterminer l’origine du SIGTRAP : Manuel, fastidieux, non-portable Mode pas-` a-pas ? =⇒ bit single-step du processeur, Arrˆ eter par point d’arrˆ et mat´ eriel ? =⇒ registres de debuggage ; Dans un appel syst` eme ? ´ El´ egant, portable, classe quoi Utiliser ptrace(PTRACE_GETSIGINFO, pid, NULL, &sig). =⇒ sig.si_code == SI_USER ? Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Options de tra¸ cage : suivi des enfants Probl` eme de fork() Solution basique : 1 ` A l’appel ` a fork(), on surveille le code de retour, =⇒ on r´ ecup` ere ainsi le PID du fils 2 On s’attache au nouveau processus, 3 On se met ` a le tra¸ cer ; Pwned ! Race condition detected ! Le scheduler peut laisser le fils ex´ ecuter des instructions avant de rendre la main au traceur. Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Options de tra¸ cage : suivi des enfants Probl` eme de fork() Solution basique : 1 ` A l’appel ` a fork(), on surveille le code de retour, =⇒ on r´ ecup` ere ainsi le PID du fils 2 On s’attache au nouveau processus, 3 On se met ` a le tra¸ cer ; Pwned ! Race condition detected ! Le scheduler peut laisser le fils ex´ ecuter des instructions avant de rendre la main au traceur. Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Follow me ! Les options PTRACE_O_TRACEFORK & Co servent ` a r´ egler ce probl` eme : Attachement automatique au fils, Le noyau met le fils en ´ etat STOPPED avant mˆ eme qu’il soit d´ eclar´ e RUNNABLE. ptrace (PTRACE SETOPTIONS, pid , NULL, PTRACE O TRACESYSGOOD) ; Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Acc` es ` a l’espace d’adressage Lecture d’un mot m´ emoire errno = 0; ret = ptrace (PTRACE PEEKTEXT, pid , targetaddr ,NULL) ; i f ( errno && ret == −1) { perror ("ptrace_peektext()" ) ; return 1; } Lecture de plusieurs octets char buf [BUFMAX] ; int fd = open("/proc/pid/mem" , O RDONLY) ; pread ( fd , buf , BUFMAX, offset ) ; Nicolas Bareil Playing with ptrace() for fun and profit
ees Acc` es ` a l’espace d’adressage Acc` es ` a l’espace d’adressage Lecture d’un mot m´ emoire errno = 0; ret = ptrace (PTRACE PEEKTEXT, pid , targetaddr ,NULL) ; i f ( errno && ret == −1) { perror ("ptrace_peektext()" ) ; return 1; } Lecture de plusieurs octets char buf [BUFMAX] ; int fd = open("/proc/pid/mem" , O RDONLY) ; pread ( fd , buf , BUFMAX, offset ) ; Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Plan 1 ptrace() 2 Injection de code 3 Applications pratiques Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme O` u injecter les instructions ? Objectifs Discr´ etion, Stabilit´ e, Portabilit´ e ; Les candidats sont : La pile, Padding des sections ELF, N’importe o` u ; Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Injection n’importe o` u On ´ ecrit directement sur les instructions point´ ees par eip. 1 Sauvegarde des octets d’eip, 2 ´ Ecrasement par nos instructions, 3 Red´ emarrage du processus (PTRACE_CONT), 4 Restauration des anciennes instructions ; Papa, r´ eveille toi ! k i l l (SIGTRAP, getpid ( ) ) ; Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Injection n’importe o` u On ´ ecrit directement sur les instructions point´ ees par eip. 1 Sauvegarde des octets d’eip, 2 ´ Ecrasement par nos instructions, 3 Red´ emarrage du processus (PTRACE_CONT), 4 Restauration des anciennes instructions ; Papa, r´ eveille toi ! k i l l (SIGTRAP, getpid ( ) ) ; Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Injection dans la pile mov ebx, 1 add eax, 4 cmp eax, 42 esp eip Fig.: Avant l’injection add eax, 4 cmp eax, 42 Code injecté esp eip ret ... ... mov ebx, 1 Fig.: Apr` es injection Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Injection dans la pile add eax, 4 cmp eax, 42 Code injecté ret ... ... mov ebx, 1 eip old eip eip est sauvegard´ e sur la pile, eip pointe sur *esp, Le shellcode se termine par un return =⇒ Retour aux instructions normales ; Pr´ ecautions =⇒ La pile doit ˆ etre ex´ ecutable ! Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Interruption d’un appel syst` eme L’injection de code dans un processus interrompu dans un appel syst` eme peut poser des probl` emes en fonction de leurs natures : Non-interruptibles, Interruptibles, pour les appels syst` eme lent Red´ emarrable manuellement (code de retour ´ egal ` a EINT), Red´ emarrable automatiquement par le noyau ; Sh*t happens. . . Le red´ emarrage automatique est le cas le plus probl´ ematique car l’injecteur n’a aucun contrˆ ole sur le noyau. =⇒ D´ ecr´ ementation d’eip de 2 octets. Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Interruption d’un appel syst` eme L’injection de code dans un processus interrompu dans un appel syst` eme peut poser des probl` emes en fonction de leurs natures : Non-interruptibles, Interruptibles, pour les appels syst` eme lent Red´ emarrable manuellement (code de retour ´ egal ` a EINT), Red´ emarrable automatiquement par le noyau ; Sh*t happens. . . Le red´ emarrage automatique est le cas le plus probl´ ematique car l’injecteur n’a aucun contrˆ ole sur le noyau. =⇒ D´ ecr´ ementation d’eip de 2 octets. Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Shellcode : Le bon, la brute et le truand Le truand Toujours pr´ ec´ eder votre shellcode de deux octets inertes (NOP) et faire pointer eip sur &(shellcode+2). La brute Faire les mˆ emes v´ erifications que le noyau avant d’injecter. =⇒ V´ erifier orig eax et eax. Le bon Utiliser l’option ad´ equate de ptrace() : PTRACE_O_SYSGOOD. Nicolas Bareil Playing with ptrace() for fun and profit
instructions ? Interruption d’appel syst` eme Oasis is good ! man PTRACE O TRACESYSGOOD L’option PTRACE_O_SYSGOOD modifie si_code de la structure siginfo_t pour indiquer l’interruption d’un appel syst` eme. ptrace (PTRACE SETOPTIONS, pid , NULL, PTRACE O TRACESYSGOOD) ; . . . s i g i n f o t sig ; ptrace (PTRACE GETSIGINFO, pid , NULL, &sig ) ; i f ( sig . si code & 0x80 ) p r i n t f ("was in a syscall\n" ) ; Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Plan 1 ptrace() 2 Injection de code 3 Applications pratiques Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Technique de l’oracle & Skype Oracle Jetez une question dans un puits et la r´ eponse est renvoy´ ee. T´ el´ ephone compatible Skype ? Le chiffrement des paquets est r´ ealis´ e par une fonction trop compliqu´ ee ` a reverser ? Plutˆ ot que de r´ e´ ecrire la fonction, utilisez la ! ` A l’aide de ptrace(), manipulez eip afin de n’ex´ ecuter que la fonction de chiffrement. =⇒ Au retour de la routine, vous avez la r´ eponse ! Voir pr´ esentation de P. Biondi & F. Desclaux ` a BlackHatEurope06. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Protection anti-reverse engineering Premi` ere protection anti-debugging ? Un processus ne peut-ˆ etre tra¸ c´ e que par un seul debugger ` a la fois. → Auto-tra¸ cage pour empˆ echer tout attachement ult´ erieur R´ eponse des analystes ´ Emulation de l’appel ` a ptrace() pour qu’il n’´ echoue jamais. R´ eponse ` a la r´ eponse des analystes Lancement de deux processus qui se tra¸ cent mutuellement avec un dialogue permanent pour s’assurer de la survie de l’autre. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Protection anti-reverse engineering Premi` ere protection anti-debugging ? Un processus ne peut-ˆ etre tra¸ c´ e que par un seul debugger ` a la fois. → Auto-tra¸ cage pour empˆ echer tout attachement ult´ erieur R´ eponse des analystes ´ Emulation de l’appel ` a ptrace() pour qu’il n’´ echoue jamais. R´ eponse ` a la r´ eponse des analystes Lancement de deux processus qui se tra¸ cent mutuellement avec un dialogue permanent pour s’assurer de la survie de l’autre. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Protection anti-reverse engineering Premi` ere protection anti-debugging ? Un processus ne peut-ˆ etre tra¸ c´ e que par un seul debugger ` a la fois. → Auto-tra¸ cage pour empˆ echer tout attachement ult´ erieur R´ eponse des analystes ´ Emulation de l’appel ` a ptrace() pour qu’il n’´ echoue jamais. R´ eponse ` a la r´ eponse des analystes Lancement de deux processus qui se tra¸ cent mutuellement avec un dialogue permanent pour s’assurer de la survie de l’autre. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall ´ Evasion d’environnement chroot´ e ch[ouc]root ? Simple restriction de la racine du syst` eme de fichier d’un processus. Contact ext´ erieur possible : m´ emoire partag´ ee, signaux. . . Pwned ! Si on peut envoyer des signaux ` a des processus, on peut les tra¸ cer ! =⇒ Injection d’un shellcode permettant de s’´ evader de la cage. Si /proc n’est pas disponible, le bruteforcage de tous les PID est n´ ecessaire. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall ´ Evasion d’environnement chroot´ e ch[ouc]root ? Simple restriction de la racine du syst` eme de fichier d’un processus. Contact ext´ erieur possible : m´ emoire partag´ ee, signaux. . . Pwned ! Si on peut envoyer des signaux ` a des processus, on peut les tra¸ cer ! =⇒ Injection d’un shellcode permettant de s’´ evader de la cage. Si /proc n’est pas disponible, le bruteforcage de tous les PID est n´ ecessaire. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall ´ Evasion d’environnement chroot´ e ch[ouc]root ? Simple restriction de la racine du syst` eme de fichier d’un processus. Contact ext´ erieur possible : m´ emoire partag´ ee, signaux. . . Pwned ! Si on peut envoyer des signaux ` a des processus, on peut les tra¸ cer ! =⇒ Injection d’un shellcode permettant de s’´ evader de la cage. Si /proc n’est pas disponible, le bruteforcage de tous les PID est n´ ecessaire. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Firewall applicatif D´ efinition ACLs bas´ ees sur l’application. =⇒ Application autoris´ ee == tremplin Objectifs d’un programme malicieux : Injection d’un connect() dans Mozilla, R´ ecup´ eration du descripteur de fichier, Transfert du descripteur de fichier au processus malicieux ; Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Processus malicieux Mozilla Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Processus malicieux Mozilla connect() Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Processus malicieux Mozilla connect() Transfert du descripteur de fichier Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Processus malicieux Mozilla connect() read() / write() Transfert du descripteur de fichier Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Contrainte Figure de style impos´ ee R´ eussir ` a faire passer toutes les applications ` a travers ce (( tunnel )). Interception des biblioth` eques dynamiques $ LD PRELOAD="/home/moi/lib/liberte.so" $ export LD PRELOAD $ wget http :// slashdot . org/ Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Surchage de connect() int connect ( int sockfd , struct sockaddr ∗ serv addr , socklen t addrlen ) { pid t pid = atoi ( getenv ("PTRACE_PWNED" ) ) ; socket (PF UNIX, SOCK STREAM, 0 ) ; . . . i f ( fork () == 0) { i n j e c t s h e l l c o d e ( pid , serv addr ) ; exit ( 0 ) ; } . . . fd = receive fd ( unixfd ) ; dup2( fd , sockfd ) ; return sockfd ; } Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Fonctionnalit´ ee m´ econnue Transfert de descripteur de fichier Il est possible de transmettre un descripteur de fichier entre deux processus ind´ ependants ` a travers une socket UNIX. struct cmsghdr ∗ch ; struct msghdr msg ; char a n c i l l a r y [CMSG SPACE( s i ze o f ( fd ) ) ] ; ch = CMSG FIRSTHDR(&msg ) ; ch−>cmsg level = SOL SOCKET; ch−>cmsg type = SCM RIGHTS; ∗( int ∗) CMSG DATA( ch ) = fd ; sendmsg( sockfd , &msg, 0 ) ; Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Shellcode Le shellcode : 1 Cr´ e´ e une socket UNIX vers le traceur, 2 Initie la connexion vers le serveur d´ esir´ e, 3 Et envoie le descripteur de fichier. Ne g` ere pas encore l’UDP. Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Conclusion ptrace() et ses limites Fonctions limit´ ees, Portabilit´ e impossible, Bugs historiques ; L’avenir L’avenir se tourne vers les dtrace-like ? Solution compl´ etement kernel-space, Haut niveau, Scriptable ; Nicolas Bareil Playing with ptrace() for fun and profit
de la force Cˆ ot´ e obscur de la force Cas pratique : Contournement de firewall Des questions ? Merci de votre attention ! Des questions ? Nicolas Bareil Playing with ptrace() for fun and profit