I was tried this code:
HMODULE hModule = LoadLibrary(argv[1]);
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + dosHeader->e_lfanew);
PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* addressOfFunctions = (DWORD*)(hModule + exportDirectory->AddressOfFunctions);
DWORD* addressOfNames = (DWORD*)(hModule + exportDirectory->AddressOfNames);
WORD* addressOfNameOrdinals = (WORD*)((DWORD_PTR)hModule + exportDirectory->AddressOfNameOrdinals);
printf("******* DLL EXPORTS *******\n");
printf("\t%i of functions\n\t%i of names\n",(int)exportDirectory->NumberOfFunctions,(int)exportDirectory->NumberOfNames);
printf("\tordinal\t\thint\t\tRVA\t\tattribute\t\tname\n");
for (DWORD i = 0; i < exportDirectory->NumberOfFunctions; i++)
{
DWORD functionRVA = addressOfFunctions[i];
const char* functionName = NULL;
for (DWORD j = 0; j < exportDirectory->NumberOfNames; j++)
{
if (addressOfNameOrdinals[j] == i)
{
functionName = ((const char*)hModule + addressOfNames[j]);
break;
}
}
if (functionName != NULL)
{
FARPROC functionAddress = GetProcAddress(hModule, functionName);
for (; importDescriptor->Name != 0; importDescriptor++) {
// imported dll modules
printf("\t%s\n", rawOffset + (importDescriptor->Name - importSection->VirtualAddress));
thunk = importDescriptor->OriginalFirstThunk == 0 ? importDescriptor->FirstThunk : importDescriptor->OriginalFirstThunk;
thunkData = (PIMAGE_THUNK_DATA)(rawOffset + (thunk - importSection->VirtualAddress));
// dll exported functions
for (; thunkData->u1.AddressOfData != 0; thunkData++) {
//a cheap and probably non-reliable way of checking if the function is imported via its ordinal number ¯\_(ツ)_/¯
if (!(thunkData->u1.AddressOfData > 0x80000000)) {
char* libname1=(char*)(rawOffset + (importDescriptor->Name - importSection->VirtualAddress));
const char* libname=libname1;
char* importfunctionname1=(char*)(rawOffset + (thunkData->u1.AddressOfData - importSection->VirtualAddress + 2));
const char* importfunctionname=importfunctionname1;
HMODULE module=LoadLibrary(libname);
if (((DWORD)functionAddress-(DWORD)hModule)==((DWORD)GetProcAddress(module,importfunctionname)-(DWORD)module))
printf("\t%i\t\t%02X\t\t%0002X\t\tforwarded\t\t%s\t\t (forwarded to %s.%s)\n", i + exportDirectory->Base,i,functionRVA,functionName,libname,importfunctionname);// (forwarded to %s.%s)
else
printf("\t%i\t\t%02X\t\t%0002X\t\tnormal\t\t%s\n", i + exportDirectory->Base,i,functionRVA,functionName);
}
printf("\t%i\t\t%02X\t\t%0002X\t\t \t\t%s\n", i + exportDirectory->Base,i,functionRVA,functionName);
}
}
}
}
FreeLibrary(hModule);
But it output this:
******* DLL EXPORTS *******
1608 of functions
1608 of names
ordinal hint RVA attribute name
It should output this instead:
******* DLL EXPORTS *******
1608 of functions
1608 of names
ordinal hint RVA attribute name
4 01 forwarded AcquireSRWLockExclusive (forwarded to NTDLL.RtlAcquireSRWLockExclusive)
What I'm doing wrong and how can I get the forwarded function name?
P/S: My compiler was MinGW (installed on Windows).
void DumpExport(PVOID hmod)
{
ULONG size;
if (PIMAGE_EXPORT_DIRECTORY pied = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size))
{
if (DWORD NumberOfFunctions = pied->NumberOfFunctions)
{
DbgPrint("NumberOfFunctions=%u\r\n", NumberOfFunctions);
if (PLONG bits = (PLONG)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (NumberOfFunctions + 7) >> 3))
{
ULONG i;
PULONG AddressOfFunctions = (PULONG)RtlOffsetToPointer(hmod, pied->AddressOfFunctions);
if (DWORD NumberOfNames = pied->NumberOfNames)
{
DbgPrint("NumberOfNames=%u\r\n", NumberOfNames);
PULONG AddressOfNames = (PULONG)RtlOffsetToPointer(hmod, pied->AddressOfNames);
PUSHORT AddressOfNameOrdinals = (PUSHORT)RtlOffsetToPointer(hmod, pied->AddressOfNameOrdinals);
do
{
PCSTR Name = RtlOffsetToPointer(hmod, *AddressOfNames++);
_bittestandset(bits, i = *AddressOfNameOrdinals++);
PVOID pv = RtlOffsetToPointer(hmod, AddressOfFunctions[i]);
if ((ULONG_PTR)pv - (ULONG_PTR)pied < size)
{
DbgPrint("%s -> %s\r\n", Name, pv);
}
else
{
DbgPrint("%08X %s\r\n", RtlPointerToOffset(hmod, pv), Name);
}
} while (--NumberOfNames);
}
DWORD Base = pied->Base;
AddressOfFunctions += NumberOfFunctions;
do
{
--AddressOfFunctions;
if (!_bittestandset(bits, --NumberOfFunctions))
{
PVOID pv = RtlOffsetToPointer(hmod, *AddressOfFunctions);
if ((ULONG_PTR)pv - (ULONG_PTR)pied < size)
{
DbgPrint("#%u -> %s\r\n", Base + NumberOfFunctions, pv);
}
else
{
DbgPrint("%08X #%u\r\n", RtlPointerToOffset(hmod, pv), Base + NumberOfFunctions);
}
}
} while (NumberOfFunctions);
LocalFree(bits);
}
}
}
}
void DumpExport(PCWSTR pszLibName)
{
if (HMODULE hmod = LoadLibraryExW(pszLibName, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE))
{
__try {
DumpExport(PAGE_ALIGN(hmod));
}
__except(EXCEPTION_EXECUTE_HANDLER){
}
FreeLibrary(hmod);
}
}