7

I'm writing in C++ and doing an exercise to familiarize myself with DLLs and shared objects (.so). How can I access internals without exporting them? GetProcAddress returns null on a call of an unexported function. I wrote the DLL so I know all of the function and variable names.

2 Answers 2

7

In case you know the address of your function in the DLL you can call in "C" language via a function pointer. Let us make an example:

Assume you have a function residing in a DLL called "notExportedFunc" with the signature

int notExportedFunc(int a, int b);

You could call it like in the following main program:

typedef int notExportedFunc(int a, int b);

int main() {

    HANDLE h = LoadLibrary(L"mydll.dll"); //Image base address, might change on every call

    if (h == 0)
    {
        printf("Cannot load mydll.dll\n");
        return -1;
    }
    int funcOffset = 0x11560;             //from the linker map
    int funcAddress = (int)h + funcOffset;
    notExportedFunc* f = (notExportedFunc*)(funcAddress);
    int result = f(3, 4);
    printf("Result = %d\n", result);
}

In the linker map, the relevant entries look like this:

0000:00000000 ___ImageBase 10000000 <=== Linker Suggestion

0001:00000000 __enc$textbss$begin 10001000 Not relevant here

0001:00010000 __enc$textbss$end 10011000 Not relevant here

0002:00000560 ?notExportedFunc@@YAHHH@Z 10011560 f dllmain.obj

The ImageBase address is returned by the "LoadLibrary("mydll.dll")" call. You should be aware that this address usually changes on every call to LoadLibrary, due to ASLR (Address Space Layout Randomization). Therefore the address of notExportedFunc must not be taken directly from the linker map, but must be calculated. In our example, the offset is 0x11560, which must be added to the address returned by LoadLibrary.

The rest of the program is usual "C" function call via a function pointer.

It might be possible to automate this further, but the example hopefully shows the general mechanics of calling private functions in a DLL.

4

The GetProcAddr Windows API is used to retrieve addresses for exported functions. It will always return null for non-exported functions as it is unable to find it in the PE file.

Exporting a function is what makes it available to other executables. Without exporting the data of where in the executable a function resides is unavailable (this is not entirely true, as symbols may still reveal that information but they're not used by GetProcAddr).

If you still wish to find a function pointer to a non exported function, you'll need to follow an exported reference chain. For example, if func1 uses func2 and func1 is exported, you can get the address for func1 and then disassemble func1 until you find the call to func2 within it. Recognising the right call may be a little tricky, but that's definitely doable.

1
  • 1
    This is a better option in cases where the DLL might change/update. Also I have seen this in exploits to call internal functions in DLLs. Although this will be harder to implement OP but it'll almost never break(assuming call chain for the function is same).
    – sudhackar
    Jul 5, 2018 at 6:57

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.