비슷한 질문을 찾았지만 찾고있는 답변이 없습니다. 그래서 여기에 간다 :dll 내보내기 함수를 열거하는 Win32 API?
네이티브 Win32 dll의 경우, 내보내기 함수 이름을 나열하는 Win32 API가 있습니까?
비슷한 질문을 찾았지만 찾고있는 답변이 없습니다. 그래서 여기에 간다 :dll 내보내기 함수를 열거하는 Win32 API?
네이티브 Win32 dll의 경우, 내보내기 함수 이름을 나열하는 Win32 API가 있습니까?
dumpbin /exports
은 원하는대로 할 수 있지만 개발자 도구는 Win32 API가 아닙니다. DONT_RESOLVE_DLL_REFERENCES
와
LoadLibraryEx
무겁게에 대해주의, 그러나이 특별한 경우 – 유용 될 일이되어 그것을 않습니다 (하지만 실제로 필요하거나 라이브러리에서 아무것도 사용하지 않음) 메모리에 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 리서치로 이동하여 우회 라이브러리를 가져옵니다. 그 예 중 하나가 당신이 요구하는 것과 정확히 일치합니다. 전체 라이브러리는 기본적으로 win32 함수 호출을 우회/재 라우팅하는 것을 매우 쉽게 만듭니다. 그 멋진 물건.
편집 :은 또한 단지 수출 테이블을보고 싶은 경우에, 당신은 (적어도 비주얼 스튜디오에서) 엑스포트/임포트 테이블을 인쇄하는 프로젝트 속성을 설정할 수 있습니다. 나는 정확한 옵션을 기억할 수 없지만 쉽게 Google에 있어야합니다.
** Edit2가 : ** 옵션은 프로젝트 속성 -입니다> 링커 -> Debugging-> 맵 파일 생성 - 당신은 단지 어떤 기능을 찾을 수있는 방법을 찾고 있다면> 예 (/ MAP)
을 DLL에서 내 보낸 경우 Microsoft의 dependency walker (depends.exe)을 사용할 수 있습니다. 그러나 실제로 프로그래밍 방식으로 내보내기를 검색해야하는 경우에는 도움이되지 않습니다.
자신의 코드를 작성하는 데 문제가 없으며이 목적으로 이미 존재하는 DLL을 사용하려는 경우 PE File Format DLL을 권장합니다. 원한다면 수정할 수 있도록 소스 코드가 제공됩니다. 걱정할 GPL이 없습니다.
DLL을 사용하는 방법을 보여주는 GUI 응용 프로그램도 사용할 수 있습니다.
내가 틀릴 수도 있고 솔직하게 두 번 확인하지 않았지만 프로세스와 다른 아키텍처에서 빌드 된 모듈에서 ephemient의 코드를 사용하면 호환성 문제가 발생할 수 있습니다. (다시 말하면, 지금 당장은 완전히 내 엉덩이에서 말하고 있을지도 모른다.)같은 기술을 사용하는 github 프로젝트가있다. (하지만 파일을 메모리에로드하더라도) 바이너리의 아키텍처에 따라 내보내기를 찾을 위치를 확인합니다. 가장 관심이있는 코드는 this file입니다.
DONT_RESOLVE_DLL_REFERENCES
의 LoadLibraryEx
이 정확한 작업이므로이 작업을 간소화 할 수 있습니다. 대신 DLL의 내보내기 디렉토리를 찾고 열거하는 대신 SymEnumerateSymbols
을 사용하여 기호를 나열 할 수 있습니다.
자신의 코드보다 약간 단순하지만 (어설 션 없이는 코드가 6 라인에 불과함) 이론적으로 Microsoft가 언젠가는 실행 파일 형식을 조금 변경하기로 결정할 경우 약간의 유연성을 제공합니다./또는 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
이 (하는 ctypes와) 파이썬 내 빠른 포트가 잘 작동하는지 충분히 잘 작동했다. 감사! –
** DONT_RESOLVE_DLL_REFERENCES 플래그로 로딩 한 후에 ** 함수를 호출하면 **로드 된 모듈에'DllMain'이 호출되지 않기 때문에 ** 쓸데없는 일이 될 수 있습니다 **. –
왜 DONT_RESOLVE_DLL_REFERENCES 대신 파일을 직접 메모리 맵핑하지 않을까요? 심지어 더 빠를 수도 있습니다. – masterxilo