VS下EXE可执行文件启动代码剖析(5)使用动态运行库的EXE
来源:互联网 发布:电子取证软件 编辑:程序博客网 时间:2024/05/22 05:24
前面看到在使用静态运行库的EXE的启动代码做了很多的工作,下面再来看看使用动态库的EXE的启动代码
使用/mtd选项生产一个EXE,在我们的main函数开头下断,查看调用堆栈可以看到程序在被系统加载完成之后,我们程序的入口由Crtexe.c文件中的__tmainCRTStartup开始
下面是代码
staticint__tmainCRTStartup( void );#ifdef _WINMAIN_#ifdef WPRFLAGint wWinMainCRTStartup(#else /* WPRFLAG */int WinMainCRTStartup(#endif /* WPRFLAG */#else /* _WINMAIN_ */#ifdef WPRFLAGint wmainCRTStartup(#else /* WPRFLAG */int mainCRTStartup(#endif /* WPRFLAG */#endif /* _WINMAIN_ */ void ){ __security_init_cookie(); return __tmainCRTStartup();}跟使用静态运行库时一样的 同样先是创建了一个cookier然后 四种情况下调用的是同一个函数__tmainCRTStartup
直接上代码 在代码中注释,相比使用静态库,使用动态库的启动代码只完成了很有限的工作。
__declspec(noinline)int__tmainCRTStartup( void ){#ifdef _WINMAIN_ _TUCHAR *lpszCommandLine; STARTUPINFOW StartupInfo; BOOL inDoubleQuote=FALSE; GetStartupInfoW( &StartupInfo );#endif /* _WINMAIN_ */#ifdef _M_IX86 /* * Enable app termination when heap corruption is detected on * Windows Vista and above. This is a no-op on down-level OS's * and enabled by default for 64-bit processes. */ //在XPSP3 VISTA 及之后的版本中增加了一个Heap管理特性,当Heap管理器发现进程中有任何使用中的Heap出现错误的时候,系统终止进程 if (!_NoHeapEnableTerminationOnCorruption) //如果该全局标准为0表示 需要开启该特性 { HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); //设置开启 }#endif /* _M_IX86 */ /* __try // { void *lock_free=0; void *fiberid=((PNT_TIB)NtCurrentTeb())->StackBase; 获取栈基址 int nested=FALSE; while((lock_free=InterlockedCompareExchangePointer((volatile PVOID *)&__native_startup_lock, fiberid, 0))!=0) { //如果__native_startup_lock为0 把fiberid的值给它 if(lock_free==fiberid) { nested=TRUE; break; } Sleep(1000); } if (__native_startup_state == __initializing) //在混合模式的情况下如果其他本地地方在初始化本地代码,那么出错,不能同时初始化 { _amsg_exit( _RT_CRT_INIT_CONFLICT); } else if (__native_startup_state == __uninitialized) { __native_startup_state = __initializing;#ifndef _SYSCRT if (_initterm_e( __xi_a, __xi_z ) != 0) { return 255; //初始化C全局对象 }#else /* _SYSCRT */ _initterm((_PVFV *)(void *)__xi_a, (_PVFV *)(void *)__xi_z); #endif /* _SYSCRT */ } else { has_cctor = 1; } /* * do C++ constructors (initializers) specific to this EXE */ if (__native_startup_state == __initializing) { _initterm( __xc_a, __xc_z ); //初始化C++全局对象 __native_startup_state = __initialized; } _ASSERTE(__native_startup_state == __initialized); if(!nested) { /* For X86, the definition of InterlockedExchangePointer wrongly causes warning C4312 */#pragma warning(push)#pragma warning(disable:4312) InterlockedExchangePointer((volatile PVOID *)&__native_startup_lock, 0);#pragma warning(pop) } */ if (__dyn_tls_init_callback != NULL && _IsNonwritableInCurrentImage((PBYTE)&__dyn_tls_init_callback)) { __dyn_tls_init_callback(NULL, DLL_THREAD_ATTACH, NULL); //初始化TLS相关的 } /* Enable buffer count checking if linking against static lib */ _CrtSetCheckCount(TRUE);#ifdef _WINMAIN_ /* * Skip past program name (first token in command line). * Check for and handle quoted program name. */#ifdef WPRFLAG lpszCommandLine = (wchar_t *)_wcmdln;#else /* WPRFLAG */ lpszCommandLine = (unsigned char *)_acmdln;#endif /* WPRFLAG */ while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine&&inDoubleQuote)) { /* * Flip the count from 1 to 0 or 0 to 1 if current character * is DOUBLEQUOTE */ if (*lpszCommandLine==DQUOTECHAR) inDoubleQuote=!inDoubleQuote;#ifdef _MBCS if (_ismbblead(*lpszCommandLine)) { if (lpszCommandLine) { lpszCommandLine++; } }#endif /* _MBCS */ ++lpszCommandLine; } /* * Skip past any white space preceeding the second token. */ while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) { lpszCommandLine++; } //去掉命令行参数中程序自身路径的部分#ifdef WPRFLAG mainret = wWinMain(#else /* WPRFLAG */ mainret = WinMain(#endif /* WPRFLAG */ (HINSTANCE)&__ImageBase, NULL, lpszCommandLine, StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? StartupInfo.wShowWindow : SW_SHOWDEFAULT //调用我们的main函数 );#else /* _WINMAIN_ */#ifdef WPRFLAG __winitenv = envp; mainret = wmain(argc, argv, envp);#else /* WPRFLAG */ __initenv = envp; mainret = main(argc, argv, envp);#endif /* WPRFLAG */#endif /* _WINMAIN_ */ /* * Note that if the exe is managed app, we don't really need to * call exit or _c_exit. .cctor should be able to take care of * this. */ if ( !managedapp ) exit(mainret); if (has_cctor == 0) _cexit(); //退出代码, } __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) ) { /* //发生异常调用退出函数 终止进程 * Should never reach here */ mainret = GetExceptionCode(); /* * Note that if the exe is managed app, we don't really need to * call exit or _c_exit. .cctor should be able to take care of * this. */ if ( !managedapp ) _exit(mainret); if (has_cctor == 0) _cexit(); } /* end of try - except */ return mainret;}
使用动态库的EXE的启动代码 除了 初始化全局对象外,并没有做其他实质性的初始化工作,然后就调用了main函数 将执行权限交给了我们
因此可以推断对CRT的初始化工作,运行库的DLL文件中,当Msvcrtxx.DLL被加载到后,DLL的启动代码完成了之前我们分析的,使用静态库的exe的启动代码所做的工作。
于是我在VC\crt\src 下搜索包含_ioinit的文件,发现crtlib.c文件中的_CRTDLL_INIT 函数调用了这个初始化io的函数
__CRTDLL_INIT 开始地方下断 果然在这里
代码
BOOL WINAPI_CRTDLL_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ){ if (dwReason == DLL_PROCESS_ATTACH) { /* * The /GS security cookie must be initialized before any exception * handling targetting the current image is registered. No function * using exception handling can be called in the current image until * after __security_init_cookie has been called. */ __security_init_cookie(); } return __CRTDLL_INIT(hDllHandle, dwReason, lpreserved);
很明显就是这个运行库DLL的启动代码了 跟EXE的如出一辙
__declspec(noinline)BOOL __cdecl__CRTDLL_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ){ if ( dwReason == DLL_PROCESS_ATTACH ) { if ( !_heap_init() ) /* initialize heap */ //分配堆 return FALSE; if(!_mtinit()) /* initialize multi-thread */ 多线程支持 { _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } if (_ioinit() < 0) { /* inherit file info */ 初始IO _mtterm(); _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } _aenvptr = (char *)__crtGetEnvironmentStringsA(); 获取环境变量 _acmdln = GetCommandLineA(); _wcmdln = GetCommandLineW();#ifdef _MBCS __initmbctable();#endif /* _MBCS */ if (_setenvp() < 0 || /* get environ info */ _cinit(FALSE) != 0) /* do C data initialize */ { _ioterm(); /* shut down lowio */ _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } proc_attached++; } else if ( dwReason == DLL_PROCESS_DETACH ) { .................................. 清理工作省略 } else if ( dwReason == DLL_THREAD_ATTACH ) {...........................................清理工作省略 } return TRUE;}
一切都是那么的熟悉有木有,所有的初始化工作这个DLL都给做了,EXE安心的调用它提供的库函数就OK了
0 0
- VS下EXE可执行文件启动代码剖析(5)使用动态运行库的EXE
- VS下EXE可执行文件启动代码剖析
- VS下EXE可执行文件启动代码剖析(2)_mtinit函数
- VS下EXE可执行文件启动代码剖析(3)_ioinit 函数
- VS下EXE可执行文件启动代码剖析(4)_cinit 函数
- 编写Android的exe可执行文件并运行
- 如何在MFC中启动其它的(.exe)可执行文件
- C++启动可执行文件(.exe)的方法CreateProcess
- windows下C++调用shell启动和关闭可执行文件exe的最简单方法
- Qt设置可执行文件(exe)的详细信息
- 运行vs编译出的exe文件
- 使用pyinstaller 生成exe可执行文件
- CreateProcess的用法---用于启动一个应用程序(exe可执行文件)
- VS如何调试后台.exe的代码
- VS2008中MFC的单独exe运行出错,但是从VS环境下打开运行没问题
- VS下运行和直接双击exe运行结果不同的解决方法
- Windows下使用运行快速打开exe的小技巧
- VS2010静态编译生成.exe可执行文件,使c++程序脱离VS环境运行
- 流程和应用结合、权限控制
- 查看ubuntu系统的版本和系统位数
- 2017年Python 学习中
- 01背包问题(当有的背包重量是非整数时)的递归(优化成动态规划+再用滚动数组优化)解法
- Restful风格API接口开发springMVC篇
- VS下EXE可执行文件启动代码剖析(5)使用动态运行库的EXE
- 教你使用免费的BMFont工具和Photoshop来制作纹理贴图和fnt文件
- MAC安装Securecrt破解
- 关于java中Exception的一些理解
- 华为经典C语言面试题(二)
- UIAlertController浅见
- 80. Remove Duplicates from Sorted Array II
- Linux学习
- linux文件传输rz