1. 程式人生 > >【收集】啟動函數

【收集】啟動函數

源碼 ffffff 編寫 IT 變量初始化 size 一個 ble star

在編寫Win32應用程序時,都必須在源碼裏實現一個WinMain函數。但Windows程序執行並不是從WinMain函數開始的,首先被執行的是啟動函數相關代碼,這段代碼是編譯器生成的。啟動代碼完成初始化進程,再調用WinMain函數。

對於Visual C++程序來說,它調用的是C/C++運行時啟動函數,該函數負責對C/C++運行庫進行初始化。Visual C++配有C運行庫的源代碼,可以在crtsrccrt0.c文件中找到啟動函數的源代碼(安裝時Visual C++必須選取安裝源代碼選項);而用於控制臺程序的啟動代碼存放在crtsrcwincmdln.c文件中。

所有的C/C++運行時啟動函數的作用基本都是相同的:檢索指向新進程的命令行指針,檢索指向新進程的環境變量指針,全局變量初始化,內存堆棧初始化等。當所有的初始化操作完畢後,啟動函數就調用應用程序的進入點函數。調用WinMain函數如下所示:

1 2 3 <span style="font-size: 13.86px;">GetStartupInfo (&StartupInfo); Int nMainRetVal = WinMain(GetModuleHandle(NULL),NULL,pszCommandLineAnsi,(StartupInfo.dwFlags&STARTF_USESHOWWINDOW)?StartupInfo.wShowWindow:SW__SHOWDEFAULT); </span>

當進入點返回時,啟動函數便調用C運行庫的exit函數,將返回值(nMainRetVal)傳遞給它,進行一些必要處理,最後調用系統函數ExitProcess退出。 下面是一個Visual C++編譯的程序,程序啟動代碼的匯編代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <span style="font-size: 13.86px;">00401180 push ebp 00401181 mov ebp, esp 00401183 push FFFFFFFF 00401185 push 004040D0 0040118A push 00401CB4 0040118F mov eax, dword ptr fs:[00000000] 00401195 push eax 00401196 mov dword ptr fs:[00000000], esp 0040119D sub esp, 00000058 004011A0 push ebx 004011A1 push esi 004011A2
push edi 004011A3 mov dword ptr [ebp-18], esp 004011A6 Call KERNEL32.GetVersion ; 確定Windows系統版本 …… 004011F4 Call KERNEL32.GetCommandLineA ; 指向進程的完整命令行的指針 …… 0040121E push eax 0040121F Call KERNEL32.GetStartupInfoA ; 獲取一個進程的啟動信息 …… 00401241 push esi 00401242 Call KERNEL32.GetModuleHandleA ; 返回進程地址空間執行文件基地址 00401248 push eax 00401249 call 00401000 ; 調用用戶編寫的進入點函數WinMain ; 分析程序時,直接跳到401000即可 0040124E mov dword ptr [ebp-60], eax 00401251 push eax 00401252 call 004012EC ; 退出程序 …… 0040126A ret </span>

【收集】啟動函數