Tres historias cortas del registro de Windows

Buenas tardes, queridos lectores.

El registro es uno de los sistemas Windows más visibles y significativos. Apenas hay una persona que no haya oído hablar de él. Después de haber estado programando en Windows durante unos 20 años, pensé que sabía todo sobre él. Pero de vez en cuando, aparece algo nuevo que me muestra lo equivocado que estaba. Por lo tanto, hoy quiero contarles sobre las formas inusuales de trabajar con el registro que conocí mientras investigaba rootkits y que me sorprendieron.


La primera historia Nombres de valores de registro y claves


Todos sabemos que en Windows hay algunas reglas para nombrar objetos, ya sean archivos, directorios o claves de registro. Los nombres de archivo no pueden contener el carácter "\". Los nombres no pueden estar vacíos. Los nombres tienen algunas restricciones de longitud, etc.

Involuntariamente, ampliamos estas restricciones a todos los sistemas Windows y las observamos cuando trabajamos con el registro. Y aquí yace nuestro error. Sorprendentemente, existen pocas restricciones en el registro al crear nombres. Por ejemplo, puede usar el carácter \ en el nombre de los valores


Sorprendido? No? Entonces, ¿qué dirá si le muestro que el símbolo "\ 0" se puede usar en el nombre de un valor? Sí, sí, exactamente el carácter nulo. El que se usa tradicionalmente para indicar el final de una línea.

Para esto, necesitamos la función NtSetValueKey exportada desde ntdll.dll

HKEY hKey = 0; RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey); UNICODE_STRING uName; uName.Buffer = L"Test\0Zero"; uName.MaxLen = uName.Length = 9 * sizeof(wchar_t); NTSTATUS status = 0; status = NtSetValueKey( hKey, &uName, 0, REG_SZ, (void*)lpData, DataSize); RegCloseKey(hKey); 

Para ejecutar la función NtSetValueKey, necesita derechos de administrador. Como resultado, un valor con el nombre Test \ 0Zero aparecerá en su registro.

Algunos desarrolladores de Microsoft también se sorprenderán, porque el editor de registro estándar no puede mostrar un valor de registro tan inusual.


Segunda historia


La segunda historia que les contaré hoy sucedió en 2013.

Al principio una pequeña digresión. En Kaspersky Lab, soy miembro del equipo que, entre otras cosas, crea Kaspersky Rescue Disk. Para curar Windows desde Linux, necesitamos analizar los archivos de registro nosotros mismos. Y para verificar el funcionamiento correcto de este mecanismo, utilizamos muchas pruebas. Entre ellos, hay uno bastante simple:

  • En Windows, escribimos valores de prueba en el registro.
  • Copie el archivo de la sección de registro en el directorio de prueba.
  • Iniciamos el programa que realiza la eliminación de los valores de prueba.
  • Cargamos el arbusto modificado en el registro para verificar la eliminación.

Y un buen día, actualizamos en el banco de pruebas de Windows a la versión 8.1, y la prueba dejó de eliminar los valores de prueba. Cómo es que me sorprendió. Copié el archivo con la colmena de registro en mi computadora en funcionamiento, ¡sin valores! Mi primer pensamiento: necesito agregar claves cambiadas a la prueba de Flush. Se agregó una llamada a RegFlushKey, reinició la prueba, ¡sin valores!

RegFlushKey no funciona, pensé. Pero, como resultó, solo estaba parcialmente en lo cierto.

El truco fue que en Windows 8.1, Microsoft cambió el mecanismo para guardar los cambios en el registro. Anteriormente, todos los cambios del registro se acumulaban en la memoria, y luego, cuando se cerraba la clave, cuando se ejecutaba RegFlushKey o después de un tiempo, el sistema guardaba los cambios en el archivo bush del registro. En Windows 8.1, los cambios en lugar del archivo de la sección de registro se guardan en archivos del mismo nombre con las extensiones .LOG, .LOG1 y .LOG2, y mi código ignoró estos archivos en esos días.

En estos archivos, los cambios se acumulan durante aproximadamente una hora. Y solo después de eso, Windows comienza la tarea de integrar los cambios en el archivo principal. Esta tarea se llama Reconciliación, y comienza cada 40 minutos o cuando Windows se cierra. Llamar a la función RegFlushKey no activa la tarea de reconciliación. Para forzar el inicio de la tarea de integración de cambios, debe llamar a ZwSetSystemInformation con el argumento no documentado SystemRegistryReconciliationInformation.

 ZwSetSystemInformation( 0x9b, //SystemRegistryReconciliationInformation NULL, 0); 

Para ejecutar la función ZwSetSystemInformation, necesita derechos de administrador. Y la arquitectura del archivo ejecutable debe coincidir con la arquitectura del sistema. Llamar a esta función desde un programa de 32 bits en Windows de 64 bits fallará.

Tercera historia


Hace algún tiempo, descubrimos un rootkit que prescribía el lanzamiento de su controlador en el registro. Nuestros productos eliminaron las claves de registro correspondientes, pero después del reinicio las claves estaban en su lugar. Parece que él pone sus funciones de devolución de llamada en los cambios del registro y restaura sus claves después de nuestros cambios, pensé. Pero resultó que no. Más precisamente, sí. El rootkit estableció las funciones de devolución de llamada, pero no tenían nada que ver con la tarea de recuperación de claves. Todo se hizo más simple y más elegante.

El controlador rootkit, en el inicio, renombró el archivo de colmena de registro SYSTEM como HARDWARE. Creé mi archivo SYSTEM y guardé periódicamente la rama HKLM / System utilizando la función RegSaveKey. Al guardar, restauró sus llaves. Al reiniciar Windows, el sistema cargó el archivo SYSTEM y lanzó el controlador rootkit. ¿Es hermoso? Agradable

Wanteded


PD: Aquí estamos buscando un desarrollador-investigador en un equipo que esté cortando un motor antispam, y también necesitamos un ingeniero de pruebas .

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


All Articles