c++ - findwindowex c#
Win32 API para enumerar funciones de exportación dll? (7)
Aunque ephemient es correcto, LoadLibraryEx
with DONT_RESOLVE_DLL_REFERENCES
puede simplificar mucho esta tarea, puede hacerlo aún más simple de lo que muestra. En lugar de buscar y enumerar el directorio de exportación de la DLL usted mismo, puede usar SymEnumerateSymbols
para listar los símbolos por usted.
Aunque solo marginalmente más simple que su código (sin las afirmaciones, su es solo media docena de líneas de código) al menos teóricamente da un poco de flexibilidad extra en caso de que Microsoft algún día decida cambiar un poco el formato ejecutable, y / o cambiar exactamente lo que señala el HMODULE, por lo que ya no funciona (ya que la mayoría de estos detalles no están oficialmente documentados de todos modos).
Encontré preguntas similares pero ninguna respuesta a lo que estoy buscando. Así que aquí va:
Para un DLL nativo Win32, ¿hay una API de Win32 para enumerar sus nombres de funciones de exportación?
Puedo estar equivocado, y no lo he comprobado dos veces para ser sincero, pero creo que puede haber algunos problemas de compatibilidad con el uso del código de ephemient en un módulo que está construido bajo una arquitectura diferente a la de su proceso. (De nuevo, puedo estar hablando completamente fuera de mi culo en este momento)
Hay un proyecto en github, llamado dll2def que usa la misma técnica (aunque carga el archivo en la memoria por sí mismo), pero parece tener algunas verificaciones para encontrar las exportaciones según la arquitectura del binario. El código que probablemente le interese está en este archivo .
Si no quiere tomarse la molestia de escribir su propio código y prefiere usar una DLL que ya existe para este fin, recomiendo PE File Format DLL . Viene con el código fuente para que pueda modificarlo si lo desea. Sin GPL de qué preocuparse.
También está disponible una aplicación GUI que muestra cómo usar el DLL.
Si solo está buscando una forma de averiguar qué funciones se exportan en una DLL, puede usar la herramienta de dependencia de dependencias de Microsoft (depends.exe). Sin embargo, esto no te ayudará si realmente necesitas descubrir las exportaciones programáticamente.
Vaya a la investigación de Microsoft y tome la Biblioteca Detours. Uno de sus ejemplos hace exactamente lo que estás preguntando. La biblioteca completa básicamente hace que las llamadas a funciones de desvío / reencaminamiento sean extremadamente sencillas. Es muy bueno.
Editar: También tenga en cuenta que si solo quiere mirar la tabla de exportación, puede (al menos en los estudios visuales) establecer las propiedades de su proyecto para imprimir las tablas de exportación / importación. No recuerdo la opción exacta, pero debería ser fácil de googlear.
** Edit2: ** La opción es Project Properties-> Linker-> Debugging-> Generate MapFile -> Yes (/ MAP)
prueba esto:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void EnumExportedFunctions (char *, void (*callback)(char*));
int Rva2Offset (unsigned int);
typedef struct {
unsigned char Name[8];
unsigned int VirtualSize;
unsigned int VirtualAddress;
unsigned int SizeOfRawData;
unsigned int PointerToRawData;
unsigned int PointerToRelocations;
unsigned int PointerToLineNumbers;
unsigned short NumberOfRelocations;
unsigned short NumberOfLineNumbers;
unsigned int Characteristics;
} sectionHeader;
sectionHeader *sections;
unsigned int NumberOfSections = 0;
int Rva2Offset (unsigned int rva) {
int i = 0;
for (i = 0; i < NumberOfSections; i++) {
unsigned int x = sections[i].VirtualAddress + sections[i].SizeOfRawData;
if (x >= rva) {
return sections[i].PointerToRawData + (rva + sections[i].SizeOfRawData) - x;
}
}
return -1;
}
void EnumExportedFunctions (char *szFilename, void (*callback)(char*)) {
FILE *hFile = fopen (szFilename, "rb");
if (hFile != NULL) {
if (fgetc (hFile) == ''M'' && fgetc (hFile) == ''Z'') {
unsigned int e_lfanew = 0;
unsigned int NumberOfRvaAndSizes = 0;
unsigned int ExportVirtualAddress = 0;
unsigned int ExportSize = 0;
int i = 0;
fseek (hFile, 0x3C, SEEK_SET);
fread (&e_lfanew, 4, 1, hFile);
fseek (hFile, e_lfanew + 6, SEEK_SET);
fread (&NumberOfSections, 2, 1, hFile);
fseek (hFile, 108, SEEK_CUR);
fread (&NumberOfRvaAndSizes, 4, 1, hFile);
if (NumberOfRvaAndSizes == 16) {
fread (&ExportVirtualAddress, 4, 1, hFile);
fread (&ExportSize, 4, 1, hFile);
if (ExportVirtualAddress > 0 && ExportSize > 0) {
fseek (hFile, 120, SEEK_CUR);
if (NumberOfSections > 0) {
sections = (sectionHeader *) malloc (NumberOfSections * sizeof (sectionHeader));
for (i = 0; i < NumberOfSections; i++) {
fread (sections[i].Name, 8, 1, hFile);
fread (§ions[i].VirtualSize, 4, 1, hFile);
fread (§ions[i].VirtualAddress, 4, 1, hFile);
fread (§ions[i].SizeOfRawData, 4, 1, hFile);
fread (§ions[i].PointerToRawData, 4, 1, hFile);
fread (§ions[i].PointerToRelocations, 4, 1, hFile);
fread (§ions[i].PointerToLineNumbers, 4, 1, hFile);
fread (§ions[i].NumberOfRelocations, 2, 1, hFile);
fread (§ions[i].NumberOfLineNumbers, 2, 1, hFile);
fread (§ions[i].Characteristics, 4, 1, hFile);
}
unsigned int NumberOfNames = 0;
unsigned int AddressOfNames = 0;
int offset = Rva2Offset (ExportVirtualAddress);
fseek (hFile, offset + 24, SEEK_SET);
fread (&NumberOfNames, 4, 1, hFile);
fseek (hFile, 4, SEEK_CUR);
fread (&AddressOfNames, 4, 1, hFile);
unsigned int namesOffset = Rva2Offset (AddressOfNames), pos = 0;
fseek (hFile, namesOffset, SEEK_SET);
for (i = 0; i < NumberOfNames; i++) {
unsigned int y = 0;
fread (&y, 4, 1, hFile);
pos = ftell (hFile);
fseek (hFile, Rva2Offset (y), SEEK_SET);
char c = fgetc (hFile);
int szNameLen = 0;
while (c != ''/0'') {
c = fgetc (hFile);
szNameLen++;
}
fseek (hFile, (-szNameLen)-1, SEEK_CUR);
char* szName = calloc (szNameLen + 1, 1);
fread (szName, szNameLen, 1, hFile);
callback (szName);
fseek (hFile, pos, SEEK_SET);
}
}
}
}
}
fclose (hFile);
}
}
ejemplo:
void mycallback (char* szName) {
printf ("%s/n", szName);
}
int main () {
EnumExportedFunctions ("C://Windows//System32//user32.dll", mycallback);
return 0;
}
salida:
ActivateKeyboardLayout
AddClipboardFormatListener
AdjustWindowRect
AdjustWindowRectEx
AlignRects
AllowForegroundActivation
AllowSetForegroundWindow
AnimateWindow
AnyPopup
AppendMenuA
AppendMenuW
ArrangeIconicWindows
AttachThreadInput
BeginDeferWindowPos
BeginPaint
BlockInput
BringWindowToTop
BroadcastSystemMessage
BroadcastSystemMessageA
BroadcastSystemMessageExA
BroadcastSystemMessageExW
BroadcastSystemMessageW
BuildReasonArray
CalcMenuBar
.....etc
dumpbin /exports
es prácticamente lo que quieres, pero es una herramienta de desarrollador, no una API de Win32.
LoadLibraryEx
con DONT_RESOLVE_DLL_REFERENCES
está muy DONT_RESOLVE_DLL_REFERENCES
, pero resulta útil para este caso en particular: hace el trabajo pesado de mapear el archivo DLL en la memoria (pero en realidad no necesita ni quiere usar nada de la biblioteca), lo que lo hace trivial para que usted lea el encabezado: el identificador del módulo devuelto por LoadLibraryEx
apunta justo a él.
#include <winnt.h>
HMODULE lib = LoadLibraryEx("library.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);
assert(((PIMAGE_DOS_HEADER)lib)->e_magic == IMAGE_DOS_SIGNATURE);
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS)((BYTE *)lib + ((PIMAGE_DOS_HEADER)lib)->e_lfanew);
assert(header->Signature == IMAGE_NT_SIGNATURE);
assert(header->OptionalHeader.NumberOfRvaAndSizes > 0);
PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)((BYTE *)lib + header->
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
assert(exports->AddressOfNames != 0);
BYTE** names = (BYTE**)((int)lib + exports->AddressOfNames);
for (int i = 0; i < exports->NumberOfNames; i++)
printf("Export: %s/n", (BYTE *)lib + (int)names[i]);
Totalmente no probado, pero creo que es más o menos correcto. (Últimas palabras famosas.)