Found of how it works.
The offset is indeed just the difference of the addresses, which can be taken from the static analysis, i.e. from IDA or Ghidra regardless in which address space it loads by default.
So, if the basis address specified by those tools (in the beginning of the image) is say: 140 000 000
and the function starts at 140 039 ea0
, then the offset is: 0x39ea0
To calculate the address aka baseAddress + Offset properly you need to remember the pointer arithmetics though.
baseAddress + Offset / (2*sizeof(pointerSize))
,
i.e.
DWORD_PTR* address = baseAddress + 0x39ea0 / (2*sizeof(DWORD))
Note: I don't quite know where why the size is twice as big in this case
- Need to make sure that the baseAddress is calculated from the correct application.
I.e. when simply doing something like: base_address = (DWORD_PTR)GetModuleHandle(NULL);
you will get back the address of the application you are currently building. So, if as in my case you are building the proxy dll, then you will get it's base address.
While the function which I was trying to hook was in the .exe file of the program, which that dll will be hooked at.
So, what you really want is:
baseAddressPtr = (DWORD_PTR*)GetModuleHandleA("<YourProgram>.exe");