Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows: Get function address in C++

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?

like image 836
Ojs Avatar asked Feb 24 '18 19:02

Ojs


1 Answers

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.

like image 55
Axalo Avatar answered Sep 29 '22 06:09

Axalo