回答
dumpbin /exports
幾乎是你想要的,但這是一個開發工具,而不是Win32 API。
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]);
完全未經測試,但我認爲它或多或少是正確的。 (着名的遺言。)
轉到Microsoft研究部門,抓住Detours圖書館。其中一個例子就是你正在問的問題。整個庫基本上使繞過/重新路由win32函數調用非常容易。它非常酷的東西。
編輯:另外請注意,如果你只是想看看導出表,你可以(至少在視覺工作室)設置你的項目屬性,打印出的導出/導入表。我不記得確切的選項,但應該很容易谷歌。
** EDIT2:**的選擇是項目屬性 - >連接器 - > Debugging->生成映射文件 - >是(/ MAP)
如果你只是尋找一種方法來找出哪些功能導出在一個DLL中,你可以使用微軟的dependency walker(depends.exe)。儘管如此,如果你真的需要以編程方式發現導出,這不會對你有所幫助。
如果你不想去編寫你自己的代碼的麻煩,而寧願使用一個已經存在的DLL爲此目的,我推薦PE File Format DLL。附帶源代碼,以便您可以根據需要進行修改。沒有GPL擔心。
另外還有一個顯示如何使用DLL的GUI應用程序。
雖然ephemient是正確的,LoadLibraryEx
與DONT_RESOLVE_DLL_REFERENCES
可以簡化這項任務很多,你可以使它甚至比他顯示更簡單。您可以使用SymEnumerateSymbols
來爲您列出符號,而不是自己查找並枚舉DLL的導出目錄。
雖然只比他的代碼稍微簡單一些(沒有斷言,他只有六行代碼),但至少在理論上這給了一點額外的靈活性,以防微軟應該有一天決定改變可執行格式, /或者改變HMODULE指向的內容,所以他不再有效(因爲大多數這些細節都沒有正式記錄)。
試試這個:
#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
- 1. 枚舉函數
- 2. 轉換枚舉來枚舉
- 3. 實體枚舉不導出
- 4. Swift枚舉函數
- 5. 風險函數調用來枚舉
- 6. 如何導出dll函數?
- 7. 導出dll類和函數,並將它們導入到Win32應用程序
- 8. 列出一個DLL的導出函數
- 9. 流API:從枚舉
- 10. Win32:如何枚舉子進程?
- 11. 枚舉拋出「不是枚舉類型」
- 12. 在Angular模塊中導出枚舉
- 13. 用C++導入DLL(Win32)
- 14. Win32 DLL導入問題(DllMain)
- 15. Perl Win32 :: API()調用()函數
- 16. 未找到Win32 API函數
- 17. Angular 2將枚舉枚舉爲HTML中的組件函數
- 18. Java枚舉與枚舉在構造函數
- 19. 通過枚舉函數在c + +
- 20. 使用Swift枚舉來減少函數中的參數數量
- 21. DLL:作爲C/C++函數導出?
- 22. 從dll導出函數唯一序號
- 23. CVTRES.exe丟棄我的DLL導出函數
- 24. 從.net DLL導出本地C函數?
- 25. C++導出和使用dll函數
- 26. C++函數導出在DLL和從C#
- 27. 鐺枚舉溢出
- 28. 鑄造整數數組來枚舉
- 29. C#枚舉作爲函數參數?
- 30. 使用枚舉作爲函數參數
已經足夠好了,我快端口到Python(與ctypes的)工作正常。謝謝! – 2010-03-24 19:27:39
需要注意的是,在使用'DONT_RESOLVE_DLL_REFERENCES'標誌加載**之後調用函數**可能會引起混亂**,因爲沒有爲加載的模塊調用DllMain。 – 2013-01-14 16:56:23
爲什麼不自己記憶映射文件而不是DONT_RESOLVE_DLL_REFERENCES?甚至可能會更快。 – masterxilo 2016-01-19 18:34:45