jueves, 20 de marzo de 2014

Un pequeño desafío - La solución (I)

En el post expliqué como realizar un exploit sobre un simple programa. Una vez resuelto mandé la respuesta a @brutelogic


Pues no ponemos manos a la obra.

En el post anterior ya anticipaba:
Ahora deberíamos de intentar sacar partido de esta vulnerabilidad.
Una vía para conseguirlo es sobreescribir el texto "clear" que es usado en la invocación a la funcion system y sustituirlo por otro valor. Por ejemplo: cmd.exe

Esto es más fácil de decir que de realizar, aunque tampoco es demasiado difícil hacerlo. La lógica del exploit será:
  • Poner en la pila el comando que deseamos ejecutar
  • Devolver control al programa cuando va a llamar a la función system
Que codificado en ensamblador queda así.


call ubica1
ubica1:
pop ebx
mov eax, ebx
add eax, shelloff
push eax
mov eax,0040108fh ; Dirección de la llamada a la función system
jmp eax
nop
shelloff equ $-ubica1
shell db 'start cmd'
shelllenght equ $-shell


Las sentencias son sencillas aunque vamos a analizarlas un poco pues si no se tiene experiencia en la codificación de este tipo de código hay cosas que puede parecer extrañas.
Y lo extraño está en la primera sentencia: se realiza una llamada (call) a la instrucción siguiente. ¿Que sentido tiene esto?.
Una característica que tienen los programas compilados y linkeditados es que todas las direcciones tanto internas como externas están resueltas y funcionamos en base a los desplazamientos respecto a esas direcciones que se corresponden con los distintos segmentos: datos inicializados, datos sin inicializar, segmento de código y referencias a otros módulos.
Pero al entrar desde una shell estamos en terreno desconocido y lo primero que hay que hacer es conocer la dirección en la que estamos cargados.
Repasemos lo que hace la instrucción call:


  • Carga la dirección siguiente a la call en la pila
  • Transfiere el control a la dirección indicada en su parámetro.

Según esta lógica lo que estamos haciendo con call siguienteinstrucción es cargar en la pila la dirección se la siguiente instrucción y ceder control a la siguiente instrucción. Luego extraemos el primer elemento de la pila y ya tenemos cargada la ubicación del programa que estamos realizando:

call ubica1
ubica1:
pop ebx

El siguiente paso es llevar a la pila el comando que deseamos cargar que será arrancar una shell de comandos. (podemos arrancar cualquier otro programa si es lo que deseamos hacer).
Aunque estamos ubicados (Registro EBX en este caso) seguimos sin poder dirigirnos a las zonas de memoria por su etiqueta pero podemos calcular el desplazamiento del texto que queremos introducir. Solo tenemos que sumar al registro EBX que contiene la dirección de la etiqueta ubica1 el desplazamiento con respecto a dicha etiqueta

mov eax, ebx
add eax, shelloff ; desplazamiento del texto
push eax

Sólo nos queda pues ceder el control nuevamente al programa inicial justo en la instrucción que va a llamar a la función system. (Ya tenemos cargado en la pila el comando que deseamos ejecutar).







mov eax,00401076h                    ; Dirección de la llamada a la función system
jmp eax

Esto en teoría debería bastar para aún es necesario hacer algunos ajustes más que veremos en el próximo post.


No hay comentarios:

Publicar un comentario