3

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!".

imnotdax
  • 67
  • 5
  • 1
    The EXE is probably not loaded at the same address every time, and its functions are not at some fixed addresses. See [Address space layout randomization](https://en.wikipedia.org/wiki/Address_space_layout_randomization) - this is a security feature designed to prevent precisely the game you are trying to play. – Igor Tandetnik Apr 19 '20 at 14:26
  • @IgorTandetnik so if I used the base address of the EXE + the function address, would it work that way? – imnotdax Apr 19 '20 at 14:30
  • Probably. Why don't you try it? – Igor Tandetnik Apr 19 '20 at 14:31
  • @IgorTandetnik thanks for your help, I will try and update here if it works! – imnotdax Apr 19 '20 at 14:32
  • Updated the original post. – imnotdax Apr 19 '20 at 15:52
  • Do you really need to call a function by hardcoded address? You can export functions from exe the same way as fromdll, and even import such exported functions in a dll. – Alex Guteniev Apr 19 '20 at 16:16
  • Yes sadly I need to call it with a hard-coded address, this is a test application but in the actual application (malware reversing) I will not have access to the source code, so I would have to use a function pointer. I tried detouring functions but that didn't work and I decided to check if I could at-least call the function from a DLL using a pointer, which didn't work either. @AlexGuteniev – imnotdax Apr 19 '20 at 16:19
  • `0x00401000` is already offset from some base address, likely `0x00400000` (which was the default base for EXEs before ASLR). You are effectively adding up two bases. Try `baseAddress + 0x1000`. Also, `GetModuleHandle(NULL)` will give you the handle of the current EXE; you don't need to go through `GetModuleFileName` – Igor Tandetnik Apr 19 '20 at 17:28
  • Thanks @IgorTandetnik, this worked perfectly! If you want, you could answer and I could mark it as the solution. If not, it's ok and I can answer it. – imnotdax Apr 19 '20 at 18:11

1 Answers1

1

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();
imnotdax
  • 67
  • 5