關鍵字 API Hook,COM Hook,ATL,Office 文檔安全,C++

  現在的木馬后門種類非常之多,其中有些木馬專門以Office 文檔為竊取目標,我最近做了一些Anti這些木馬的工作,在工作中我基本上實現了阻止未知程序利用Office自動化接口竊取Word內容,但限于公司利益我只能寫一些基本上已經比較成熟和公開的技術,當然其中了包含我的設計思想,我想多多少少會讓你有所收獲,你可任意轉載文章,但請注明作者和出處,謝謝!
  首先我們知道Ole拖放是由DoDragDrop啟動的,為此你可以事先要準備一些參數給DoDragDrop使用,最開始我的想法是直接阻止DoDragDrop調用,后來我發現這樣做會使Word文檔窗口內部的拖放操作失效,這會給人一種很不好的感覺,好的保護軟件應該在客戶沒有感覺到不方便的情況提供保護,而后我又仔細看了DoDragDrop的參數想發現有沒有什么可以利用的地方,我發現它有四個參數:
  • IDataObject * pDataObject;
  • IDropSource * pDropSource;
  • DWORD dwOKEffect;
  • DWORD * pdwEffect;

  后兩個參數基本上沒有什么利用價值,我想到Hook IDataObject的GetData函數,可是在Ole Drop客戶端編程時,通常當我調用COleDataObject的相關成員函數時拖放已經差不多完成,鼠標已經在我的程序窗口上了。
  而我現在的想法是在拖放操作剛離開Word的文檔窗口,還沒有到達外部程序窗口時就讓它失效,這樣Hook IDataObject的虛函數肯定不行,我只有再研究一下最后一個沒有研究過的參數pDropSource,它是一個IDropSource類型指針,我發現它有一個虛函數QueryContinueDrag查看了一下MSDN發現它似乎就是我要找的。
  我的理解是這個函數是讓Ole拖放的服務端在調用DoDragDrop啟動Ole拖放操作后,有機會取消拖放操作而設的一個CallBack,于是我寫了一段代碼Hook住DoDragDrop并從DoDragDrop中進一步Hook住IDropSource的QueryContinueDrag虛函數,我發現它會全程跟蹤整個拖放操作,只要這個CallBack一返回DRAGDROP_S_CANCEL整個拖放操作就會被取消,這樣我只要知道當前鼠標下的窗口是否是文檔窗口就可以了,一旦離開了文檔窗口我就讓這個CallBack返回DRAGDROP_S_CANCEL取消整個拖放操作。
  這樣做就可以不影響文檔窗口內部的拖放操作,又可以阻止將文檔窗口內部的東西拖放到其它程序中,基本上不會讓客戶感到不方便,這很有意思!不是嗎?
  那么從鼠標位置得到窗口句柄可能嗎?答案是肯定的! GetCursorPos函數可以返回一個POINT變量,它指示當前的鼠標位置,而WindowFromPoint則可以返回某一個POINT位置下的窗口句柄。寫到這里我想差不多已經說完了我的思路,不知道你是否看得明白。
  總結一下,用ATL向導生成一個COM框架,增加一個ATL簡單對象,在這個對象上實現_IDTExtensibility2接口,在_IDTExtensibility2的OnConnection中Hook住DoDragDrop API,在Word調用DoDragDrop時記錄下當前的文檔窗口句柄,并Hook住第二個參數pDropSource的QueryContinueDrag虛函數,在QueryContinueDrag里跟蹤當前鼠下的窗口是否還是文檔窗口(比較句柄是否等于DoDragDrop時記錄下的文檔窗口句柄),如果不是則返回DRAGDROP_S_CANCE取消拖放操作,并彈出一個警告信息的MessageBox,否則執行原有的操作(讓拖放操作正常進行)。

最后,別忘了注冊你的Word插件(用Regsvr32。exe),詳細的鍵值和代碼細節見源程序吧!

2005年10月15日夜

參考資料:

  • MSDN October 2001
  • Microsoft Office 2000/Visual Basic Programmer''s Guide
  • ATL Internals
  • Inside C++ Object Model