Miércoles, 20 de Agosto de 2008
Win32.Girigat: Inicialización
· Generalidades
· Inicialización
· Automutación
· Activaciones gráficas
· Residencia por proceso
· Búsqueda por acción directa
· Infección del formato PE
· Nombre del virus
· Conclusión
· Girigat1.jpg
· Girigat3.jpg
· Presentación

Volver al indice de articulos
Desensamblando el código de una aplicación infectada podemos ver claramente cómo está estructurado Girigat, ya que el autor del virus, Mister Sandman, fiel a su trayectoria, no ha implementado en este espécimen tipo alguno de encriptación.

El inicio del código consiste, como de costumbre, en la típica rutina de call+pop+sub, empleada con el fin de obtener el desplazamiento relativo o delta offset. En este caso Girigat emplea un pequeño truco de optimización, moviendo el valor sacado de la pila al registro EBX, para la posterior obtención de la dirección base del programa huésped o host.

El paso siguiente consiste en obtener la dirección real o VA (Virtual Address) del punto de entrada o entry point del host. Tanto este paso como el anterior (la obtención de la dirección base) están basados en valores guardados por el propio virus en su código, en variables dinámicas, durante el momento de la infección; estos valores los obtiene gracias a la información proporcionada al respecto por la cabecera PE de las aplicaciones que infecta. Su formato es el conocido como RVA (Relative Virtual Address), que necesita como complemento vital la dirección base del programa en ejecución de cara a conseguir la dirección real (VA), que es la que verdaderamente representa la situación en memoria, una vez que la aplicación está en ejecución, de cada uno de los bytes de dicha aplicación. Así las cosas, todo se resumiría en la siguiente fórmula:

RVA + dirección base = VA (dirección real)

Tras la cual enseguida comprendemos la necesidad por parte de cualquier virus de Win32 de guardar todas las RVAs necesarias para el proceso de inicialización, así como de obtener la dirección base del proceso actual, con el fin de poder dar juego a dichas RVAs.

Una vez que Girigat ha completado esta etapa, más tediosa de explicar que de programar (constituye menos de diez líneas de código), el siguiente paso consiste en obtener la dirección de las APIs necesarias para su funcionamiento. Muchos de los virus que hoy en día existen para Windows cometen el error de asumir direcciones absolutas para cada una de estas APIs, lo cual presenta de entrada como gran inconveniente el hecho de que el virus será completamente dependiente de la plataforma en la que fue programado: si fue programado en WindowsNT no funcionará en Windows95 o 98, y viceversa, de la misma manera que corre el riesgo de no funcionar en versiones posteriores del sistema. El motivo es tan sencillo como observar que la dirección de una misma API en una y otra plataforma varía de manera ostensible.

La solución más sólida planteada a este problema por parte de los escritores de virus de la scene vino de la mano de Jacky Qwerty, del grupo español 29A; es por esto que Mister Sandman, autor de Girigat y ex-miembro fundador del grupo, decidió seguir en su virus la línea propuesta por Jacky y ya vista en otros virus de este grupo. Esta solución a la que nos referimos consiste en sacar partido de la API GetProcAddress, que permite al programador obtener la dirección actual de cualquier API documentada del sistema.

No obstante la solución al problema no es tan sencilla. Para un mayor aprovechamiento de la memoria, los desarrolladores de Win32 decidieron en su momento distribuir las APIs en diversos módulos, que aparecen en forma de DLLs en el directorio \SYSTEM de Windows. Por esta razón, cada vez que se llama a la API GetProcAddress es necesario indicar, además del nombre de la API cuya dirección buscamos, la dirección del módulo al que dicha API pertenece, y es aquí donde aparece un nuevo problema para el escritor de virus: ya que las APIs básicas que necesita emplear para que su virus funcione correctamente pertenecen al módulo KERNEL32.dll, antes de poder llamar a la API GetProcAddress deberá haber obtenido la dirección de dicho módulo.

La alternativa más clara de cara a solventar este pequeño escollo, además de la más frecuente entre los virus de Win32, es la de llamar a la API GetModuleHandle, la cual, tras solicitarle el nombre del módulo deseado, nos devuelve la dirección base de dicho módulo. Otros autores de virus han optado por métodos menos estables, dependientes en cualquier caso de asumir por defecto una dirección absoluta (hardcoded) de KERNEL32. No obstante, llegados al punto de ir a usar GetModuleHandle, se nos presenta un nuevo problema: ¿cómo va el virus a obtener la dirección de dicha API, si precisamente la está llamando porque desconoce la dirección de las APIs que necesita usar en su código? se les plantea aquí todo un caso de "huevo-gallina" a los escritores de virus, que, cómo no, han salido al paso una vez más con distintas soluciones al problema.

Probablemente la solución más extendida a este inconveniente es la que consiste en guardar las RVAs de GetModuleHandle y GetProcAddress dentro del código vírico durante la infección de una determinada aplicación. Dado que la práctica totalidad de los ejecutables "normales" de Win32 incluyen estas dos APIs en su tabla de importación o IT (Import Table), muchos virus se aprovechan durante el momento de la infección para buscar las RVAs de estas dos APIs, y así emplearlas en su posterior inicialización. Éste es el método que hemos visto emplear en virus como Cabanas o Marburg y que, sin embargo, presenta un par de inconvenientes que desaconsejan su uso. El más claro es el hecho de que muchas de las aplicaciones que poseemos en nuestro ordenador, especialmente las del sistema, aparecen binded, mientras que otras muchas aplicaciones están unbinded. La diferencia radica en el empaquetamiento o no de los nombres de las APIs listadas en la IT, y esto es algo que plantea ciertos problemas a los virus que emplean la técnica anteriormente citada, con especial énfasis desde el momento en el que ya no sólo existen binds y no binds, sino que también han aparecido, de la mano de Microsoft, los new binds, característicos de Windows98 y NT, y que difieren sustancialmente de los empleados en Windows95. Por otra parte, el segundo de los inconvenientes radica en el hecho de que, en el caso de que una aplicación infectada bajo, por ejemplo, Windows98, fuese copiada a NT, el virus dejaría de funcionar, ya que estaría asumiendo una serie de RVAs intrínsecas de Windows98, pero que en ningún caso guardan relación con NT.

Girigat es de los pocos virus que va más allá y plantea una alternativa más sencilla y estable: en lugar de basarse en RVAs obtenidas durante el proceso de infección, el virus escanea la IT de su host para buscar la dirección base de la API GetModuleHandle. La IT de cada aplicación PE es rellenada con los datos correspondientes una vez que dicho programa ha sido ejecutado, de manera que Girigat se encuentra con el 50% del trabajo hecho mediante este sencillo pero ingenioso truco, teniendo la certeza de estar manejando en todo momento datos de una fuente tan fidedigna como el propio sistema en el que está corriendo.

Llegados a este punto es importante resaltar la existencia de los formatos ANSI y Unicode. Con el primero tanto europeos como americanos ya estamos familiarizados desde Windows 3.1x, mientras que el segundo constituye toda una novedad de la mano de Windows95 y sucesivas versiones, ya que está diseñado para dar soporte a alfabetos distintos del latino, el griego y el cirílico, como pueden ser el árabe, el hebreo, el chino o el hindú, al que más tarde en este análisis haremos referencia por otro motivo. El sistema Unicode está basado en conceder dos bytes, en lugar de uno, a cada letra o carácter que posea dicho formato. De esta forma se emplea el segundo byte como identificador del tipo de carácter que constituye el primer byte de la serie. En el siguiente ejemplo lo veremos con mayor claridad:

Texto "HispaSec" en ANSI: db "H","i","s","p","a","S","e","c"

Texto "HispaSec" en Unicode: db "H",0,"i",0,"s",0,"p",0,"a",0,"S",0,"e",0,"c",0

En este caso, al tratarse del alfabeto latino, el byte de control permanece a cero, dígito que sería distinto en caso de tratarse de otro tipo de alfabeto, como los ejemplos citados anteriormente. Lo que aquí nos interesa es que la aparición del Unicode ha afectado también en lo que a la programación de las propias aplicaciones se refiere, y así, lo que en Windows 3.1x era la API GetModuleHandle, a partir de Windows95 ha pasado a llamarse o bien GetModuleHandleA (versión ANSI, que requiere cadenas en formato ANSI como parámetros) o bien GetModuleHandleW (versión Unicode, que requiere cadenas en formato Unicode como parámetros, aunque en ciertos casos también admite ANSI). Lo realmente importante a este respecto en lo que concierne al análisis de Girigat, y en general de cualquier virus compatible de Win32, es que, a pesar de que en Windows9x es prácticamente improbable topar con aplicaciones que empleen APIs en Unicode debido a la falta de soporte, en NT son tanto o más frecuentes que las APIs en ANSI, por lo que, si un virus quiere funcionar en NT en las mismas condiciones en las que lo hace bajo Windows9x, debe tener en cuenta la existencia de APIs en Unicode, y saber cómo manejarlas a partir de ciertas rutinas.

Girigat no es menos, y la primera puesta en práctica de la teoría anterior se produce en los primeros bytes de su código, cuando busca GetModuleHandle en la IT de su host: se trata de los pocos virus de Win32 que tienen en cuenta el hecho de que, si su host no importa GetModuleHandleA, posiblemente sí que importe GetModuleHandleW. Es muy probable que esta circunstancia se dé en pocas ocasiones, pero en cualquier caso el autor del virus parece no estar dispuesto a perder ni una sola ocasión de hacer que su virus funcione.

Llegados a este punto, uno de los pasos más tediosos ya está dado: una vez que el virus conoce la dirección base de la API GetModuleHandle ya está en entera disposición de, llamando a dicha API, conocer también la dirección base del módulo KERNEL32. A partir de aquí el punto de atención se centra en torno al uso de la API GetProcAddress, especialmente en lo que respecta a su obtención. Una vez más, muchos virus, quizás una mayoría, han optado por obtener la RVA de esta API durante el proceso de infección del ejecutable que actualmente hace las veces de huésped. El virus Girigat vuelve a optar por una vía alternativa mediante la cual evita los inconvenientes anteriormente descritos, y en este caso, conocedor de la dirección base de KERNEL32.dll, se limita a escanear su tabla de exportaciones o ET (Export Table) con el fin de encontrar la API GetProcAddress, emulando el funcionamiento de dicha API. Aquí uno podría pararse a pensar por qué Girigat no busca directamente en la ET de KERNEL32 todas las APIs que necesita, en lugar de buscar tan sólo GetProcAddress para tal fin... ¿no sería más directo, rápido y lógico optar por lo primero? Lo cierto es que desconocemos la respuesta a esta pregunta, y lo único que podemos pensar es que probablemente Mister Sandman decidió emplear GetProcAddress y no un escaneo constante de la ET de KERNEL32 para evitar posibles conflictos, especialmente bajo NT, ya que el empleo de la citada API tiende a ser más estable.

El caso es que, con las direcciones base de KERNEL32 y de GetProcAddress en el zurrón, el virus está por fin en condiciones de obtener el resto de las APIs necesarias para poder trabajar, las cuales consigue por medio de un bucle un tanto lioso, debido a la cantidad de registros que entran en juego. Tras esto podemos darle la bienvenida a lo que es la acción vírica en sí, que ha necesitado valerse del código que acabamos de describir para poder ejecutarse sin complicaciones.