Erwin.Ried.cl / Documentos / Windows /
El problema del compositor y el escritorio seguro

En Windows Vista, especialmente con Aero Glass, tenemos un compositor de ventanas (Desktop Window Manager). Como este compositor corre en espacio de usuario, entonces cualquier aplicación podría afectarlo sin pedir elevación de privilegios. ¿Qué hacer frente a una suspensión del administrador de ventanas en donde Vista queda completamente inutilizable? (12/09/2008 08:09 PM)


1. ¿Porqué un compositor de ventanas?

Sea Quartz, Xcmpmgr, Compiz, Beryl o DWM, en los tiempos modernos los sistemas operativos están optando por incorporar un compositor en vez de sólo un Windows Manager. ¿El motivo?



Un compositor permite obtener efectos en dos o tres dimensiones, gráficos limpios, sombras y un par de características (como poder mostrar la ventana en otro equipo de forma remota) que serían impensables de otra forma.

Claro que tanta maravilla tiene un costo. Lo bueno es que generalmente las actuales tarjetas gráficas hacen todo el trabajo.


2. ¿Que pasa entonces con el compositor de Vista?

El compositor de ventanas (llamado Administrador de ventanas del escritorio) de Windows Vista es administrado a través del servicio UxSms, que lo vigila constantemente para volver a ejecutarlo en caso de problemas y otras funciones.

Así, este compositor corre sin privilegios de administrador, recibiendo mensajes de diversos componentes del sistema y generando la salida gráfica. Si no corre con privilegios elevados entonces podemos aplicar ciertas funciones administrativas sobre él, como por ejemplo suspenderlo con "Process Explorer":




3. Sin compositor no somos nada... o casi nada

Incluso en las versiones sin los efectos gráficos de Vista, el compositor es vital.

Aunque no componga lo que vemos, las aplicaciones, incluyendo "explorer.exe" le mandan mensajes y esperan por su respuesta (cosa necesaria para otras funciones como el escritorio remoto).

Entonces al suspenderlo nuestro sistema siempre queda totalmente inutilizable (aunque en menor forma con la interfaz clásica o la llamada Aero Basic).


4. El escritorio seguro

Probablemente notes lo molesto que es que en cada pregunta del control de cuentas de usuario de Vista, toda la pantalla se oscurezca y aparezca el diálogo sin el estilo de Aero Glass.

Esto tiene un motivo, Windows saca una foto de tu escritorio y pasa a un escritorio de la cuenta de sistema. Este escritorio nunca puede ser alterado por otras aplicaciones ajenas (controlando tu ratón, teclado o viendo tu pantalla).


5. Adiós accesibilidad

En la pantalla de opciones de seguridad (la misma utilizada para iniciar sesión en el equipo) hay un ícono que sirve para mostrar las opciones de accesibilidad:



Luego de un par de retoques, ya podemos imaginar las funciones de análisis con la metáfora del siguiente botón:



Lo único que debemos hacer así es reemplazar la utilidad original que ejecuta ese botón (Utilman.exe) por el Administrador de tareas. En efecto, funciona perfectamente:




6. Windows totalmente vulnerado

No todo este poder es bueno. Ejecutar el Administrador de tareas en el escritorio seguro con la cuenta SYSTEM de Windows es una tarea sumamente peligrosa.

La cuenta SYSTEM tiene todos los privilegios imaginados. Tal poder incluso nos permitiría finalizar el proceso mismo que maneja el inicio de sesión (LogonUI.exe) y otros vitales.

Adicionalmente, como SYSTEM no es realmente una cuenta diseñada para ser interactiva es indeseable hacer cosas que requieran un explorador de archivos, como “explorer.exe” por ejemplo, pues tendrán que prepararse para su primera ejecución.

Así, con este poder, es necesario proteger nuestro equipo. Un usuario cualquiera podría tomar el control de nuestro equipo sin siquiera tener una cuenta con privilegios de administración ni nada, sólo abriendo el administrador de tareas desde la pantalla de inicio de sesión, sin nunca iniciar una.


7. Con un gran poder viene una gran responsabilidad

Es necesario hacer una especie de bypass, con una protección por contraseña. Preliminarmente tenemos algo así:



La aplicación que reemplazamos (Utilman.exe) es la que se encarga de manejar todas las aplicaciones de accesibilidad. Importante sería no perder esta capacidad, así podemos detectar cuando nuestra aplicación sea ejecutada desde la cuenta de SYSTEM:

Código:
Boolean runningAsSystem = Environment.UserName==Settings.Default.SystemAccount;


Y simplemente redirigir sus parámetros al administrador de aplicaciones de accesibilidad como era en un comienzo:

Código:
String[] CommandLineArgs = Environment.GetCommandLineArgs();

// Ejecutar la aplicación cuando no estamos en el escritorio seguro
try
{
    System.Diagnostics.Process.Start(Settings.Default.RunNormally,
        String.Join(" ", CommandLineArgs, 1, CommandLineArgs.GetUpperBound(0)));
} catch { }


Esto genera una capa invisible, todo sigue funcionando como siempre y adicionalmente tenemos acceso a nuestro Administrador de tareas en la pantalla de opciones de seguridad.

Cabe destacar de que como detalle, la contraseña está codificada en el archivo de configuraciones XML de la aplicación, usando la clase de criptografía provista por la CLR:

Código:
public string EncodeString(string p)
{
    Byte[] original = ASCIIEncoding.Default.GetBytes(p);
    Byte[] encoded = new System.Security.Cryptography.SHA512Managed().ComputeHash(original);

    return BitConverter.ToString(encoded);
}


Adicionalmente es posible configurar nuestra pequeña aplicación con el archivo de configuración provisto. Así podríamos cambiar las aplicaciones que son ejecutadas o la clave por defecto.

Naturalmente se debe incluir un mecanismo para cambiar la clave fácilmente sin estar modificando el archivo de configuración (en donde está codificada):




8. Sólo una instancia

Una característica deseable es que no existan múltiples instancias de esta aplicación.

Hay muchas formas para lograr esto, pero recapitulando un poco de mis ramos de sistemas operativos se me ocurrió utilizar un Mutex admnistrado por el sistema operativo:

Código:
bool instance = false;
Mutex mutex = new Mutex(true, Application.ProductName, out instance);


¿Qué pasa si el sistema operativo no puede crear un Mutex con ese nombre?, la variable instancia seguirá falsa, así:

Código:
if (!instance)
{
    // Buscar instancias de este mismo proceso
    Process c = Process.GetCurrentProcess();
    Boolean firstSeen = false;

    foreach (Process p in Process.GetProcessesByName(c.ProcessName))
        if (p.Id != c.Id)
            if (!firstSeen)
            {
                firstSeen = true;
                SetForegroundWindow(p.MainWindowHandle);
            }
            else
                p.Kill();

    return;
}
else
{
    Application.Run(new FormMain());
    GC.KeepAlive(mutex);
}


Así matamos todos los procesos (aunque no pueda suceder) y le damos el foco al primer proceso que vemos que sea idéntico a nosotros.


9. Resumen para replicar la experiencia

1. Cambiar el propietario y otorgarse privilegios sobre los archivos "utilman.exe" y "es-ES/utilman.exe.mui" que están en el directorio de sistema.

2. Renombrar aquellos archivos (por defecto usaré en el archivo de configuración "_utilman.exe" como los archivos originales) y colocar nuestro "bypass" en ese directorio de sistema.

3. Modificar el mapa de bits del botón (recurso 11118) con un editor de recursos en "authui.dll".

4. También modificar la cadena de "Accesibilidad" en "es-ES/authui.dll.mui" con un editor de recursos.


10. Código, imágenes y ejecutables

Ejecutables y archivo de configuración del "bypass" (9 kb)

Código fuente para Visual Studio 2005 en C# (56 kb)

Mapa de bits del nuevo botón para reemplazar (11 kb)

Haga clic sobre una de las estrellas para calificar este artículo.

Opiniones y comentarios (Escribir un nuevo comentario)
(Por el momento, este artículo no tiene ningún comentario)

Copyright © 2013 por Erwin Ried.