扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
在微软开发者大会上看到Vista和IE 7之后,我已经表示它们的保护模式不仅仅阻挡了间谍软件,也让合法的IE插件变得非常困难。当我试用了Vista beta 2之后,我体验到了这种困难——我的产品之一是一个IE工具栏,保护模式破坏了它的许多主要功能,因为这个工具栏需要与IE之外的另一个进程进行通信。经过多次尝试,我最终让这些功能又可以正常使用了。关于如何在这种安全模式下对自己的应用程序做出必要的修改,我根据自己的经历总结出一些经验,希望和有这方面需求的朋友分享。
这篇文章假定你已经熟悉C++、GUI和COM编程。示例代码是使用Visual Studio 2005、WTL 7.5和Windows SDK建立的。如果你想更多的了解WTL,可以查看我的关于WTL的系列文章(http: //www.codeproject.com/wtl/wtl4mfc1.asp)。WTL只用于图形化界面;本文介绍的概念适用于所有应用程序,没有依赖于任何类库。
一.介绍保护模式
IE浏览器的保护模式是Vista中的一个新功能,是类似用户帐号控制(UAC)的一种安全功能。在保护模式下,通过限制运行在IE进程下的代码不能修改系统部分文件,从而来保护计算机的安全。这样,即使一个恶意网页利用了IE或IE插件中的一个代码注入漏洞,注入的代码也不能够对系统造成破坏。
在我们深入了解保护模式对IE插件开发者意味着什么之前,我们需要先快速了解一下相关的安全功能。
1.完整性级别和UIPI
Vista引入了一种叫做强制完整性级别的安全对象新属性。分为四个级别:
系统:被操作系统组件使用,不应被应用程序所使用;
高:在提升的完全管理权限下运行的进程;
中:正常方式启动的进程;
低:被IE和Windows Mail使用来提供保护模式。
Windows中关于进程的信息包含它是使用哪一个完整性级别启动的。一旦该进程启动后这个级别永远不会发生改变,它只能在进程被创建的时候被设定。一个进程的完整性级别具有以下三个主要的作用:
(1)这个进程所创建的任何安全对象具有与它相同的完整性级别。
(2)这个进程不能够存取完整性级别比它高的资源。
(3)这个进程不能发送Windows消息到具有更高完整性级别的进程。
这不是一个完整的列表,但是以上所列的三个是对插件具有最大影响的。前两条防止一个低完整性的进程篡改IPC资源,例如共享内存,包含敏感数据或一个应用程序正常运行所需要的数据。最后一条被称为用户界面特权隔离(UIPI),被设计来防止类似粉碎窗口攻击(shatter attack)之类的攻击,在粉碎窗口攻击中,攻击者通过发送给进程一个它不希望收到的消息,从而导致它运行非信任的代码。
启用你的插件和其他应用程序之间的通信
看到这儿,我们已经可以使用运行在IE进程中的代码来处理所有文件系统和注册表了。下面我们看一个更复杂的话题,它也需要一个更复杂的解决方案:运行在一个更高完整性级别的另一个进程的IPC。我们将介绍两种不同形式的IPC:内核对象和windows消息。
1.创建一个IPC对象
当一个插件和一个单独的进程希望通信的时候,这种通信发生在两个代码之间,而不用经过IE封装。NT安全API和强制性完整级别现在可以发挥它们的作用了,默认情况下从一个插件到一个单独的应用程序的通信是被阻挡的,因为这个应用程序运行在比IE更高的完整性级别。
如果这个单独的应用程序创建了一个插件需要使用的内核对象(例如,一个事件或互斥对象),在插件存取它们之前,这个应用程序必须降低这个对象的完整性级别。这个应用程序可以使用安全API来修改对象的ACL来降低它的完整性级别。下面的代码是从MSDN的文章“Understanding and Working in Protected Mode Internet Explorer”摘取的,将一个HANDLE赋给一个内核对象,并设置它的完整性级别为低。
// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity LPCWSTR LOW_INTEGRITY_SDDL_SACL_W = L"S:(ML; ; NW; ; ; LW)";
bool SetObjectToLowIntegrity( HANDLE hObject, SE_OBJECT_TYPE type = SE_KERNEL_OBJECT)
{
bool bRet = false;
DWORD dwErr = ERROR_SUCCESS; PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL;
BOOL fSaclPresent = FALSE; BOOL fSaclDefaulted = FALSE;
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW ( LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD, NULL ) )
{
if ( GetSecurityDescriptorSacl ( pSD, &fSaclPresent, &pSacl, &fSaclDefaulted ) )
{
dwErr = SetSecurityInfo ( hObject, type, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl );
bRet = (ERROR_SUCCESS == dwErr);
}
LocalFree ( pSD );
}
return bRet;
}
这个示例代码使用了两个mutex,其目的是让这个插件告诉什么时候这个应用程序在运行。当这个进程启动的时候DemoAPP EXE创建了它们,当你点击其中一个Open Mutex按钮的时候这个插件尝试去打开它们。Mutex 1具有默认的完整性级别,而mutex 2则通过上面所说的SetObjectToLowIntgrity()函数设置到低完整性级别。这意味着当保护模式启用的时候,这个插件将只能存取 mutex 2。以下是当你点击两个Open Mutex按钮时所看到的结果:
运行时检测保护模式
为了判断我们的插件是否运行在一个保护模式IE进程中,我们使用IEISProtectedModeProcess():
HRESULT IEIsProtectedModeProcess(BOOL* pbResult);
如果返回值是一个成功的HRESULR和*pbResult是True,那么保护模式就被启用了。根据在*pbResult中返回的值,你可以在你的代码中采取不同的操作:
HRESULT hr;
BOOL bProtectedMode = FALSE;
hr = IEIsProtectedModeProcess ( &bProtectedMode );
if ( SUCCEEDED(hr) && bProtectedMode ) // IE is running in protected mode else // IE isn't running in protected mode
示例band插件在一启动的时候调用了这个API,并显示了关于保护模式状态的一个消息。
2.写文件系统
当保护模式被启用的时候,扩展插件只能对用户配置下的几个目录进行写操作。只有在Temp、Temporary、Internet Files、Cookies和Favorites目录下的几个特定低完整性目录可以进行写操作。IE还有某些兼容性补偿功能,它虚拟化其他常用目录。对这些目录的写操作将被重定向到Temporary Internet Files的子目录中。如果一个扩展插件试图对一个敏感进行写操作的话,例如对windows目录,这个操作将会失败。
当一个扩展插件希望写这个文件系统的时候,它应该使用IEGetWriteableFolderPath()这个API,而不是GetSpecialFolderPath()、GetFolderPath()或SHGetKnownFolderPath()。
IEGetWriteableFolderPath ()可以发现保护模式,如果一个插件请求一个不允许写的目录,IEGetWriteableFolderPath()将返回 E_ACCESSDENIED。IEGetWriteableFolderPath()的原型如下:
HRESULT IEGetWriteableFolderPath(GUID clsidFolderID, LPWSTR* lppwstrPath);
保护模式中的其他限制
1.运行其他应用程序
IE具有另一个防止恶意代码启动或与其他进程通信的机制。如果一个插件试图启动另一个进程,IE将在启动这个进程前要求该用户同意。举个例子来说,使用查看源代码命令会引起如下提示:
如果你的插件需要运行一个单独的EXE,你可以增加一个注册表键值来告诉IE你的EXE可以被信任并能够无须提示就被运行。这个控制这种行为的注册表键值是HKLM\Software\Microsoft\Internet Explorer\Low Rights\ElevationPolicy。创建一个新的GUID,然后在名称为那个GUID的ElevationPolicy下增加一个键值。在这个新的键值中,创建三个值:
AppName:可执行文件的文件名,例如“DempApp.exe”。
AppPath:EXE所在的目录。
Policy:设置成3的DWORD值
如果你的安装没有创建一个类似的键的话,当你选择对话框中的“Do not show me the warning for this program again”,IE自己将创建一个。
2、拖拽到其他应用程序
如果你试图从一个网页的内容拖拽到另一个应用程序中,会出现一个类似的提示窗口:
这个提示窗口也可通过一个注册表键来禁止。格式如上面所述,但是你的应用程序的键应该放在DragDrop下,而不是前面的ElevationPolicy。
DemoApp作为一个拖拽的对象来演示,如果你在IE中选择了一些文本内容,并把它拖拽到DemoApp对话框中,它将显示一个消息来表示它已经收到这个拖拽动作.
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者