• 找到程序真正的入口(使用IDE追踪)


    一、程序的真正入口

    main或WinMain只是“语法规定的程序入口” 并不是“应用程序入口”。

    我们使用VC++ 6.0 的栈回溯功能,找到main函数之前的代码。菜单View -> Debug Windows -> Call Stack 打开栈回溯窗口(快捷键 Alt + 7)。 
    1.png

    上图显示程序运行时调用了三个函数,分别为:KERNEL32.DLL、mainCRTStartup和main。 其中KERNEL32! 7C81776F 表示在系统库KERNEL32.dll中的地址7c81776f处调用了mainCRTStartup。 
    通过双击 mainCRTStartup,我们可以找到这个函数定义在 crt0.c 中,你可以在crt0.c中找到mainCRTStartup的源码。

    下面是crt0.c中注释的摘抄:

    /***
    *crt0.c - C runtime initialization routine
    *
    *       Copyright (c) Microsoft Corporation. All rights reserved.
    *
    *Purpose:
    *       This is the actual startup routine for apps.  It calls the user's main
    *       routine [w]main() or [w]WinMain after performing C Run-Time Library
    *       initialization.
    *
    *       With ifdefs, this source file also provides the source code for:
    *       wcrt0.c     the startup routine for console apps with wide chars
    *       wincrt0.c   the startup routine for Windows apps
    *       wwincrt0.c  the startup routine for Windows apps with wide chars
    *
    *******************************************************************************/
    

    这里说明了函数真正的入口

    /***
    *mainCRTStartup(void)
    *wmainCRTStartup(void)
    *WinMainCRTStartup(void)
    *wWinMainCRTStartup(void)
    *
    *Purpose:
    *       These routines do the C runtime initialization, call the appropriate
    *       user entry function, and handle termination cleanup.  For a managed
    *       app, they then return the exit code back to the calling routine, which
    *       is the managed startup code.  For an unmanaged app, they call exit and
    *       never return.
    *
    *       Function:               User entry called:
    *       mainCRTStartup          main
    *       wmainCRTStartup         wmain
    *       WinMainCRTStartup       WinMain
    *       wWinMainCRTStartup      wWinMain
    *
    *Entry:
    *
    *Exit:
    *       Managed app: return value from main() et al, or the exception code if
    *                 execution was terminated by the __except guarding the call
    *                 to main().
    *       Unmanaged app: never return.
    *
    *******************************************************************************/
    

    由于我安装的的VC++6.0不是完整版,未找到crt0.c。然后,我切换到vs2010下,找到了crt0.c,其中有这样一段定义:

    #ifdef _WINMAIN_
    
        #ifdef WPRFLAG
            #define _tmainCRTStartup    wWinMainCRTStartup
        #else  /* WPRFLAG */
            #define _tmainCRTStartup    WinMainCRTStartup
        #endif  /* WPRFLAG */
    
    #else  /* _WINMAIN_ */
    
        #ifdef WPRFLAG
            #define _tmainCRTStartup    wmainCRTStartup
        #else  /* WPRFLAG */
            #define _tmainCRTStartup    mainCRTStartup
        #endif  /* WPRFLAG */
    
    #endif  /* _WINMAIN_ */
    

    当然,如果你装了完整版的VC++6.0 应该与此不同。 不过,这些函数的目的总是为了:申请堆空间、初始化堆空间、获取环境变量、获取CommandLine、全局数据初始化、浮点寄存器初始化等。

    二、修改程序入口

    菜单Project -> Settings -> Link -> Output 在 Entry-point symbol中可以指定程序入口。

    2.png

    重新指定入口后,没有调用 mainCRTStartup 函数,直接就调用了入口函数MyEntry。 如下图: 
    3.png

    但是,由于没有调用mainCRTStartup函数,堆空间是没有初始化的,当使用堆空间时,程序会报错崩溃,如下图:

    4.png


    备注: 从Visual Studio 2003(VC7.0)开始,微软加入了防止缓冲区溢出的选项:/GS,编译器会在每个函数的栈内分配一个随机标记,而这个随机标记的种子数由应用程序入口的代码负责初始化。

    http://my.oschina.net/huangsz/blog/286246

  • 相关阅读:
    [knowledge][perl][pcre][sed] sed / PCRE 语法/正则表达式
    [knowledge][模式匹配] 字符匹配/模式匹配 正则表达式 自动机
    [daily] 内存越界的分析与定位
    [DPI] Cisco Application Visibility and Control
    [bigdata] palantir
    [daily][nfs] nfs客户端设置
    [knowledge][ETA] Encrypted Traffic Analytics
    [tcpreplay] tcpreplay高级用法--使用tcpreplay-edit进行循环动态发包
    [redhat][centos] 让不同小版本的CentOS7使用相同的内核版本
    [grub2] grub2修改启动顺序
  • 原文地址:https://www.cnblogs.com/findumars/p/5208478.html
Copyright © 2020-2023  润新知