CREANDO MALWARED DESDE CERO -1

Bueno lamento traer este capitulo hasta ahora después de lo acordado, el problema es que tuve un pequeño contratiempo y no pude prepararla hasta ahora. Quiero comentarles que desde que inicie con la primer parte he recibido muchos comentarios y se ha obtenido una buena respuesta, ya que hay muchas personas que les ha gustado la idea pero también ha habido otro tanto que me han preguntado cual es la finalidad de hacer un curso sobre desarrollo de malware y pues bien mi respuesta es : “ La finalidad de hacer un curso en tutoriales sobre de desarrollo de malware es la misma que se pretende al redactar cualquier tipo de investigación del tema de la seguridad informática, y es compartir el conocimiento, es obvio que mientras conozcas y domines el tipo de ataque y cómo funcionan,  la manera de protegerte y prevenirlos será mucho más sencilla, es responsabilidad de cada quien la forma en que lo usen pero recuerden depende de cada uno hacer el conocimiento adquirido un arte, quedando claro esto quiero pasar con lo siguiente:
Como les comente la segunda y tercer parte serian algo pesadas, pues bien en estas primeras partes se definirá si estás preparado para lo que sigue, a continuación hablaremos  del lenguaje ensamblador, si ese mismo, pero vamos que no es nada del otro mundo, al contrario veras lo sencillo que resulta ser comprender tan maravilloso lenguaje y del cual dominándolo se pueden lograr muchísimas cosas, comenzamos.

(algunas partes de aquí es tomado del tutorial #3 del colega fabio escudero)


Assembler:
Registros del procesador:
Los registros los podemos ver como espacios físicos que residen dentro del procesador y se emplean para controlar instrucciones en ejecución, manejar direccionamientos de memoria y proporcionar capacidades aritméticas y lógicas. Siempre que hablemos de registros vamos a hacer referencia a los registros de 32 bits, los cuales aparecieron con los procesadores 386 en adelante, no a los antiguos registros de 16 bits que utilizábamos en programas DOS.
Registro generales:
EAX: registro acumulador, es un registro de propósito general pero también muy utilizado en operaciones matemáticas, es utilizado para obtener el valor de retorno de las API’s, CreateFileA.

EBX: registro base, se suele utilizar para direccionar el acceso a datos situados en la memoria. También como el registro eax lo podemos dividir en BX, BH y BL.

ECX: registro contador, se utiliza como contador en determinadas instrucciones. También podemos usar CX, CH y CL.

EDX: registro de datos, además de su uso general. También se lo utiliza en operaciones de Entrada/Salida. Podemos utilizar EDX, DX, DH y DL.

Registros de puntero:

ESP: es un registro que apunta a la dirección del último valor introducido en la pila, o sea del primero que podríamos sacar. Cuando ingresamos o sacamos valores del stack el SO lo actualiza automáticamente para que siempre apunte al último valor. De todas formas podemos modificarlo desde nuestro código, ya veremos cómo. Pueden utilizarse los 16 bits inferiores con SP.

EIP: este registro apunta a la dirección de la próxima instrucción a ejecutarse y se va modificando automáticamente según se va ejecutando el programa.


Registros de base:
EBP: se utiliza para direccionar el acceso a datos situados en la pila y también para uso general. Pueden utilizarse los 16 bits inferiores con BP.
Registros de índice:
ESI y EDI: estos registros se utilizan para acceder a posiciones de memoria, por ejemplo cuando queremos trasferir datos de un lugar a otro o cuando queremos comparar dos bloques de memoria contigua. ESI actúa como puntero al origen (source) y EDI como puntero al destino (destination).
Podemos acceder a los bytes inferiores con SI y DI.

Los flags:

Las banderas también son un registro de 32 bits, donde cada uno de estos bits tiene un significado propio, que generalmente son modificados por las operaciones que realizamos en el código, y los cuales se los utiliza para tomar decisiones en base a las mismas: comparaciones, resultados negativos, resultados que desbordan los registros, etc.
01

C (Carry o acarreo): se pone a uno cuando se efectúa una operación que no cabe en el espacio correspondiente al resultado.

P (Paridad): se pone a uno cuando se efectúa una operación cuyo resultado contiene un número par de bits con el valor 1.

A (Auxiliar): similar al de acarreo (C), pero para las operaciones efectuadas con números en formato BCD (Binary Coded Decimal), o sea decimal codificado en binario.

Z (Cero): se pone a uno cuando se efectúa una operación cuyo resultado es cero. Ojo con esto porque a veces confunde, si se pone en cero, el resultado es distinto de cero y viceversa.

S (Signo): se pone en uno si el resultado de una operación da como resultado un valor negativo

T (Detención): si está en uno el procesador genera automáticamente una interrupción después de la ejecución de cada instrucción, lo que permite controlar paso a paso la ejecución del programa.

D (Dirección): en este caso este flag no cambia por acciones realizadas, sino que lo modificamos desde nuestro código para afectar ciertas operaciones, ya que indica la dirección a utilizar en ciertos comandos (hacia adelante o hacia atrás), como por ejemplo en comparaciones de bloques de memoria contiguos. Para modificarlo utilizamos las instrucciones std y cld, que luego veremos.
O (Overflow o desbordamiento): se pone a uno cuando se efectúa una operación cuyo resultado cambia de signo, dando un resultado incorrecto.


Las instrucciones básicas:

Veremos algunas instrucciones básicas lo cual es esencial comprendas el funcionamiento de estas y aunque no es necesario las guarden de memoria pues podrían regresar a consultar este escrito en cualquier momento que surjan las dudas, veamos:

nop (No Operation): este comando literalmente no hace nada, su utilidad es para rellenar huecos en el código o para ocupar ciclos del procesador.

mov (Move): esta instrucción tiene dos operandos, y lo que hace es copiar el origen (representado en segundo lugar) en el de destino (en primer lugar). Por ejemplo si ponemos:
ejemplo:
“mov     eax, 24”
mov ecx, eax “
Lo que estamos haciendo aquí es mover el 24 al registro eax, para después mover el contenido del registro eax, al registro ecx.

xchg (Exchange): intercambia los contenidos de los dos operandos.

inc (Increment) / dec (Decrement): incrementan y decrementan respectivamente el valor indicado en el operando.

add (Add): suma los contenidos de sus dos operandos y coloca el resultado en el operando representado en primer lugar.

adc (Add with Carry): igual que la anterior, pero suma también el valor del flag de acarreo. Se utiliza para sumar valores mayores de 32 bits.

sub (Subtract): esta instrucción resta el contenido del segundo operando del primero, colocando el resultado en el primer operando.

sbb (Integer Subtraction with Borrow): esta instrucción es una resta en la que se tiene en cuenta el valor del flag de acarreo.

mul (Unsigned Multiply) / imul (Signed Multiply): estas instrucciones se utilizan para multiplicar dos valores. La diferencia entre las dos, es que en la primera no se tiene en cuenta el signo de los factores, mientras que en la segunda sí.

div (Unsigned Divide) / idiv (Signed Divide): Divide dos valores, y al igual que para mul hay dos instrucciones: una considera el signo, la otra no.

push (Push Onto the Stack): esta instrucción resta del registro ESP la longitud de su operando que puede ser de tipo word o double word (4 u 8 bytes), y a continuación lo coloca en la pila. Tiene unas variantes como pushad y pushf para guardar los valores de los registros y los valores de los flags.

pop (Pop a Value from the Stack): es la inversa de push, es decir que incrementa el registro ESP y retira el valor disponible de la pila y lo coloca donde indica el operando.

and (Logical AND) / or (Logical Inclusive OR) / xor (Logical Exclusive OR) / not (Negation): realiza estas operaciones lógicas bit a bit entre los operandos.

cmp (Compare): esta instrucción compara dos valores. Generalmente se utiliza acompañada de un salto condicional de acuerdo al resultado de esa comparación.

jmp (Inconditional Jump): indica un salto que no está sujeto a ninguna condición, es decir que se ejecuta siempre.
jz / je / jne / etc. (Conditional Jump): estas instrucciones se ejecutan condicionalmente de acuerdo a los valores de los flags.

call  (Call Procedure): efectúa el salto al punto de inicio de una subrutina. Además de esto, coloca en la pila la dirección de la instrucción siguiente, que será el punto de regreso después de ejecutarse la misma.

ret (Return from Procedure): complementa a la anterior y sirve para regresar a la instrucción siguiente a la que llamó a la subrutina. Para ello, efectúa un salto a la dirección contenida en la pila, quedando ésta como estaba antes del call.

loop (Loop According to ECX Counter): esta instrucción efectúa un bucle o loop un número de veces determinado por el registro ECX. Lo que hace esta instrucción es decrementar ECX, si llegó a cero sale del bucle, sino salta a la dirección indicada en la instrucción.

rep (Repeat): se utiliza en combinación con otra instrucción, lo que hace es repetir la misma la cantidad de veces indicada por ECX. Se utiliza por ejemplo con movsb, lodsw, etc.


Instrucciones de flags

clc (Clear Carry Flag): pone a cero el flag de acarreo (CF).

stc (Set Carry Flag): pone a uno el flag de acarreo (CF).

cld (Clear Direction Flag): pone a cero el flag de dirección (DF).

std (Set Direction Flag): pone a uno el flag de dirección (DF).

cli (Clear Interrupt Flag): pone a cero el flag de interrupción (IF).

sti (Set Interrupt Flag): pone en uno el flag de interrupción (IF).


Bien algo complicado si nunca has ocado este lenguaje, pero no se preocupen que no es necesario aprenderlo de memoria, podras regresar en cualquier momento si tienes dudas cuando continuamos, lo importante es que vayas adaptandote en este lenguaje.
Hasta aqui llego esta primer parte, pero aún no termina la parte pesada en el proximo hablaremos de la estructura PE y durante ese mismo comenzaremos algo ligero y mas divertido sobre los comienzos del desarrollo, asi que no desesperen ya que todo esfuerzo tiene una recompensa.