Cómo revertir el software de ingeniería (Windows) de la manera correcta

publicado en: tutoriales | 0

¿Alguna vez ha sentido el deseo de desmontar algún mecanismo para averiguar cómo funciona? Bueno, ¿quién no lo ha hecho? Ese deseo es la fuerza principal de la ingeniería inversa. Esta habilidad es útil para analizar la seguridad de los productos, averiguar el propósito de un archivo .exe sospechoso sin ejecutarlo, recuperar la documentación perdida, desarrollar una nueva solución basada en software heredado, etc.

En este artículo, discutimos la base de conocimiento necesaria para realizar la ingeniería inversa, los principios básicos de la ingeniería inversa de una pieza de software de Windows, los desensambladores y las herramientas. También proporcionamos un ejemplo paso a paso de la ingeniería inversa de una aplicación.

¿Qué es la inversión de software?

La ingeniería inversa es el proceso de descubrir los principios que hay detrás de una pieza de hardware o software, como su arquitectura y estructura interna. La pregunta que impulsa la ingeniería inversa es ¿Cómo funciona?

Obviamente, si tienes documentación, todo el proceso se vuelve mucho más simple. Pero a menudo sucede que no hay documentación y necesitas encontrar otra forma de aprender cómo funciona un software.

¿Cuándo podrías necesitar hacer ingeniería inversa de un software y cómo podría ayudarte?

Hay muchos usos de la ingeniería inversa en el campo de la informática, incluyendo:

  • Investigación de los protocolos de comunicación de la red
  • Encontrar los algoritmos utilizados en los programas maliciosos como virus informáticos, troyanos, programas de rescate, etc.
  • Investigar el formato de archivo utilizado para almacenar cualquier tipo de información, por ejemplo, bases de datos de correos electrónicos e imágenes de disco
  • Comprobando la capacidad de su propio software para resistir la ingeniería inversa
  • Mejorar la compatibilidad del software con las plataformas y el software de terceros
  • Usando las características de la plataforma no documentada

Servicios conexos

Ingeniería inversa

La legalidad de la ingeniería inversa depende de su propósito y de cómo se utilizará el software. Todos los propósitos mencionados anteriormente son completamente legítimos, suponiendo que haya obtenido una copia del software legalmente. Pero si tiene la intención, por ejemplo, de realizar ingeniería inversa de una determinada característica de una aplicación cerrada y luego implementarla en otra aplicación, probablemente tendrá problemas.

En lo que respecta a la documentación legal, la ingeniería inversa suele estar prohibida por los acuerdos de licencia de usuario final (EULA). Pero la Ley de Derechos de Autor del Milenio Digital de los EE.UU. especifica que la inversión de una pieza de software es legal si se hace para mejorar la compatibilidad con otros productos.

Los requisitos legales varían de un país a otro, así que tómese su tiempo para investigarlos antes de empezar.

Ahora veamos cómo hacer ingeniería inversa de software.

¿Qué necesitamos para la ingeniería inversa?

Para iniciar el software de ingeniería inversa, necesitas:

  1. conocimiento en el campo donde se quiere aplicar la ingeniería inversa
  2. herramientas que le permitirán aplicar sus conocimientos mientras intenta desmontar el software.

Consideremos un ejemplo genérico que no está conectado al software. Digamos que tienes un reloj y quieres saber si es mecánico, de cuarzo o automático.

Tener conocimiento del campo significa que debes saber que hay tres tipos de relojes. Además, deberías saber que si hay una batería, está ubicada dentro del reloj, y puedes verla si la abres. También deberías tener un conocimiento básico de la estructura interna de un reloj, cómo es la pila y qué herramientas necesitas para abrir la caja de un reloj. Tener las herramientas para aplicar tus conocimientos significa que debes tener un destornillador u otra herramienta dedicada que te permita abrir el reloj.

Al igual que la ingeniería inversa un reloj requiere un conjunto de habilidades y herramientas específicas, el software de ingeniería inversa requiere su propio conocimiento y herramientas específicas del campo.

Conocimiento teórico. Proceso de ingeniería inversa de software

Para las diferentes tareas de ingeniería inversa de software, se necesitan diferentes tipos de conocimientos. Por supuesto, hay conocimientos comunes que le ayudarán en la mayoría de las tareas de ingeniería inversa: conocimiento de las estructuras de aplicación comunes, lenguajes de programación, compiladores, etc. Sin embargo, sin un conocimiento teórico especial, no se pueden resolver tareas específicas de ingeniería inversa.

Si tú…

Necesitas conocimiento de…

ingeniería inversa de cualquier aplicación de red

los principios de las comunicaciones entre procesos, la estructura de las redes, las conexiones, los paquetes de red, etc.

algoritmos de criptografía inversa

la criptografía y los algoritmos más populares utilizados en el campo

estructuras de archivos de investigación

conceptos básicos de los archivos y cómo funcionan los diferentes sistemas o componentes con los archivos

Las técnicas especiales pueden ahorrar mucho tiempo al revertir tipos especiales de software. En el caso de las interacciones con archivos, hacer una prueba que escriba valores de tipo único en un archivo mientras se registran las compensaciones y el tamaño de los datos en el archivo de almacenamiento real puede ayudar a encontrar patrones comunes en las compensaciones. Esto le dará una pista sobre las estructuras internas de estos archivos.

Al iniciar un proceso de ingeniería inversa, los desarrolladores de software generalmente utilizan un desensamblador para encontrar los algoritmos y la lógica del programa en su lugar. Hay muchos formatos de archivos ejecutables diferentes, compiladores (que dan diferentes salidas) y sistemas operativos. Esta diversidad de tecnologías impide el uso de una sola tecnología para invertir todos los tipos de software.

Para entender el código descompilado, se necesita algún conocimiento del lenguaje ensamblador, convenciones de llamada de funciones, estructura de la pila, concepto de los marcos de la pila, etc.

Lee también:

Clases de Restauración – Consejos útiles para los ingenieros de software

Conocer la salida del ensamblador para diferentes muestras de código puede ayudarte a descubrir la funcionalidad original. Consideremos algunos ejemplos para la plataforma Windows x86.

Digamos que tenemos el siguiente código:

                int cuenta = 0;for (int i = 0; i < 10; ++i){cuenta++;}std::cout << cuenta;

Si compilamos este código en un archivo ejecutable, veremos esto en el desensamblador:

                004113DE loc_4113DE:004113DE mov eax, [ebp-14h]004113E1 add eax, 1004113E4 mov [ebp-14h], eax004113E7 loc_4113E7:004113E7 cmp [ebp-14h], 0Ah004113EB jge corto loc_4113F8004113ED mov eax, [ebp-8]004113F0 add eax, 1004113F3 mov [ebp-8], eax004113F6 jmp corto loc_4113DE004113F8 loc_4113F8:004113F8 mov ecx, ds:?cout@std004113FE push eax00411400 call ds:basic_ostream@operator<<(int)00411404 xor eax, eax00411406 retn

Como podemos ver, el ciclo regular se convirtió en código de montaje con comparaciones y saltos. Noten que el código de ensamblaje no usa el bucle de ensamblaje regular con el contador en el registro ecx. Además, las variables locales aquí se denominan [ebp-14h] y [ebp-8] en consecuencia.

Veamos qué pasará si compilamos este código usando el release build:

                00401000 proc principal cerca de00401000 mov ecx, ds:?cout@std00401006 push 0Ah00401008 call ds:basic_ostream@operator<<(int)0040100E xor eax, eax00401010 retn00401010 main endp

Este pedazo de código no se parece en nada al anterior. Esto se debe a cómo se optimizó el código. Técnicamente, el bucle fue eliminado, ya que no hace nada valioso más que incrementar la variable de conteo a 10. Así que el optimizador decidió mantener el valor final de la variable de conteo y colocar el valor directamente como un argumento para el operador de salida de conteo.

Los compiladores que usamos hoy en día son muy buenos para optimizar el código. Por eso, cuando se hace ingeniería inversa, es mejor entender la idea que hay detrás del código (los principios del código) que intentar obtener el código original en sí. Si entiendes la idea detrás del código, puedes escribir tu propio prototipo que se ajuste a la tarea original.

Lee también:

OS X y iOS Ingeniería Inversa: Cómo hacer ingeniería inversa en una aplicación iOS

Será muy útil saber qué código ensamblador obtendrás si compilas diferentes operadores, estructuras y otras construcciones del lenguaje. Entender el código ensamblador resultante es una buena manera de comenzar el proceso de ingeniería inversa de C++, pero no entraremos en detalles técnicos de ello aquí.

Herramientas útiles para la ingeniería inversa del software de Windows

Ya hemos descrito varias herramientas de ingeniería inversa, incluyendo ProcessMonitor y ProcessExplorer, en nuestra investigación de arquitectura de aplicaciones. Estas herramientas son absolutamente indispensables para la ingeniería inversa.

En esta sección, revisaremos los desensambladores más populares y algunas herramientas más que usamos para nuestros proyectos de ingeniería inversa.

Puede obtener más detalles y ejemplos de uso en nuestro artículo sobre las mejores herramientas de ingeniería inversa de software.

Desmontadores

Un desensamblador es un programa que traduce un archivo ejecutable a lenguaje ensamblador. El más popular es IDA Pro

IDA Pro

IDA Pro

IDA Pro es una herramienta conveniente y poderosa para el desmontaje. Tiene un gran número de instrumentos que le permiten desmontar rápidamente una pieza de software. Puede mostrar la función árbol de llamadas , parse importación y exportación del ejecutable, y mostrar información sobre ellos. Incluso puede mostrar el código en C. Además, soporta múltiples arquitecturas de CPU, por lo que es posible utilizar IDA Pro para realizar ingeniería inversa de código para ARM, AVR, M68k, y muchas otras arquitecturas.

Radare

Radar

El desensamblador Radare es una alternativa a la IDA. Básicamente tiene todas las características de IDA sin ser tan robusto y estable. Pero es libre y de código abierto. Radare en sí mismo es una herramienta de consola, pero tiene un frontal Cutter, lo que lo convierte en una verdadera alternativa a IDA.

Windows Sysinternals

Las utilidades de Windows Sysinternals se utilizan generalmente para la administración, diagnóstico, solución de problemas y supervisión del entorno de Microsoft Windows. Pero también son adecuadas para la ingeniería inversa de software de Windows.

TCPView es un sniffer de red que muestra toda la información sobre los paquetes TCP/UDP de todos los procesos. Esta herramienta es útil para invertir los protocolos de red.

PortMonis es un monitor de puertos del sistema físico. Monitorea los puertos en serie y paralelos y todo el tráfico que pasa por ellos.

WinObjs muestra todos los objetos globales del sistema en una estructura jerárquica. Esta herramienta puede ser útil cuando se invierte una aplicación que funciona con primitivas de sincronización como los mutex y los semáforos y también cuando se invierten los controladores del modo del núcleo de ingeniería.

Instrumentos de vigilancia de la red

Wireshark

Wireshark

Wireshark es uno de los más poderosos olfateadores de redes. No sólo permite capturar el tráfico de la red, sino que también contiene analizadores para varios protocolos de red, desde los de muy bajo nivel como Ethernet, TCP e IP hasta los protocolos específicos de aplicaciones como WebSockets y XMPP.

Fiddler

Fiddler

Fiddler es un proxy web que registra el tráfico de los navegadores y permite analizar las peticiones HTTP/HTTPS. A diferencia de Wireshark, muestra sesiones HTTP en lugar de paquetes de red separados. Fiddler también le permite analizar datos comprimidos enviados por HTTP y analizar datos JSON y XML cuando monitoriza peticiones SOAP, REST y AJAX.

Monitor API

Monitor API

El Monitor de API es una herramienta útil para descubrir qué API son llamadas por una aplicación y qué comportamiento espera la aplicación de esas API. Esta herramienta cuenta con una potente base de datos y permite ver las llamadas a un gran número de funciones de la API no sólo del kernel32 y del ntdll sino también del entorno gestionado COM , y otros. Además, el monitor de la API proporciona mecanismos de filtrado convenientes.

Depuradores

Un depurador es inestimable para que cualquier desarrollador vea lo que un programa está haciendo ahora mismo. Obtienes el mismo beneficio de la depuración al revertir las aplicaciones que el que obtienes de la depuración de las aplicaciones en vivo.

Los depuradores más populares son OllyDbg, WinDbg y Windbg Preview.

OllyDbg

OllyDBG

OllyDbg (y su sucesor x64dbg) es probablemente el mejor depurador cuando se trata de ingeniería inversa de software. Fue desarrollado específicamente para las necesidades de reversión, y tiene todas las herramientas necesarias para ese propósito:

  • un desensamblador incorporado con la capacidad de analizar e identificar estructuras de datos clave
  • una función de análisis de importaciones y exportaciones
  • un motor de ensamblaje y parcheo incorporado

La capacidad de analizar las funciones de la API y sus parámetros hace que sea fácil invertir las interacciones con un sistema. La vista de la pila proporciona mucha información sobre la pila de llamadas. Otra ventaja importante es que se puede usar OllyDbg con aplicaciones protegidas por depuración, cuando los depuradores habituales no pueden hacer nada.

WinDbg

Windbg

A pesar de su simple interfaz, WinDbg tiene poderosas herramientas para la depuración. Tiene un desensamblador incorporado, varios comandos que le permiten saber casi todo sobre el proceso/sistema que está depurando, y la capacidad de hacer la depuración en modo kernel, que es probablemente la característica más valiosa. Es una gran ventaja para revertir los controladores, en particular los controladores en modo kernel.

Avance de Windbg

Avance de Windbg

Windbg Preview es una nueva versión de Windbg desarrollada por Microsoft. Se distribuye sólo a través de la tienda de Windows. Tiene todas las características del clásico Windbg junto con una nueva interfaz de usuario y varias características nuevas. Una de estas nuevas características es la Depuración de Viajes en el Tiempo, que le permite grabar algún período de ejecución del programa y luego reproducirlo tantas veces como sea necesario. De esta manera, puedes ejecutar las partes interesantes del código por pasos, sin tener miedo de ejecutar algún código accidentalmente y perder el contexto o todos los datos.

Lee también:

9 Mejores herramientas de ingeniería inversa para 2018

Ejemplo de ingeniería inversa de software en la vida real

Ahora veremos un ejemplo de cómo hacer ingeniería inversa en un software. Imaginemos que tienes un archivo ejecutable sospechoso. Necesitas averiguar qué hace este programa y si es seguro para los usuarios.

Considerando el escenario, es una buena idea no ejecutar este ejecutable en el ordenador del trabajo, sino utilizar una máquina virtual. Iniciemos la aplicación en nuestra máquina virtual.

El proceso crea un servicio

Como podemos ver, este archivo crea un servicio de Windows llamado TestDriver. Tiene el tipo de kernel, así que sabemos que es un controlador. ¿Pero de dónde toma el archivo del controlador para poder ejecutarse? Podemos usar ProcessMonitor de Sysinternals Suite para averiguarlo. Cuando abrimos ProcessMonitor, podemos configurar filtros para que nos muestren sólo la actividad del archivo del proceso que nos interesa. Su registro de actividad se ve así:

Información de FileMon

El archivo del controlador se crea por el proceso que estamos invirtiendo, y este proceso pone este archivo en el directorio temporal del usuario . No es necesario buscar el archivo en la carpeta temp ya que vemos que el proceso lo borra justo después de su uso. Entonces, ¿qué hace el proceso con este archivo? Si desempaqueta el archivo, podemos intentar encontrarlo en la sección de recursos del proceso, ya que es un lugar común para almacenar este tipo de datos. Busquemos allí. Usaremos otra herramienta – Resource Hacker – para examinar los recursos. Vamos a ejecutarlo:

Examinar los recursos con el Resource Hacker

¡Bingo! Como podemos ver por el contenido de los recursos encontrados, este es probablemente el archivo ejecutable de Windows, ya que comienza con una firma MZ y tiene la cadena «Este programa no puede ser ejecutado en modo DOS». Comprobemos si es nuestro archivo controlador. Para ello, extraemos el recurso usando el Resource Hacker y lo abrimos en el desensamblador.

Pantalla desensambladora

Como sabemos, DriverEntry es el punto de entrada para los controladores del modo kernel en los sistemas Windows. Podemos continuar nuestra investigación, ya que parece que hemos encontrado el controlador adecuado.

Cómo hacer ingeniería inversa a un conductor

Para comenzar la ingeniería inversa del controlador, examinamos las funciones que se llaman desde DriverEntry una por una. Si vamos a sub_14005, no encontramos nada interesante, así que continuamos con sub_110F0 y encontramos este código:

Código pieza 1

Código pieza 2

Código pieza 3

Código pieza 4

Algunas líneas se omiten aquí por razones de simplicidad.

En la primera lista, se crea una cadena de unicode, y esta cadena apunta a la ruta C:hola.txt. Después de eso, la estructura OBJECT_ATTRIBUTES se llena con valores regulares; sabemos que esta estructura es a menudo necesaria cuando se llaman funciones como ZwCreateFile.

En la segunda lista, vemos que ZwCreateFile se llama de hecho, lo que nos hace estar bastante seguros de que el controlador crea el archivo – y sabemos dónde se encuentra este archivo después de su creación.

A partir del tercer y cuarto listado, podemos ver que el controlador toma la cadena unicode y la escribe en el búfer (esto sucede en la función sub_11150), y el búfer se escribirá en el archivo usando la función ZwWriteFile. Al final, el controlador cierra el archivo utilizando la API de ZwClose.

Resumamos. Descubrimos que el programa original extrae el archivo del controlador de sus recursos, lo pone en la carpeta temp del usuario actual, crea el servicio de Windows para este controlador y lo ejecuta. Después de eso, el programa se detiene y elimina el servicio y el archivo del controlador original del directorio temp . A partir de este comportamiento y del análisis del desmontaje, parece que el controlador no hace nada excepto crear un archivo en la unidad C llamado hello.txt y escribir la cadena «Hello from driver».

Ahora tenemos que comprobar si estamos en lo cierto. Vamos a ejecutar el programa y comprobar la unidad C:

Pantalla de aplicación

¡Maravilloso! Hemos invertido la ingeniería de este simple programa y ahora sabemos que es seguro de usar.

Podríamos haber logrado este resultado de muchas maneras diferentes – usando la depuración o API Mon, pruebas de escritura, etc. Puedes encontrar tus propias formas de hacer ingeniería inversa de software que te sirvan.

Conclusión

La ingeniería inversa de software de Windows requiere una sólida formación educativa y experiencia en programación. Para poder realizar la ingeniería inversa, es necesario combinar habilidades en el desmontaje, la supervisión de redes, la depuración, la integración de API, varios lenguajes de programación, compiladores, etc. También tiene que tener mucho cuidado al invertir el software para no infringir las leyes de derechos de autor o dañar su sistema.

En Apriorit, tenemos un equipo experimentado de ingenieros de reversa. Si desea aplicar las habilidades de ingeniería inversa a su proyecto, ¡no dude en contactarnos!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *