1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
/*
* Copyright (C) by Argonne National Laboratory
* See COPYRIGHT in top-level directory
*/
#include <windows.h>
#include <stdio.h>
#include <time.h>
/* This function returns a pointer to the section header containing the RVA. Return NULL on error */
template < typename NTHeaderType > static inline PIMAGE_SECTION_HEADER GetSecHeader(DWORD rva,
NTHeaderType *
pNTHeader)
{
PIMAGE_SECTION_HEADER section;
section = IMAGE_FIRST_SECTION(pNTHeader);
for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++) {
DWORD size = section->Misc.VirtualSize;
DWORD secRVA = section->VirtualAddress;
if ((secRVA <= rva) && (rva < (secRVA + size))) {
return section;
}
}
return NULL;
}
/* This function returns the real address from the RVA. Returns NULL on error */
template < typename NTHeaderType > static inline LPVOID GetRealAddrFromRVA(DWORD rva,
NTHeaderType * pNTHeader,
PBYTE imageBase)
{
PIMAGE_SECTION_HEADER pSectionHdr = GetSecHeader(rva, pNTHeader);
if (!pSectionHdr) {
return NULL;
}
/* Since we map the DLL manually we need to calculate mapShift to get the real addr */
INT mapShift = (INT) (pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);
return (PVOID) (imageBase + rva - mapShift);
}
/* This function reads the exported symbols from a dll/exe and prints a DLL definition file, compatible with gcc,
with those symbols.
INPUT:
pImageBase : Pointer to the base of the dll image, offset = 0
pNTHeader : Pointer to the NT header (32-bit/64-bit) section of image.
*/
template < typename NTHeaderType > void PrintDefFileWithExpSymbols(PBYTE pImageBase,
NTHeaderType * pNTHeader)
{
/* Export Section RVA */
DWORD expSecRVA =
pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
/* From RVA get the real addrs for the various components of the exports section */
PIMAGE_EXPORT_DIRECTORY pExportDir =
(PIMAGE_EXPORT_DIRECTORY) GetRealAddrFromRVA(expSecRVA, pNTHeader, pImageBase);
PDWORD pszFuncNames =
(PDWORD) GetRealAddrFromRVA(pExportDir->AddressOfNames, pNTHeader, pImageBase);
printf("EXPORTS\n");
for (unsigned int i = 0; i < pExportDir->NumberOfFunctions; i++) {
/* FIXME: Assumes that the current DLL does not have ordinal nums */
if (i < pExportDir->NumberOfNames) {
/* Ordinal numbers start at 1 - not 0 */
printf("\t%s @ %d ;\n", GetRealAddrFromRVA(pszFuncNames[i], pNTHeader, pImageBase),
i + 1);
} else {
break;
}
}
}
static void HelpUsage(char *exe_name)
{
printf("Usage: %s <DLLNAME>\n", exe_name);
printf
("\t\t The tool reads the export section from <DLLNAME> and prints the definition file for gcc to stdout\n");
}
int main(int argc, char *argv[])
{
HANDLE hFile, hFileMapping;
LPVOID lpFileBase;
PIMAGE_DOS_HEADER pImgHeader;
PIMAGE_NT_HEADERS pImgNTHeader;
PIMAGE_NT_HEADERS64 pImgNTHeader64;
if ((argc < 2) || (strcmp(argv[1], "/?") == 0) || (strcmp(argv[1], "--help") == 0)) {
HelpUsage(argv[0]);
exit(1);
}
/* Open the DLL and map it to memory */
hFile =
CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Unable to open dll, %s\n", argv[1]);
exit(-1);
}
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hFileMapping == 0) {
CloseHandle(hFile);
printf("Cannot open file mapping for dll, %s\n", argv[1]);
exit(-1);
}
lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
if (lpFileBase == 0) {
CloseHandle(hFileMapping);
CloseHandle(hFile);
printf("Cannot map view of dll, %s\n", argv[1]);
exit(-1);
}
/* pImgHeader points to the MS-DOS HEADER section, offset=0, of dll */
pImgHeader = (PIMAGE_DOS_HEADER) lpFileBase;
/* pImgNTHeader points to the NT HEADER section of the dll, pImgHeader + <File address of new exe header> */
pImgNTHeader = (PIMAGE_NT_HEADERS) ((DWORD_PTR) pImgHeader + (DWORD_PTR) pImgHeader->e_lfanew);
/* In the case of the 64-bit dlls, the Optional header section within NT header has 64-bit fields */
pImgNTHeader64 = (PIMAGE_NT_HEADERS64) pImgNTHeader;
/* The Magic number is always a WORD. This number is used to determine if the dll is 32-bit or 64-bit */
if (pImgNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
/* 64-bit dll */
PrintDefFileWithExpSymbols((PBYTE) pImgHeader, pImgNTHeader64);
} else {
/* 32-bit dll */
PrintDefFileWithExpSymbols((PBYTE) pImgHeader, pImgNTHeader);
}
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
}
|