在 Windows® 中,DLL 所導出的函數可以替換為其他可提供相同簽名的自定義函數。該技術稱為“掛鉤”。它通過更改 DLL 的導入地址表 (IAT) 內部的函數地址指針來工作。每個被導入的 API 都在 IAT 中具有它自己的保留位置。在 IAT 中,導入函數的地址由 Windows 加載程序寫入。在模塊加載以后,IAT 就包含在調用導入的 API 時調用的地址。
我的掛鉤函數包含在 HookSupport 類中,該類作為與本文關聯的代碼下載的一部分,可在 MSDN_Magazine Web 站點上得到。該類上最重要的方法是 HookImportFunctionsByName,它采用將在其中掛鉤導入函數的模塊句柄、要掛鉤的模塊的名稱、包含要掛鉤的函數名稱的結構數組,以及新的自定義函數過程地址。John Robbins(MSDN Magazine 的 Bugslayer 專欄作家)在使用 Win32_ 的時期經常說明如何掛鉤函數。我將使用 John 在他的調試著作 Debugging Applications for Microsoft .NET and Microsoft Windows (Microsoft Press, 2003) 中介紹的技術。
正如前面提到的那樣,ASP 客戶端無法使用 .NET 異常的原因是,該異常最初被使用 SetErrorInfo 設置為線程的錯誤對象;隨后,當腳本運行庫調用 GetErrorInfo 以生成 IDispatch Invoke 方法所必需的 EXCEPINFO 結構時,該異常被清除。在理論上,如果可以在另一個自定義函數中掛鉤和替換 SetErrorInfo 函數,則在腳本運行庫調用 GetErrorInfo 以清除 .NET 異常接口指針之前,可以使用 EMAB 提取和發布它。
SetErrorInfo 函數定義在 OLEAUT32 模塊中。遺憾的是,盡管該模塊是從 mscorwks/mscorsvr 中加載的,但無法容易地掛鉤它,因為 OLEAUT32 模塊在 mscorwks/mscorsvr 的導入地址表中不存在(該模塊只存在于單獨的延遲加載 IAT 中)。這是因為該模塊被延遲加載:在運行時,LoadLibrary 和 GetProcAddress 被調用以解析 SetErrorInfo 的函數地址。得到的地址隨后被存儲在延遲加載 IAT 中,以便將來的調用能夠直接轉向 API。
盡管掛鉤依賴于對模塊的導入表進行修改,但對于延遲加載的 DLL 而言,在模塊內部對該函數進行首次調用之前,必須完成這一工作。由于您不顯式加載 mscorwks.dll,因此當您開始掛鉤時,您無法確保尚未對 SetErrorInfo 進行首次調用。
延伸閱讀
文章來源于領測軟件測試網 http://www.kjueaiud.com/