这篇博客本来去年底就应该写的了,但是,可能因为懒,或者就是觉得内容不太重要,所以,一直没有写。
EPM是在IE10中出现的,是以前的保护模式的加强版,提供“深度的保护”,以防止攻击者安装恶意软件,或者修改系统设置。保护模式基于最小权限的原则——通过限制Internet Explorer所拥有的能力,使得入侵代码所获得的能力也相应地受到了限制。当然,这也会让大部分正常的插件不能使用。
EPM在IE10中是默认关闭的,而在IE11中则默认开启(后来又变回关闭了)。在程序中可以通过IEIsProtectedModeProcess(BOOL *pVal)来判断IE是否启用了EMP。
EPM开启后,会将IE运行在APPContainer中,以限制其能力。所以在IE11中,插件会因为权限原因,无法正常使用。
解决办法就是将插件添加在APPContainer中。在插件注册的方法DllRegisterServer中添加下面代码即可:
ICatRegister* pcr = NULL ;
class __declspec(uuid("{59FB2056-D625-48D0-A944-1A85B5AB2640}")) AppContainerCompatible;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
CATID rgcatid[1] ;
rgcatid[0] = __uuidof(AppContainerCompatible);
hr = pcr->RegisterClassImplCategories(CLSID_AtiveX, 1, rgcatid);//CLSID_AtiveX为插件的CLSID
其作用是:在注册表中,添加
HKEY_CLASSES_ROOT\CLSID\(插件的CLSID)\Implemented Categories\{59FB2056-D625-48D0-A944-1A85B5AB2640},表示将这个控件添加到AppContainer。
完成上述操作后,发现插件的部分功能恢复正常了,不过使用RPC与系统服务通信的模块依旧出问题。接下来,需要创建COM组件(EXE类型,假设为RPCBroker.exe)来充当RPC通信的桥梁,也就是将调用RPC的方法,移植到RPCBroker.exe中执行(如NdrClientCall2方法)。这里主要比较纠结的地方,就是参数的传递,因为有些参数类型,ATL中并不支持。
创建COM组件 http://www.cnblogs.com/xiaokang088/archive/2011/05/16/2047376.html 文中是创建的COM是dll类型的,我们应该选择可执行文件(EXE)类型。
COM组件需要注册才能使用,因此要在插件的DllRegisterServer中注册COM组件:RpcBroker.exe /RegServer。另外卸载COM组件:RPCBroker.exe /UnRegServer
使用RPCBroker.exe后,RPC通信也正常了。不过,在IE中启用控件的时候,会出现下面的警告。
这是由于RPCBroker.exe打破了APPContainer的限制,提高了插件的权限。所以我们需要在注册表项(HKLM\Software\Microsoft\Internet Explorer\Low Rights\ElevationPolicy)中配置RPCBroker.exe的Policy(DWORD),AppName(REG_SZ),AppPath(REG_SZ)等信息。其中Policy有四个数值,我们需要将其设置为3。
关于EMP的详细介绍: http://msdn.microsoft.com/en-us/library/bb250462(v=vs.85).aspx
注册部分代码:
static void ShellProcess(LPSTR pszFile, LPSTR pszParameters)
{
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = pszFile;
ShExecInfo.lpParameters = pszParameters;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
}
void RegisterBroker()
{
HKEY hKey;
HKEY hSubKey;
char exeDir[_MAX_PATH];
char exeFullPath[_MAX_PATH];
memset(exeFullPath,0,sizeof(exeFullPath));
GetModuleFileName((HMODULE)_hInstance, exeDir, _MAX_PATH);
char *p = strrchr(exeDir, '\\');
p[1] = 0;
strcat_s(exeFullPath,sizeof(exeFullPath), exeDir);
strcat_s(exeFullPath,sizeof(exeFullPath), g_szQQCertBrokerName);
ShellProcess(exeFullPath, "/Regserver");
//注册IE低权限
HRESULT hr;
hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy"),0,KEY_ALL_ACCESS,&hKey);
if(ERROR_SUCCESS == hr){
if(ERROR_SUCCESS == RegCreateKeyEx(hKey,"{COM组件的CLSID}",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hSubKey,NULL)){
RegSetValueEx(hSubKey,_T("AppName"),0,REG_SZ,(BYTE *)g_szQQCertBrokerName,sizeof(g_szQQCertBrokerName));
RegSetValueEx(hSubKey,_T("AppPath"),0,REG_SZ,(BYTE *)exeDir,sizeof(exeDir));
DWORD dwValue = 0x3;
RegSetValueEx(hSubKey,_T("Policy"),0,REG_DWORD,(BYTE *)&dwValue,sizeof(DWORD));
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
}
}
补充:浏览器插件结合COM组件的使用方式,可以突破较多的限制。比如在Win8系统中,插件加载驱动程序出现Access Denied的问题~