浅析 main 之前代码 (VS2015)

4 篇文章 0 订阅

        用VS2015 如何追踪 main之前代码尼?

#include <stdlib.h>
#include <stdio.h>

void main()
{
	printf("%d\n", 1);
}


在printf处设置断点,反汇编代码,在ret 设置断点,f5, 再f10单步。便能跳到 编译器插入的代码。

 printf("%d\n", 1);
00CE1070  push        1 
00CE1072  push        0CE2118h 
00CE1077  call        printf (0CE1040h) 
00CE107C  add         esp,8 
}
00CE107F  xor         eax,eax 
00CE1081  ret                                //该处设置断点,f5 再单步 f10

f10后,将调到下面代码部分,右击,点击转到源码处。
00CE14A3  call        ___p___argv (0CE1C30h) 
00CE14A8  mov         edi,eax 
00CE14AA  call        ___p___argc (0CE1C2Ah) 
00CE14AF  mov         esi,eax 
00CE14B1  call        __get_initial_narrow_environment (0CE1C06h) 
00CE14B6  push        eax 
00CE14B7  push        dword ptr [edi] 
00CE14B9  push        dword ptr [esi] 
00CE14BB  call        main (0CE1070h) 
00CE14C0  mov         esi,eax            
        //
        // main has returned; exit somehow...
        //

原型毕露
//exe_common.inl
static __declspec(noinline) int __cdecl __scrt_common_main_seh() throw()
{
    if (!__scrt_initialize_crt(__scrt_module_type::exe))
        __scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);

    bool has_cctor = false;
    __try
    {
        bool const is_nested = __scrt_acquire_startup_lock();

        if (__scrt_current_native_startup_state == __scrt_native_startup_state::initializing)
        {
            __scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);
        }
        else if (__scrt_current_native_startup_state == __scrt_native_startup_state::uninitialized)
        {
            __scrt_current_native_startup_state = __scrt_native_startup_state::initializing;

            if (_initterm_e(__xi_a, __xi_z) != 0)
                return 255;

            _initterm(__xc_a, __xc_z);

            __scrt_current_native_startup_state = __scrt_native_startup_state::initialized;
        }
        else
        {
            has_cctor = true;
        }

        __scrt_release_startup_lock(is_nested);

        // If this module has any dynamically initialized __declspec(thread)
        // variables, then we invoke their initialization for the primary thread
        // used to start the process:
        _tls_callback_type const* const tls_init_callback = __scrt_get_dyn_tls_init_callback();
        if (*tls_init_callback != nullptr && __scrt_is_nonwritable_in_current_image(tls_init_callback))
        {
            (*tls_init_callback)(nullptr, DLL_THREAD_ATTACH, nullptr);
        }

        // If this module has any thread-local destructors, register the
        // callback function with the Unified CRT to run on exit.
        _tls_callback_type const * const tls_dtor_callback = __scrt_get_dyn_tls_dtor_callback();
        if (*tls_dtor_callback != nullptr && __scrt_is_nonwritable_in_current_image(tls_dtor_callback))
        {
            _register_thread_local_exe_atexit_callback(*tls_dtor_callback);
        }

        __telemetry_main_invoke_trigger(nullptr);

        //
        // Initialization is complete; invoke main...
        //

        int const main_result = invoke_main();

        //
        // main has returned; exit somehow...
        //

        __telemetry_main_return_trigger(nullptr);

        if (!__scrt_is_managed_app())
            exit(main_result);

        if (!has_cctor)
            _cexit();

        // Finally, we terminate the CRT:
        __scrt_uninitialize_crt(true, false);
        return main_result;
    }
    __except (_seh_filter_exe(GetExceptionCode(), GetExceptionInformation()))
    {
        // Note:  We should never reach this except clause.
        int const main_result = GetExceptionCode();

        if (!__scrt_is_managed_app())
            _exit(main_result);

        if (!has_cctor)
            _c_exit();

        return main_result;
    }
}

再用 od跟踪,谁调用 __scrt_common_main_seh,

发现 是一个 jmp __scrt_common_main_seh的指令,而且刚好位于,__scrt_common_main_seh下面

vs反汇编窗口向下滚动,发现这两条语句,刚好和od吻合。

00CE153D  call        __security_init_cookie (0CE1A53h) 
00CE1542  jmp         __scrt_common_main_seh (0CE13C1h) 

右击,转到源码处

// exe_main_cpp

extern "C" int mainCRTStartup()
{
    return __scrt_common_main();
}

//exe_common.inl

// This is the common main implementation to which all of the CRT main functions
// delegate (for executables; DLLs are handled separately).
static __forceinline int __cdecl __scrt_common_main() throw()
{
    // The /GS security cookie must be initialized before any exception handling
    // targeting the current image is registered.  No function using exception
    // handling can be called in the current image until after this call:
    __security_init_cookie();

    return __scrt_common_main_seh();
}

ok ,这是 vs2015的源码。我们来一步一步来剖解

mainCRTStartup -> __scrt_common_main -> _scrt_common_main_seh

ok,先看 __sexurity_init_cookie(); // gc_support.c

/***
*gs_support.c - initialize the global buffer overrun security cookie
*
*       Copyright (c) Microsoft Corporation.  All rights reserved.
*
*Purpose:
*       Define __security_init_cookie, which is called at startup to initialize
*       the global buffer overrun security cookie used by the /GS compile flag.
*
*******************************************************************************/

#include <windows.h>

#if defined (_M_IX86) && defined (_CRTBLD) && defined (_DEBUG)
/*
 * __security_init_cookie must be called before any exception handlers using
 * the cookie are registered.  We do a spot check for this condition in the
 * debug version of the x86 CRT.
 */

#define CHECK_FOR_LATE_COOKIE_INIT

#define EXCEPTION_CHAIN_END ((struct _EXCEPTION_REGISTRATION_RECORD * POINTER_32)-1)

EXCEPTION_DISPOSITION __cdecl
_except_handler4(
    IN struct _EXCEPTION_RECORD *ExceptionRecord,
    IN PVOID EstablisherFrame,
    IN OUT struct _CONTEXT *ContextRecord,
    IN OUT PVOID DispatcherContext
    );

#endif  /* defined (_M_IX86) && defined (_CRTBLD) && defined (_DEBUG) */

/*
 * Default value used for the global /GS security cookie, defined here and
 * in gs_cookie.c (since standalone SDK build can't use CRT's internal.h).
 */

#ifdef _WIN64
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232
#else  /* _WIN64 */
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
#endif  /* _WIN64 */

/*
 * The global security cookie.  This name is known to the compiler.
 */
extern UINT_PTR __security_cookie;
extern UINT_PTR __security_cookie_complement;

/*
 * Union to facilitate converting from FILETIME to unsigned __int64
 */
typedef union {
    unsigned __int64 ft_scalar;
    FILETIME ft_struct;
} FT;

/***
*__security_init_cookie(cookie) - init buffer overrun security cookie.
*
*Purpose:
*       Initialize the global buffer overrun security cookie which is used by
*       the /GS compile switch to detect overwrites to local array variables
*       the potentially corrupt the return address.  This routine is called
*       at EXE/DLL startup.
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/

void __cdecl __security_init_cookie(void)
{
    UINT_PTR cookie;
    FT systime={0};
    LARGE_INTEGER perfctr;

    /*
     * Do nothing if the global cookie has already been initialized.  On x86,
     * reinitialize the cookie if it has been previously initialized to a
     * value with the high word 0x0000.  Some versions of Windows will init
     * the cookie in the loader, but using an older mechanism which forced the
     * high word to zero.
     */
     // __security_cooki = 0cc960ca 非调试版本
    if (__security_cookie != DEFAULT_SECURITY_COOKIE
#if defined (_M_IX86)
        && (__security_cookie & 0xFFFF0000) != 0
#endif  /* defined (_M_IX86) */
       )
    {
        __security_cookie_complement = ~__security_cookie;
        return;   //release  版本直接返回。
    }


    /*
     * Initialize the global cookie with an unpredictable value which is
     * different for each module in a process.  Combine a number of sources
     * of randomness.
     */

    GetSystemTimeAsFileTime(&systime.ft_struct);
#if defined (_WIN64)
    cookie = systime.ft_scalar;
#else  /* defined (_WIN64) */
    cookie = systime.ft_struct.dwLowDateTime;
    cookie ^= systime.ft_struct.dwHighDateTime;
#endif  /* defined (_WIN64) */

    cookie ^= GetCurrentThreadId();
    cookie ^= GetCurrentProcessId();

#if _CRT_NTDDI_MIN >= NTDDI_VISTA 
#if defined (_WIN64)
    cookie ^= (((UINT_PTR)GetTickCount64()) << 56);
#endif  /* defined (_WIN64) */
    cookie ^= (UINT_PTR)GetTickCount64();
#endif  /* _CRT_NTDDI_MIN >= NTDDI_VISTA  */

    QueryPerformanceCounter(&perfctr);
#if defined (_WIN64)
    cookie ^= (((UINT_PTR)perfctr.LowPart << 32) ^ perfctr.QuadPart);
#else  /* defined (_WIN64) */
    cookie ^= perfctr.LowPart;
    cookie ^= perfctr.HighPart;
#endif  /* defined (_WIN64) */

    /*
     * Increase entropy using ASLR relocation
     */
    cookie ^= (UINT_PTR)&cookie;

#if defined (_WIN64)
    /*
     * On Win64, generate a cookie with the most significant word set to zero,
     * as a defense against buffer overruns involving null-terminated strings.
     * Don't do so on Win32, as it's more important to keep 32 bits of cookie.
     */
    cookie &= 0x0000FFFFffffFFFFi64;
#endif  /* defined (_WIN64) */

    /*
     * Make sure the cookie is initialized to a value that will prevent us from
     * reinitializing it if this routine is ever called twice.
     */

    if (cookie == DEFAULT_SECURITY_COOKIE)
    {
        cookie = DEFAULT_SECURITY_COOKIE + 1;
    }
#if defined (_M_IX86)
    else if ((cookie & 0xFFFF0000) == 0)
    {
        cookie |= ( (cookie|0x4711) << 16);
    }
#endif  /* defined (_M_IX86) */

    __security_cookie = cookie;
    __security_cookie_complement = ~cookie;

}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值