《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;
}
// 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.
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 之间。
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
《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口的更多相关文章
- C++反汇编与逆向分析技术揭秘
C++反汇编-继承和多重继承 学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的 ...
- 《C++反汇编与逆向分析技术揭秘》--算术运算和赋值
一.加法 1.Debug下: 14: int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果 00C0550E C7 45 F8 F4 FF FF FF mov dword ...
- 《C++反汇编与逆向分析技术揭秘》——观察各种表达式的求值过程
---恢复内容开始--- 加法: 示例: 常量相加,则在编译期间就计算出两个常量相加后的结果,直接将这个结果参与运算,减少了运行期的计算.当有变量参与运算时,会先取出内存中的数据,放入通用寄存器中,再 ...
- 《C++反汇编与逆向分析技术揭秘》——基本数据类型的表现形式
---恢复内容开始--- 基本的浮点数指令 示例代码: Visual Studio 2013的反汇编代码是: 对于movss,表示移动标量单精度浮点值 将标量单精度浮点值从源操作数(第二个操作数)移到 ...
- 《C++反汇编与逆向分析技术揭秘》之十——构造函数
对象生成时会自动调用构造函数.只要找到了定义对象的地方,就找到了构造函数调用的时机.不同作用域的对象的生命周期不同,如局部对象.全局对象.静态对象等的生命周期各不相同,只要知道了对象的生命周期,便可以 ...
- 《C++反汇编与逆向分析技术揭秘》——函数的工作原理
各种调用方式的考察 示例: cdecl方式是调用者清空堆栈: 如果执行的是fastcall: 借助两个寄存器传递参数: 参数1和2借助局部变量来存储: 返回值 如果返回值是结构体: 返回值存放在eax ...
- 《C++反汇编与逆向分析技术揭秘》——流程控制语句的识别
if...else...语句 示例: if构成多分支语句 switch 有序线性的switch: 3E82D8位置存放了一个表,标明了要跳转到的地址: 这里的每四字节都标明的是每个case块的首地址: ...
- 《C++反汇编与逆向分析技术揭秘》之12——继承
识别类和类之间的关系 在父类中声明为私有的成员,虽然子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然存在. 在没有提供构造函数的时候,系统会尝试提供默认的构造函数: 当子类中没 ...
- 《C++反汇编与逆向分析技术揭秘》之11——虚函数
虚函数的机制 当类中定义有虚函数时,编译器会将该类中所有虚函数的首地址保存在一张地址表中,这张表被称为虚函数地址表.编译器还会在类中添加一个虚表指针. 举例: CVirtual类的构造函数中没有进行任 ...
随机推荐
- 云原生系列3 pod核心字段
pod是容器化的基础,好比大楼的地基. Pod跟容器的关系 类比一下: POD: 物理机容器: 物理机上的一个进程: 容器只是Pod的一个普通字段. Pod的作用范围 跟容器的linux namesp ...
- URLSearchParams & Location & URL params parse
URLSearchParams & Location & URL params parse URL params parse node.js env bug node.js & ...
- Node.js & process.env & OS Platform checker
Node.js & process.env & OS Platform checker Window 10 Windows 7 ia32 CentOS $ node # process ...
- webpack loader & pulgin
webpack loader & plugin https://webpack.js.org/concepts/loaders/ https://webpack.js.org/concepts ...
- overwrite & override
overwrite & override explanation https://stackoverflow.com/questions/8651562/overwrite-or-overri ...
- Baccarat凭什么能成为DeFi后时代火爆新趋势?
在各币种经历涨涨跌跌以后,DeFi后时代已然来临.那么,当前DeFi市场中哪个项目更被市场生态建设者看好呢?毫无疑问,Baccarat会成为最被看好的DeFi项目. Baccarat采用了独特的共识算 ...
- (转载)VoLTE简介
转载地址:http://www.360doc.cn/article/2909773_637471256.html,本文介绍了移动通信领域相关概念,如CS.PS.VoIP.VoLTE.IMS.CSFB. ...
- css故障文字动画
免费分享95套java实战项目,不仅有源码还有对应的开发视频,关注公众号『勾玉技术』回复"95"即可获取 首先给内容上hover和before, .glitch:hover:bef ...
- linux调度全景指南
- LiteOS:SpinLock自旋锁及LockDep死锁检测
摘要:除了多核的自旋锁机制,本文会介绍下LiteOS 5.0引入的LockDep死锁检测特性. 2020年12月发布的LiteOS 5.0推出了全新的内核,支持SMP多核调度功能.想学习SMP多核调度 ...