Win32程序入口
我們都知道用C/C++語言寫一個程序,首先會寫一個main函數。同樣的在windows平臺寫一個win32應用程序,同樣有一個"main"函數作為入口。win32的main函數如下:
int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow);
The WinMain function is the conventional name for the user-provided entry point for a Microsoft Windows-based application.
參數說明:
#define WINAPI __stdcall#define APIENTRY __stdcall#define APIENTRYWINAPI
WINAPI是個宏也是一種調用約定,也寫做APIENTRY,都是同一種壓棧方式即__stdcall並且是函數內部平衡棧。__stdcall修飾的函數,其參數都是從右向左通過堆棧傳遞,函數調用在返回前要由被調用函數平衡棧。類似的調用約定還有fastcall,cdecl等等。這個不是此次學習記錄的重點。
第一個參數:
HINSTANCE hInstance;
Handle to the current instance of the application.
當前應用的句柄,實際也是當前應用程序在內存(4GB空間)運行時的偏移,即應用程序的ImageBase。這個參數非常重要,就是我們逆向尋找其入口函數的標識。
第二個參數:
HINSTANCE hPrevInstance,
Handle to the previous instance of the application. This parameter is always NULL.
這個參數不是很重要,通常為NULL,但可以用來設計只能運行一個實例的應用程序。即互斥鎖。在後面的學習記錄會寫這個。
第三個參數
LPSTR lpCmdLine;
Pointer to a null-terminated string specifying the command line for the application, excluding the program name. To retrieve the entire command line, use the GetCommandLine function.
命令行參數,即通過命令行嚮應用程序傳參數,並且不傳遞程序名稱。和C語言main函數參數很類似。
int main(int argc,char *argv,char* envp[]);//argc 代表參數個數,第一個為應用程序名稱,第二個才是參數//argv 被傳遞的參數
第四個參數
int nCmdShow;
Specifies how the window is to be shown. This parameter can be one of the following values.
窗口的顯示方式,比如SW_SHOWNORMAL(正常顯示)和SW_HIDE(隱藏)等等,詳見MSDN
在反彙編中定位入口
上面說了很多,下面我們就在OD中尋找入口點。
首先我們用OD打開自己寫的win32應用程序:
OD停到OEP(函數入口點)
然後我們向下滑:
看到了push了四個參數,和我們的WinMain的參數一樣但是不是哪?我們在上文了解到winmain的對一個參數是個句柄,即應用程序的ImageBase。而箭頭所指的函數GetModuleHoduleA就是獲取應用程序或dll的句柄。當傳入參數為NULL時,返回當前應用進程的句柄。
HMODULE WINAPI GetModuleHandle( __in_opt LPCTSTR lpModuleName);
If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
感覺和winmain很相近了,但是還要判斷以下是否有寄存器傳參數。所以我們需要進入函數看看是否使用了有直接調用的寄存器。如果函數領空內直接從寄存器裡取值,並且沒有找到對該寄存器的命令,就可以認為是寄存器傳參數。
進入前
函數領空領空結束處
在函數領空內,並沒有找到直接取寄存器的操作,並且在領空結束處可以看到ret 0x10。所以可以得出只有四個參數。所以call後面的地址就是WinMian函數。
在反彙編中判斷函數是否WinMain的條件:
1.四個參數
2.參數從右向左壓棧,且是函數內部平衡棧
3.第一個參數為該應用程序的句柄,即應用程序的ImageBase