天天看點

《C++反彙編與逆向分析技術揭秘》--認識啟動函數,找到使用者入口

 《C++反彙編與逆向分析》和《程式員的自我修養》都是以VC6的代碼作為例子講解的。這裡是在vs2017下,CRT代碼有些差別,但整體流程上都是初始化環境,設定參數,最後轉到使用者main函數。

class COne
{
public:
    COne()
    {
        printf("COne \r\n");
    }
    ~COne()
    {
        printf("~COne \r\n");
    }
};

COne g_One;

int main()
{
    printf("main函數識别 \r\n");
    return 0;
}      
《C++反彙編與逆向分析技術揭秘》--認識啟動函數,找到使用者入口
《C++反彙編與逆向分析技術揭秘》--認識啟動函數,找到使用者入口
《C++反彙編與逆向分析技術揭秘》--認識啟動函數,找到使用者入口
// The implementation of the common executable entry point code.  There are four
// executable entry points defined by the CRT, one for each of the user-definable
// entry points:
//
//  * mainCRTStartup     => main
//  * wmainCRTStartup    => wmain
//  * WinMainCRTStartup  => WinMain
//  * wWinMainCRTStartup => wWinMain
//
// These functions all behave the same, except for which user-definable main
// function they call and whether they accumulate and pass narrow or wide string
// arguments.  This file contains the common code shared by all four of those
// entry points.
//
// The actual entry points are defined in four .cpp files alongside this .inl
// file.  At most one of these .cpp files will be linked into the resulting
// executable, so we can treat this .inl file as if its contents are only linked
// into the executable once as well.      

View Code

 mainCRTStartup()

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

__scrt_common_main()

// This is the common main implementation to which all of the CRT main functions 在處理任何異常之前,必須初始化/GS cookie
// delegate (for executables; DLLs are handled separately).
static __forceinline int __cdecl __scrt_common_main()
{
    // 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();
}      

__scrt_common_main_seh()

static __declspec(noinline) int __cdecl __scrt_common_main_seh()
{
    if (!__scrt_initialize_crt(__scrt_module_type::exe))//初始化crt 運作庫
        __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)//通路函數指針表并将其初始化的内部方法。第一個指針位于表中的起始位置,第二個指針位于結束位置。      
//_initterm_e  如果初始化失敗并引發錯誤,則傳回一個非零的錯誤代碼;如果未發生錯誤,則傳回 0。
                return 255;

            _initterm(__xc_a, __xc_z);//函數執行時,_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();//tls init
        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();//tls destructor
        if (*tls_dtor_callback != nullptr && __scrt_is_nonwritable_in_current_image(tls_dtor_callback))
        {
            _register_thread_local_exe_atexit_callback(*tls_dtor_callback);
        }

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

        int const main_result = invoke_main();//初始化完成,傳回使用者入口 main

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

        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;
    }
}      

其中C模式來編譯程式的時候  函數指針數組被放到__xi_a和__xi_z 之間   ;使用C++編譯連結程式時,這些函數指針被放到了__xc_a和__xc_z 之間。

《C++反彙編與逆向分析技術揭秘》--認識啟動函數,找到使用者入口
《C++反彙編與逆向分析技術揭秘》--認識啟動函數,找到使用者入口
static int __cdecl pre_c_initialization()
{
    main_policy::set_app_type();

    file_policy::set_fmode();
    file_policy::set_commode();

    if (!__scrt_initialize_onexit_tables(__scrt_module_type::exe))
        __scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);

    #ifdef _M_IX86
    // Clear the x87 exception flags.  Any other floating point initialization
    // should already have taken place before this function is called.
    _asm { fnclex }
    #endif

    #ifdef _RTC
    _RTC_Initialize();
    atexit(_RTC_Terminate);
    #endif

    if (argv_policy::configure_argv() != 0)
        __scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);

    __scrt_initialize_type_info();

    // If the user provided a _matherr handler, register it with the Universal
    // CRT.  Windows OS components cannot set a custom matherr handler (this is
    // a policy decision, to reduce complexity).
    #ifndef _CRT_WINDOWS
    if (__scrt_is_user_matherr_present())
    {
        __setusermatherr(_matherr);
    }
    #endif

    _initialize_invalid_parameter_handler();
    _initialize_denormal_control();

    #ifdef _M_IX86
    _initialize_default_precision();
    #endif

    _configthreadlocale(_get_startup_thread_locale_mode());

    if (_should_initialize_environment())
        environment_policy::initialize_environment();

    __scrt_initialize_winrt();

    if (__scrt_initialize_mta() != 0)
    {
        __scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);
    }

    return 0;
}

static int __cdecl post_pgo_initialization()
{
    // This function calls the __local_stdio_{printf,scanf}_options() functions.
    // These functions are defined in public headers with external linkage and
    // thus may be PGO-instrumented.  We must not call these functions before the
    // PGO instrumentation library is initialized.
    __scrt_initialize_default_local_stdio_options();

    return 0;
}

static void __cdecl pre_cpp_initialization()
{
    // Before we begin C++ initialization, set the unhandled exception
    // filter so that unhandled C++ exceptions result in std::terminate
    // being called:
    __scrt_set_unhandled_exception_filter();

    _set_new_mode(_get_startup_new_mode());
}

// When both the PGO instrumentation library and the CRT are statically linked,
// PGO will initialize itself in XIAB.  We do most pre-C initialization before
// PGO is initialized, but defer some initialization steps to after.  See the
// commentary in post_pgo_initialization for details.
_CRTALLOC(".CRT$XIAA") static _PIFV pre_c_initializer    = pre_c_initialization;
_CRTALLOC(".CRT$XIAC") static _PIFV post_pgo_initializer = post_pgo_initialization;
_CRTALLOC(".CRT$XCAA") static _PVFV pre_cpp_initializer  = pre_cpp_initialization;      

全局對象構造

21: COne g_One;
00957100 55                   push        ebp  
00957101 8B EC                mov         ebp,esp  
00957103 81 EC C0 00 00 00    sub         esp,0C0h  
00957109 53                   push        ebx  
0095710A 56                   push        esi  
0095710B 57                   push        edi  
0095710C 8D BD 40 FF FF FF    lea         edi,[ebp-0C0h]  
00957112 B9 30 00 00 00       mov         ecx,30h  
00957117 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0095711C F3 AB                rep stos    dword ptr es:[edi]  
0095711E B9 41 9E A1 00       mov         ecx,offset g_One (0A19E41h)  
00957123 E8 B6 C0 FF FF       call        COne::COne (09531DEh)  //構造函數
00957128 68 D0 2A 9F 00       push        offset `dynamic atexit destructor for 'g_One'' (09F2AD0h)  
0095712D E8 DD BC FF FF       call        _atexit (0952E0Fh)  //構造對象完畢,調用atexit函數來保證析構函數的調用。
00957132 83 C4 04             add         esp,4  
00957135 5F                   pop         edi  
00957136 5E                   pop         esi  
00957137 5B                   pop         ebx  
00957138 81 C4 C0 00 00 00    add         esp,0C0h  
0095713E 3B EC                cmp         ebp,esp  
00957140 E8 42 BD FF FF       call        __RTC_CheckEsp (0952E87h)  
00957145 8B E5                mov         esp,ebp  
00957147 5D                   pop         ebp  
00957148 C3                   ret        

invoke_main()

static int __cdecl invoke_main()
    {
        return main(__argc, __argv, _get_initial_narrow_environment());
    }      
static int __cdecl invoke_main()
    77:     {
0095AB50 55                   push        ebp  
0095AB51 8B EC                mov         ebp,esp  
    78:         return main(__argc, __argv, _get_initial_narrow_environment());
0095AB53 E8 DE 92 FF FF       call        __get_initial_narrow_environment (0953E36h)  
0095AB58 50                   push        eax  
0095AB59 E8 4F 8A FF FF       call        ___p___argv (09535ADh)  
0095AB5E 8B 00                mov         eax,dword ptr [eax]  
0095AB60 50                   push        eax  
0095AB61 E8 78 77 FF FF       call        ___p___argc (09522DEh)  
0095AB66 8B 08                mov         ecx,dword ptr [eax]  
0095AB68 51                   push        ecx  
0095AB69 E8 A0 88 FF FF       call        _main (095340Eh)  
0095AB6E 83 C4 0C             add         esp,0Ch  
    79:     }
0095AB71 5D                   pop         ebp  
0095AB72 C3                   ret