elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Recopilación Tutoriales y Manuales Hacking, Seguridad, Privacidad, Hardware, etc


  Mostrar Temas
Páginas: [1]
1  Seguridad Informática / Desafíos - Wargames / Resolviendo el CTF: RickdiculouslyEasy: 1 @ VulnHub.com en: 5 Noviembre 2017, 17:49 pm
Buenas a modo de aporte, dejo este posteo que realice en mi blog sobre un CTF que hice paso a paso para resolverlo. Vulnhub es una pagina que cuenta con un sinfin de CTFs/sistemas preparados para ser atacados. Ojala sea de utilidad este aporte e insite a que muchos comiencen a postear sus metodos de resolverlos.

https://www.vulnhub.com/author/cnfs,358/  - Mi blog mirar firma
Link de referencia del CTF: https://www.vulnhub.com/series/rickdiculouslyeasy,134/

Let's GO!



Se procede a escanear el host vulnerable, en mi caso siguiente IP: 192.168.0.93.
$> nmap -p 1-65535 -T4 -A -v 192.168.0.93

El resultado arroja datos interesantes, posee los siguientes puertos abiertos:



Procedo a testear cada puerto en busca de informacion util.. empiezo con el vsftpd en el puerto 21, utilizando Filezilla, como no tengo ninguna credencial, simplemente conecto y veo que loguea como Anonymous..



Si entro al directorio /pub/, veo que no hay nada, y que no tengo permisos tampoco para crear archivos. Me queda verificar el otro archivo interesante llamado "FLAG.txt":

FLAG{Whoa this is unexpected} - 10 Points

Ok, ya tenemos 10 puntos de 130.
Mmm... esto me recuerda a "http://www.tzr.io/yarn-clip/8398500e-ebb2-48d8-8e75-28c23727732d"

Conecto al puerto 22 con netcat y me encuentro con lo siguiente:



Es raro porque el CTF corre en un fedora, sin embargo nos arroja un banner de "Ubuntu 14.04", sin dudas hay algo que no anda bien ahi.. sigo investigando.

Abro el browser y conecto al site que tiene en el puerto 80, una imagen de fondo y el codigo fuente no parece arrojar mucho contenido:



Verifico con el browser el puerto 9090; el cual segun nmap nos habla de un 'Cockpit web service', para interiorizarme un poco mas encuentro la siguiente url: https://www.poftut.com/cockpit-easy-web-administration-linux/. La cual nos explica que es una app web que provee una facil administracion para servers linux, principalmente desarrollada para Fedora pero que pueden ser usadas en otras distros tambien.

Sin embargo, en esa web vemos que poseemos un LOGIN correcto con su respectivo campo de USERNAME y PASSWORD, cosa que no vemos en el host vulnerable. Como sea, obtenemos 10 puntos mas segun la frase del index "FLAG {THERE IS NO ZEUS, IN YOUR FACE!} - 10 POINTS":



Ok continuamos.. el siguiente puerto raro es el 13337:



Bien, conseguimos 10 puntos mas.. ya llevo "30 puntos" de 130. Sigo..

De momento el puerto 22222 donde parece haber un servidor SSH no me es interesante, solo de momento, y procedo a conectar al siguiente y ultimo puerto el 60000:



Wow.. parece ser una reverse shell.. publica???. Investigo y me permite alistar archivos y encontrar un flag mas, ahora tenemos 40 puntos de 130:


# ls -lah
FLAG.txt
# cat FLAG.txt


FLAG{Flip the pickle Morty!} - 10 Points

Sin embargo, no puedo hacer mucho mas, que decepcion..

Voy a enfocarme en el sitio web a ver si puedo encontrar algo. Realizo un escaneo simple con Nikto y me arroja lo siguiente:



Veo que existe el archivo "robots.txt".. suelo darle prioridad siempre a eso, luego prosigo con lo demás en el orden correspondiente. Este archivo suele darme una idea, de que cosas el administrador quiere que los bots, personas, etc, encuentren y que no.



Bien se pone interesante, si me dirijo a root_shell.cgi, no puedo hacer mucho, ademas del mensaje en el codigo fuente gracioso, luego el directorio en general cgi-bin no me permite ver el contenido.
Lo único que permite hacer algo es el "tracertool.cgi".. que como dice su nombre, parece ser una herramienta tracert.



Bien por lo que veo el funcionamiento no es mas que una simple llamada a "traceroute" por ejemplo:


$> traceroute google.com


Se me viene a la mente de poder lograr hacer command injection, es un simple ataque en el que se busca como objetivo ejecutar codigo arbitrario remotamente sobre el sistema operativo host via una app vulnerable como en este caso puede ser el form del trace.

Se podría romper de varias maneras la instrucción pero con un simple ";" creo que bastaría seguido de un pwd:



Bien, vamos a intentar cat'ear el passwd:


;cat /etc/passwd


Y obtenemos la respuesta de un grafico ASCII lo que parece ser un gato.. so.. algo anda mal, voy a probar verificar con otro archivo, intento un $> cat /bin/bash y me arroja nuevamente el gato.
Por ende, creo entender que pasa, el /usr/bin/cat fue modificado... para que siempre que se use, termine arrojando el gatito.. vamos a probar otro comando, podria ser HEAD, o MORE.

Voy a sacarme la duda y hago un MORE /usr/bin/cat a ver que pasa:



Bingo, como deduje el binario 'cat' fue modificado.. ahora sabemos que el MORE funciona bien. Probamos nuevamente con ;more /etc/passwd:



Ok, obtuvimos el password que estaba oculto en el html como comentario. No tengo otra mejor idea que probar este password con los 3 usuarios que encontramos anteriormente en el sistema:


  • shad0w@SHRC-GOV:~$ ssh RickSanchez@192.168.0.93 -p 22222
    The authenticity of host '[192.168.0.93]:22222 ([192.168.0.93]:22222)' can't be established.
    ECDSA key fingerprint is SHA256:rP4CX/V9xNZay9srIUBRq2BFQTnmxUO9cs1F3E9yzg0.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '[192.168.0.93]:22222' (ECDSA) to the list of known hosts.
    RickSanchez@192.168.0.93's password:
    Permission denied, please try again.


No tuve suerte con RickSanchez, tampoco con Morty, sin embargo....Summer funciono:



Ok, alisto los archivos y veo el FLAG.txt:


  • [Summer@localhost ~]$ ls -lah
    total 20K
    drwx------. 2 Summer Summer  99 sep 15 11:49 .
    drwxr-xr-x. 5 root   root    52 ago 18 18:20 ..
    -rw-------. 1 Summer Summer   1 sep 15 11:51 .bash_history
    -rw-r--r--. 1 Summer Summer  18 may 30 14:53 .bash_logout
    -rw-r--r--. 1 Summer Summer 193 may 30 14:53 .bash_profile
    -rw-r--r--. 1 Summer Summer 231 may 30 14:53 .bashrc
    -rw-rw-r--. 1 Summer Summer  48 ago 22 02:46 FLAG.txt
    [Summer@localhost ~]$ more FLAG.txt

FLAG{Get off the high road Summer!} - 10 Points

Ahi tenemos 10 puntos mas y ya vamos 50 puntos de 130. Aprovecho ir a /var/www/html/passwords/FLAG.txt que anteriormente no habia ido y se me paso por alto para obtener 10 puntos mas. Ahora tenemos 60 de 130 puntos.

Investigo por los diferentes /home/ y veo que en el de /home/Morty hay dos files interesantes:


  • [Summer@localhost Morty]$ ls
    journal.txt.zip  Safe_Password.jpg

El journal.txt.zip esta comprimido con clave. El archivo Safe_Password.jpg parece tener algun tipo de pista con ese nombre.. por ende trato de descargarlo para analizarlo mejor localmente..

Lo descargo via SSH con el SCP de la siguiente manera:


  • shad0w@SHRC-GOV:~$ scp -P 22222 Summer@192.168.0.93:/home/Morty/Safe_Password.jpg /home/shad0w/Escritorio/


Trato de extraer cadenas del archivo a modo investigación manual y me encuentro con lo siguiente:



Bingo, parece que tenemos un posible password.. trato de descargar el archivo comprimido y luego procedo a extraerlo:



Genial, 20 puntos mas.. 80 de 130 tenemos. Y prestamos atencion al mensaje del FLAG que nos da una pista, 131333.

Sigo investigando y me voy a la carpeta de RickSanchez/, me encuentro un file llamado SAFE, parece ser un binario, si embargo como muestro en la imagen al estar con el usuario Summer y verificar los permisos del archivo Safe, no me permitiría ejecutarlo ya que no tiene permisos:



Bien lo que se me ocurre es copiarlo a alguna carpeta en la que podamos ejecutarlo, y nos pertenezca.
Podriamos probar en /home/Summer o el clasico y viejo amigo /tmp.. de momento lo hice en /home/Summer, luego lo ejecute sin argumentos el cual recibo una pista, y recuerdo el numero de flag que me habia dado anteriormente junto al mensaje, era: 131333. Pruebo nuevamente ejecutando safe y el numero se lo paso como argumento, recibo lo siguiente:



Recibimos 20 puntos mas, obteniendo 100 puntos de 130. El mensaje deja algunas pistas como las de no olvidar como crear un script para generar passwords, que sigamos esas pistas en orden.. 1 uppercase y 1 digito.. mmmm algo tendre que romper je je. Como ultima pista nos dice que la palabra tiene como relacion su antigua banda.

Como no soy seguidor sinceramente de esta serie, busco en google por ayuda.. con un simple search con palabras clave como "rick sanchez+old band", el primer resultado me informa que la banda de Rick Sanchez era:



Bien, tenemos el nombre de la banda "The Flesh Curtains". Y el mensaje anterior nos dijo que hagamos las cosas en ORDEN, por ende la password estaría compuesta de la siguiente manera según las pistas dadas: 1 UPPERCASE + 1 DIGIT + 1 PALABRA DE SU ANTIGUA BANDA (Flesh o Curtains, como el THE es un articulo, trato de no probarlo, en caso de que falle lo incluyo mas adelante nuevamente).

Podría hacerlo de varios modos el diccionario, pero voy a codear algo simple en python.



Una vez se me genera el diccionario uso un programa como THC HYDRA para atacar el SSH.



Y luego de unos minutos de ataque por fuerza bruta el diccionario funciono:



Bingooooo... bien, de que sirve esto?, conectarnos por SSH como RickSanchez, con una pista del flag anterior que decía "Sudo is wheely good".. que me esta queriendo decir? que RickSanchez pertenece al grupo sudoers?. Como me doy cuenta si un usuario en Linux tiene permisos sudo? fácil, con $> sudo -l, a continuación pongo la diferencia a la izquierda logueado con RickSanchez y a la derecha con Summer... ambos tipeando sudo -l:



Confirmamos que RickSanchez pertenece a SUDOERS y puede ejecutar lo que se le de la gana. Hacemos un simple "sudo su" y somos root. Nos vamos a la carpeta /root/ y vemos el FLAG.txt. Obtenemos el ultimo flag y los 30 puntos que nos llevan a 130. CTF RESUELTO!! :D

# shad0wCNFS
# blog: mirar firma

MOD: Link propio redireccionado a firma de usuario.
2  Seguridad Informática / Bugs y Exploits / How to exploit.. de basico a avanzado (3era Parte): GDB en Linux mas a fondo. en: 10 Marzo 2013, 05:17 am
Buenas antes que nada, queria aclarar que estoy con ganas de 'escribir' algunos papers enfocados a exploiting desde un entorno Linux, da igual para Windows a excepción de algunas herramientas obviamente.
Estoy aca hace años asi que queria compartir esto con ustedes, ya que hay gente bastante experimentada.. me gustaria ver su punto de vista..

Son 3 posteos en 1 solo, ya que fui sacando por partes, es una introduccion a gdb desde linux.. una base para ir escalando y meternos en el exploiting..




#How to Exploit.
Estos papers que pienso escribir iran enfocados para aquellos que tengan curiosidad sobre como explotar vulnerabilidades, descubrirlas, realizar ingeniería inversa, etc etc..
Me enfocare desde mi entorno Linux, pero es viable para Windows también, salvo excepciones de algunas herramientas, la esencia es la misma.

¿Requisitos?.
Simplemente tener conocimientos basicos de programación.. compiladores, arquitectura, todo lo que nos rodea y usamos habitualmente, y en otros casos lo usamos pero no tenemos idea que lo hacemos.. Un requisito mas podria ser el saber y querer entender 'el porque de las cosas', no tirar un exploit a lo scriptkiddie. De todas maneras intentare enfocarme y detallar lo maximo que pueda. Para el resto, Google. Usare muchas herramientas como GDB, Objdump, IDA, GCC, Python,etc, etc..

#Primero, lo aburrido, pero necesario para entender.
Vamos a familiarizarnos un poco con el código fuente, compilar, desensamblar, algunas herramientas que ayudan este proceso y todas esas cosas.
Para empezar tenemos preparado para esta prueba un pequeño codigo fuente  "analizaMe",
esta codeado en C, y es de lo mas básico, pero me ayudara a explicarlo de manera rápida.. asi que deberíamos compilarlo. ¿Compilar?.

Suponiendo que si llegan hasta acá, siguieron al pie los requisitos de tener conocimientos basicos de programación, assembler, etc..  no sera muy difícil entender lo que refresco por encima a continuacion. Para comprender realmente el significado de Compilar, tenemos que movernos al origen de los procesadores, pero resaltaremos lo importante, el procesador x86.
Intel desarrollo la cpu 8086 que fue el primer procesador x86.. luego creo otros mas avanzados como el 386, 486.. etc.. El procesador x86 que se refiere a los anteriormente mencionados, posee varios registros que son como las 'variables' internas para dicho procesador. Algunos de estos registros son los conocidos 'EAX,ECX,EDX,EBX', son registros usados para varios fines, entre ellos como contadores o acumuladores.. sirven como variables temporales para el procesador cuando esta ejecutando instrucciones. Hay 4 registros mas a resaltar que son 'EBP, ESP, ESI y EDI'.
Estos registros llevan el nombre de EBP puntero base, ESP puntero de pila, ESI indice de origen y EDI indice destino. El puntero EIP, es el puntero de instruccion, es quien nos ayuda y nos señala a la instruccion que el procesador esta leyendo en ese preciso momento.

Bueno, como sabrán con el código fuente no vamos a poder hacer nada, hasta el momento en el que lo compilamos y lo convertimos en un archivo ejecutable.
Let's Go!

El programa analizaMe:

Código
  1. #include <stdio.h>
  2. int main() {
  3.  int contar;
  4.  for(contar=0; contar < 5; contar++)
  5.  {
  6.    printf("La variable contar vale: %i \n", contar);
  7.  }
  8. }

Bien, lo primero sera explicar un poco este código, y luego compilarlo.
Básicamente y de manera rápida, este programa lo que hace es mostrar en pantalla un mensaje y el valor de la variable 'contar'. Mientras sea la variable menor de 5 el mensaje sera mostrado via la funcion 'printf'. Cuando llega a 5, el programa finaliza. Analicémoslo mas en detalle..
(cada vez que vean $> es la manera de decirles que son comandos a tipear en la shell)

Vamos a compilarlo con GCC (es el GNU Compiler Collection), la función de los compiladores basicamente es la de convertir el código fuente en lenguaje maquina, la manera en la que entienden los procesadores.

$> gcc analizaMe.c -o analizaMe
$> chmod +x
$> ./analizaMe


Invocamos al compilador y le decimos que nos compile el codigo fuente en c. El resultado es un nuevo archivo llamado analizaMe. Le damos permisos de ejecución. Y luego lo ejecutamos..
El resultado es el siguiente:

La variable contar vale: 0
La variable contar vale: 1
La variable contar vale: 2
La variable contar vale: 3
La variable contar vale: 4

Ok, vemos el resultado del programa, pero veamos que es lo que no esta a simple vista, como es que funciona este programa realmente..

Invocamos en la shell, a ojbdump, es una gran utilidad para desensamblar facilmente binarios compilados.

$> objdump -D analizaMe -M intel |grep -A15 main.:

(Le decimos a objdump que (-D) desensamble el binario 'analizaMe', (-M intel) que nos muestre el resultado con la sintaxis Intel ya que es mas prolija y acostumbrado que la de AT&T (por default objdump nos arroja esta ultima por eso es que forzamos a que nos muestre con la de Intel)).. (grep -A15 main.:) invocamos a 'grep' y aplicamos una expresión regular para que nos muestre solo las primeras 15 lineas de la funciona principal, main.
Podríamos no limitar a 15, pero arrojaría muchas lineas innecesaria para este momento.
Y hasta acá esta primera parte de introducción..

http://insecuritynotes.blogspot.com.ar/

---------------------------------------------------------------------------------------------------------------------

#How to exploit 2: Un poco de Assembler y GNU Debugger.




Traje esta segunda parte que escribí, nose si tienen sugerencias positivas o negativas, cualquiera me serviría. Saludos.

Retomando con el paper anterior, y nuestro código de ejemplo, vamos a repasar un poco sobre Assembler y GNU Debugger durante esta segunda parte. Veremos por 'encima' el tema de assembler ya que mi interés no es un tutorial de este, sino repasarlo para introducirlo con el Debugger.

Para invocar al GDB
Utilizaremos el crudo y puro gdb desde la linea de comandos con sintaxis INTEL.
Para configurar GDB con sintaxis INTEL, vamos a hacer lo siguiente:

$> sudo gedit /etc/gdb/gdbint

Y luego pegamos al final la siguiente linea y guardamos el archivo:

set disassembly-flavor intel

La sintaxis de intel nos mostrara las operaciones de esta manera en gdb:

instrucciones "[destino],[origen]"
Por ejemplo: "mov ebx, eax"

En este ejemplo el valor del registro 'eax', sera movido al registro 'ebx'.
Recordar que las operaciones del origen y destino pueden ser un valor,
una dirección de memoria, o un registro como en este caso.

Operaciones comunes que veremos en assembler para refrescar memoria:

MOV: Mueve contenido
INC: Incrementa de a 1 el valor
DEC: Resta de a 1 el valor
ADD: Suma 
SUB: Resta
CMP: Compara dos registros o un registro y dirección de memoria.
JMP/JNE etc: Todos los que empiecen con J.. son saltos condicionales e incondicionales.
Hay mas pero como dije, son los básicos y el paper no esta orientado a un manual de assembler.

 
# GDB

El debugger es una herramienta que nos permite ejecutar programas y analizarlos. Ya sea para localizar errores o entender un poco mas a fondo que es lo que hace una determinada aplicación.

GDB dispone de un comando muy particular y uno de los mas útiles a la hora de verificar la memoria.
Este comando se llama 'examine' y como su nombre indica, nos sirve para examinar la memoria.
GDB puede examinar detenidamente cada aspecto de la ejecución de un programa, ejecutarlo, detenerlo, verificar los registros, direcciones de memoria, lo que se nos ocurra.
(Lo practico de GDB también es que la mayoría de los comandos se pueden 'abreviar', por ejemplo examine se puede acortar a una simple 'x' y este se reconoce como un comando)

El comando examine, tiene varias maneras de arrojar la información que requerimos ver en una determinada dirección de memoria. Podemos especificar el formato en el que se muestra usando alguna de las siguiente abreviaturas:

x = Muestra el resultado en Hexadecimal
u = Muestra el resultado en Decimal.
o = Muestra el resultado en Octal.
t = Muestra el resultado en Binario.

Veamos un ejemplo con nuestro pequeño programa del paper anterior que adjunto nuevamente:


Código
  1. #include <stdio.h>
  2. int main() {
  3.  int contar;
  4.  for(contar=0; contar < 5; contar++)
  5.  {
  6.    printf("La variable contar vale: %i \n", contar);
  7.  }
  8. }
    $> gdb -q ./analizaMe
    De esta manera le pasamos a gdb el binario a debugguear.

    (gdb) break main
    Punto de interrupción 1 at 0x804840f (en mi caso esto nos responde gdb al poner un break)

    Le decimos que genere un breakpoint en la función principal "main". Un breakpoint no hace otra cosa que poner una barrera una vez que se ejecuta el programa, le dice al gdb que cuando llegue a nuestro breakpoint el programa se parara obligatoriamente ahi en ese break. Podemos poner varios break, de momento solo haremos uno en la función main.

    (gdb) run
    Breakpoint 1, 0x0804840f in main () (esto nos responde el gdb al encontrar el break que seteamos)

    Corremos el programa desde el debugger con run o también con una simple 'r' y va a parar en el primer breakpoint que seteamos en la función "main"

    (gdb) info register

    eax            0x1    1
    ecx            0xbffff344    -1073745084
    edx            0xbffff2d4    -1073745196
    ebx            0xb7fc1000    -1208217600
    esp            0xbffff2a8    0xbffff2a8
    ebp            0xbffff2a8    0xbffff2a8
    esi            0x0    0
    edi            0x0    0
    eip            0x804840f    0x804840f <main+3>
    eflags         0x246    [ PF ZF IF ]
    cs             0x73    115
    ss             0x7b    123
    ds             0x7b    123
    es             0x7b    123
    fs             0x0    0
    gs             0x33    51

    Este comando "info register" nos permite ver el estado actual de los registros.
    Como ven obtenemos un status de todos los registros de ese preciso momento.

    (gdb) info register eip
    eip            0x804840f    0x804840f <main+3> (respuesta del gdb)

    Podemos filtrar a algún registro en particular escribiéndolo al lado como en el ejemplo 'eip'.
    Además, como les conté antes podemos 'abreviar' este comando asi: "i r eip"
    Vemos como EIP contiene el valor 0x804840f.

    (gdb) x/x $eip
    0x804840f <main+3>:    0x83f0e483 (ahora examinamos la memoria a la que esta señalando el registro EIP usando la dirección almacenada en EIP). Vemos que donde arriba EIP contenia '0x804840f', examinamos este registro y contiene lo siguiente: 0x83f0e483.

    De esa manera usamos el 'examine' abreviado con la primer 'x', luego le decimos que nos arroje la info en hexadecimal con la segunda 'x'. Y el registro 'eip'. Fíjense que en este caso hay que poner el registro luego de un $. A diferencia de el info register que no lo anteponíamos.

    También se puede anteponer un numero al formato del comando examine, para examinar varias unidades en esas direcciones objetivos que tengamos. Por ejemplo:

    (gdb) x/4x $eip
    0x804840f <main+3>:    0x83f0e483    0x44c720ec    0x00001c24    0x19eb0000

    Las unidades tienen un tamaño predeterminado de 4 bytes. Conocidas como WORD.
    De la misma manera que podemos cambiar el formato que nos arroja el resultado con 'examine' ya sea en hexadecimal, octal, binario o decimal, tambien podemos cambiar el tamaño de las unidades que estamos examinando, agregandole una letra de tamaño al final de la de formato y estos son:

    b: byte
    h: half-word (2 bytes)
    w: word (4 bytes)
    g: giant o qword (8 bytes)


    Veamos un ejemplo practico:

    1)(gdb) x/4xb $eip
    0x804840f <main+3>:    0x83    0xe4    0xf0    0x83

    2)(gdb) x/4xh $eip
    0x804840f <main+3>:    0xe483    0x83f0    0x20ec    0x44c7

    3) (gdb) x/4xw $eip
    0x804840f <main+3>:    0x83f0e483    0x44c720ec    0x00001c24    0x19eb0000

    4) (gdb) x/4xg $eip
    0x804840f <main+3>:    0x44c720ec83f0e483    0x19eb000000001c24
    0x804841f <main+19>:    0x042444891c24448b    0xe8080484e82404c7

    1- Como vemos en el ejemplo uno, le decimos a gdb que nos examine el registro $eip, y nos arroje en 4 unidades, en hexadecimal, y en tamaño byte.
    2- En el segundo de la misma manera pero ya con 2 bytes.
    3- Igual pero con 4 bytes.
    4- Por ultimo igual, pero con 8 bytes.

    #Resumen de este paper:

    Ya sabemos, compilar un código fuente, gcc analizaMe.c.
    Sabemos invocar el gdb y pasarle un binario para debuggearlo: gdb -q ./analizaMe
    Sabemos que para poner un breakpoint y que se detenga el programa invocamos el comando 'break' + nombre de la función, o dirección en memoria donde queremos que pare.
    Sabemos que una vez que para en el breakpoint, podemos verificar el status de los registros mediante 'info register' o alguno en particular como en nuestro caso anterior 'info register eip'.
    Sabemos que la herramienta 'examine' nos permite verificar todas la memoria, direcciones y valores que se nos ocurra y arrojar el resultado de la manera que mas cómoda nos parezca, como en el ejemplo de 'x/x $eip' para ver el valor que contiene el registro EIP en ese momento y que nos arroje el resultado en hexadecimal.
    Sabemos como mostrar por unidades como "x/2x"
    Sabemos como mostrar examine en tamaño de unidades b,h,w,g (byte, 2bytes,4bytes, 8bytes).[/left][/li]


De momento dejamos acá esta segunda parte, y ya pronto escribo la tercera.
c0nfused.


---------------------------------------------------------------------------------------------------------------------

Vamos a retomar con este tercer paper, y analizar lo que hace nuestro humilde programa codeado en C.

Antes que nada, vamos a eliminar nuestro analizaMe compilado anteriormente, y vamos a volverlo a compilar con un parámetro nuevo que es la option flag "-g".
Genera mayor información de debug para ser utilizada por GDB.
Let's work!.

$> gcc -g analizaMe.c -o analizaMe (compilas con option flag -g)
$> chmod +x analizaMe (le damos permisos de ejecucion)
$> ./analizaMe (ejecutamos el binario para testear que todo haya salido correcto y recordar que hacia)

La variable contar vale: 0
La variable contar vale: 1
La variable contar vale: 2
La variable contar vale: 3
La variable contar vale: 4

Ok, todo funciono bien por fuera, analicemos que hace por dentro, con lo aprendido anteriormente en GDB.

ACLARACIÓN: Puede que las direcciones de memoria de SUS PCS respecto a las mías en estos ejemplos NO SEAN IGUALES. Y seria algo lógico..
Asi que no se preocupen, que podrán seguir igual los ejemplos...

$> gdb -q ./analizaMe (abrimos el binario creado con nuestro debugger favorito :))

(gdb) b main  (breakpoint en la funcion principal main)
Punto de interrupción 1 at 0x8048415: file analizaMe.c, line 4. (respuesta del gdb).

(gdb) r (corremos el programa con el comando run o r abreviado)
Breakpoint 1, main () at analizaMe.c:4
4      for(contar=0; contar < 5; contar++)

Bien como vemos, para en el punto de interrupción que nosotros mismos pusimos en main.
Y como vemos nos adjunta '+ información' gracias al option flag -g que agregamos.
Bien, vamos a verificar como esta el panorama..

(gdb) i r $eip
eip            0x8048415    0x8048415 <main+9>
(verificamos la información del registro $eip y vemos que apunta a esa direccion).

(gdb) x/3i $eip
=> 0x8048415 <main+9>:    mov    DWORD PTR [esp+0x1c],0x0
      0x804841d <main+17>:    jmp    0x8048438 <main+44>
      0x804841f <main+19>:    mov    eax,DWORD PTR [esp+0x1c]

Como anteriormente vimos, la opción 'i' era la de instrucción. Le decimos a GDB que nos muestre solo las próximas 3 instrucciones a ejecutarse para guiarnos de que esta haciendo el programa y que va a hacer.

Si hicieron la tarea y refrescaron un poco assembler, fundamental para explotar cualquier vulnerabilidad... recordamos también cuando explique algunas instrucciones de assembler, como por ejemplo 'mov'.

A simple vista entonces, GDB nos dice que donde ahora mismo esta parado, va a realizar una operación en la cual 'moverá' el valor de la derecha '0x0' hacia la izquierda en donde tenemos como destino una dirección en memoria (esp+0x1c). Nota: Es muy común ver este tipo de direcciones, porque si recordamos sabemos que EAX, EBX, EDI, ESI, ESP, etc son registros y es común leer ESP+4 o EBP-4 y cosas asi, este caso nos dice que lo va a mover a ESP+0x1c. 0x1c en decimal equivale a 28. Por lo que seria $esp+28.
Si recordamos también que el programa paro en nuestro breakpoint en main justo cuando comenzaba el for y nos arrojo esta información:

"4   for(contar=0; contar < 5; contar++)"

Podríamos deducir que ese valor 0x0 que va a mover, es el que le dimos en el FOR a nuestra variable llamada 'contar'.
Analicemos esa dirección de memoria que valor contiene en este momento con el programa pausado en nuestro breakpoint:

(gdb) i r $esp
esp   0xbffff270 (En el registro ESP encontramos una dirección de memoria 0xbffff270)

Por lo tanto BFFFF270 + 1C  (ESP+28) = BFFFF28C. (tranquilos, todo eso el debugger lo obvia por nosotros y lo sabe, pero para que entendamos, otra aclaración for dummys, siempre que veamos 0x12345678 esa '0x' del principio nos indica que es una notación Hexadecimal, la dirección seria 12345678.)

Bien, volviendo a la practica verificamos con GDB, la siguiente linea:

=> 0x8048415 <main+9>:    mov    DWORD PTR [esp+0x1c],0x0

(gdb) x/x $esp+0x1c
0xbffff28c:    0xb7fc1000

Como vemos nos responde lo que anteriormente les aclare, esp contiene una dirección y esa dirección + 28 (1c) es BFFFF28c, y GDB nos dice que esa dirección contiene el siguiente valor: 0xb7fc1000.
Por lo tanto lo que pasaría ahora es que al ejecutar la siguiente instrucción:

"mov    DWORD PTR [esp+0x1c],0x0" ..ese valor dejaria de existir y pasaria a ser 0x0 con la operacion de mov.

Voy a comentarles un nuevo comando el cual nos permite por asi decirlo, crear temporalmente un 'acceso directo' a una determinada direccion, para no tener que escribirla constantemente y verificar si tiene cambios en su contenido:

(gdb) print $esp+0x1c
$1 = (void *) 0xbffff28c

(Le decimos a gdb que nos cree una variable temporal de la dirección de memoria $esp+0x1c, para accederla fácilmente cuando queramos, y gdb nos responde diciendo que se creo la variable $1)

Ahora usaremos el comando 'nexti' para ejecutar  la siguiente instrucción, nexti hace que el programa vaya paso a paso, instruccion por instruccion, luego del breakpoint que pusimos.

(gdb) nexti
0x0804841d    4      for(contar=0; contar < 5; contar++)

Ejecutamos nexti. Veamos si la dirección $esp+0x1c (0xbffff28c)    0xb7fc1000 que contenía valores aleatorios.. ha cambiado.

(gdb) x/x $1 
0xbffff28c:    0x00000000

Efectivamente, se cumplió la operación 'mov' y movió el valor '0x0' a la dirección de esp+0x1c.
Veamos donde esta parado ahora el registro EIP y cuales son sus siguientes operaciones:

(gdb) x/10i $eip  (le decimos a gdb que nos arroje las proximas 10 instrucciones).



Como vemos en la imagen, EIP apunta a una instrucción en donde hay un JMP (JUMP), un salto el cual tiene como destino la dirección 0x8048438. Que es la 7ma linea de las 10 que pedimos que nos muestre. Le damos a nexti.

(gdb) nexti
0x08048438    4      for(contar=0; contar < 5; contar++)

Vemos que seguimos en el FOR.

(gdb) x/3i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>
      0x804843f <main+51>:    leave

Ok, confirmamos que salto a la dirección 8048438 como sabíamos.

Y ahora lo que va a hacer es a comparar mediante la instrucción 'cmp'. El valor 0x4 (4) contra el valor que esta guardado en la dirección [esp+0x1c] (nuestra famosa dirección que podemos acceder temporalmente mediante la variable $1 que seteamos anteriormente).

Como sabemos por la ultima vez que vimos la dirección esa contenía el valor '0'. Por lo tanto comparara el valor 4, contra el valor 0. Exactamente en esta parte del FOR estamos: "contar < 5"
Le damos a nexti...

(gdb) nexti
0x0804843d    4      for(contar=0; contar < 5; contar++)

(gdb) x/i $eip
=> 0x804843d <main+49>:    jle    0x804841f <main+19>

Luego de ejecutar 'nexti' nos lleva a la siguiente instrucción, y si la verificamos con examine para ver donde esta parado EIP, nos encontramos con un JLE. Como recordamos, J.. es sinónimo de JUMP, pero en este caso es un salto 'condicional' que significa JUMP LESS EQUAL. Y quiere decir que SALTA, SI ES MENOR o IGUAL.....

Como evidentemente esto es cierto, ya que 0 es menor que 4.. entonces salta a la dirección 0x804841f.

(gdb) x/i $eip
=> 0x804841f <main+19>:    mov    eax,DWORD PTR [esp+0x1c]

Estábamos en lo correcto, y salto nomas a la dirección previamente dicha.
Si verificamos las siguientes 10 instrucciones:



Observamos que en la 4ta linea de las 10 solicitadas, hay un "CALL 0x80482F0".
Que es el encargado de llamar a la función PRINTF. (La que imprime en pantalla el primer mensaje de "La variable contar vale: 0" que observamos al ejecutar el programa).

Para que se entienda, cuando llegamos a una instrucción donde hay un CALL como en este caso el programa se desvia a una subrutina, es como si fuese una porción de código aparte en la cual se realizan otras operaciones y una vez que se concluyen al final de ese código de la subrutina hay una instrucción llamada RET (de return/regreso).

Vean la siguiente imagen.. (sacada de Google Imágenes).



Por lo tanto, luego de la llamada a esa función, el RET debería dejarnos justituto en la siguiente dirección 0x8048433:



Ok, siguiendo con nuestro análisis, ya estamos por el final, espero no se hayan perdido.

(gdb) x/5i $eip
=> 0x8048433 <main+39>:    add    DWORD PTR [esp+0x1c],0x1
      0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>
      0x804843f <main+51>:    leave
      0x8048440 <main+52>:    ret

EIP apunta a una instrucción conocida llamada 'add' la cual sirve para 'sumar' dos operandos y lo guarda en el lugar destino, en este caso 0x1 en nuestra conocida dirección de memoria ;).

Le damos a 'nexti'.. y luego verificamos después de esta operación si el valor de esa dirección de memoria tuvo algún cambio..

(gdb) nexti
0x08048438    4      for(contar=0; contar < 5; contar++)

(gdb) x/x $1
0xbffff28c:    0x00000001

Efectivamente.. ahora contiene el valor de 1.
Si miramos un poco mas las siguientes dos instrucciones:

(gdb) x/2i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>

Ya nos resulta conocida, y es que esta nuevamente comparando el valor de 4 con el ahora 1.
Luego viene el ya explicado JLE - va a saltar si es menor o igual que 4.
Como lo és, salta a 0x804841f. Y así seguiría el loop.. hasta que si seguimos analizando el programa paso a paso con nexti y verificando el valor de la dirección en $1.. llegaríamos a:

(gdb) x/x $1
0xbffff28c:    0x00000005

(gdb) x/i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4

(gdb) x/5i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>
      0x804843f <main+51>:    leave
      0x8048440 <main+52>:    ret

Luego de ir sumándole 1 por cada loop de imprimir en pantalla, nuestra famosa dirección contiene el valor de 5.
Por lo tanto al siguiente 'cmp', de comparar si 5 es menor o igual que 4? y matemáticamente es negativo, NO se cumpliría el JLE condicional por lo que las siguiente dos instrucciones serian:

(gdb) x/2i $eip
=> 0x804843f <main+51>:    leave
      0x8048440 <main+52>:    ret
      0xb7e344d3 <__libc_start_main+243>:    mov    DWORD PTR [esp],eax
      0xb7e344d6 <__libc_start_main+246>:    call   0xb7e4dfb0 <exit>

(gdb) nexti
[Inferior 1 (process 5324) exited with code 034]

De esta manera finaliza el tercer paper.. y uno de los mas largos.
Gracias :).

#c0nfused - allmenage@gmail.com - http://insecuritynotes.blogspot.com

Páginas: [1]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines