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.