I'm trying to get the function address to copy its content into a buffer using memcpy.
The problem I'm having is with getting function address. Here is my code:
__declspec(noinline) int gio()
{
const char yle[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
return 7;
}
int main(int argc, TCHAR* argv[])
{
int(*funcptr)() = gio;
unsigned char *p = (unsigned char *)&funcptr;
size_t ik;
for (ik = 0; ik < sizeof funcptr; ik++)
{
printf("%02x ", p[ik]);
}
putchar('\n');
printf("gio x -> %x\n", gio);
printf("gio p -> %p\n", gio);
}
I created a little test program where I try to print function address with different ways.
I'm using Visual Studio and had turn off the optimization and inline function expansion(but used noinline anyway). all the print statements print same output(0x00d213ca
screenshot) but when I put my cursor(inside VS) on gio
function it shows totally different address(0x00d218c0
screenshot).
When I right click on gio function and Go To Dissasembler
I jump to the address which was shown when I put my cursor on it(0x00d218c0
screenshot). Which clearly shows where this function really is.
I got little confused here, seems like I don't understand something.
Why do print statements show incorrect value? What is the way to get the "real" function address?
Visual Studio "lies" to you here. When you print either funcptr
or gio
you see the actual address, that is the address you jump to when writing
gio() // or funcptr()
With Incremental Linking enabled this value is different from what Visual Studio tells you when you hover over gio
because of thunking, see /INCREMENTAL.
May contain jump thunks to handle relocation of functions to new addresses.
To figure out the address of your code you can either disable Incremental Linking or
use the DIA SDK:
// initialize DIA SDK, etc.
void (*fp)() = &foo;
printf("foo(): %p\n\n", foo);
HMODULE hModule = GetModuleHandle(NULL);
DWORD rva = (DWORD)((size_t)fp - (size_t)hModule);
IDiaSymbol *pDiaSymbol;
hr = pDiaSession->findSymbolByRVA(rva, SymTagPublicSymbol, &pDiaSymbol);
if(FAILED(hr) || !pDiaSymbol)
return hr;
ULONGLONG targetVA;
hr = pDiaSymbol->get_targetVirtualAddress(&targetVA);
pDiaSymbol->Release();
if(FAILED(hr))
return hr;
if(hr == S_OK)
printf("foo is a thunk, actual address: %p\n\n", (LPVOID)((size_t)hModule + targetVA));
But there might be a simpler way that I'm not aware of.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With