Análisis de bootkit

Hola a todos! En relación con el lanzamiento del curso de "Ingeniería inversa", realizamos una lección abierta planificada. Desmontó el algoritmo de operación de bootkit en diferentes etapas de su carga.



Profesor: Arthur Pakulov , analista de virus en Kaspersky Lab.

El siguiente artículo es introductorio y es una versión de texto de solo una parte de la lección, dedicada al instalador del bootkit. Un análisis detallado del propio bootkit, vea el video.

Un bootkit es un programa malicioso que modifica Master Boot Record, el primer sector del primer disco físico o sector de arranque, VBR. Los programas de este tipo tienen principalmente funcionalidad troyana y se utilizan para llevar a cabo acciones ocultas en el sistema. En nuestro ejemplo, el bootkit realiza la escalada de privilegios al nivel de proceso, cuyo nombre comienza con una secuencia de letras: "inte". De hecho, un bootkit es un rootkit que comienza a funcionar en el anillo de protección 0, que se inicia incluso antes de que el sistema operativo comience a cargarse. Es por esto que es de gran interés para la investigación.

Para desarrollar dicho programa, las habilidades habituales de ingeniería inversa no son suficientes. No basta con poder leer la lista, también debe comprender cosas como la arquitectura del procesador, el direccionamiento de memoria, etc. En una lección abierta, analizamos los lugares clave del kit de arranque.

Para el trabajo, se preparó una muestra especial bootkit-xp.exe, trabajando bajo Windows XP. Por lo tanto, además de estudiar el bootkit, estábamos un poco nostálgicos por este sistema operativo. Pero en general, se eligió el OS XP para que sea más fácil revertirlo, ya que XP es una buena visualización y la ausencia de complicaciones innecesarias. Bueno, la muestra fue escrita específicamente para este sistema operativo, a juzgar por su código.

Así es como se ve el instalador del bootkit :



Con solo mirarlo, puedes sacar ciertas conclusiones. Por ejemplo, es inmediatamente evidente que este archivo tiene un peso pequeño. Si observa el punto de entrada, puede ver que el código está recibiendo un descriptor de archivo con el nombre de un enlace simbólico al primer disco físico: "PhysicalDrive0":



Además, por conveniencia de la percepción del código, cambiamos a IDA . Queda claro que, para un troyano típico, la funcionalidad disponible es bastante pequeña. Incluso la tabla de importación es sospechosamente pequeña:



Tal imagen generalmente surge al analizar muestras empaquetadas. Pero, en nuestro caso, el archivo no parece empaquetado. Resulta que la muestra está cubierta por algún protector / criptor y en el proceso de su trabajo recibe las direcciones de las funciones de forma dinámica, después de lo cual llama al funcional deseado, o todo está bien, y la muestra está como está.

Seguimos explorando el código.



Como vimos en HIEW, la función CreateFileA se llama con un argumento interesante como primer parámetro. ¿Qué se está haciendo exactamente aquí? Aquí es apropiado recordar algo como los objetos del núcleo . No se pueden manipular directamente desde el modo de usuario, son controlados por el núcleo del sistema operativo. Desde el modo de usuario, un programa solo puede hacer una solicitud para recibir / cambiar el estado de cualquier objeto del núcleo. Para indicar al sistema con qué objeto del núcleo en particular trabajará el programa, es necesario obtener el identificador del objeto del núcleo requerido. Al solicitar el recibo, si se pasan todos los cheques, el sistema operativo nos devolverá el identificador del OA solicitado. Y ya usando handle, podemos trabajar con el OA asociado.

Por lo tanto, en la imagen de arriba, usando CreateFile, se accede a un enlace simbólico al primer disco duro físico conectado. Si se le otorga acceso, puede trabajar con un "archivo" como con cualquier otro archivo simple. Es decir, todo el disco duro se presentará como un solo archivo grande.

Entonces, continuemos. Handle está de vuelta, y nos encontramos aquí:



¿Qué pasa después? Y luego la función ReadFile lee los primeros 0x200 bytes. Y tenemos allí el primer sector del primer disco físico.



Como habrás adivinado, este es Master Boot Record (MBR). MBR consta de 3 partes: parte de código, tabla de particiones y firma. En una situación normal, BIOS lee el MBR en la memoria en la dirección 0: 0x7c00h, pasándole el control. Entonces, la parte del código del MBR comienza a ejecutarse. Durante la ejecución, analiza la tabla de particiones, encuentra el sector de arranque y lo carga. En el caso de un bootkit, si se sobrescribe el MBR, su código ahora recibirá el control.

Ok, se lee MBR, y ¿qué sigue ? Y luego el bootkit abre PhysicalDrive0 nuevamente, pero con el modo de acceso de escritura.



A continuación, se establece un puntero en el desplazamiento número 600. Es decir, el sector original se lee y copia al tercer sector .

¿Por qué respaldar un sector? Obviamente, esto es necesario por el hecho de que será necesario en el futuro.

Entonces comienza el ciclo. Naturalmente, mirando el código, uno no puede dejar de prestar atención a constantes como var_1C, 1BEh y otros. Y, al mismo tiempo, la estructura MBR ubicada arriba debe actualizarse en la memoria. En particular, estamos interesados ​​en la columna "Offset".



Vea, el buffer de lectura del primer sector está en lpBuffer . Luego se le agrega 1BEh . De hecho, el puntero va al comienzo de la tabla de particiones. Todos los datos desde la tabla hasta el final del sector se insertan en _marked_bytes , comenzando desde el mismo desplazamiento: 1BE.



Es decir, las partes segunda y tercera del MBR original se insertan en _marked_bytes .

¿Qué pasa después? Y luego SetFilePointer establece el puntero al comienzo de nuestro "archivo", es decir, al MBR.



Luego hay una escritura (WriteFile) formada _marked_bytes y liberando memoria. En esto, la funcionalidad del instalador de bootkit finaliza.

Pero sería bueno ver qué es exactamente en la primera parte de _marked_bytes . Para hacer esto, volcarlo en el disco y analizarlo. Lo primero que llama la atención es una disminución en 2 del contenido de la variable en la dirección 0x413.



Si observa la documentación técnica, puede encontrar que la variable en 0X413 contiene la cantidad de memoria física instalada en kilobytes. En consecuencia, el código del bootkit "corta" dos kilobytes de memoria:



Ahora, para no seguir adelante, se considerará que hay 2 kilobytes de memoria menos de lo que era. Por qué, aún no está claro.

A continuación, la dirección física se calcula en el trozo de memoria "bit off" utilizando un desplazamiento a la izquierda de 6 bits:



Un cambio de 6 realiza dos acciones a la vez: convierte kilobytes a bytes (multiplicando el valor de la variable por 2 ^ 10), obteniendo así la dirección física de la memoria mordida, y extrae el número de segmento de ella, dividiendo el resultado por 0x10 (2 ^ 4).

Después de eso, su cuerpo será copiado sobre esta pieza de memoria y, dado que el código del bootkit está en la pieza "bit off", nadie lo molestará más . Además, ninguna interrupción no cambiará lo que está escrito en esta área de memoria. Podemos decir que el código se vuelve prácticamente invisible para el sistema , como si no hubiera memoria allí.

Esto es solo el comienzo del kit de arranque. Luego habrá una intercepción de interrupción, seguimiento de firma ntldr, modificación del módulo del kernel del sistema operativo, etc.

Por lo tanto, no lo estropearemos, es mejor mirar el seminario web hasta el final para no perderse nada.

Source: https://habr.com/ru/post/482086/


All Articles