Search code examples
c++pointersidareversingghidra

Calling function from dll with pointer not working


I made a test program and made a function that just prints some text, and I am trying to call it from a DLL by reversing it using IDA/Ghidra and getting a pointer to it.

What it looks like in Ghidra

I thought IDA was giving the wrong address so I checked with Ghidra and I got the same address...

Here is my code to call the function from my DLL

#include <iostream>

void coolRoutine() {
    printf("starting...\n");
    void(*ofunct)() = (void(__cdecl *)())(0x00401000);
    printf("got funct!\n");
    ofunct();
    printf("done!\n");
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        coolRoutine();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

The program prints "starting..." and "got funct!" but does not call the original function.

I have tried looking at several posts and I can't figure out what I am doing wrong as someone else did something similar and it worked for them.

Update: as someone suggested, I have tried adding the base address to the function pointer however I have ended up with the same result.

Here is what I tried:

void coolRoutine() {
    printf("starting...\n");
    uintptr_t baseAddress = (uintptr_t)GetModuleHandle(0);
    std::cout << "Base Address: " << baseAddress << std::endl;
    void(*ofunct)() = (void(__cdecl *)())(baseAddress + 0x00401000);
    printf("got funct!\n");
    ofunct();
    printf("done!\n");
}

It is getting the base address correctly (or atleast I think it is, since it isn't null), but it isn't executing ofunct and print "done!".


Solution

  • This is due to ASLR. The base address of the application changes every time it is restarted, and the disassembly in Ghidra shows what the address of it would have been without ASLR.

    The default base address of an application pre-ASLR was 0x00400000, so we would have to do 0x00401000 - 0x00400000 to get our relative address to the base address which is 0x1000.

    Now, we want to add 0x1000 to base address to get our function pointer.

    This can be achieved using

    //Get the base address of the application
    uintptr_t baseAddress = (uintptr_t)GetModuleHandle(0);
    //Add the offset of the function relative to the base
    uintptr_t functAddress = baseAddress + 0x1000;
    //typecast it to the correct function signature
    void(*funct)() = (void(__cdecl *)())(functAddress);
    //call it
    funct();