Viernes, 5 de Septiembre de 2008
Win32.Girigat: Infección del formato PE
· 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
El primero de los pasos de cara a los últimos chequeos y a la posterior infección del fichero es más o menos la piedra angular de toda rutina de infección nativa de Win32 que se precie: el mapeo de ficheros en memoria. Esta técnica, también descubierta por el autor Jacky Qwerty, y empleada desde entonces en la inmensa mayoría de los virus de Win32, viene a ser una simplificación en cuanto a manejo de ficheros con respecto al obsoleto sistema de apertura empleado en los virus de DOS y en los ejemplares más primitivos de Win32.

La principal ventaja para los escritores de virus radica en el hecho de que, por medio del mapeo de ficheros, no es necesario emplear funciones de lectura, ni de escritura, ni de movimiento de la posición del puntero dentro del fichero abierto. Es mucho más fácil que eso. Al mapear un fichero en memoria se obtiene una dirección en EAX a partir de la cual Win32 ha colocado una imagen íntegra del fichero que hemos especificado, y basta con referenciar cualquier desplazamiento de dicha imagen por medio de su dirección real para poder trabajar en él, sin necesidad de punteros. Asimismo, una vez que se desmapea el fichero, cualquier cambio efectuado en su código durante el mapeo queda automáticamente guardado, sin necesidad de recurrir a la función de escritura. Y no sólo se trata de ventajas a la hora de programar, sino también a la hora de correr lo que se ha programado, ya que la rapidez de ejecución de un código en el que se emplea mapeo de memoria es muy superior a la de uno en el que se utilicen las tradicionales y obsoletas funciones de lectura, escritura y movimiento de puntero, y esto es algo que juega a favor de los virus, que en todo momento buscan la velocidad y la optimización, con el fin de pasar inadvertidos.

El mapeo de ficheros se lleva a cabo por medio de las APIs CreateFileMapping y MapViewOfFile, las cuales necesitan un handle del fichero a procesar, obtenido a partir de la manida CreateFile, empleada la mayor parte de las veces, a pesar de lo que pueda aparentar su engañoso nombre, para abrir ficheros, en lugar de para crearlos. Una vez que Girigat ha mapeado a una posible víctima en memoria, procede a comprobar, por orden, la presencia de la marca MZ (característica intrínseca de todo fichero EXE), la de la marca de infección del virus (un ";)", siguiendo con la línea del autor), situada en el offset 12h de la cabecera MZ del EXE, la existencia de una cabecera PE en la dirección especificada por el puntero situado en el desplazamiento 3ch (característica intrínseca de toda aplicación nativa de Win32, es decir, EXEs de formato PE con cualquier extensión), y, por último, comprueba por medio de la sección Characteristics de la cabecera PE que no se trata de una DLL renombrada. Si estos chequeos no presentan ningún problema, el virus guarda la fecha (día y mes) de la infección y cede el control a lo que es la rutina de infección de PE en sí.

El método empleado por Girigat para infectar PEs es el puesto de moda por, quién si no, Jacky Qwerty, que ha creado toda una escuela de programación en lo que a Win32 se refiere. Hoy en día se pueden distinguir, a grandes rasgos, tres tipos de infección PE: la creación de una nueva sección (el método más antiguo, empleado por Quantum en su virus Bizatch), la adhesión del cuerpo del virus al código de la última sección del ejecutable (la técnica inventada por Jacky Qwerty), y, por último, la puesta en práctica por parte de un pequeño grupo de virus neocompanion, entre los cuales quizás el más importante sea el Mylene de SSR, que funcionan de manera independiente, instalándose en la memoria del sistema como una aplicación legítima, aunque su código en realidad es volcado por medio de aplicaciones que fueron infectadas con anterioridad. El más extendido de los citados es el segundo, ya que es más difícil de detectar y, sin duda, pasa más desapercibido a los ojos de aquellos usuarios de nivel medio que ocasionalmente decidan inspeccionar por medio de un editor hexadecimal la cabecera de las aplicaciones PE en las que sospechen que se pueda esconder un virus.

La anexión de código vírico a la última sección no es un proceso complicado, ni mucho menos: basta con obtener el número de secciones de código, por medio del campo NumberOfSections, y hacer unas sencillas operaciones aritméticas para calcular, conociendo la longitud estándar de cada sección (28h bytes), cuál es el punto de entrada de la última sección de la aplicación PE que se pretende infectar. Girigat lo tiene aún más fácil, debido a un original y eficiente truco de programación: mientras lo normal durante el proceso de API hooking es emplear las funciones GetCurrentProcess y WriteProcessMemory para parchear la IT del host, debido a la posibilidad de causar un error de protección general en caso de pretender escribir un código en ejecución directamente. El motivo se esconde tras los atributos que posee cada sección, que son capaces de restringir, entre otras cosas, los permisos de escritura. Girigat mata en este punto dos pájaros de un tiro, ya que procede a añadir atributos de escritura a todas las secciones de las aplicaciones que infecta. De esta forma no se tiene que preocupar de emplear WriteProcessMemory en su rutina de residencia por proceso, y, como recompensa, además tiene más fácil la localización del punto de entrada de la última sección, ya que, con simplemente restar el tamaño de ésta (28h) tras efectuar el bucle de parcheo, el trabajo está hecho. A partir de aquí, el virus ha de obtener el tamaño de la sección, el valor de alineamiento del ejecutable, y el punto de entrada de la aplicación, perteneciendo estos dos últimos campos a la cabecera PE, mientras que el primero está ubicado en la última sección. Un punto importante para cualquier virus es no confundir SizeOfRawData, que es el tamaño real del código de una sección, con el valor especificado en VirtualSize, que es el tamaño mínimo de la sección una vez adaptado a 32 bits por medio del alineamiento por defecto de la aplicación a la que pertenece. Manejando estos valores, Girigat calcula el final de la última sección (añadiendo SizeOfRawData al punto de entrada de la sección), fija esa dirección como punto de entrada de la aplicación (en el offset 28h de la cabecera PE), anexa su código a partir de ese punto de la última sección, y modifica los valores correspondientes al SizeOfRawData y al VirtualSize (por medio del FileAlignment), así como SizeOfImage, perteneciente a la cabecera PE. Este último campo es, en la mayoría de los virus, objeto de olvido, y la consecuencia más inmediata es la posibilidad de causar errores de protección general en algunas aplicaciones al trabajar bajo WindowsNT. Durante el proceso, y de manera desornenada con el fin de optimizar bytes, Girigat obtiene las RVAs necesarias para su posterior proceso de inicialización, tal y como describimos en el primer capítulo de este análisis.

Es importante fijarse en este tipo de detalles dentro de la "oscuridad" intrínseca de la mayoría de las rutinas de infección, que suelen seguir unas pautas determinadas y ofrecen pocas posibilidades de innovación a los autores de virus, que en algunos casos se limitan a copiar los procedimientos de infección de otros virus, como ocurría con otro tipo de rutinas estándar en el DOS, como, por ejemplo, las de ocultación o stealth.