Interpretar las principales operaciones de registro con Process Monitor: RegCreateKey

En el primer artículo de esta seríe describí las funciones RegOpenKeyEx y RegCloseKey, así como la forma de interpretarlas, básicamente, desde la herramienta de Process Monitor. En esta nueva entrega me concentraré exclusivamente a la función RegCreateKeyEx, puesto que es un poco más completa de comprender cuando estamos haciendo diagnóstico.

RegCreateKeyEx

La operación principal de esta función, perteneciente a la API de Windows, consiste en crear una subclave de registro; en caso de que la subclave ya exista, la función la abre para utilizarla posteriormente. Ahora, tomando de ejemplo la subclave HKEY_CURRENT_USER\WinSide, la siguiente gráfica explica la definición que acabo de dar:

SNAGHTML256a06ea

 

HKEY_CURRENT_USER o su abreviación, HKCU, como lo dije en el primer artículo de esta serie, es una clave raíz; aunque WinSide es la verdadera subclave, se le puede llamar también subclave a todo el conjunto, es decir, HKEY_CURRENT_USER\WinSide.

Teniendo en cuenta la misma subclave de ejemplo, HKCU\WinSide, analicemos un poco el código que podríamos escribir en C/C++ con la API. Estas son las variables que requiere la función:

//RegCreateKeyEx
    HKEY hKey = HKEY_CURRENT_USER;
   LPCWSTR subKey = L”WinSide”;
    DWORD reserved = 0;
    LPWSTR classType = NULL;
    DWORD options = REG_OPTION_NON_VOLATILE;
    REGSAM samDesired = KEY_WRITE;
    LPSECURITY_ATTRIBUTES securityAttributes = NULL;
    HKEY createdKey;
    DWORD disposition;

La variable hKey contiene la clave raíz que pudo ser abierta por alguna función como RegOpenKeyEx o, como en este caso, una de las claves raíces que tiene el registro de Windows; la variable de subKey es un apuntador al nombre de la subclave que deseamos abrir o crear, en este caso WinSide; reserved es una variable reservada por el sistema y siempre debe ser cero; classType es el tipo de clase definida para la clave, pero puede ser NULL; la variable options me permite indicar diferentes comportamientos que puede tener la subclave, en el caso de REG_OPTION_NON_VOLATILE, le indica a Windows que la información almacenada se conserva después del reinicio; samDesired indica los derechos de acceso para la subclave, es decir, qué quiero hacer; la variable de securityAttributes almacena los atributos de seguridad, pero al darle NULL la subclave obtiene los predeterminados; createdKey va a tener el handle de la subclave abierta o creada; y disposition me indicará si la sublcave existía y se abrio o no existía y se creó.

Para poder ilustrar lo que Process Monitor captura, invocaré a la función RegCreateKeyEx para que abra o cree la subclave:

/* Función para crear o abrir la subclave
    HKEY_CURRENT_USER\WinSide */

    LONG createKey = RegCreateKeyEx(hKey, subKey, reserved,
                            classType, options, samDesired,
                securityAttributes, &createdKey, &disposition);

La variable createKey recibirá el código de error devuelto por el manejador de errores de Windows; yo puedo utilizar una función adicional para traducir eso a texto, pero obtaré por lo más sencillo que es validar si es satisfactorio o si es necesario mostrar el código de error, así:

if (createKey != ERROR_SUCCESS)
    {
        wprintf(L”Error opening the key. Code: %li\n”, createKey);
    }
    else
    {
        wprintf(L”Subkey was opened or created!\n”);
    }

 

Por supuesto, yo podría darle un poco más de estilo y aprovechar el valor retornado por disposition: es REG_CREATED_NEW_KEY si Windows creó la clave desde cero o REG_OPENED_EXISTING_KEY si la clave ya existía y solo se abrió. Nada más útil que llamar al condicional switch.

switch (disposition)
        {
        case REG_CREATED_NEW_KEY:
            wprintf(L”Key did not existed and was created\n”);
            break;

        case REG_OPENED_EXISTING_KEY:
            wprintf(L”Key existed and was just opened\n”);
            break;

        default:
            wprintf(L”Unkown value\n”);
            break;
        }

El código de toda la validación se vería así:

if (createKey != ERROR_SUCCESS)
    {
        wprintf(L”Error opening the key. Code: %li\n”, createKey);
    }
else
    {
       
        switch (disposition)
        {
          case REG_CREATED_NEW_KEY: //Key was created
            wprintf(L”Key did not existed and was created\n”);
            break;

          case REG_OPENED_EXISTING_KEY: //Key was opened
            wprintf(L”Key existed and was just opened\n”);
            break;

          default:
            wprintf(L”Unkown value\n”);
            break;
        }

        //Do not forget to close the handle!
        RegCloseKey(createdKey);
    }

De esta forma la consola mostrará el mensaje adecuado según se haya creado o abierto la subclave.

Aquí pueden ver la documentación oficial de RegCreateKeyEx:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724844(v=vs.85).aspx 

Process Monitor en acción

Empecemos por ver cómo nos muestra Process Monitor las operaciones que se hagan sobre la subclave HKCU\WinSide, para eso basta con filtrar por ruta y proceso de la aplicación, así:

image

Al ejecutar la aplicación, sin que esté la subclave creada, la validación se va por el REG_CREATED_NEW_KEY y me muestra el mensaje correspondiente:

image

¿Qué pasa en Process Monitor? Esto es lo que me muestra después de mostrado el mensaje:

image

La primera operación que hay listada es RegCreateKey, que corresponde a la que en código tengo como RegCreateKeyEx, está trabajando sobre el Path de HKCU\WinSide, handle que abrió o creó, según sea la disposición. El resultado, como también pueden ver fue SUCCESS, lo que indica que la operación se completó sin problemas y, finalmente, la columna de Detail me da datos importantes como el Desired Access (derechos de acceso solicitados) y Disposition (que me indica si la clave se creó o se abrió).

Después de estas operaciones, vemos que RegCloseKey se encarga de hacer la operación sobre la misma subclave, HKCU\WinSide, para cerrar el handle, es decir, terminar lo que se está haciendo sobre la subclave.

Noten que aunque yo conozco el código, los datos extraídos son todos desde Process Monitor, así que no necesitaría el código para saber qué pretende hacer la aplicación efectuando esa operación. Como datos adicionales, puedo entrar a las propiedades de la operación haciendo doble clic, pestaña de Process y ver detalles más completos:

image


Integrity
me indica el nivel de integridad en el que se está ejecutando el proceso, que en este caso es Medium, como cada proceso de usuario estándar; Architecture me indica, como su nombre en inglés lo dice, la arquitectura de la aplicación, que en este caso es 32-bit, por lo que en algún punto está actuando también la capa de emulación de WOW64.

Si vamos a la pestaña de Stack, podremos ver detalles de toda la transición entre User Mode y Kernel Mode, información bastante completa para alguien que entienda de Windows Internals. Una de las cosas que se puede identificar, por ejemplo, es que puedo ver que a la función exacta que se llama es RegCreateKeyExW (el W al final indica que se compiló como Unicode).

image


Nota:
para ver claramente esto, es necesario que Process Monitor tenga configurado los símbolos.

Aunque desde la vista general de Process Monitor puedo ver los detalles, también está disponible la pestaña de Event en donde tengo todo el resumen:

image

Es importante anotar que así en el código de la aplicación el valor de disposition sea NULL, Process Monitor podrá mostrarlo y así sabremos, a ciencia cierta, si la clave se abrió o se creó. Por ejempo, si yo ejecuto otra vez la misma aplicación de muestra, pero esta vez sin indicarle el disposition, puedo el resultado será el mismo:

image

Debido a que la subclave ya existía, puedo concluir, gracias al detalle de Process Monitor (Disposition: REG_OPENED_EXISTING_KEY), que Windows abrió la clave sin necesidad de crearla otra vez.

Una característica particular que tiene las llamadas a la API es que puedo crear más de una subclave de una vez. Por ejemplo, si en el código que mostré en este artículo quisiera abrir o crear la subclave HKCU\WinSide\Learning\Internals, bastaría con indicarle a la variable subKey todo el árbol, así:

LPCWSTR subKey = L”WinSide\\Learning\\Internals”;


Nota:
el doble signo de ‘\’ es para indicarle que deseamos poner una barra inversa y no una secuencia de escape.

Después de esto, solo es necesario ejecutarlo y esperar el resultado. El mensaje que nos devolverá será para toda la subclave y no para cada una individualmente.

En Process Monitor, sin embargo, podremos ver todo el proceso:

image

Lo primero que intenta hacer la aplicación es abrir la subclave HKCU\WinSide\Learning\Internals; como la clave no existe, empieza a hacer todo el procedimiento de abrir o crear desde la primera subclave, WinSide, hasta la última subclave, Internals. Noten que cada subclave se va cerrando después de pasar el handle a la otra. Cuando termina toda la operación hasta Internals, todos los handles se cierran y el resultado es nuestra subclave creada:

image

Desde Process Monitor, entonces, podemos identificar cuál es la subclave final desde antes de que la aplicación la cree y hacer un seguimiento detallado de cada subclave.

Espero que esto les pueda servir tanto como a mi me está sirviendo para aprender. Intentaré mejorar cada vez más las entradas, conforme vaya aprendiendo yo; además, es posible que toque otras funciones, sea de registro o de sistema de archivos.

 

P.D.: cualquier comentario o corrección es bienvenido.

 

Saludos,

—Checho

Interpretar las principales operaciones de registro con Process Monitor: RegOpenKey y RegCloseKey

Si alguna vez llegan a utilizan Process Monitor mientras diagnostican un problema o siguen algún comportamiento de Windows, se darán cuenta de que, sin duda alguna, es una herramienta indispensable  para trabajar. Aunque la herramienta no se ve tan compleja después de ejecutarla, el reto más grande pasa por saber interpretar correctamente los resultados de cada traza y resolver el problema. De la necesidad propia de comprenderla nació esta entrada de blog.

Unas de las operaciones más útiles en Process Monitor son las de registro de Windows, puesto que nos permite saber, a ciencia cierta, qué pasó exactamente mientras alguna operación se estaba ejecutando. Sin embargo, no es tan intuitivo ver nombres como RegOpenKey, RegCreateKey o RegSetValue, así que hoy quiero desglosar un poco estas tres operaciones comunes y mostrar cómo se pueden interpretar desde la consola de Process Monitor.

A continuación, describiré un poco qué hace cada operación y luego mostraré cómo se puede leer desde Process Monitor cuando hagamos algún diagnóstico.

Nota: no entraré en detalles demasiado técnicos, no por falta de interés, sino porque me falta el conocimiento para poder hacerlo.

RegOpenKey

La forma más sencilla que encontré para entender esta operación fue trabajar con la función de la API de Windows, RegOpenKeyEx, ya que los resultados que suministra Process Monitor están basados en ella.

La función de RegOpenKeyEx se utiliza, básicamente, para abrir una clave de registro, con el fin de realizar alguna operación adicional con las subclaves, valores de registro o bien crear alguna subclave nueva.

Consideremos la siguiente subclave: HKEY_CURRENT_USER\WinSide.

HKEY_CURRENT_USER o su abreviación, HKCU, es una de las 6 claves raíces que tiene el Registro de Windows, así que siempre va a estar presente y no se puede eliminar. WinSide, por el contrario, es una subclave que puede o no existir dentro de HKCU y se puede modificar.

Para poder comprobar con una aplicación creada en C o C++ que la subclave de WinSide existe, podemos declarar las siguientes variables:

LONG openKey;
HKEY key = HKEY_CURRENT_USER;
LPCWSTR subKey = L”WinSide”;
DWORD options = 0;
REGSAM samDesired = KEY_READ | KEY_WRITE;
HKEY handleKeyResult;
PHKEY phKey = &handleKeyResult;

openKey es la variable necesaria para recibir el tipo de valor retornado por RegOpenKeyEx; en la variable key tenemos el handle a una clave raíz abierta, HKCU; en subKey indicamos la subclave que deseamos abrir; options contiene la opción que aplica al abrir la clave, pero no es relevante con esta función; samDesired especifica los derechos de acceso deseados sobre la subclave que vamos a abrir, en este caso de lectura (KEY_READ) y escritura (KEY_WRITE); y phKey es un apuntador a un tipo de valor HKEY que recibirá otro handle, en caso de que la subclave abra correctamente.

La llamada a la función quedaría así:

openKey = RegOpenKeyEx(key, subKey, options, samDesired, phKey);

La línea anterior intentará abrir la subclave de HKCU\WinSide y asignará el código de error a la variable openKey declarada ateriormente.

Ahora supongamos que haremos una operación desde la aplicación para intentar abrir la subclave de WinSide, pero la validación sobre error será básica, por ejemplo:

if (openKey != ERROR_SUCCESS)//Si no abre la clave

wprintf(L”No pude abrir la subclave %s. Código: %li\n”, subKey, openKey);

else //Si la clave abre.
{
wprintf(L”La clave %s fue abierta.\n”, subKey);

//Cerrar handle para la clave
 RegCloseKey(*phKey);
}

En la validación anterior estoy validando si (if) openKey es diferente a ERROR_SUCCESS, es decir, cualquier otro mensaje inválido. En caso de que esto pase, mostraré un mensaje que me indica el código de error retornado por el manejador de errores de Windows. Si el valor retornado por la función es ERROR_SUCCESS, el programa se va para el else, así que muestro el mensaje satisfactorio y luego proceso a cerrar el handle de la clave con la función RegCloseKey.

Si yo ejecuto el programa sin crear la subclave de WinSide, el resultado se vería así:

image

Hasta aquí he mostrado la cara desde el desarrollo, así que sería relativamente fácil identificar qué está sucediendo y a qué hace referencia el número dos en el código. Sin embargo, la idea de esta entrada es aprender a interpretar lo que está sucediendo desde Process Monitor, pues casi siempre no tendremos acceso al código. Veamos cómo podríamos utilizar Process Monitor para deducir casi todo lo que he mostrado en código.

Primero, es necesario establecer algunos filtros en Process Monitor para que solo muestre los resultados de la aplicación RegApp.exe cuando está haciendo operaciones de registro, incluir lo que contenga WinSide y excluir todo lo demás. Después de configurar los filtros, basta con reproducir el resultado en consola que mostré antes mientras monitoreo con Process Monitor y empezar a analizar el resultado:

image

Interpretemos cada columna:

Process Name: RegApp.exe es el nombre de proceso que se está ejecutando y que está realizando la operación descrita en la tercera columna. Esto siempre es importante, puesto que sabemos de primera mano quién está tratando de realizar manipulaciones en el registro.

PID: cada que sea crea un proceso en Windows se le asigna un identificador de proceso con el que el sistema operativo sigue trabajando hasta que se termina el proceso. En cada nueva ejecución se crea un nuevo Identificador de proceso (PID).

Operation: como vemos en la captura de pantalla, la operación que está realizando la aplicación es la de RegOpenKey, es decir, tal cual lo vimos con la función de la API, está tratando de abrir una subclave de registro. Cada que veamos esta operación podemos tener la certeza de que la aplicación solo está tratando de abrir la subclave de registro y no creándola; opción que sí tiene la operación de RegCreateKeyEx, que veremos después. La subclave sobre la que está trabajando se muestra en la siguiente columna.

Path: esta es una de las columnas más importantes, puesto que me indica en qué ruta exacta, en este caso de registro, se está desarrollando la operación descrita anteriormente. En el caso de la captura anterior y de la aplicación que mostré, la ruta es HKCU\WinSide; como pueden recordar, HKCU es la abreviatura de HKEY_CURRENT_USER, así mismo lo hace con las demás claves raíces.

Result: de esta columna depende, la mayoría de las veces, seguir analizando la entrada o pasar a una próxima. Lo que vemos aquí es el resultado de la operación que la aplicación intentó hacer. El texto que muestra es el código de error devuelto por Windows, pero un poco más abreviado, y será de gran importancia de acuerdo al código que se reciba. Algunos de los más comunes son: SUCCESS, ACCESS DENIED, PATH NOT FOUND, NAME NOT FOUND, etc.

Para el caso de la captura anterior, el resultado arrojado es NAME NOT FOUND, el cual indica que la subclave de registro no existe en la ruta que está buscando.

Detail: aquí podemos ver información adicional de la operación específica que está realizando la aplicación; en el caso de las operaciones de registro, podemos ver la máscara de acceso que solicitó la aplicación. Si nos devolvemos un poco a la primera porción de código, yo declaré una variable llamada samDesired en la que pedí los derechos de acceso KEY_READ y KEY_WRITE, es decir, de escritura. En Process Monitor se ve como Desired Access: Read/Write.

Con la máscara de acceso podemos saber qué quiere hacer la aplicación con la subclave, por ejemplo, poder leer y escribir nuevo contenido, pero es el descriptor de seguridad el que tiene la última palabra sobre lo que en verdad puede hacer en la subclave. Es un tema complejo de seguridad en el que no entraré por falta de conocimiento.

La idea es ir leyendo los resultados de izquierda a derecha para poder entenderlos correctamente. Si resumimos todo, podemos decir que el proceso RegApp.exe, que tiene un identificador de proceso 3956, está intentando abrir la subclave de registro de HKCU\WinSide, pero no la encontró, lo cual indica que no está creada. Los derechos de acceso que había solicitado la aplicación era de escritura y de lectura.

Si queremos ver todo estos detalles un poco más agrupados, podemos hacer doble clic sobre la entrada o clic derecho y seleccionar Properties. Incluso podemos comparar con las declaraciones que hice en el código para que veamos qué tanto detalle puedo extraer con Process Monitor.

image

¿Qué pasa si la subclave de WinSide existe? Ejecutando la aplicación, el resultado sería este:

SNAGHTML20c388f

Del lado de Process Monitor, podremos ver un poco más de detalles:

SNAGHTML20f8e90

No tiene caso volver a describir cada columna, así que me concentraré en la lectura. La primera operación dentro de las tres que están resaltadas en la captura es la de RegOpenKey, que intenta abrir la subclave HKCU\WinSide y esta vez, a diferencia de lo que mostré, el resultado es SUCCESS, quiere decir que la subclave estaba creada en el registro de Windows. La máscara de acceso sigue conteniendo escritura y lectura (Read/Write), por ende, podrá crear otras subclaves o valores, a menos que el descriptor de seguridad de la subclave no lo permita.

El resultado de SUCCESS es equivalente a cero y en el código entraría en el else:

else //Si la clave abre.
    {
        wprintf(L”La clave %s fue abierta.\n”, subKey);

        //Cerrar la clave.
        RegCloseKey(*phKey);

    }

Después de esto hay una operación llamada RegSetInfoKey que ignoraremos por ahora; luego aparece la operación de RegCloseKey, la cual está encargada de cerrar el handle abierto cuando el trabajo con la subclave está terminado. La operación de RegCloseKey no tiene mayor ciencia, mas voy a tocar unos detalles que encontré interesantes cuando escribía esto.

RegCloseKey

El trabajo de la función RegCloseKey, como ya lo mencioné, es el de cerrar el handle abierto que obtuvimos con RegOpenKeyEx. El código para cerrarlo en la aplicación Si en el código no cerramos manualmente el handle, Windows lo hará eventualmente, pues va cerrando todo lo que esté abierto antes de hacerlo con la clave raíz de HKEY_CURRENT_USER.

Lo anterior se puede comprobar quitando del código la llamada a RegCloseKey; después de ejecutado y analizado con Process Monitor, se puede ver que el handle se cierra más adelante:

SNAGHTML221c921

Lo ideal es que esto esté gestionado desde el código de la aplicación y no dejarle la tarea a Windows. Desde Process Monitor sería muy complicado saber si desde el código el handle se cerró después de la operación en registro, pero si es así, generalmente estará la operación de RegCloseKey justo después de terminadas las otras tareas con la subclave de registro.

En la próxima entrada referente a esto, me enfocaré en interpretar la operación de RegCreateKey y luego en RegSetValue. La función de RegCloseKey la seguiré mostrando, pero no con detalles.

Traté de acertar lo más que pude, pero igual podría haberme equivocado en algunos aspectos, puesto que es un tema muy ligado a Windows Internals. ¡Comentarios bienvenidos!

Saludos,

—Checho