API Win32 для перечисления функций экспорта dll?
Я нашел похожие вопросы, но не ответил на то, что я ищу. Итак, вот:
Для родной DLL Win32 существует ли API Win32 для перечисления имен функций экспорта?
Ответы
Ответ 1
dumpbin /exports
- это в значительной степени то, что вы хотите, но инструмент разработчика, а не API Win32.
LoadLibraryEx
с DONT_RESOLVE_DLL_REFERENCES
с большой осторожностью против, но, оказывается, полезно для этого конкретного случая – он тяжело поднимает отображение DLL в память (но на самом деле вам не нужно или ничего не нужно использовать из библиотеки), что делает тривиальным для вас чтение заголовка: дескриптор модуля, возвращаемый LoadLibraryEx
точками справа на нем.
#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]);
Полностью непроверенный, но я считаю его более-менее правильным. (Знаменитые последние слова.)
Ответ 2
Перейдите к исследованиям Microsoft и возьмите библиотеку Detours. Один из его примеров делает именно то, что вы просите. Вся библиотека в основном упрощает обход/перенаправление вызовов функций win32. Его довольно классный материал.
Detours
Изменить: Также обратите внимание: если вы просто хотите посмотреть таблицу экспорта, вы можете (по крайней мере, в визуальных студиях) установить свойства проекта для печати таблиц экспорта/импорта. Я не могу вспомнить точный вариант, но должен быть удобным для Google.
** Edit2: ** Опция - это Свойства проекта → Коннектор- > Отладка- > Сгенерировать MapFile → Да (/MAP)
Ответ 3
В то время как эфемер правильный, что LoadLibraryEx
с DONT_RESOLVE_DLL_REFERENCES
может значительно упростить эту задачу, вы можете сделать ее еще проще, чем он показывает. Вместо того, чтобы самостоятельно находить и перечислять каталог экспорта DLL, вы можете использовать SymEnumerateSymbols
, чтобы перечислить символы для вас.
Хотя он только немного проще, чем его код (без утверждений, его всего полдюжины строк кода), по крайней мере теоретически он дает небольшую дополнительную гибкость в случае, если Microsoft когда-нибудь решит немного изменить исполняемый формат и/или изменить то, что указывает HMODULE, поэтому он больше не работает (поскольку большинство этих деталей официально не документированы).
Ответ 4
попробуйте следующее:
#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);
}
}
Пример:
void mycallback (char* szName) {
printf ("%s\n", szName);
}
int main () {
EnumExportedFunctions ("C:\\Windows\\System32\\user32.dll", mycallback);
return 0;
}
выход:
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
Ответ 5
Если вы не хотите идти на поводу написания собственного кода и предпочитаете использовать DLL, которая уже существует для этой цели, я рекомендую PE File Format DLL. Поставляется с исходным кодом, так что вы можете изменить, если хотите. GPL не беспокоиться.
Также доступно графическое приложение, которое показывает, как использовать DLL.
Ответ 6
Если вы просто ищете способ узнать, какие функции экспортируются в DLL, вы можете использовать Microsoft зависимый ходок ( depends.exe). Это не поможет вам, если вам действительно нужно искать экспорт программным путем.
Ответ 7
Возможно, я ошибаюсь, и я не проверял честность, но считаю, что могут возникнуть проблемы с совместимостью с использованием эфемерного кода в модуле, который построен под другой архитектурой, чем у вашего процесса. (Опять же, я могу говорить полностью из моей задницы прямо сейчас)
Там есть проект на github, называемый dll2def, который использует ту же технику (хотя сам он загружает файл в память) но, похоже, есть некоторые проверки, чтобы найти экспорт в зависимости от архитектуры двоичного файла. Код, который вам больше всего интересен, находится в этом файле.