Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Reconociendo bucles en ingeniería reversa

  • 1 Respuestas
  • 4532 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado LucaSthefano

  • *
  • Underc0der
  • Mensajes: 399
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
« en: Abril 02, 2014, 01:54:50 am »

Luego de haber estado reconociendo estructuras comunes en ingeniería reversa (parte I y parte II) hace algunas semanas, continuaremos con la útil tarea de vislumbrar patrones entre las diversas líneas de código. Hoy es el turno de los bucles, esas estructuras que permiten la ejecución repetida de las instrucciones.

Dado que, al realizar reversing, la cantidad de instrucciones de un programa puede ascender a los cientos de miles, resulta muy poco práctico realizar un análisis instrucción por instrucción. Por eso, se hace necesario lograr cierto nivel de abstracción en el proceso; con un poco de práctica podemos acostumbrarnos a ver un amplio panorama de lo que hace el código, mediante el análisis de grupos de instrucciones en lugar de instrucciones individuales. Asimismo, si pensamos en lenguajes de alto nivel, nos daremos cuenta de que existen estructuras o construcciones que, al ser combinadas, le dan funcionalidad a un programa. Entre esas construcciones encontramos aquellas que rigen el flujo de ejecución, como los condicionales, bucles y demás. Si reconocemos estas estructuras entre el código en ensamblador, estaremos más cerca del lenguaje de alto nivel, con todas las ventajas que esto ofrece.

Para poder reconocer bucles entre las líneas de código en lenguaje ensamblador, primero debemos entender la estructura de un bucle en un lenguaje de alto nivel. Por ello, en la siguiente imagen observamos un programa sencillo con un bucle en C:


El código mostrado imprime por pantalla 9 líneas, desde “Contando 1” hasta “Contando 9”. Ahora bien, si nos centramos en el funcionamiento del bucle, podemos bosquejar el siguiente pseudocódigo:

  • Asignar a la variable i el valor 1
  • Si el valor de i es mayor o igual a 10, ir al paso 6. Si es menor que 10, continuar con el paso 3
  • Imprimir por pantalla “Contando i”, con el valor actual de i
  • Sumar 1 a la variable i
  • Ir al paso 2
  • Salir del bucle

Los pasos mostrados se marcan con números en la siguiente imagen. Debemos notar que los números utilizados se corresponden con el pseudocódigo presentado arriba.


Si ahora trasladamos este ejemplo particular al caso general, notaremos que los bucles contarán con las siguientes secciones:

  • La encargada de inicializar las variables
  • La que realiza una comparación, en la cual se basa la repetición
  • La que contiene el código a ejecutar repetidamente
  • Aquella que incrementa la variable de comparación

Por lo tanto, cuando estemos realizando reversing sobre un ejecutable, debemos observar aquellos grupos de instrucciones que se correspondan con estas secciones, prestando especial atención a las instrucciones de salto, el pegamento que une las secciones. Teniendo esto en cuenta, a continuación se muestra el código correspondiente al programa desensamblado:


Vemos las cuatro secciones marcadas con distintos colores. En rojo se encuentra la sección de inicialización, que consiste en una sola instrucción mov que asigna el valor 1 a la variable local i que se encuentra en el stack de main. Luego vemos un salto a la sección de comparación, en verde, que comprueba si el valor de i es mayor o igual a 10. De ser así, deja de ejecutar el bucle; caso contrario (si se cumple la condición de iteración, i < 10) continúa con la ejecución. A continuación se pasa a la sección de ejecución, en naranja, que inserta el valor de i junto con la cadena de formato (ubicada en la dirección de memoria 0×403000 en este caso) al stack, para invocar a printf (instrucción call). Por último, se realiza un salto a la sección de incremento, violeta, donde se suma 1 al valor de i.

Ya hemos mencionado las bondades de algunas herramientas como IDA, que nos permiten ver el flujo de ejecución en forma gráfica:


Puede que antes de leer este post dicha estructura gráfica no nos llamara la atención, pero ahora vemos claramente la presencia de las 4 secciones y de la flecha ascendente (del bloque 4 al 2) que nos indica la presencia de un bucle.

Esto es todo por hoy, pero en futuros posts continuaremos analizando otras estructuras de control y de datos.

Saludos!

Agradecimientos: Matías Porolli, Laboratorios ESET

Desconectado kasiko

  • *
  • Underc0der
  • Mensajes: 2
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
« Respuesta #1 en: Mayo 17, 2014, 09:35:29 am »
muy bueno  ;)

 

¿Te gustó el post? COMPARTILO!



Gray Hat Python: Programación en Python para hacking e ingeniería inversa

Iniciado por dracko.rx

Respuestas: 5
Vistas: 7589
Último mensaje Abril 04, 2016, 01:55:09 pm
por noxonsoftwares
INGENIERIA INVERSA BASICA I ("Aprediendo sobre los programas")

Iniciado por CronuX

Respuestas: 0
Vistas: 2083
Último mensaje Marzo 21, 2010, 07:25:53 pm
por CronuX
Nueva versión de REMnux, la distribución Linux para el análisis e Ingeniería Inv

Iniciado por morodog

Respuestas: 0
Vistas: 2756
Último mensaje Abril 11, 2013, 10:58:44 am
por morodog
[F.A.Q] ¿Eres nuevo? - Aprende Ingeniería Inversa desde cero

Iniciado por .:UND3R:.

Respuestas: 8
Vistas: 9176
Último mensaje Junio 04, 2015, 02:49:09 am
por Baxtar
[VIDEO] Ingeniería inversa de circuitos integrados - Eduardo Cruz

Iniciado por El_maquinista_69

Respuestas: 2
Vistas: 3875
Último mensaje Agosto 13, 2017, 10:22:42 am
por user_en1gm4