關(guān)鍵字 API Hook,COM Hook,ATL,Office 文檔安全,C++

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

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

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

2005年10月15日夜

參考資料:

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