Análisis de malware

Construcciones de código importantes en lenguaje ensamblador: avanzado

13 de abril de por Ninja de seguridad

Hemos cubierto algunas operaciones básicas y declaraciones condicionales en la Parte 1. En este artículo, cubriremos algunas estructuras de datos más complejas para reconocer en ensamblaje, como matrices, listas vinculadas y estructuras. Así que sin más preámbulos, comencemos.

matrices

Las matrices se utilizan para almacenar elementos de datos similares. Las matrices también se pueden definir global o localmente, en las que prevalece el concepto de global y local, como se trata en la Parte 1. Considere la siguiente parte del código.

¡Conviértete en un ingeniero inverso certificado!

Obtenga capacitación práctica en vivo sobre análisis de malware desde cualquier lugar y conviértase en un analista certificado de ingeniería inversa. Comienza a aprender

Ent i;

Ent x[5];

para (i=0;i10;i++)

{

x[yo]=yo;

}

El código se explica por sí mismo; simplemente asigna el valor actual de i al valor correspondiente en la matriz x en el índice I mientras recorre el bucle diez veces (i10). Lo principal es reconocer cómo el código ensamblador atraviesa la matriz. Todavía no sabemos el tamaño de cada elemento y también tiene que haber alguna dirección base mediante la cual se haya accedido a todas las ubicaciones de memoria de la matriz y se le haya asignado algún valor. Veamos el código ensamblador.

Movimiento [ebp+var_4], 0

Jmp corto loc_123456 :

Ubicación 987654:

Mover eax, [ebp+var_4]

Añadir eax, 1

Mov [ebp+var_4], eax

Ubicación 123456:

Cmp [ebp+var_4], 10

Juez 234567:

Mov ecx, [ebp+var_4]

Mov[ ebp+ecx*4+var_8 ],ecx

Jmp corto loc_987654

Como podemos ver aquí, primero se produce la inicialización y comparación normal del bucle ‘for’. Luego, el valor actual se transfiere a ecx. ¿Por qué? Se utilizará como índice de la matriz x. En la declaración [ebp+ecx*4+var_8], var_8 se utiliza como la dirección base de la matriz x. Intente poner diferentes valores de ecx desde 0,1,2,3… Verá cómo a cada ubicación de memoria de la matriz se le ha asignado el valor. Entonces, al reconocer matrices, busque estas construcciones que incluyen la dirección base y la variable de indexación.

estructuras

Si ve matrices que no son capaces de manejar datos heterogéneos, existe otra estructura de datos llamada struct para ayudar. Las estructuras pueden contener elementos de diferentes tipos de datos. Si recuerdas en mi serie PE, hay muchas estructuras en el directorio de datos. Considere el siguiente código de estructura donde se enumeran la declaración de variables de estructura, la asignación de memoria y la definición:

estructura Test_struct *Prueba; // declaración de variables

Vacío principal()

{

Prueba = (struct Test_struct *) malloc(sizeof(Test_struct)); // asignación de memoria para estructura

prueba(Prueba);

}

test_struct // definición de estructura

{

Ent x[3];

carácter b;

}

Prueba nula (estructura Test_struct *a)

{

Ent yo,

a-b=’l’;

para (i=0;i3;i++)

{

a-x[i]=i;

}

}

Tenga en cuenta aquí que he declarado una variable de estructura de puntero y, por lo tanto, utilicé – para acceder al miembro de la estructura. En el caso de una variable de estructura simple, la variable de punto (.) se utiliza para acceder a los miembros de la estructura. Veamos el código ensamblador. Dado que el código tiene varias construcciones, también veremos su código ensamblador en partes.

Principal:

Empuje epp

Mov ebp, esp

Empujar 16h

llamar a malloc

Añadir esp, 4

mov dword_126785,eax

Mover eax, dword_126785

empujar eax

Llame a la ubicación 234567

Añadir esp,4

………

Ubicación 234567:

Empuje epp

Movimiento ebp, esp

Empuje ecx,

Mover eax,[ebp+var_4]

Byte de movimiento [eax+13h],6 canales

Movimiento [ebp+var_8], 0

Jmp corto loc_123456

Ubicación 987654:

Mover eax,[ebp+var_8]

Añadir eax,1

Mov [ebp+var_8],eax

Ubicación 123456:

Cmp [ebp+var_8], 3

Jue 12345:

Mover eax,[ebp+var_8]

Mov edx,[ebp+var_8]

Mov ecx,[ebp+var_4]

Mover[ecx+eax*4],edx

Jmp corto loc_987654

Bien, esto parece un poco complejo al principio, pero si miramos instrucción por instrucción, será simple. La primera función sizeof pasa 16h a la pila para asignar espacio para la estructura. Luego se llama a malloc y luego se borra la variable. Después de eso, dword_126785 contiene la dirección base de la estructura y se pasa a la función de prueba mediante push eax. Luego pasamos a la función de prueba donde se accede a la dirección base y ponemos el valor en eax. La variable a las 13h dentro de la dirección eax es el carácter ‘l’ con valor 6ch. Luego, en var_8 está la dirección base de la matriz de enteros y se hace referencia a la matriz de enteros desde ecx+eax*4 donde ecx contiene la ubicación base de la estructura y eax atravesará la matriz de enteros en un índice. El análisis principal de esta estructura es que diferentes variables están dentro de la misma estructura de datos, es decir matriz de caracteres y enteros dentro de la misma estructura de datos. Entonces esta estructura no puede no ser una matriz.

Lista enlazada

Los elementos de datos de la lista vinculada están vinculados entre sí, es decir, cada registro apunta al siguiente elemento de datos. Pero no se garantiza que estos también se almacenen de la misma manera en la memoria. Para identificar esta estructura de datos, es necesario encontrar un objeto que contenga el puntero a otro objeto. Tenga en cuenta que en este artículo solo estamos hablando de listas enlazadas individualmente. Considere la siguiente implementación de lista vinculada con estructura de nodo.

Nodo de estructura

{

Ent a;

Nodo de estructura *siguiente;

}

Vacío principal()

{

Nodo *inicio, *temp;

Ent i;

inicio=NULL;

para(i=0;i5;i++)

{

temp=( Nodo *)malloc(tamañode(Nodo)); // puntero a la dirección base de la estructura

temperatura -a=i; // almacenando i en un

temperatura -siguiente=inicio; // apunta al siguiente nodo

inicio=temperatura; // guardando el valor de temp en inicio

}

}

Empuje epp

Mov ebp, esp

Movimiento[ebp+var_4],0

Movimiento[ebp+var_8],1

Ubicación: 987654

Cmp [ebp+var_8],5h

Jue 12345:

Empujar 8h

llamar a malloc

Mov[ebp+var_c],eax

Mov edx, [ebp+var_c]

Mover eax,[ebp+var_8]

Mov[edx],eax

Mover eax,[ebp+var_4]

Mov edx,[ebp+var_c]

Mover[edx+4],eax

Mover eax,[ebp+var_c]

Mov [ebp+var_4],eax

Jmp loc corta _123456

Ubicación: 123456

Mover eax,[ebp+var_8]

Añadir eax,1

Mov[ebp+var_8],eax

Jmp 986754

Entonces, en este ensamblaje lo que sucede es que inicialmente se calcula y almacena el desplazamiento del primer nodo. Luego, el valor de i se almacena en el desplazamiento del primer nodo y NULL se almacena en *next en [edx+4]. Al final, el valor de desplazamiento base se almacena en *start. En el segundo recorrido, si se calcula el tamaño del segundo nodo, se almacena el desplazamiento y nuevamente el valor var i se almacena allí. En edx+4 se almacena el valor del primer desplazamiento y al final del desplazamiento transversal del segundo nodo se almacena al inicio nuevamente para que el 3.er nodo apunte al 2.º nodo formando así una lista. Puede haber múltiples variaciones del código ensamblador. El código a reconocer es la siguiente variable que apunta a otra estructura una y otra vez formando así una lista vinculada.

Así que todo esto se trata de estructuras que discutiremos. Como el objetivo de esta serie de artículos y de PE es desarrollar habilidades de análisis de malware, creo que ahora podemos comenzar a analizar el análisis de malware, que comenzaré en el próximo artículo.

Agregue un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *