怎样写一个与Win8 IE11兼容的标准BHO?
环境:Windows8.1 x86 IE11(其它环境未讨论)
作者:magictong
日期:2014/02/02
概述
微软在2013年6月份推出了Windows8.1并且带上了IE11,在一个不起眼的地方,偷偷的勾上了“启动增强保护模式”功能(最新消息,11月份的时候微软发了个更新又取消了这个勾,但是说不定哪天又发个更新给勾上)。然后你会发现一大批的IE插件沦陷了(迅雷,QQ下载助手等等,都无法生效了)。
等等!我大微软不是号称兼容做得最好的吗……难道一棍子把所有的插件全部打死了?!
现象
我们看看自己的BHO插件的情况,找一个在老的浏览器下面工作的很好的BHO插件,然后在Windows8.1IE11下面注册使用,慢着,BHO是啥?怎么写一个BHO,这……参考[1]和[2]吧,只能帮助你到这里了。
注册之后打开IE11,发现IE11的下面有这样的提示。
某某插件与增强安全功能不兼容。打开这个详细信息看看,发现是告诉你怎么关闭这个增强安全功能。
查看管理加载项里面的状态,也是“不兼容”。
这下用户心里开始纠结了,从这个描述上看你的增强保护模式是加强安全保护的,如果关闭了是不是我就不安全了?如果不关闭,以前的一些好用的插件都无效了,这要用户怎么选?!当然更多的用户是不知道发生了神马,嗯!而对于我们这些软件厂商来说,这是更大的负担,看似一个小小的改动,又得忙活几天了,对于软件开发者来说,当然希望用户不关闭增强保护功能(既不能帮助用户关闭,也不能提示用户关闭,这毕竟是一种不负责任的行为),那么要想我们的插件在用户的机器上生效,看来得做点什么……
解决方案
解铃还须系铃人,当然得去问问微软在这个增强保护模式上面做了什么,参考[3],前面主要讲IE11下面对Web访问的影响等等,可以快速浏览下。和插件相关的在后半部分,需要仔细研究下。
这里面提到,如果你的插件(不管是BHO,Axtivex还是其它插件)想兼容EPM(增强保护模式),需要在注册时标明本插件是增强保护模式兼容的,具体来说就是要把插件注册到一个特殊的Com组件类型库中,这个特殊的组件类型库就是CATID_AppContainerCompatible,OK,注册组件类型库是不难的,我们试一下,在BHO的注册代码里面添加下面的代码。
DEFINE_GUID(CATID_AppContainerCompatible, 0x59fb2056, 0xd625,0x48d0, 0xa9, 0x44, 0x1a, 0x85, 0xb5, 0xab, 0x26, 0x40);
//DllRegisterServer - Adds entries to the system registry
STDAPIDllRegisterServer(void)
{
HRESULThr =_AtlModule.DllRegisterServer();
ICatRegister*pcr =NULL;
HRESULThrRegCat =CoCreateInstance(CLSID_StdComponentCategoriesMgr,NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister, (void**)&pcr);
if(SUCCEEDED(hrRegCat)&&pcr)
{
CATIDrgcatid[1];
rgcatid[0] =CATID_AppContainerCompatible;
pcr->RegisterClassImplCategories(CLSID_AdPromotionImp, 1,rgcatid);
}
if(pcr)
pcr->Release();
returnhr;
}
看起来很简单,但是行不行呢?试一下(注意:要重新注册BHO,直接只替换文件是不行的!上面这种是动态注册的方法,还有一种静态注册的方法(等下说),这种动态注册的方法要注意的是,如果是用向导生成的BHO代码,那么DllRegisterServer里面会有一段(_AtlModule.DllRegisterServer();)代码,你的组件注册代码要放在它后面,否则注册会被覆盖掉而不生效,静态注册的方法没有这种问题)。
是不是看到了熟悉“启用”不“不启用”提示?!果断“启用”。现在BHO是不是加载了,并且大部分功能都正常了呢?
有人说,我想那个启动不启用提示也没有是否可以呢?答案是肯定的,但是过程却是曲折的,如果你的BHO永远只想当一个良民(标准BHO),还真的很困难,你得修改HKCU\Software\Microsoft\InternetExplorer\Approved Extensions\{05F5F404-7C24-4B39-B5CC-340CEDEB9C0D}这个注册表下面的二进制值,这个里面存储的是微软IE下的某个插件获取到用户信任(也就是用户主动点了启用)的数据,而这个值微软是加密的,难以轻易破解,否则微软架构的这套安全机制轻易就完蛋了。那只能走其它的路子,做一个不标准的BHO,主要体现在不注册COM,也不在标准BHO的注册表位置注册(IE通过枚举这个位置来加载BHO),然后我们通过其它方式注入(消息钩子,驱动,远程线程……),这不是本文重点,可以参考[4]。
之前提到,还有一种静态注册COM组件类型库的方法,也很简单,只需要在RGS文件里面添加如下的内容就可以了。
其实原理都是类似的(不过要注意的是静态添加的方法无法区分系统版本,而在低于win8的系统环境下面上面的rgs代码是会注册失败的,除非你确信你的BHO只会在win8上存在,否则慎用)。。
更多问题
事情完全搞定了吗?No,No,No!万里长征才走了第一步,我想有些人可能已经注意到了我在上面提到现在大部分功能已经正常了,也就是说还有很多功能是不正常的,这就牵扯出了IE11增强保护模式下的特殊权限问题,你会发现虽然IE加载了你的BHO,但是很多API都调用失败了,很多IPC通信也无法完成,原因不外乎,读\写文件,读\写注册表失败,打开某内核对象失败,而且都是权限问题,这又是另外一个自IE下保护模式出现以来就有的兼容性问题了,但是因为这个和本文关系不是特别大,而且网上介绍保护模式的文件汗牛充栋[5],因此就不详细介绍了。这里仅仅点到即止,说明一下IE11下增强保护下出现的新问题,在增强保护模式下IE运行在一种特殊的完整性权限下,叫AppContainer,在[3]里面有提到,在这种情况下BHO或者插件需要访问的资源的用户组权限需要在一个特殊的组里面,这个组叫ALL_APPLICATION_PACKAGES,这个组的SID是“S-1-15-2-1”(当然Low完整性权限也是必须要的),你给BHO所有要访问的资源,内核对象通过权限控制API,添加上这个用户组,基本上BHO就都可以访问了,另外就是建议你的BHO不要去直接操作文件注册表这些敏感资源,一来是一般没权限不被系统允许,二来是风险很高,建议你通过IPC告知高权限进程去进行这些敏感操作。
参考资料
[1]如何使用BHO定制你的Internet Explorer浏览器http://www.vckbase.com/index.php/wv/1145
[2]用VisualStudio2005生成浏览器帮助对象http://www.cnblogs.com/jcss2008/archive/2009/06/06/1497518.html
[3] UnderstandingEnhanced Protected Modehttp://blogs.msdn.com/b/ieinternals/archive/2012/03/23/understanding-ie10-enhanced-protected-mode-network-security-addons-cookies-metro-desktop.aspx
[4] BHO强制注入IE技术方案简述http://km.oa.com/group/QQPCMGR_tech/articles/show/165005
[5]面对IE保护模式的开发者生存之道http://tech.it168.com/msoft/2007-12-04/200712041740771.shtml