关键字 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