基礎介紹
我們在進行Windows編程的時候,經常會調用Windows API。在 Windows 程序中,調用 Windows 函數與調用 C 語言的庫函數沒有什麼兩樣。
最主要的區別就是 C 語言庫函數的機器代碼會直接鏈接到你的程序代碼中去,而 Windows 函數則是放到你的程序之外的 DLL 裏。
每個 Windows 的 EXE 文件包含它所要用到的各個動態鏈接庫以及庫中的函數的引用地址。
當一個 Windows 程序被裝入內存後,程序中的函數調用都被解析 DLL 函數入口的指針,同時這些被調用的函數也被裝入內存。
當鏈接 Windows 程序以生存可執行文件時,一定得鏈接你的編程環境所提供的特殊的“導入庫”。
用戶態和內核態
我們知道Win32API的調用,都是從用戶態到內核態的,也就是函數真正的實現在內核。
這裏借圖,不詳細解釋了。
從彙編角度看Windows API調用
以MessageBox爲例:
MessageBox是一個比較常見的Windows API函數,從user32.dll中導出。
1.在程序裏調用MessageBox。首先進行的操作就是壓參,然後會call MessageBox,但這裏我們可以看到call 的是一個地址,機器指令是FF 15,後面跟的是絕對地址(調用時後面直接跟的是函數地址,並且不需要主調函數來平衡堆棧)。
這個地址裏的地址就是MessageBoxA的地址。
我們寫個程序測試,也確實沒毛病。
2.進入到函數地址,發現還是在壓參和調用函數。
因爲MessageBoxA在裏面又調用了MessageBoxExA()。
接下來的話,也是一些函數對參數的傳遞和處理。
MessageBoxExA()調用MessageBoxIndirectA(),也發現MessageBoxIndirectA是靠MessageBoxIndirectW實現的
追蹤下去MessageBoxIndirectW裏調用了MessageBoxTimeoutIndirectW()。
在MessageBoxTimeoutIndirectW裏開始對參數的處理,開始真正的實現功能。
未完…
3.總歸言之,經過層層調用,最終還是要到內核中去,一個簡單的API調用,背後的實現卻不簡單。