PDA

Ver la Versión Completa : ¿Se puede obtener el nombre de un handle?


Al González
20-12-2003, 02:21:33
¡Buen día a todos!

Mi pregunta es la siguiente:

¿De qué manera puedo obtener el nombre que tiene asociado un objeto Windows, a partir de su identificador (handle)?

Me refiero a los objetos eventos, mutex, memorias compartidas, semáforos, etc., que el sistema operativo guarda internamente.

Por ejemplo, si ejecuto el código:

Var
Identificador :THandle;

Begin
Identificador := CreateFileMapping (Invalid_Handle_Value, Nil,
Page_ReadWrite, 0, 10, 'Prueba');

para crear un objeto de memoria compartida (file mapping). ¿Más tarde puedo obtener el nombre que le dí ('Prueba'), a partir del valor guardado en la variable Identificador? Es decir, como si existiera una función llamada GetHandleName:

Var
Nombre :String;
Begin
Nombre := GetHandleName (Identificador);


Se que Windows guarda y administra la información de todos los objetos creados y sus identificadores abiertos (handles). Pero ¿habrá una forma de tener acceso a los detalles de dicha información, o por lo menos a los nombres de los objetos?

¿Se necesita una API adicional? ¿Es una dura restricción del sistema?

Les agradezco todas sus aportaciones al respecto. Seguimos en contacto.

Al González :).

delphi.com.ar
22-12-2003, 15:10:42
Windows internamente maneja tres tipos genéricos de objetos: Que son los del User, GDI y Kernler. Todos estos objetos se identifican con un Handle y no necesariamente pertenecen a la misma lista, mismo si comparas un Handle de un objeto del Kernler con uno del GDI notarás que el del Kernler es mucho mas bajo que el del GDI, esto se debe a que el handle del GDI normalmente es el valor del un puntero, en cambio el del Kernler es una referencia al indice de la tabla interna del proceso.
En tu caso estas mezclando objetos del User (Objeto Window) con objetos del Kernler (FileMapping), y si hay forma de obtener información sobre estos objetos, pero hay funciones muy diferentes para cada tipo de objeto.

Saludos!

Al González
23-12-2003, 01:00:20
¡Buen día a todos!

Delphi.com.ar:

Agradezco tus valiosos comentarios.

Aprovecho para actualizarles los resultados de mi investigación.

Después de leer varios documentos y estudiar algunas aplicaciones, he encontrado que Windows guarda una estructura de tipo EPROCESS por cada proceso activo en el sistema. Que dicha estructura contiene un campo llamado ObjectTable de tipo _HANDLE_TABLE, el cual es un arreglo que contiene las direcciones de memoria de todos los objetos pertenecientes al proceso (mutex, eventos, mapeos de archivo, etc.).

Dichos objetos se encuentran dentro del espacio de memoria del nucleo (kernel) del sistema. Cada uno tiene su propia estructura, pero con una cabecera de datos común de tipo _OBJECT_HEADER. La estructura _OBJECT_HEADER, tiene un campo llamado NameOffset, que es un desplazamiento negativo para encontrar el nombre del objeto.

Cuando creo un objeto de memoria compartida con la función CreateFileMapping, por ejemplo, ésta me regresa un valor de tipo HANDLE. Este valor entero es el índice o desplazamiento que tiene la entrada correspondiente en el campo ObjectTable de la estructura EPROCESS del programa en ejecución.

Esto quiere decir, que para obtener el nombre de un objeto mutex, evento, mapeo de archivo, etc. de un proceso, a partir de su identificador HANDLE, primero hay que localizar la estructura EPROCESS del proceso, enseguida usar el identificador HANDLE como índice en el campo ObjectTable; de ahí tomar el puntero que señala la dirección de memoria del objeto. Estos punteros señalan el comienzo del cuerpo (body) del objeto, así que hay que hacer un desplazamiento negativo del tamaño de _OBJECT_HEADER, para tener acceso a los campos de la cabecera (header). De ahí se toma el valor del campo NameOffset, para hacer otro desplazamiento negativo hacia el lugar donde se encuentra una estructura de tipo OBJECT_NAME, la cual contiene una cadena Unicode con el nombre del objeto.

Bien, en teoría esto no parece tan difícil: sólo hay que saber obtener la dirección de memoria de la estructura EPROCESS de un proceso, para tener acceso a su tabla de objetos (ObjectTable).

Existe una función llamada PsLookupProcessByProcessId, cuyo propósito es precisamente obtener la dirección de memoria de la estructura EPROCESS de un proceso dado. Esta función se localiza en el archivo estándar NTOSKRNL.EXE, el cual contiene las funciones API nativas el sistema operativo. Según he visto, este archivo y sus funciones sólo pueden ser utilizados en modo kernel, es decir, en ese modo especial en el que trabajan ciertos programas como los controladores de dispositivos, entres otros.

Sinceramente creo que debe existir otra manera de acceder a la estructura EPROCESS, bajo el modo de ejecución normal (user mode). No he encontrado otra función que sirva para obtener de forma directa y explícita la dirección de memoria de dicha estructura. Sin embargo creo que se podrían utilizar algunas de las funciones existentes en Kernel32.dll para lograr este objetivo.

Baso mi argumento en lo que descubrí con los programas Process Explorer 8.1 (http://www.sysinternals.com/) y PE Explorer 1.94 (http://www.heaventools.com/?=pex). El primero muestra un listado de todos los objetos mutex, eventos, mapeos de archivo (sections), de cada proceso activo en el sistema. Con el segundo analizo las dependencias que tiene Process Explorer.

Según la información arrojada por PE Explorer, Process Explorer no utiliza ninguna función de NTOSKRNL.EXE (ni directa ni indirectamente). Es decir, no accede a la estructura EPROCESS de cada proceso con la función PsLookupProcessByProcessId. Process Explorer sólo utiliza unas cuantas DLLs estándares y muy comunes de Windows, entre ellas Kernel32.dll y ADVAPI32.dll, e indirectamente NTDLL.dll, que según he leído es la interfaz que existe para acceder a elementos del nucleo en modo normal de usuario.

Estoy seguro de que Process Explorer utiliza alguna técnica de mapeo de memoria para acceder a la estructura EPROCESS y su lista ObjectTable de cada programa en ejecución, y así poder mostrar los nombres de todos los objetos mutex, eventos y mapeos de archivo creados por los procesos. Es decir, Process Explorer, sin usar la API nativa NTOSKRNL.EXE ni la función PsLookupProcessByProcessId, y aparentemente sin entrar de forma explícita en modo kernel, localiza la estructura EPROCESS, lee su arreglo ObjectTable, accede a la memoria de cada objeto y lee sus nombres.

Es decir, si es viable en modo de usuario obtener el nombre de un objeto kernel, a partir de uno de sus identificadores HANDLE. Aparentemente sólo me falta saber localizar la estructura EPROCESS. De última hora me viene a la mente que tal vez esa estructura ocupa los primeros bytes de la memoria virtual del proceso.

Agradezco cualquier aportación que se haga a este tema. Pienso que éste puede ser un hilo valioso, ya que existe poca literatura gratuita en español que hable de las estructuras internas de Windows.

Anexo algunos enlaces importantes que encontré durante mi investigación:

http://www.alkor.ru/~00077500/kb/ntfiles.htm
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngenlib/html/msdn_handles1.asp?frame=true&hidetoc=true
http://www.sysinternals.com/index.shtml
http://www.theparticle.com/files/txt/hacking/phrack/p59-0x10.txt
http://www.linuxgazette.com/issue23/flower/page1.html
http://www.ntkernel.com/resources.shtml
http://www.informit.com/content/index.asp?product_id={85C5B554-9725-46D3-B827-302DF1E029E7}

Espero esto sea de utilidad. Seguimos en contacto.

Al González :).

delphi.com.ar
23-12-2003, 15:57:07
En concreto... ¿Que es lo que quieres lograr?.. algo similar al panel inferior del ProcessExplorer??...

Al González
23-12-2003, 17:26:01
¡Buen día a todos!

Delphi.com.ar:

Agradezco tu interés en este caso.

En términos generales, mi respuesta a tu pregunta es sí. Deseo localizar los nombres de los objetos que pertenecen a un proceso a partir de sus identificadores HANDLE.

Más concretamente, si en un programa creo varios objetos y guardo sus identificadores (HANDLEs) en una lista, más tarde deseo poder obtener el nombre que se le dio a cada uno. Esto es para una bilioteca de funciones, donde sólo el programador final sabrá cuántos objetos crea y con qué nombres. Quiero evitar el uso de una lista alterna de nombres relacionados con los identificadores, bajo el conocimiento de que esa relación ya existe en las estructuras internas de Windows (¿para qué ocupar más memoria?).

Además, pretendo facilitar el camino a otros desarrolladores Delphi interesados en el aprovechamiento de los recursos internos de Windows.

Muchas gracias por sus aportaciones.

Atentamente,

Al González :).

delphi.com.ar
23-12-2003, 17:48:55
Ok.. Basándonos en toda la teoría que has escrito en el mensaje anterior, podríamos recorrer todos los procesos con la "ToolHelp" (CreateToolhelp32Snapshot, Process32First...), abrir los procesos (OpenProcess) y acceder a la memoria de estos procesos con ReadProcessMemory.
El problema, es que seguramente estas estructuras que has nombrado difieran entre las plataformas, por eso siempre es mejor utilizar las funciones indicadas para cada caso. En este caso, he buscado funciones para listar los objetos de un proceso, y a simple vista no encontré nada.

Espero que te sirvan mis comentarios, y no olvides tenernos al tanto de la investigación, y contá conmigo para las inquietudes!
Saludos!