[逆向]尋找PE文件的main與winmain


0x01 定義

main是C/C++的標准入口函數名,程序執行總是從main函數開始,如果有有其他函數,則完成對其他函數的調用后再返回到主函數,最后由main函數結束整個程序,其他函數是不能調用main函數的。在執行程序時,由系統先行調用main函數。

WinMain是windows API窗體程序的入口函數,該函數的功能是被系統調用,作為一個32位應用程序的入口點。WinMain函數應初始化應用程序,顯示主窗口,進入一個消息接收一發送循環,這個循環是應用程序執行的其余部分的頂級控制結構。

0x02 區別

二者在同一環境下的不同區別:

Windows支持兩種類型的應用程序:

一種是基於控制台用戶界面的應用程序(Console User Interface,簡稱CUI),
另一種是基於圖形用戶界面的程序(Graphic User Interface,簡稱GUI)。

0x03 函數詳解

3.1 main函數

在 Microsoft C 中,程序啟動時調用的函數稱為 main。 沒有針對 main 聲明的原型,可以用零個、兩個或三個參數對其進行定義:

int main( void )
int main( int argc, char *argv[] )
int main( int argc, char *argv[], char *envp[] )

其中三個參數的解釋如下:

argc 表示有多少個命令行參數,第一個就是執行程序名,所以argc最少為1。 
argv 是具體程序運行的地址與相搭配的參數。 
envp 是系統的環境變量,很少有介紹的。“名稱=值”的形式,以NULL結束。

3.2 winmain函數

WinMain是用於應用程序入口點的常規名稱,他的句法如下:

int __clrcall WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR     lpCmdLine,
  int       nShowCmd
);

其中四個參數的解釋如下:

hInstance        類型:HINSTANCE,應用程序當前實例的句柄,也就是他所處的基地址。
hPrevInstance    類型:HINSTANCE,應用程序先前實例的句柄。此參數始終為NULL。
lpCmdLine        類型:LPSTR,應用程序的命令行,不包括程序名稱。
nShowCmd         待定

0x04 實驗查找

這里用兩個程序分別進行查詢main函數與winmain函數:

  1. Fport.exe --> main函數

  2. 360zipInst.exe --> winmain函數

單獨用IDA與OD進行查找:不過還是IDA方便理解一些

4.1 IDA查找main函數

ida打開之后,直接找到start:

反匯編查看偽代碼:這里可以看到它是以v7返回值退出的,着重看v7,大部分程序都是以主函數退出:

這里的sub_407D10函數其實就是main函數:

v7 = sub_407D10(dword_41BFC8, dword_41BFCC);

雙擊步入函數,里面存在相應的命令行顯示字符串:

整個的函數邏輯也會存在其中,我們再拿OD調試一下

4.2 OD查找main函數

F8單步運行到這里,觀察OD的棧面板窗口,程序運行到 main 函數時,經常會伴隨着棧的活動:

這三個數值,其實就是上面所介紹到的main函數的3個參數,來一一對應一下:

Arg1 對應的就是 argc ,表示有多少個命令行參數,第一個就是執行程序名,所以argc最少為1 這里的數值也是 = 00000001

選中 Arg2 ,追蹤一下數據:

可以看到數據面板窗口其中就存在着一個物理地址,而這個地址正好對應了 main函數中的 argv ,由於我們運行時,沒有搭配任何參數,所以參數為空。

同樣的方法,再來看一下Arg3,這里對應的就是相應的系統環境了:

三個參數的數值都可以對應上main函數的參數,那么這里的 Fport.00407D10 也就是整個程序的主入口了

為了進一步證明,F2下個斷點,F9運行到斷點處,F7進到函數里面:

相應的命令行字符串直接在旁邊顯示了出來,找對地方了!

4.3 IDA查找winmain函數

這里的操作與上面打開IDA的操作是類似的,直接找到start,進入其中,開啟反匯編,查看偽代碼:

這里同樣是着重看一下,程序是以哪個變量退出的:

很輕松就可以看到這里的變量是v5,后面緊跟着的就是winmain函數,進到函數里面看一下是不是主函數:

很明顯,這里的參數值,就是我們先前介紹的 winmain 的句法參數!

4.4 OD查找winmain函數

這里與上面查找main函數的方法亦是同理,F8單步運行到這里,觀察OD的棧面板窗口,程序運行到 main 函數時,經常會伴隨着棧的活動:

可以看到,在臨近exit時,上面出現了四個參數,其實這里的 Arg1 是上面所介紹的 hInstance ,應用程序當前實例的句柄,也就是他所處的基地址,在OD里面可以用 ALT+E 查看程序的基地址:

這里的基地址正好 = 00400000

再來看 Arg2 = 0 ,也對應了上面介紹的始終為 NULL 的 hPrevInstance

同理追蹤 Arg3 :

找到第三個參數:lpCmdLine 應用程序的命令行格式:

第四個參數無實意,為了證明此函數為 winmain函數,同樣的方法進到函數里面,查看其內容:

成功進入到程序主函數內!

0x05 參考鏈接

https://www.cnblogs.com/shucome/p/7572142.html
https://blog.csdn.net/m0_37925202/article/details/78944329
https://docs.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-winmain
https://docs.microsoft.com/zh-cn/cpp/c-language/arguments-to-main?view=vs-2019


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM