在平常的事情中,应用hook操纵偶然可以或者大大进步咱们的事情效力。此中,典型的例子有:为了便于对法式停止调试,咱们可以或者对Windows API函数履行hook操纵或者为了停止歹意软件检测,咱们也可以或者对Windows API函数履行hook操纵。在这些场景中,每每是一些DLL被注入到目标过程中,而后对相干的功效函数履行hook操纵,有几种方法可以或者做到这一点,但这并非本文要评论辩论的重点,感兴趣的读者可以或者在网上搜刮与DLL相干的技巧文章。
在组件对象模子(COM)的天下中,想要对COM组件接口函数履行hook操纵并非一件轻易的事情。缘故原由是由于COM组件是基于对象的,是以平日情况下咱们是不可以或者得到COM组件接口函数地点的。而且,由于COM组件接口函数不直接导出,是以经由过程挪用GetProcAddress或类似的方法也是无奈找到这些函数地点的。别的,纵然COM组件中的某些函数的地点被找到,履行hook操纵也必要将一些代码注入到目标过程中,这类操纵在某些情况下(比方受掩护的过程)险些是不可以或者实现的。
但颠末咱们的研讨发明,COM组件供给了另一种“hooking”操纵或者相当于重定向的机制,此机制可以或者将一个CLSID重定向到另一个CLSID,MSDN文档中把这类机制称之为“仿真”功效,就像一个类可以或者模仿另一个类的功效似的。这类机制在一定程度上打开了将一个类重定向到另一个类的可以或者性,而不必要注入代码到目标过程中或者对某些函数履行hook操纵。
Hooking COM接口函数实例
上面让咱们一路来看一个详细的例子。Windows中的后盾智能传输办事(BITS)供给了异步下载/上传办事,该办事具备进度关照,收集主动规复等功效。歹意软件可以或者经由过程BITS办事来下载其有用载荷,而不必要其直接下载有用载荷,直接下载会使歹意软件更轻易裸露在反歹意软件检测对象中。经由过程BITS下载使得歹意软件与下载的有用载荷没有甚么直接的联系关系,进一步加大了对歹意软件的检测难度。
由于BITS是基于COM组件来实现的,是以可以或者应用上述所说的“仿真”机制对任何必要得到BITS操纵的函数履行hook操纵,以得到BITS模块的履行成果。实现这个设法主意的症结是COM组件中的CoTreatAsClass 这个API函数,该函数将一个TreatAs键添加到原始键中,并将其值指向备用的CLSID。尽管如此,可以或者咱们照样没有方法来对某些BITS操纵履行hook操纵,缘故原由是由于任何COM激活哀求(比方经由过程CoCreateInstance)都将重定向到TreatAs CLSID,是以咱们没有方法只重定向某些特定的哀求。
是以,对哪些CLSID应当履行hook操纵是咱们应当要好好斟酌和研讨的成绩。在BITS的情况下,咱们必要操纵的对象是BackgroundCopyManager,它是应用BITS操纵时肯定会创立的对象。或者你们会觉得一个更好的CLSID目标对象是由BITS创立的现实Job对象,然则如许做将起不到任何的感化,由于没有如许的CLSID对象。像很多基于COM组件的API同样,只有几个对象现实上可以或者应用COM大众激活API创立并具备CLSIDs。经由过程函数直接创立的一些对象,是不必要经由过程COM激活机制的。
如下是创立“替代类”以拦阻BITS哀求所需的代码:
HRESULT hr = ::CoTreatAsClass(
__uuidof(BackgroundCopyManager),
__uuidof(FakeBitsManager));
上述代码中的FakeBitsManager是我创立的一个COM类,该类必要实现与原始对象(IBackgroundCopyManager)雷同的接口;不然,机械上的一切BITS操纵都将失败!由于拜访权限的缘故原由,上述CoTreatAsClass函数将挪用失败,纵然从高权限的过程中挪用也是无用的。缘故原由是HKCR\CLSID {4991d34b-80a1-4291-83b6-3328366b9097}下的这个注册表键值由TrustedInstaller领有,它不允许被窜改,乃至不允许体系帐户去改动这个键值! 但是,超等管理员用户可以或者经由过程履行Take Ownership特权,成为该注册表键值的新领有者,是以咱们照样有权变动该键值权限的,如下图所示,咱们如今曾经领有对该键值的改动权限:
那末,咱们在哪里挪用CoTreatAsClass函数比拟适合呢?颠末一些试验咱们发明该挪用可以或者在一些装置法式中实现,装置法式可以或者是一个简略的批处置或PowerShell剧本,而且可以或者直接应用注册表函数停止准确的设置,详细如下图所示:
上面是一个应用ATL实现的COM类,经由过程实现IBackgroundCopyManager和IUnknown以用来对BITS管理器类履行拦阻操纵,代码如下所示:
class ATL_NO_VTABLE CFakeBitsManager :
public CComObjectRootEx,
public CComCoClass,
public IBackgroundCopyManager
{
//...
BEGIN_COM_MAP(CFakeBitsManager)
COM_INTERFACE_ENTRY(IBackgroundCopyManager)
END_COM_MAP()
HRESULT FinalConstruct();
CComPtr m_spRealBits;
public:
STDMETHOD(CreateJob)(
LPCWSTR DisplayName,
BG_JOB_TYPE Type,
__RPC__out GUID *pJobId,
IBackgroundCopyJob **ppJob);
STDMETHOD(GetJob)(
REFGUID jobID,
IBackgroundCopyJob **ppJob);
STDMETHOD(EnumJobs)(
DWORD dwFlags,