c++winapiportable-executable

Getting the forwarded function name


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).


Solution

  • 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);
        }
    }