Carga de DLLs Forward

Iniciado por paulagarcum, 6 Noviembre 2013, 14:06 PM

0 Miembros y 1 Visitante están viendo este tema.

paulagarcum

Hola a todos.

Pregunto sobre una DLL que tiene funciones que a su vez importa de otras DLL. Ejemplo:

El Kernel32.dll tiene funciones que están implementadas dentro del Kernel32.dll por ejemplo Beep. Pero tiene otras funciones que son implementadas en otras DLLs, por ejemplo OpenProcessToken que está implementada en la DLL API-MS-WIN-CORE-PROCESSTHREADS-L1-1-0.DLL. (Hablo por ejemplo en Windows 7)

Es por ello que si se ve la Export Address Table del Kernel32.dll, la función OpenProcessToken aparece como Forwarded a API-MS-WIN-CORE-PROCESSTHREADS-L1-1-0.DLL.

Entonces, la pregunta por la que viene todo esto:

¿Cuando mi programa se carga en memoria para ejecutarse, y el loader de Windows carga la Kernel32.dll en el espacio de direcciones del proceso de mi programa, también carga automáticamente la DLL API-MS-WIN-CORE-PROCESSTHREADS-L1-1-0?

O sea: ¿cuando el loader de Windows carga una DLL que un programa necesita, también carga automáticamente todas las DLL Forwarded, que la primera DLL necesita?

Dicho de otra manera: Si yo cargo una DLL con LoadLibrary, pongamos la Kernel32.dll -> LoadLibrary("kernel32.dll") ¿LoadLibrary cargará además de la Kernel32, también todas las DLL Forwarded que la Kernel32 importe?

Gracias.

The Swash

Creo que esto te responderá algo:

CitarExport Forwarding
      A particularly slick feature of exports is the ability to "forward" an export to another DLL. For example, in Windows NT®, Windows® 2000, and Windows XP, the KERNEL32 HeapAlloc function is forwarded to the RtlAllocHeap function exported by NTDLL. Forwarding is performed at link time by a special syntax in the EXPORTS section of the .DEF file. Using HeapAlloc as an example, KERNEL32's DEF file would contain:
   EXPORTS
   •••
   HeapAlloc = NTDLL.RtlAllocHeap
      How can you tell if a function is forwarded rather than exported normally? It's somewhat tricky. Normally, the EAT contains the RVA of the exported symbol. However, if the function's RVA is inside the exports section (as given by the VirtualAddress and Size fields in the DataDirectory), the symbol is forwarded.
      When a symbol is forwarded, its RVA obviously can't be a code or data address in the current module. Instead, the RVA points to an ASCII string of the DLL and symbol name to which it is forwarded. In the prior example, it would be NTDLL.RtlAllocHeap.

paulagarcum

Gracias por responderme,

Sin embargo decirte que eso no responde a lo que yo preguntaba.

Ahí en lo que tú me has puesto explica cómo se ve en la EAT (Export Address Table) si una función está o no Forwarded.

Pero no explica lo que yo preguntaba:

¿Si cargo una DLL, por ejemplo con LoadLibrary, todas las DLLs que esa DLL importa, LoadLibrary también las carga? ¿O sólo carga la DLL que se le pasa a LoadLibrary?



MCKSys Argentina

Cuando cargas una DLL, LoadLibrary cargará (o al menos tratará de hacerlo) todas las DLL que estén referenciadas en la IAT de dicha DLL.

Además, ejecutará el entrypoint de la DLL, lo que podría también generar la carga de otras DLLs que no están en la IAT.

No estoy muy seguro (pero creo que es posible) que si una DLL tiene TLS y se cargan DLLs en el mismo, estas tambien se cargarán.

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


paulagarcum

#4
¡¡Muy bueno!! Gracias por tu respuesta MCKSys Argentina. Me has aclarado finalmente.

Mira, (mirad), he hecho la prueba con este programilla ASM:

;------------------------------------------------------------------------------
.386p
.model flat

extrn   LoadLibraryA: proc
extrn   GetProcAddress: proc
extrn   ExitProcess: proc


.data
kernel32            db   "KERNEL32.DLL", 0
funcion              db   "SetDefaultDllDirectories", 0

.code
@inicio:   push   offset kernel32
              call      LoadLibraryA
         
              push     offset funcion
              push   eax
              call      GetProcAddress

              push     200h
              call      eax ; llama a SetDefaultDllDirectories

              push   0
              call      ExitProcess

              end     @inicio
;------------------------------------------------------------------------------

La API SetDefaultDllDirectories está declarada en la DLL Kernel32.dll
Sin embargo está forwarded y está implementada en la API API-MS-WIN-CORE-LIBRARYLOADER-L1-1-0.DLL (Windows 7)

Cuando el programilla EXE se carga, el Loader de Windows carga la Kernel32.dll ya que el EXE importa 3 funciones de ella: LoadLibraryA, GetProcAddress y ExitProcess. Aún así, quizás de forma redundante, el propio programa vuelve a cargar la Kernel32.dll al inicio.

Cuando el programilla se ejecuta y llama a la función SetDefaultDllDirectories, (call  eax), la llamada se hace correctamente y todo va ok.
Eso permite concluir que como decía MCKSys Argentina, al llamar a LoadLibrary, se carga no sólo la DLL que se le pasa, sino todas las demás DLLs que son importadas por la primera. O sea, se carga API-MS-WIN-CORE-LIBRARYLOADER-L1-1-0.DLL, ya que es importada por la Kernel32.dll.
(yo no había importado a mano  API-MS-WIN-CORE-LIBRARYLOADER-L1-1-0.DLL)

Gracias de nuevo MCKSys. Saludo a todos.