Análisis de malware 1

Introducción

El propósito del análisis de malware es, normalmente, proveer la información necesaria para responder a una intrusión a la red. El objetivo sera determinar con exactitud que ha sucedido y asegurar que se hayan localizado todos los equipos y archivos infectados.

Cuando se han identificado cuales archivos requieren análisis se desarrollan firmas, basadas en host o basadas en red, para detectar infecciones de malware.

Las firmas basadas en host son utilizadas para detectar código malicioso en el equipo de la victima. Indican archivos creados o modificados por el malware, o cambios específicos que se hacen en el registro. A diferencia de las firmas de los antivirus, los indicadores de malware se enfocan en lo que el malware realiza en el sistema, no en las características del malware por si mismo, lo cual lo hace más efectivo en detectar malware.

Firmas basadas en red se utilizan para detectar código malicioso a través del monitoreo del trafico de red. Esta firmas pueden ser creadas sin analizar el malware, pero aquellas que si analizan malware son más efectivas, ofreciendo una tasa más alta de detección y pocos falsos positivos.

Después de obtener las firmas, el siguiente paso es descubrir como el malware trabaja.

Técnicas de análisis

Existen dos enfoques fundamentales para analizar el malware: estático y dinámico. El análisis estático involucra examinar el malware sin ejecutarlo. El análisis dinámico involucra  ejecutar el malware. Ambas técnicas se dividen en básico y avanzado.

Análisis estático básico

Consiste en examinar el archivo ejecutable sin ver las instrucciones ejecutadas. Este análisis puede confirmar si el archivo es malicioso, provee información de su funcionalidad y en algunos casos provee información que permita producir firmas de red. Este tipo de análisis es sencillo y rápido pero no es efectivo con malware sofisticado y puede pasar por alto comportamientos importantes.

Análisis dinámico básico

Involucra ejecutar el malware y observar su comportamiento en el sistema con el fin de eliminar la infección, producir firmas efectivas o ambas. Sin embargo, antes de ejecutar el malware se debe establecer un ambiente de prueba que permita estudiar el malware en ejecución sin riesgo de daño al equipo o la red. Como el análisis estático básico, este tipo de análisis puede ser utilizado por personas sin conocimiento profundo en programación aunque no es efectivo con todo el malware.

Análisis estático avanzado

Consiste en realizar ingeniería inversa al malware por medio de cargar el ejecutable en un desensamblador y descubrir lo que el programa realiza. Este análisis requiere una curva de aprendizaje mayor que el análisis básico y conocimiento en ingeniería inversa, constructores de código y conceptos de Windows; todo esto lo estaremos viendo mas adelante conforme avanza el curso.

Análisis dinámico avanzado

Se usa un debugger para examinar el estado interno del malware en ejecución y así proveer otra manera de extraer información detallada de un ejecutable.

Tipos de malware

Cuando realizamos un análisis de malware tenemos que descubrir que tipo de malware estamos revisando con el fin de saber que resultados esperar. Los tipos de malware conocidos los puede ver aquí.

Reglas generales para el análisis

  1. Debemos enfocarnos en características claves, no en los detalles, debido a que la mayoría de malware son programas grandes y complejos.
  2. Recordar que existen diferentes herramientas y enfoques. Cada situación es diferente por lo que en algunos casos si no tenemos suerte con una herramienta, utilizamos otra o analizar el malware desde otro enfoque.
  3. El análisis de malware es como el juego del gato y el ratón. Así como nuevas técnicas de análisis de malware son desarrolladas también los creadores de malware responden con nuevas técnicas para frustrar el análisis.

En el próximo post entraremos en detalle con el análisis estático básico.

PV.

 

 

 

Cursos de Ingeniería inversa, análisis de malware y análisis forense de memoria.

Voy a empezar con varios tutoriales técnicamente mas complejos relacionados a la ingeniería inversa (RE), análisis de malware y análisis forense de memoria; estos temas aunque parecen diferentes están muy relacionados entre si.

¿Que es la ingenieria inversa y porque debemos estudiarla?

Como indica Wikipedia “…es descubrir cómo funciona un programa, función o característica de cuyo código fuente no se dispone, hasta el punto de poder modificar ese código o generar código propio que cumpla las mismas funciones…“.

Nos sirve para tener un profundo conocimiento de las aplicaciones o el sistema operativo, crear aplicaciones mas seguras, analizar malware, construir exploits, entre otros.

Algunos de los temas que se abordaran son:

  • X86 y X64
  • ARM
  • El kernel de Windows
  • Debugging y automatizacion
  • Ofuscación
  • Trucos anti RE
  • Analizando packers y manual unpacking
  • Y muchos más

¿Que es analisis de malware y porque debemos estudiarlo?

El malware es un componente muy importante en la mayoría de incidentes de seguridad y su análisis es el arte de diseccionar el software para entender como trabaja, como identificarlo y como eliminarlo.

Algunos de los temas que se abordaran son:

  • Análisis estático y dinámico
  • Análisis en maquinas virtuales
  • Análisis de programas para Windows.
  • Comportamiento
  • Evitar ingeniería inversa
  • Y muchos más

¿Que es análisis forense de memoria y porque debemos estudiarlo?

Cada función desarrollada por el sistema operativo o una aplicación resulta en modificaciones a la memoria RAM, y con frecuencia persiste mucho tiempo después de ejecutada esa función. Datos críticos residen exclusivamente en la memoria tales como llaves criptograficas, mensajes de chat, mensajes de correo sin encriptar, registros de Internet no guardados en cache, entre otros.

En este tema veremos todo lo relacionado con la memoria en Windows, Linux y Mac: como se adquiere, registro, kernel, sistemas de archivos, rootkits, entre otros.

Computer programming is an art, because it applies accumulated knowledge to the world, because it requires skill and ingenuity, and especially because it produces objects of beauty. A programmer who subconsciously views himself as an artist will enjoy what he does and will do it better” Donald Knuth

 

 

 

Es necesario saber programar para ser hacker?

Esto, por supuesto, es la habilidad fundamental del hacking debido a que si conoce la programación, podrá diseccionar el código y analizarlo, por ejemplo entender el funcionamiento de un exploit, ademas de ser capaz de escribir sus propios scripts o sus propias herramientas de hacking y no ser únicamente un script kiddie.

Vamos a ver diferentes lenguajes de programación, no desde un punto de vista de aprendizaje del mismo ya que para eso existen bastantes sitios en Internet sino mas bien en temas de hacking.

Hay dos lenguajes muy importantes para un hacker en la actualidad: Python y Ruby. Sin embargo para desarrollar habilidades como hacker es ideal aprender estos cinco: Python, C / C ++, Java, Perl y LISP debido a que representan enfoques muy diferentes de la programación así como diferente nivel de dificultad.

Python es el core para crear exploits y herramientas, aquí hay muchos tutoriales para aprenderlo, ademas si usted nunca ha programado le recomiendo empezar por este lenguaje debido a su simpleza para principiantes y que ademas existe mucha documentación.

Ruby también es muy útil para escribir exploits. Ademas Metasploit fue hecho en Ruby por lo que nos sirve para hacer scripts.

También tenemos otros utilizados para diferentes ataques como HTML, Java, PHP y SQL para la parte web, ensamblador para ingeniería inversa y C/C++ debido a que es el lenguaje core de Unix.

PV.

D3N.

 

 

 

Fundamentos de Arquitectura 2

Nivel Principiante

Continuando con lo visto en el post anterior esta vez hablaremos de otros temas que nos servirán para buffer overflows, shellcode, análisis de malware, entre muchas cosas más. La teoría es algo aburrida pero es necesaria para luego entrar a la parte divertida.

Proceso de memoria

Cuando un proceso se ejecuta, este es organizado en la memoria tal como se muestra:

Proceso Memoria

El proceso es dividido en cuatro regiones: Text, Data, Heap y Stack.

La parte Text, o segmento de instrucción, es fijada por el programa y contiene el código del programa (instrucciones). Esta región es marcada como read-only, debido a que el programa no debería cambiar durante la ejecución.

La región Data es dividida en inicializada y no inicializada. Datos inicializados incluyen items tales como variables declaradas que son predefinidas y pueden ser modificadas. Datos no inicializados, llamados Block Started by Symbol (BSS), también inicializa variables que son inicializadas a cero o no tiene inicialización explicita (por ejemplo static int x).

El siguiente es Heap e inicia después del segmento BSS. Durante su ejecución el programa puede solicitar mas espacio en memoria mediante llamadas al sistema vía brk y sbrk, y utilizados por malloc, realloc y free. Por lo tanto el tamaño de los datos de esta región puede ser extendido. En otros post profundizamos sobre este tema.

La ultima región de la memoria es Stack, la cual es la mas importante para nuestros propósitos.

Pila (Stack)

La pila es un bloque de memoria tipo LIFO (Last-in-First-out). Esta ubicada en la parte mas alta de la memoria. La pila puede ser usada para guardar las direcciones de retorno de una función, pasar los argumentos de una funcion, almacenar variables locales, entre otros. El propósito del registro ESP (Stack Pointer) es identificar la parte superior de la pila y si es modificada cada vez que un valor ingresa pushed in (PUSH), o sale popped out (POP).

Antes de ver como la pila trabaja y como operar en ella, es importante entender como la pila crece. La pila puede crecer hacia arriba, hacia las direcciones de memoria mas altas y también puede crecer hacia abajo, hacia las direcciones de memoria mas bajas.

En resumen, la pila es una estructura LIFO y las operaciones mas fundamentales son PUSH y POP. El puntero principal para estas operaciones es ESP, el cual contiene las direcciones de memoria para lo mas alto de la pila y cambia durante cada operación PUSH y POP.

instrucción PUSH: PUSH E

Proceso PUSH: Un PUSH es ejecutado, y el registro ESP es modificado.

Valor de inicio: ESP apunta a lo mas alto de la pila

Proceso: La instrucción PUSH resta 4 (en 32 bits) u 8 (en 64 bits) del ESP y escribe los datos a la dirección de memoria del ESP, luego actualiza el ESP a lo mas alto de la pila. Recuerde que la Pila crece hacia atrás, por lo tanto PUSH resta 4 u 8, con el fin de apuntar a la ubicación de memoria mas baja de la pila. Si no lo restamos, la operación PUSH sobreescribira la ubicación actual apuntada por ESP (lo mas alto) y podremos perder datos.

Valor final: ESP apunta a la parte superior de la pila -4

PUSH

Ahora, un ejemplo mas detallado de la instrucción PUSH:

Valor de inicio: ESP apunta a la dirección de memoria 0x0046A3B0

Proceso: El programa ejecuta la instrucción PUSH 1. ESP disminuye en 4, llegando a ser 0x0046A3AF, y el valor 1 sera empujado a la pila.

Valor final: ESP apunta a la siguiente dirección de memoria: 0x0046A3AF

PUSH1.png

Proceso POP: Un POP es ejecutado, y el registro ESP es modificado.

Valor de inicio: ESP apunta a la parte superior de la pila (Previo ESP +4)

Proceso: La operación POP es lo opuesto a PUSH y recupera datos de lo mas alto de la Pila. Por lo tanto los datos contenidos en la ubicación de la dirección en el ESP (la parte superior de la pila) es recuperada y almacenada (usualmente en otro registro). Después de la operación POP el valor de ESP es incrementado, en x86 por 4 o en x64 por 8.

Valor final: ESP apunta a la parte superior de la pila (igual que la ubicación anterior antes del PUSH).

POP

Ahora, un ejemplo mas detallado de la instrucción POP:

Valor de inicio: ESP contiene el valor de la dirección de memoria. Después de PUSH 1, ESP apunta a la siguiente dirección de memoria: 0x0046A3AF

Proceso: El programa ejecuta la instrucción inversa POP EAX. El valor (00000001) contenido en la dirección del ESP sera sacado de la pila y sera copiado en el registro EAX. Luego ESP es actualizado agregando 4 y llegara a ser 0x0046A3B0.

Valor final: ESP apunta a la siguiente dirección de 0x0046A3B0. El regresa a su valor original.

POP1.png

Cuando el valor es sacado de la pila no es borrado o puesto es cero. El se mantendrá en la pila hasta que otra instrucción lo sobreescriba.

Ya que conocemos mas sobre la Pila, en el siguiente post analizaremos como trabajan los procedimientos y funciones, esto es importante ya que los procedimientos y funciones alteran el flujo normal del proceso.

D3N.

Black Hat Hacker, White Hat Hacker o Penetration Tester

A veces puede existir alguna confusión con los términos utilizados para describir a un hacker. Para un mejor entendimiento estas son las diferencias:

  • Black Hat Hacker: esta persona solo necesita encontrar una simple falla o debilidad en cualquier área de un sistema para atacarlo y utilizar la información para beneficio personal o en mala fe (por ejemplo vender información clasificada / confidencial).
  • White Hat Hacker / Ethical Hacker: esta persona encuentra una simple falla en el sistema pero utiliza la información para mejorar el sistema (por ejemplo reportar la falla a la empresa).
  • Penetration Tester: esta persona es más experto a los otros debido a que tiene que encontrar todas las fallas en un sistema, anotarlas, crear un reporte e incluir detalles de como el hackeo o ataque fue ejecutado y como puede ser replicado. Ademas involucra una metodología, evaluación de riesgos y el alcance de una prueba de penetración está enfocada a un área particular de un sistema, red o  aplicación.

La gran mayoría de los temas que veremos en futuros posts son aplicables para todos los tipos descritos anteriormente, en algunos casos hablaremos sobre temas que únicamente aplican para Pentesting y también veremos como defendernos ante ciertos tipos de ataques.

Feliz hacking!!

D3N

 

Fundamentos de Arquitectura 1

Nivel Principiante

Empezaremos con conceptos y términos importantes que nos ayudaran a entender los ataques y exploits que después usaremos.

Veremos CPU, instrucciones, registros, lenguaje máquina y ensamblador, memoria y muchas cosas más.

CPU, ISA y Ensamblador

La unidad central de procesamiento (CPU) es la parte encargada de ejecutar el lenguaje máquina de un programa. El lenguaje máquina o código máquina, es el conjunto de instrucciones que el CPU procesa. Cada instrucción es un comando primitivo que ejecuta una operación especifica tal como mover datos, cambiar el flujo de ejecución del programa, desarrollar operaciones aritméticas y lógicas entre otros.

Las instrucciones del CPU son representadas en formato hexadecimal (HEX). Debido a su complejidad es imposible para las personas utilizar en su formato natural, por lo tanto, el lenguaje maquina es traducido en código nemotécnico (un lenguaje mas legible). Esto es llamado lenguaje ensamblador (ASM). Los dos mas populares son NASM (Netwide Assembler) y MASM (Microsoft Macro Assembler). El ensamblador que vamos a usar es NASM.

En este ejemplo vemos las diferencias entre ambos:

Machine language vs Assembler

Cada CPU tiene su propia arquitectura del conjunto de instrucciones (ISA). ISA es lo que un programador (o un compilador) debe entender y usar para escribir un programa correctamente para un CPU especifico. En otras palabras ISA es lo que un programador ve: memoria, registros, instrucciones, entre otros.

Uno de los mas comunes ISA es el conjunto de instrucciones (o arquitectura) X86, originada del Intel 8086. El acronimo X86 identifica procesadores de 32 bits, mientras X64 (conocido como X86_64 o AMD64) identifica las versiones de 64 bits. (En otros posts veremos con mas detalle este tema).

Registros

El numero de bits, 32 o 64, se refiere al ancho de los registros del CPU. Cada CPU tiene un conjunto fijo de registros que son accedidos cuando sean requeridos. Se puede imaginar a los registros como las variables temporales usadas por el CPU para conseguir y almacenar datos.

Aunque la mayoría de los registros son pequeñas porciones de memoria en el CPU y sirven para almacenar datos temporalmente, nos enfocaremos en un grupo especifico de registros: The General Purpose Registers (GPRs).

La siguiente tabla resume los 8 registros de propósito general. Note que la nomenclatura se refiere a la arquitectura X86.

Nomenclatura X86La nomenclatura para el viejo CPU de 8 bits tiene registros de 16 bits dividido en dos partes: un bit bajo, identificado por una L (Low) al final del nombre, y un bit alto, identificado por una H (High) al final del nombre.

La nomenclatura de 16 bits combina la L y la H, y las reemplaza con una X. Mientras que para los registros Stack Pointer, Base Pointer, Source Pointer y Destination únicamente elimina la L.

En los 32 bits, el acronimo del registro utiliza una E al inicio, significa extendido. Mientras que la arquitectura de 64 bits, la E es reemplazada con una R.

Lo siguiente resume las nomenclaturas utilizadas:

Nomenclatura Arquitectura

En adición a los 8 registros de propósito general, existe otro registro que es importante: EIP (nomenclatura X86). Instruction Pointer (EIP) controla la ejecución del programa almacenando un puntero a la dirección de la siguiente instrucción (lenguaje máquina) que sera ejecutada, en otras palabras le indica al CPU en donde es la siguiente instruccion.

En el siguiente post de arquitectura veremos el proceso de memoria, la pila, endianness y NOPs.

Pura Vida!!!

D3N.

 

De que se trata esto?

Muy simple, hablaremos de ingeniería inversa, análisis de malware, lenguajes de programación útiles para hacking, pentesting (redes, aplicaciones web y móviles), certificaciones que valgan la pena (tecnicamente hablando), y muchas otras cosas más que permitan mejorar nuestras habilidades. Además los temas se indicarán si son para principiantes, intermedios o avanzados.

Saludos desde Costa Rica!!

D3N.