Professional Documents
Culture Documents
Principios en ensamblador
en 18:13 | | Etiquetas: ASM, PFC, Reversing
Introduccin
El objetivo de esta entrada no es otro que dar unas nociones bsicas de ASM para tener una base con la que
empezar a realizar reversing para los menos avezados.
Qu es?
Una entrada donde se condensen los principios bsicos a conocer y tener en cuenta para introducirnos un
poco en el mundo del reversing. Tmalo como una pequea gua de referencia, nada ms.
Para un buen aprendizaje de ASM consulta el libro The art of assembly language.
Qu no es?
No se trata de un tutorial sobre programacin en ASM, ni se trata de explicar conceptos avanzados en la
materia ni lenguaje.
Prerrequisitos
Sistema binario.
Sistema hexadecimal.
Conocer el funcionamiento de una CPU.
Conocer cmo se estructura un sistema operativo.
Conocer como se procesan y almacenan los datos en memoria.
Qu es la ingeniera inversa?
Wikipedia (El objetivo de la ingeniera inversa (reversing) es obtener informacin a partir de un producto
accesible al pblico, con el fin de determinar de qu est hecho, qu lo hace funcionar y cmo fue fabricado.
El mtodo se denomina as porque avanza en direccin opuesta a las tareas habituales de ingeniera, que
consisten en utilizar datos tcnicos para elaborar un producto determinado.
La ingeniera inversa es un mtodo de resolucin. Aplicar ingeniera inversa a algo supone profundizar en el
estudio de su funcionamiento, hasta el punto de que podamos llegar a entender,modificar y mejorar dicho
modo de funcionamiento.)
Adentrndonos en ASM
Obtener unas nociones bsicas de ensamblador es fundamental para comenzar nuestra incursin en el
mundo del reversing, hazte a la idea de que tendrs que manejarte al dedo con l.
Olvdate de las facilidades que podas gozar en python, C, C++, perl, etc. Esto es otra historia, aqu usaremos
abreviaturas y nmeros, y probablemente al comienzo todo te parezca bastante lioso e incluso frustrante.
BIT Unidad mnima de informacin. Su valor puede oscilar entre el 0 o 1. El sistema binario se
forma por la unin de varios bits.
BYTE Un byte est formado por 8 bits. Su valor puede oscilar entre 0-255. Es un sistema en base
2. Nosotros para facilitar la lectura de los nmeros binarios, usaremos el sistema hexadecimal (sistema en
base 16) por la rapidez y facilidad para leer.
WORD Son dos bytes o lo que es lo mismo 16 bits. Su valor oscila entre 0-65535d (0h 0FFFFh)
DWORD Son dos words o lo que es lo mismo 32 bits. Su valor oscila entre 0-4294967295d(0h0FFFFFFFFh)
Registros
Similar a las variables. Un registro es una zona especial en la memoria de nuestro procesador donde
podemos almacenar y consultar un valor nico. Con la salvedad de que existen un nmero limitado de
ellos y cada uno tiene un cometido especfico.
En arquitecturas Intel (que ser la elegida por nosotros) podemos distinguir un total de 8 registros:
EAX (Extended Accumulator Register) Destacamos dos funcionalidades de uso comn para este
tipo de registro: Almacenar el valor de retorno de una funcin y utilizarlo como contenedor para resolver
sencillas operaciones matemticas.
Es un registro voltil, dado que su valor no es almacenado. A pesar de que se establezca el valor de retorno
de una funcin al contenido del mismo.
EBX (Extended Base Register) - Suele utilizarse como apoyo para acelerar el clculo de
operaciones. Es un registro no voltil.
ECX (Extended Counter Register) Registro voltil que puede ser utilizado como contador de bucle
o contenedor de parmetros que sean pasado a funciones
EDX (Extended Data Register) Registro voltil usado mayormente como parmetro para funciones.
Normalmente se usa tambin para almacenar variables a corto plazo dentro de una funcin.
ESI (Extended Source Index) Registro no voltil que normalmente es usado como puntero. Es
utilizado por aquellas funciones que requieren un origen y un destino para los datos que se utilizan.
Apuntando este al origen en todo momento.
EDI (Extended Destination Index) - Al igual que el registro ESI, es no voltil y usado como puntero, a
diferencia de que este apunta al destino siempre.
EBP (Extended Base Pointer) Registro no voltil con dos usos comunes segn el compilador que
utilicemos, as puede desempear el papel de un registro como otro cualquiera o ser el puntero al marco de
pila.
ESP (Extended Stack Pointer) Almacena un puntero a la parte inferior de la pila. Tras ejecutar una
funcin el valor que tena el registro al principio debe de coincidir con el asociado tras la funcin
EIP (Extended Instruction Pointer)
Estos registros de 32 bits a su vez pueden ser divididos en registros de menor tamao (16 bits, y 8 bits,
distinguiendo la parte superior e inferior).
Por tanto tenemos:
8 registros de 32 bits: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP EIP
8 registros de 16 bits: AX, BX, CX, DX, SI, DI, BP, SP, IP
De esta forma ECX = 0x24101989, quedara como CX = 0x1989, CH = 0x19 y CL = 0x89, y de paso ya
sabis cundo hacerme un regalo (rubias por favor ;D).
Ahora mismo debemos de quedarnos con una idea ligeramente similar a esta:
Z-Flag (Zero flag) Ser el flag que ms acabaremos usando, cuando su valor es 1 nos indica que
el resultado de una operacin fue 0. Su valor puede ser cambiado por todas aquellas instrucciones que
realicen operaciones matemticas y por la instruccin cmp
C-Flag (Carry flag) Su valor va ligado al uso de acarreo en operaciones de suma y resta.
O-Flag (Overflow flag) Su valor cambia a disposicin del valor que adopte el bit ms significativo. Si
queremos realizar la suma de 127 consigo mismo, este es representado como 0111 1111, en este momento
el MSB es 0, pero al realizar la operacin (0111 1111 + 0111 1111) obtenemos 1111 1110, siendo 1 ahora el
valor del MSB.
La pila
Podemos ver el concepto de pila como una estructura de datos, en la que el modo de acceso a sus elementos
es de tipo LIFO (Last Input First Output Ultimo en entrar, primero en salir).
Cuando llamamos a una funcin, todos sus parmetros son almacenados en sentido inverso en la pila antes
de hacer de pasar el flujo de ejecucin a la funcin.
NuestraFuncion(int param1, int param2, char param3, float param4)
push param3
push param2
push param1
call NuestraFuncion
add esp, 10h
Como comentabamos vamos pasando los parmetros a nuestra pila para posteriormente realizar la llamada.
Despus de acabar la ejecucin de nuestra funcin el puntero a pila sigue teniendo 16 bytes por delante de
lo que tena en un principio. Con la intencin de restaurar el estado original de la misma, debemos aadir al
puntero el valor 10h que corresponde a los 4 elementos que hemos introducido en la pila (4bytes por cada
instruccin push ejecutada).
Operaciones lgicas
A lo largo de nuestro recorrido deberemos conocer cmo funcionan las operaciones lgicas a nivel de bits:
Instrucciones
Instruccin NOP Es una abreviatura de No operation y su uso es de simple relleno.
Desplazando datos:
'mov' Instruccin anloga a '=', puede mover datos entre un registro y memoria, dos registros o
incluso entre una constante y memoria.
'movsx' Versin especializada para usar con registros de diferentes tamaos y con signo.
'movzx' Versin especializada para usar con registros de diferentes tamaos y sin signo.
lea (Load Effective Address) Uso similar a mov y utilizado para calcular desplazamientos en
vectores, dado que podemos hacer uso de [direccin comienzo + offset*datasize] para encontrar la
direccin de un elemento en concreto del vector. Su uso tambin se basa para clculos de multiplicaciones y
sumas.
add eax, 5
sub ecx, 5
add ebx, eax
inc ebx
dec eax
and, or, xor, neg Instrucciones encargadas de realizar las operaciones lgicas a nivel de bits,
que hemos explicado anteriormente.
mul, imul, div, idiv, cdq Correspondientes a las operaciones de multiplicacin y divisin,
ambas hacen uso de los registros de 64 bits edx:eax. mul multiplica el valor sin signo almacenado en el
registro eax con el operando y almacena el resultado en el registro de edx:eax. Por otro lado imul realizad
la misma operacin a excepcin de que el valor es con signo.
Cuando se usan dos parmetros, el comportamiento es el esperado, multiplica el primero por el segundo y
almacena el resultado en el primer parmetro.
div divide el valor almacenado en el registro edx:eax por el operando y el cociente lo almacena en eax. El
resto o mdulo es almacenado en edx. Al igual que suceda con imul la operacin idiv permite utilizar
valores con signo.
Por otro lado la operacin cdq es usada antes que idiv y su cometido es convertir el valor de 32bit
almacenado en eax en un valor de 64 bit para almacenarlo en edx:eax sobreescribiendo cualquier valor que
haya en edx con ceros en caso de ser eax positivo o con F en caso de ser eax negativo.
shl, shr Shift Left y Shift Right respectivamente, nos permiten realizar desplazamiento a nivel de
bits hacia la derecha e izquierda, al igual que los operadores << y >> usados en C.
Saltos Estas instrucciones son utilizadas en caso de bucles y condiciones de comprobacin. Realizando una
comprobacin del valor que almacena el registro, direccin o constante asociada a la instruccin.
call, ret call tiene un uso similar a jmp a excepcin de que adems de realizar el salto a la
direccin solicitada, almacena en la pila la direccin de la instruccin ejecutada.
Por otro lado ret obtiene el tope de la pila y desplaza el flujo de ejecucin de nuestra aplicacin hasta la
direccin de memoria asociada. Si el registro SP apunta a una direccin errnea o esta ha sido sobreescrita
desencadenar que nuestra aplicacin se cierre inesperadamente. Con estas instrucciones jugaremos ms
adelante.
cmp, test cmp compara los dos operandos y establece una serie de flags como resultado de la
operacin realizada.
Por otro lado test realiza una operacin and a nivel de bit entre las dos variables y posteriormente realiza
una comparacin con 0.
o
o
o
cmp eax, ebx ; Compara EAX y EBX y establece el flag Zero si son iguales
cmp EAX, [404000] ; Compara EAX con el contenido de 404000
test eax, eax