3

我正在尝试以这种方式获取 main() 函数的地址:

int main(int argc, char *argv[])
{
   void *pMainAddress=(void *)&main;
   printf("Address of main() 0x%08X \n", pMainAddress);

当我使用Release配置构建项目时,结果是:
main() 地址:0x00401000

这是在调试器下:

00401000  /$  68 00104000  PUSH GetMain.00401000    ;  Entry address
00401005  |.  68 50A14000  PUSH GetMain.0040A150    ;  ASCII "0x%p \n"
0040100A  |.  E8 8B000000  CALL GetMain.0040109A

但是当使用/Zi选项编译或使用Debug构建时,地址被重定向:
地址 main() : 0x0041178A。这个地址是通过无条件跳转获得的,实际地址是0x00412530

这是在调试器下:

00412530  /> \55                      PUSH EBP
...
00412539  |.  C745 FC 8A174100        MOV [LOCAL.1],GetMain.0041178A  ;  Entry address
00412540  |.  8B45 FC                 MOV EAX,[LOCAL.1]
00412543  |.  50                      PUSH EAX                                                         
00412544  |.  68 5CEC4200             PUSH GetMain.0042EC5C           ;  ASCII "0x%p \n"

为什么会这样?如果代码是在 Debug build 中编译的,
如何获取 main() 函数的真实地址(在上面的例子中)?0x00412530

编辑:
为什么会这样?已经在这里回答了:奇怪的函数调用间接级别

下面的函数解决了我的第二个问题,这里我写了 answer 。

void *GetMainAddress(void)
{
    void *pMainAddress=(void*)&main;/* address in main() function */
    unsigned long calculateJump=0;
    unsigned char *ptrJump;   
    printf("Address of main() : 0x%08X\n",  pMainAddress);


    ptrJump=(unsigned char*)pMainAddress;/* get pointer to main address */
    if(*(unsigned char*)ptrJump == 0xE9)/* address point to jmp opcode ? */
    {
        calculateJump = ( *(unsigned long *)(ptrJump+1) ); /* get address after 0xe9 */
        pMainAddress =  ptrJump + calculateJump + 5; /* calculate real address */
        printf("Unconditional jump is performed\n");
        printf("Actual sddress of main() is: 0x%08X \n", pMainAddress);
    }
    else
    {
        printf("Unconditional jump is not performed\n");
    }
    return   pMainAddress;
}  
4

2 回答 2

3

如果您需要获取函数地址,只需省略括号即可。

例如:

int main(){
    printf("main is at %p\n", main);
    return 0;
}
于 2013-07-10T23:36:21.933 回答
1

这是在Visual Studio的项目配置中设置Debug Information Format时如何获取main()函数实际地址的解决方案。 这是我的功能: /ZI

void *GetMainAddress(void)
{
    void* pMainAddress = (void*)&main;
    unsigned long calculateJump = 0;
    unsigned char* ptrJump;

    ptrJump = (unsigned char*)pMainAddress;
    if(*(unsigned char*)ptrJump == 0xE9)
    {
        calculateJump = (*(unsigned long*)(ptrJump + 1));
        pMainAddress = (ptrJump + calculateJump + 5);
        printf("Unconditional jump is performed\n");
        printf("Address of main() : %#x \n", pMainAddress);
    }
    else
    {
        printf("Unconditional jump is not performed\n");
        printf("Address of main() : %#x \n", pMainAddress);     
    }
    return   pMainAddress;
}

要进行测试,请使用 Visual Studio 创建控制台应用程序Debug,然后Release从解决方案配置中进行选择。
将其GetAddressOfMain()放入您的int main(), 并构建解决方案。

函数也适用于 64 位项目配置,但您需要使用适当的格式说明符才能正确打印地址。

于 2013-08-07T01:25:43.527 回答