Esta charla tratará de enseñar todos los conocimientos básicos para poder llevar a cabo el análisis de un programa dentro de un debugger. Para esto, se enseñará la arquitectura y el lenguaje ensamblador usados en el intel x86 de 32 bits, para después realizar un reversing de un binario para la resolución de un crackme. La teoría, así como las técnicas mostradas en esta charla, servirán a todos los oyentes como bases necesarias en el mundo del análisis de malware, así como en el mundo del exploiting. Es por tanto recomendable a todos los oyentes que quieran seguir el ejemplo que se verá, traer un ordenador portatil con windows (puede usarse una máquina virtual) ya sea de 64 o 32 bits, con el debugger OllyDBG o el debugger x64debugger instalados.
2. Reversing, Técnicas de Ingeniería Inversa 2
Who Am I
• Eduardo Blázquez (Fare9, F9, el de la foto de Ilonqueen,…)
• Graduado en Ingeniería de Computadores por la UAH
• Junior Malware Analyst en Panda Security
• Con intereses en Reversing, exploiting, análisis de malware y no
tan análisis…
@Farenain https://f9.29wspy.ru
4. Reversing, Técnicas de Ingeniería Inversa 4
Reversing, una introducción
Algo de terminología
“La Ingeniería inversa conocida en el mundo anglosajón como reversing. Realización
de una ‘contra-elaboración’ de un producto. En nuestro caso, nos referiremos a
obtener el código o esquemas de un software compilado”
5. Reversing, Técnicas de Ingeniería Inversa 5
Terminología
• Arquitectura de computadores
• Lenguaje Ensamblador
• Disassemblers
• Debuggers
• Usos del Reversing (Malware Analysis, Exploiting, “Cracking”…)
6. Reversing, Técnicas de Ingeniería Inversa 6
Arquitectura de Computadores
Según Kai Hwang y Fayé Briggs, la arquitectura de computadores “es
en realidad, un concepto del sistema que integra hardware, software,
algoritmos y lenguajes para realizar grandes cálculos”
Según J. L. Baer es “el arte o ciencia de planificar, diseñar, construir y
dar tratamiento decorativo a los computadores”
Y… blah, blah, blah, blah
7. Reversing, Técnicas de Ingeniería Inversa 7
Arquitectura de Computadores
Sólo era una aburrida introducción para poner la arquitectura de Von
Neumann.
8. Reversing, Técnicas de Ingeniería Inversa 8
Lenguaje Ensamblador
• Nivel más bajo en la cadena del software
• “Lenguaje del reversing por excelencia”
• Es una clase de lenguaje, no un lenguaje en sí
• Es la representación a nivel “humano” del código máquina
• Es dependiente de la arquitectura
9. Reversing, Técnicas de Ingeniería Inversa 9
Disassemblers
Programas que toman los binarios ejecutables como entrada, y
generan textos que contengan el código ensamblador del programa
completo o parte.
Cada desensamblado es específico de la arquitectura.
Son usados en un análisis o reversing estático.
Disassemblers más conocidos…
10. Reversing, Técnicas de Ingeniería Inversa 10
Debuggers
Programa que permite observar otro programa durante su ejecución.
Esto permite ver las trazas, posibles errores, modificaciones del
sistema. Todo esto instrucción por instrucción.
Existen dos tipos, unos vienen integrados en los IDEs, y debuggers
como programas a parte.
Debuggers más conocidos…
11. Reversing, Técnicas de Ingeniería Inversa 11
Special Thanks To
Duncan Ogilvie (Main x64dbg Developer) and x64dbg community (they are a
great community), for let me give this talk and little training with x64dbg.
In final training, we will use his debugger with some plugins I’ve installed and
packed in zip for students.
12. Reversing, Técnicas de Ingeniería Inversa 12
Usos del reversing
• Análisis de malware: para obtener en detalle qué acciones realiza
un malware, se analiza el código a bajo nivel.
• Exploiting: igual que antes se analiza el código de un programa
para buscar vulnerabilidades.
• Cracking: no hace falta explicarlo, ¿no?
13. Reversing, Técnicas de Ingeniería Inversa 13
Arquitectura x86-32
• Arquitectura CISC de 32 bits, se trata de una arquitectura Little-
Endian.
• Opera en dos modos:
• Modo Real: según arranca, soporta instrucciones de 16 bits.
• Modo Protegido: un modo en el que soporta la paginación, y la
memoria virtual.
14. Reversing, Técnicas de Ingeniería Inversa 14
Los anillos de poder: de Ring O a Ring 3
• La arquitectura x86 soporta el concepto de separación de
privilegios.
• Para ello se usan 4 anillos de privilegio, el Ring 0 (mayor nivel de
privilegio) y el Ring 3 (menor nivel de privilegio), Ring 1 y 2 no
suelen utilizarse.
• Los sistemas operativos suelen implementar el nivel de usuario en
el Ring 3 y el nivel de kernel en el Ring 0.
15. Reversing, Técnicas de Ingeniería Inversa 15
Los Registros
• Se trata de pequeños montones de memoria disponibles para la
CPU de acceso rápido.
• Tenemos 4 categorías principales:
16. Reversing, Técnicas de Ingeniería Inversa 16
Los Registros
• Estos registros tienen un tamaño de 32 bits, pero algunos de ellos
pueden ser divididos en porciones más pequeñas
17. Reversing, Técnicas de Ingeniería Inversa 17
Los Registros
• Algunos registros aunque generales, suelen tener unos usos
concretos
Registro Propósito
EAX Acumulador, producto, división…
ECX Contador en bucles
ESI Fuente en operaciones de cadenas/memoria
EDI Destino en operaciones de cadenas/memoria
EBP Base de los frames de pila (ya lo veremos)
ESP Puntero de la pila (ya lo veremos)
EDX Suele utilizarse en productos, divisiones junto con EAX
18. Reversing, Técnicas de Ingeniería Inversa 18
Los Registros
• Otros registros interesantes (que no se suelen tratar):
• CRX: registros de control.
• CR0: Controla la paginación.
• CR1,5,6,7: Reservados para la CPU.
• CR2: contiene la dirección que provoque un fallo de página.
• CR3: guarda la dirección base de la estructura de paginación.
• CR4: controla la virtualización.
• DRX: usados para establecer breakpoints de hardware.
• DR0-DR3: guardan la dirección del breakpoint.
• DR4-DR7: usados para status.
• Registros específicos del modelo (MSRs): variables según el
procesor (AMD e Intel usan diferentes)
19. Reversing, Técnicas de Ingeniería Inversa 19
Sintaxis de Ensamblador
• Dependiendo del assembler/disassember usado, hay dos sintaxis
diferentes, Intel y AT&T.
Intel
mov ecx, 40233033h
mov ecx, [eax]
mov ecx, eax
AT&T
movl $40233033h, %ecx
movl (%eax), %ecx
movl %ecx, %eax
20. Reversing, Técnicas de Ingeniería Inversa 20
Set de Instrucciones
Moviendo Datos
Instrucción MOV
En Intel x86 de 32 bits, se permiten los siguientes tipos de
movimientos:
• Valor Inmediato a registro. mov eax,40h
• Registro a registro. mov eax, ebx
• Inmediato a memoria. mov [04030201h],33h
• Registro a memoria y memoria a registro. mov [04052233h], ebx
• Memoria a memoria (con algunas instrucciones) inc dword ptr [04032221h]
21. Reversing, Técnicas de Ingeniería Inversa 21
Set de Instrucciones
Acceso a memoria
Como se ha visto, se usan los corchetes ([ ]) para el acceso a memoria, los accesos
se pueden hacer a byte, word y dword de la siguiente forma:
• byte: mov al, byte ptr [<address>]
• word: mov ax, word ptr [<address>]
• dword: mov eax, dword ptr [<address>]
A memoria se puede acceder también a través de registros, por índice, índice y
desplazamiento…
• mov ebx, [eax] ; acceso a memoria por registro
• mov ebx, [eax + 8] ; acceso por desplazamiento
• mov ebx, [eax + esi * 4] ; acceso por índice y desplazamiento…
22. Reversing, Técnicas de Ingeniería Inversa 22
Set de Instrucciones
LEA eso y LEA lo otro
LEA (Load Effective Address) es una instrucción que hace uso de los corchetes,
pero en lugar de cargar de memoria, evalúa la expresión entre corchetes, y asigna el
valor. (También lo permiten los ensambladores para hacer multiplicaciones).
LEA ebx, [ebp + 3] ; Mete en ebx, el valor que tenga ebp + 3
LEA edx, [eax * 5] ; Mete en edx, el valor que tenga eax * 5
movb,movw, movd
Mueven un byte, word o double, de una dirección apuntada por ESI, a una dirección
apuntada por EDI.
LEA esi, [04050607h + 03h]; esi ahora = 0405060Ah
LEA edi, [04050600h + 02h]; edi ahora = 04050602h
movd; mueve los 4 bytes apuntados por 0405060Ah a la dirección 04050602h
23. Reversing, Técnicas de Ingeniería Inversa 23
Set de Instrucciones
Instrucciones Aritméticas
• ADD eax, 02h ; eax = eax + 2
• SUB eax, 20h ; eax = eax – 20h
• inc eax; eax = eax + 1
• dec eax; eax = eax – 1
Instrucciones Lógicas
• AND eax, 00000100h ; operación AND ( 1 cuando ambos están a 1)
• OR eax, FFFFFFFFh ; operación OR ( 1 cuando al menos uno está a 1)
• XOR eax,eax ; operación XOR (1 exclusivo 1-0 o 0-1)
• NOT eax; da la vuelta a todos los bits (Complemento a 1)
• SHL/SHL eax,<numero/cl> ; desplaza bits a izq. o der. n veces
• ROL/ROR eax,<numero/cl> ; rota bits a izq. o der. n veces
24. Reversing, Técnicas de Ingeniería Inversa 24
Set de Instrucciones
Multiplicación
• MUL <reg/mem> ; multiplica por al,ax o eax y guarda en ax, dx:ax o edx:eax
• IMUL <reg/mem> ; multiplica por al,ax o eax y guarda en ax, dx:ax o edx:eax
• IMUL <reg1>,<reg2/mem>; reg1 = reg1 * reg2/mem
• IMUL <reg1>,<reg2/mem>,<numero>; reg1 = reg2/mem * numero
División
• DIV <reg/mem> ; divide edx:eax o dx:ax o ax entre valor dado, y guarda
resultado en eax o ax o al, y resto en edx o dx o ah.
• IDIV <reg/mem> ; divide edx:eax o eax o ax entre valor dado, y guarda
resultado en eax o ax o al, y resto en edx o dx o ah.
25. Reversing, Técnicas de Ingeniería Inversa 25
Push y Pop, la hora de la Stack
La Pila o Stack
Se trata de una zona de memoria la cual empieza en zonas altas de memoria, y
crece hacia las zonas bajas. Se trata de una estructura LIFO.
Para saber la dirección del stack se revisa el registro ESP. Se usa en conjunto de
EBP para quedar “frames”.
La stack se usa en los programas para: pasar parámetros a las funciones, variables
locales, guardar el estado del procesador en un momento dado…
26. Reversing, Técnicas de Ingeniería Inversa 26
Push y Pop, la hora de la Stack
Antes de nada y para poder entenderlo todo, vamos a ver las funciones para meter y
sacar valores de la stack. Recordemos habría que meter 4 bytes (32 bits).
Meter valores en la stack:
push <reg/mem/inmediato>
Esto es igual que:
sub esp,4
mov [esp],<reg/mem/inmediato>
pop <reg/mem>
Esto es igual que:
mov <reg/mem>,[esp]
add esp,4
27. Reversing, Técnicas de Ingeniería Inversa 27
Push y Pop, la hora de la Stack
En programación, se utilizan las funciones para evitar la repetición de código, pero el
programa debe saber a dónde volver tras acabar la función.
Estas funciones normalmente suelen tener parámetros, los cuales son pasados por
la pila. Luego se realiza una llamada a la función (CALL)
Al entrar a una función, se introduce la dirección de retorno y se crea un pequeño
“frame” o “marco”, para que la función tenga “su propia pila”.
Entonces se reserva espacio para variables locales.
Finalmente, se “libera” el pequeño frame de la pila, se recupera el valor de retorno
para ir, y se “liberan” los parámetros. (RET)
28. Reversing, Técnicas de Ingeniería Inversa 28
Push y Pop, la hora de la Stack
int suma(int a,int b)
{
int valor;
valor = a + b;
return valor;
}
suma(1,2)
proc suma
push ebp
mov ebp,esp
sub esp,4
mov eax, [ebp + 8]
mov ebx, [ebp + C]
mov [esp],ebx
add [esp], eax
mov eax, [esp]
mov esp,ebp
pop ebp
ret 8
endp
push 2
push 1
call suma
29. Reversing, Técnicas de Ingeniería Inversa 29
Push y Pop, la hora de la Stack
Convenciones de llamada
Son “normas” que índican cómo se pasan los parámetros a una función (primero los
de la derecha o primero los de la izquierda), y cómo se limpian los parámetros de la
pila (si tiene que limpiarla el método que llama a una función, o el método llamado).
CDECL STDCALL
proc suma
push ebp
mov ebp,esp
sub esp,4
mov eax, [ebp + 8]
mov ebx, [ebp + C]
mov [esp],ebx
add [esp], eax
mov eax, [esp]
mov esp,ebp
pop ebp
ret 8
endp
push 2
push 1
call suma
add esp,8
push 2
push 1
call suma
proc suma
push ebp
mov ebp,esp
sub esp,4
mov eax, [ebp + 8]
mov ebx, [ebp + C]
mov [esp],ebx
add [esp], eax
mov eax, [esp]
mov esp,ebp
pop ebp
ret
endp
30. Reversing, Técnicas de Ingeniería Inversa 30
Saltos In/Condicionales
Para cambiar el flujo de ejecución de un programa, se utilizan los saltos. Estos nos
permiten dirigir la ejecución del programa.
Dos tipos de salto:
• Incondicionales: siempre se toman (Instrucción JMP)
• Condicionales: se toman dependiendo de una condición (Instrucciones Jcc)
Antes ya vimos un tipo de salto incondicional con la instrucción CALL.
Los saltos condicionales, dependen de valores dentro de un registro conocido como
“EFLAGS”.
31. Reversing, Técnicas de Ingeniería Inversa 31
EFLAGS
Los valores de estos EFLAGS son modificados después de instrucciones como las
aritmetico-lógicas. Ya que indican ciertas situaciones de interés que se han podido
dar.
Los valores de los EFLAGS al ser bits serán sólo ‘0’ o ‘1’.
Para establecer estos valores, se suelen utilizar unas instrucciones llamadas de
“comparación”. Estas son:
• CMP: compara dos números restando uno con otro, pero sin guardar el
resultado en ningún registro.
• TEST: realiza una operación lógica AND, igualmente sin guardar el resultado
en ningún registro.
Tras esto se pueden establecer los siguientes flags:
• zero flag(zf): el resultado dio 0
• carry flag(cf): el resultado dio un acarreo (overflow números sin signo).
• sign flag(sf): el resultado es negativo.
• Overflow flag(of): números con signo que desbordan su máximo.
32. Reversing, Técnicas de Ingeniería Inversa 32
Saltos Condicionales
Por tanto, los saltos condicionales revisarán los valores de estos EFLAGS.
Vamos a ver una tabla que explique los saltos más típicos:
Salto condicional Descripción EFLAGS
Implicados
JB/JNAE Salta si por debajo, o no mayor ni igual, números sin signo. CF = 1
JNB/JAE No por debajo, por encima o igual, sin signo. CF = 0
JE/JZ Igual o cero. ZF = 1
JNE/JNZ No igual, no cero. ZF = 0
JL Menor qué, números con signo. (SF ^ OV) = 1
JGE/JNL Mayor o igual, no menor que, números con signo. (SF ^ OV) = 0
JG/JNLE Mayor, no menor o igual que, números con signo. ((SF ^ OV)|ZF) = 0
34. Reversing, Técnicas de Ingeniería Inversa 34
Ejecutables de Windows
Archivos PE
Se conoce así a los ejecutables de Windows, PE (Portable Executable). Este se usa
en archivos ejecutables, código objeto y DLLs.
Se trata de una estructura con la información necesaria para que el cargador del
sistema, pueda arrancar una aplicación.
Esta estructura cuenta con una cabecera, con información valiosa (por ejemplo en el
análisis de malware), tenemos por ejemplo: librerías y funciones enlazadas,
funciones importadas, funciones exportadas (en las DLLs)…
35. Reversing, Técnicas de Ingeniería Inversa 35
Ejecutables de Windows
Secciones de un archivo PE
• .text: sección que contiene las instrucciones que la CPU ejecuta.
• .rdata: contiene información de importaciones y exportaciones. Esta sección
también puede guardar información de sólo lectura. Suele dividirse en .idata
(importaciones) y .edata (exportaciones).
• .data: contiene los datos globales del programa.
• .rsrc: contiene los recursos usados por el ejecutable.