La aplicación que daba Acceso Denegado con el proceso elevado, UAC, Process Explorer, ResHacker y su solución

Una de las cosas que hacemos en Tulpep, empresa donde actualmente trabajo, cuando solucionamos un problema de alguna aplicación que requiere muchos pasos manuales, es ofrecer una solución alternativa en la que creamos un instalador y automatizamos los procesos con el objetivo de que sea más fácil para el cliente. Estos procesos suelen hacerse con Inno Setup, a no ser que sea un desarrollo propio.

Hace unos días terminé un instalador que debía entregar a un cliente y por supuesto, debía probar el funcionamiento en un laboratorio. Una de las Fuentes que tenía referenciado en el script de Inno Setup, era un .BAT que iba a correr después de terminada la instalación:

2015-04-18_19-20-58

El archivo en cuestión, utilizaba Robocopy para copiar unos archivos necesarios de la carpeta fuente de instalación, a la de otro programa que se enviaba a instalar desde el asistente:

2015-04-18_19-32-02

Hasta aquí nada raro, de hecho la instalación funcionaba muy bien desde el Inno Setup que previamente había lanzado como administrador.

El problema

Una vez probado todo, procedí a compilar el instalador y a probar desde él toda la instalación. Sabía que debía tener privilegios administrativos para las tareas que iba a ejecutar, pero solo con darle doble clic al Setup.exe que había creado, Windows me pedía elevación de privilegios:

2015-04-18_19-39-05

Con eso creí que era suficiente, ya que si el instalador pedía elevación, todo lo que ejecutara debía obtener el mismo token administrativo y proceder a realizar operaciones.

Sin embargo, al llegar al momento en que se lanzaba el BAT, recibí un mensaje de acceso denegado:

2015-04-18_19-52-32

Ahí se quedaba en un bucle infinito tratando de escribir y no pasaba. ¿Por qué?

La causa

Normalmente un proceso siempre adquiere el token o privilegios otorgados por su proceso padre; además de sus niveles de integridad. Si este ejecutable me pedía elevación, yo suponía que debía estar con los privilegios elevados pero, la única forma de comprobarlo iba a ser con Process Explorer de Sysinternals.

Lo que hice fue ejecutar Proccess Explorer, habilitar la columna de Integirty Levels y dejarlo en segundo plano mientras lanzaba la aplicación haciendo doble clic y aceptando el mensaje del UAC. Esto fue lo que encontré al dejar el instalador abierto y ver en Procexp:

2015-04-18_20-12-48

El árbol que muestra Process Explorer, ubica el proceso padre mucho más alineado a la izquierda que el hijo. En este caso, el proceso padre era Setup.exe, luego Setup.tmp y abajo de él, pero en el mismo nivel, estaban otros Setup y finalmente el cmd.exe que a su vez llamaba al Robocopy.exe.

A parte de que se creaban dos instancias: Setup.exe y Setup.tmp; el nivel de integridad que tenía heredado cmd y Robocopy era Medium (ver gráfica), cuando en realidad debería ser High como el que estaba arriba de cmd.exe. Todo esto quiere decir que cmd.exe estaba heredando el token del primer Setup.exe, así que siempre iba a ejecutarse con privilegios estándar y NO elevados.

La ventana del UAC que me pedía consentimiento elevaba la segunda instancia del Setup.exe, pero esto no servía de nada, ya que siempre los demás ejecutables o archivos por lotes que llamaba iban a seguir ejecutándose sin permisos administrativos. El resultado de todo esto: ¡Acceso Denegado!

Ahora, ¿Qué pasaba al tomarme el trabajo de darle clic derecho sobre el Setup.exe y seleccionar Ejecutar como administrador? Esto muestra Process Explorer:

2015-04-18_21-10-33

Básicamente, no había otra instancia del .EXE y .TMP. Las únicas dos instancias que existían estaban con el nivel de integridad en High (Alto); o sea que todo lo que el proceso llamara se iba a ejecutar con privilegios administrativos. Por ejemplo, el Robocopy:

2015-04-18_21-14-20

En pocas palabras, para que todo se ejecutara e instalara correctamente, necesitaba que la aplicación obtuviera el token administrativo desde su proceso padre.

¿Por qué una instancia quedaba elevada al hacer doble clic? No sé responder eso, pero lo que sí sabía en ese momento es que el instalador no estaba pidiendo elevación de privilegios administrativos. ¿Por qué me salía el primer mensaje pidiendo elevación? No sé, probablemente el UAC estaba

En este punto, una de las personas que más admiro, Ricardo Polo, me dio la pista clave: El archivo manifiesto de UAC que estaba en el instalador. No entraré en detalle porque me falta mucho conocimiento para escribir bastante al respecto, pero básicamente es un XML donde entre otras cosas, se le pide a Windows con qué nivel de privilegios debe ser ejecutada la aplicación. Existen tres, los máximos privilegios que el usuario le pueda otorgar, como se invoque (que se traduce básicamente a estándar) y pedir administrador. Técnicamente, se reconocen como: highestAvailable, asInvoker y requiereAdministrator.

Intentaré describir en otro post cómo lo hice, pero en esencia utilicé Strings de Sysinternals para ver los binarios del instalador y de ese resultado buscar el manifiesto. Este fue el resultado al verlo en un TXT:

2015-04-18_21-35-09

Debido a que el manifiesto que Inno Setup integraba a la aplicación pedía asInvoker, siempre se iba a ejecutar con privilegios estándar si se lanzaba con doble clic. El reto consistía en modificar ese manifiesto para que pidiera privilegios administrativos al ejecutarse.

La solución

Para poder modificar el manifiesto sobre el ejecutable, descargué Resource Hacker y procedí a hacer lo siguiente:

1. Lancé Resource Hacker haciendo clic derecho y Ejecutar como administrador.

2. Abrí el instalador desde ResHacker haciendo clic en File > Open.

2015-04-18_21-42-59

3. Expandí el nodo 24 > 1 y clic en 1033 para ver el string que tenía. Estos números pueden variar:

2015-04-18_21-44-53

4. Cambié el level por requiereAdministrator y clic en el botón Compile Script.

2015-04-18_21-52-38

5. Hice clic en el menú File > Save as…

2015-04-18_21-56-53

6. Le puse un nombre descriptivo con la extensión .EXE y lo guardé:

2015-04-18_21-58-34

7. Cerré Resource Hacker.

Finalmente, fui hasta la ruta del instalador y el nuevo instalador ahora tenía el escudo de UAC que identifica el requerimiento de privilegios para ejecutarse:

2015-04-18_22-00-08

Al ejecutarlo, aparecía el UAC y después de aceptar se elevaba el privilegio como debía ser:

2015-04-18_22-01-04

Este mismo procedimiento se le puede aplicar a cualquier instalador que deseen modificarle el manifiesto, si es que lo tiene.

Espero sea de utilidad.

PD: No olviden seguirme en Twitter: www.twitter.com/secalderonr

Checho

[How to] Monitorear Windows con Process Monitor en el inicio y cierre de sesión

La mayoría de los casos que suelo exponer en este blog, muestro cómo utilicé alguna característica de Process Monitor para encontrar pistas, causas o incluso la solución. Una de las características que más he utilizado en casos donde el problema se reproduce al inicio de sesión, o antes, es la de Boot Logging que me permite monitorear Windows incluso después de reiniciar el equipo.

Sin embargo, no siempre es práctico tener tantos datos cuando se está buscando algo muy concreto pero que se reproduce en un escenario de cierre o inicio de sesión. En este post mostraré cómo aprovechar PsExec y Process Monitor para cubrir este escenario sin necesidad de habilitar Boot Logging.

*Nota: Si lo que se quieres es monitorear controladores u otro tipo de cosas que suceden antes del inicio de sesión, la única opción es Boot Loggging.

Caso real de ejemplo:

Ahora, consideremos un problema que ha tenido cierta frecuencia en los foros de Microsoft; básicamente iniciamos sesión en Windows y nos encontramos con un mensaje de error como este:

2015-04-05_21-27-00

Como casi siempre pasa, después de aceptar el mensaje, no sucede nada más. El Administrador de tareas –si estamos de suerte- para este caso mostraría algo así:

2015-04-05_21-29-56

Deshabilitarlo serviría para evitar el mensaje, pero estaría actuando directamente sobre el proceso real de wscript.exe y no sobre la causa raíz. Obviamente NO iríamos por el camino fácil. =)

Como dije al inicio, el camino directo sería usar Boot Logging; aun así podemos combinar Process Monitor y PsExec para hacer algo más productivo:

Requerimientos

1. Descargar Process Monitor desde aquí:
https://technet.microsoft.com/es-es/sysinternals/bb896645

Descomprimir el archivo .ZIP.

2. Descargar PsExec desde aquí:
https://technet.microsoft.com/es-es/sysinternals/bb897553

Descomprimir el archivo .ZIP.

3. Copiar y pegar Procmon.exe y PsExec.exe al directorio raíz C:

2015-04-05_21-42-22

Combinando Procmon y PsExec

Hacemos clic derecho en el botón de Inicio y luego en Símbolo del sistema (administrador):

2015-04-05_21-46-25

Aceptamos la ventana del UAC y una vez en la consola, ejecutamos en orden:

cd C:

Esto nos ubicará en el directorio raíz C:

2015-04-05_21-50-11

Una vez en la raíz, podremos ejecutar sin problemas Procmon y PsExec. Para que Proccess Monitor siga ejecutándose incluso después del cierre de sesión, ejecutamos:

PsExec –s –d C:Procmon.exe /AccepEula /Quiet /BackingFile C:Log.pml

2015-04-05_21-54-00

*Nota: PsExec me permite ejecutar procesos remotamente, pero además utilizar el usuario con súper poderes SYSTEM con la bandera –s; –d es para que PsExec se cierre sin esperar a que Procmon.exe lo haga y lo demás es para aceptar el EULA, que no muestre mensajes y que todo se vaya guardando en el archivo Log.pml ubicado en la misma unidad.

Utilizando Process Explorer de Sysinternals se puede verificar que Process Monitor está en ejecución, bajo la sesión 0 perteneciente a los servicios y con el usuario de SYSTEM:

2015-04-05_21-59-36

Procedemos a cerrar sesión, iniciar nuevamente, esperar a que el mensaje extraño vuelva a salir y hacemos lo siguiente:

Clic derecho otra vez en el botón de Inicio, Símbolo del sistema (administrador):

2015-04-05_21-46-25

En el símbolo del sistema, ejecutamos:

cd C:

2015-04-05_21-50-11

Finalmente, ejecutamos lo siguiente para terminar el monitoreo:

PsExec –s –d C:Procmon.exe /AcceptEula /Terminate

2015-04-05_22-03-38

Si todo sale bien, el log nos habrá quedado guardado en la raíz del disco local C:

2015-04-05_22-05-55

Lo único que queda es abrir el log y y empezar a jugar con Process Monitor para descubrir qué causa el mensaje de error.

Por ejemplo y para este caso, lo primero sería referenciar detalles sobre el proceso que lanza el wscript.exe; esto es fácil presionando las teclas CTRL + T para abrir el árbol de procesos y ubicar la ocurrencia que buscamos de wscript:

2015-04-05_22-09-02

Tal como ven, el proceso padre fue Explorer.exe, con su respectivo PID 2384.

Ya que es el Explorer.exe, indica que probablemente se ejecutó algún archivo al momento de iniciar sesión, no necesariamente que el proceso haya sido alterado.

Una buena práctica es siempre ver qué se está lanzando en ubicaciones tan comunes como la carpeta de Inicio que ha existido durante tanto tiempo y que le dice a Windows todo lo que debe ejecutar automáticamente.

Para que Process Monitor nos muestre las operaciones de lectura que hace solo en este directorio, podemos filtrar diciendo que excluya todos los PID diferentes al 2384 –en este caso-, que el resultado sea SUCCESS, la ruta contenga Startup y la categoría sea Read:

2015-04-05_22-15-03

Noten que en la mayoría excluí lo que no quería, con el resultado que deseaba.

El resultado sería más o menos así:

2015-04-05_22-19-09

Gracias a que lo que dejaría Process Monitor sería muy conciso, identificar un archivo extraño como un acceso directo se podría hacer sin mayor dificultad.

*Nota: No me enfoqué en los filtros de Process Monitor, porque el objetivo era mostrar cómo ejecutarlo al cerrar e iniciar sesión; sin embargo intentaré crear otros artículos donde detalle más el tema.

Espero sea de utilidad.

Saludos.

Checho