0

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

4
  • 1
    If this is compiled for a 64-bit target, the code truncates addresses all over the place. Things like (DWORD)functionAddress will do exactly what you wrote, which possibly does not coincide with what you meant. Commented Oct 17, 2023 at 16:03
  • 1
    how can I get the forwarded function name unclear at all, what you trying todo. unclear your question. the code is terrible Commented Oct 17, 2023 at 18:57
  • 1
    When determining the values for addressOfFunctions and addressOfNames, you are not casting hModule to DWORD_PTR before performing arithmetic on it, like you do with your other uses of hModule, so you are performing pointer arithmetic instead of integer arithmetic, using the wrong pointer type. Commented Oct 17, 2023 at 19:49
  • @RemyLebeau I did use it to be detecting the forwarded functions and it did works without that modifies. Commented Oct 18, 2023 at 14:00

1 Answer 1

0
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);
    }
}
Sign up to request clarification or add additional context in comments.

10 Comments

A compiler error I was encountered looks like this: "_bittestandset doesn't declared" What function should I write as a replacement?
@winapiadmin if you simply search in google, you can find _bittestandset - and Header file <intrin.h> - so you need #include <intrin.h>
Yes but it can't include in my code before I was comment., and the RtlOffsetToPointer is the Windows Drivers function. What replacement should I write (simple)?
@winapiadmin again - RtlOffsetToPointer not a function. this is macro - in what problem use it definition ?! #define RtlOffsetToPointer(B,O) ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O)) )) or use another analog. in what problem #include <intrin.h> ? or just copy/paste unsigned char _bittestandset(long *, long) ? this is compiler instrinsic. in any case all this not related to your question at all. this is for very basic knowledge or language and common logic
After changing, the undefined reference...C:\Users\asdfs\AppData\Local\Temp\ccbMmHlw.o: In function Z10DumpExportPv': C:\Users\asdfs\OneDrive\pedumper\example/main.cpp:162: undefined reference to _bittestandset(long*, long)' C:\Users\asdfs\OneDrive\pedumper\example/main.cpp:182: undefined reference to `_bittestandset(long*, long)' collect2.exe: error: ld returned 1 exit status
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.