Windows改进的安全机制
windows 7增加了session隔离机制,Windows 实现了各Session之间的独立,使得操作系统的安全性,有了较大的提高。windows的服务进程都运行在system下在系统的Session 0里。
用户界面特权隔离
在早期的Windows操作系统中,同一用户下运行的所有进程,有着相同的安全等级,拥有相同的权限。例如,一个进程可以自由地发送一个窗口消息给其他进程的窗口。而从Windows Vista、7开始,某些关键的Windows消息就不能自由发送了。
Win7后进程拥有一个新的属性——特权等级(Privilege Level)。即便两个进程在相同的用户权限下运行,一个特权等级较低的进程向一个特权等级较高的进程发送消息会被过滤拦截掉。
UIPI的作用是防止恶意程序发送消息给那些拥有较高权限的窗口,从而获取较高的权限。在计算机系统中,这是一种维护系统安全的有效方式。因此,在 Windows 7 操作系统中运行的用户进程,在运行时具有不同的完整性(MIC)等级,那么相互间的通信无法像 Windows XP 那样正常进行。
UIPI的运行机制
UIPI:用户界面特权隔离(User Interface Privilege Isolation),是 Windows 7 通过 MIC 机制新引入的一种安全特性,用于拦截比自身进程 MIC 等级低的进程发来的消息。
UIPI 的目的是为了规范跨进程间的窗口消息,默认情况下,高权限进程不会接收到低权限进程发送的窗口消息的,但是低权限进程能够接收到高权限进程的窗口消息。UIPI 的本质是系统检查目标窗口和发送方是否具有相同的 MIC 等级或者发送方具有更高的 MIC 等级,如果符合上述条件,则允许消息的传递,否则将消息丢弃。
在 Windows 7 操作系统中运行的用户进程,如果运行时具有不同的完整性等级(特权),即具有不同的 MIC 等级,那么相互间的通信将会被隔离。
Windows 7: Message Integrity Check(消息完整性检查)
MIC消息完整性检查(Message Integrity Check),是 Windows 7 增加的 Windows 安全对象访问控制安全机制,系统利用完整性级别标记一个安全对象,通过降低进程的完整性级别限制进程对安全对象的写入权限,类似于用户帐户组的成员被限制访问系统组件的方式。完整性检查机制降低进程修改系统或损害用户数据文件的可能性。
消息完整性检查分为 6 个等级:
MIC等级 说明
SECURITY_MANDATORY_UNTRUSTED_RID 不信任的MIC等级
SECURITY_MANDATORY_LOW_RID 低MIC等级,如IE
SECURITY_MANDATORY_MEDIUM_RID 中MIC等级,默认为这个等级,如Explorer
SECURITY_MANDATORY_HIGH_RID 高MIC等级,以管理员身份运行的程序
SECURITY_MANDATORY_SYSTEM_RID 系统MIC等级,一般是服务应用程序
SECURITY_MANDATORY_PROTECTED_PROCESS_RID 被保护进程的MIC等级
MIC 等级的获取是和父进程完整性级别相关的。
在 Windows 7 系统中 Explorer.exe 的完整性级别是中 MIC 等级,因为权限继承的关系,其启动的进程具有的 MIC 等级也都默认是中 MIC 等级。一个安全对象的 MIC 等级由其访问控制列表项中的某一项标识,可以使用工具 Process Explorer 查看一个进程的 MIC 等级。
Windows 7 系统正常启动后,Explorer.exe 进程的 MIC 等级默认为:中 MIC 等级。
UIPI的等级划分为低等级(low),普通(normal),高等级(high),系统(system)。
在Windows 7中,当UAC(User Account Control)在启用时,UIPI的运行可以得到最明显的体现。当管理员用户登录系统后,操作系统会创建两个令牌对象(Token Object):第一个是管理员令牌,拥有大多数特权(类似于Windows Vista之前的System用户),而第二个是一个过滤后的简化版本令牌,只拥有普通用户的权限。
默认情况下,以标准用户启动的进程,拥有普通等级特权。以管理员运行的进程,例如,用户右键单击选择“以管理员身份运行”或者是通过添加“runas”参数调用ShellExecute运行的进程,这样的进程就拥有较高(high)的特权等级。
同一用户下,系统可以运行两种不同特权等级的进程。我们可以使用Windows Sysinternals工具集中的进程浏览器(Process Explorer)查看各个进程的特权等级。

UIPI所带来的限制
进程之间Windows消息通信发生问题时,不妨使用进程浏览器查看一下两个进程之间是否有合适的特权等级。
等级的划分,是为了防止以下犯上。
有了用户界面特权隔离,一个运行在较低特权等级的应用程序,它的行为就受到了诸多限制,它不可以:
- 验证由较高特权等级进程创建的窗口句柄
- 通过调用SendMessage和PostMessage向由较高特权等级进程创建的窗口发送Windows消息
- 使用线程钩子处理较高特权等级进程
- 使用普通钩子(SetWindowsHookEx)监视较高特权等级进程
- 向一个较高特权等级进程执行DLL注入
但是,一些特殊Windows消息是容许的。因为这些消息对进程的安全性没有太大影响。这些Windows消息包括:
0x000 - WM_NULL
0x003 - WM_MOVE
0x005 - WM_SIZE
0x00D - WM_GETTEXT
0x00E - WM_GETTEXTLENGTH
0x033 - WM_GETHOTKEY
0x07F - WM_GETICON
0x305 - WM_RENDERFORMAT
0x308 - WM_DRAWCLIPBOARD
0x30D - WM_CHANGECBCHAIN
0x31A - WM_THEMECHANGED
0x313, 0x31B (WM_???)
ChangeWindowMessageFilterEx
Windows引入了一个新的API函数ChangeWindowMessageFilter。
如果我们想容许一个消息发送给较高特权等级的进程,我们可以在较高特权等级的进程中调用ChangeWindowMessageFilter函数,以MSGFLT_ADD作为参数,将消息添加进消息过滤器的白名单。同样的,我们也可以以MSGFLT_REMOVE作为参数,将这个消息从白名单中删除。
消息的发送包括:系统消息的发送和用户自定义消息的发送。
ChangeWindowMessageFilter 与 ChangeWindowMessageFilterEx 这两个 API 为 Win7 系统新增的API接口,而 WinXP 系统没有这两个接口。
查看MSDN可知,ChangeWindowMessageFilter 作用:从 UIPI【用户界面特权隔离】消息过滤器中增加或移除一个消息。ChangeWindowMessageFilterEx 作用:为特定窗口修改 UIPI【用户界面特权隔离】消息过滤器。
ChangeWindowMessageFilterEx 函数
ChangeWindowMessageFilterEx 函数,指定窗口修改用户界面特权隔离 (UIPI) 消息过滤器。
函数原型:
BOOL WINAPI ChangeWindowMessageFilterEx(
__in HWND hWnd,
__in UINT message,
__in DWORD action,
__inout_opt PCHANGEFILTERSTRUCT pChangeFilterStruct
);
【参数】
hWnd 要修改其 UIPI 消息过滤器的窗口句柄。
message 要允许或阻止通过消息过滤器的消息。
action 要执行的操作,可以采取下列值之一:
MSGFLT_ALLOW :
允许消息通过过滤器。允许窗口接收该消息,不管源消息是什么,甚至它来自一个低特权的进程。
MSGFLT_DISALLOW :
如果消息来自低特权的进程,阻止它转递给窗口。
MSGFLT_RESET :
为窗口重置消息过滤器为默认,任何全局允许消息或进程范围内的将通过。但不包含这两个类别,其中其中来自低特权的进程将被阻塞。
pChangeFilterStruct
指向CHANGEFILTERSTRUCT结构指针的可选项。
【返回值】
如果函数成功,则返回值为非零值。
如果该函数失败,则返回值为零。要获取扩展的错误的信息,请调用GetLastError 。
对于系统消息的处理,非常简单,接受消息的进程需要将该消息加入到白名单中,可以通过下面的代码实现:
需要在高权限程序开始的地方加入以下代码,指定什么消息可以接受
例子:
//设置高权限程序的消息过滤白名单
BOOL bRes = ChangeWindowMessageFilterEx(m_hWnd, WM_COPYDATA, MSGFLT_ALLOW, NULL);
解决文件拖放失效的问题,由于Win7的安全机制,导致与文件拖放的WM_DROPFILES消息和WM_COPYGLOBALDATA消息被系统拦截了,从而导致了文件拖放失效的问题。
解决问题的办法就是,调用ChangeWindowMessageFilter函数,放行WM_DROPFILES消息和WM_COPYGLOBALDATA消息。
放行文件拖放相关事件消息
ChangeWndMessageFilter( WM_DROPFILES, TRUE );
ChangeWndMessageFilter( WM_COPYGLOBALDATA, TRUE );
上述代码让系统对该程序不再过滤掉【WM_DROPFILES】消息和【WM_COPYGLOBALDATA】消息。再次生成可执行程序,【以管理员身份运行】程序窗口就可以接收到拖放文件消息【WM_DROPFILES】了。
原因是 WinXP 及 Win2003 系统用户库 USER32.dll 没有 ChangeWindowMessageFilter、ChangeWindowMessageFilterEx 这两个接口,而 Windows 7 系统下,则新增之。
由于 WinXP、Win2003 系统安全机制不会拦截消息,因此也就没有必要运行上述新增的代码了。但若想该测试程序在 WinXP、Win2003 系统下运行正常,且要在 Win7 系统下能正常接收上述消息,可直接从 Win7 之 USER32.dll 库中获取上述 API 函数入口地址,在 Win7 系统下肯定是可以获取到入口地址的;而在 XP 系统下就肯定获取不到其入口地址,但没关系不会影响程序运行,亦不会报错。
typedef BOOL (WINAPI * ChangeWindowMessageFilterOkFn)( UINT , DWORD );
HMODULE hModUser32 = NULL;
hModUser32 = LoadLibrary(_T( "user32.dll" ));
if (hModUser32 == NULL) {
return FALSE;
}
ChangeWindowMessageFilterOkFn pfnChangeWindowMessageFilter = (ChangeWindowMessageFilterOkFn) GetProcAddress(hModUser32, "ChangeWindowMessageFilter" );
if (pfnChangeWindowMessageFilter == NULL)
{
FreeLibrary(hModUser32);
return FALSE;
}
FreeLibrary(hModUser32);
return pfnChangeWindowMessageFilter(nMessage, bAllow ? MSGFLT_ADD : MSGFLT_REMOVE);
}
Windows 7引入了UIPI(用户界面特权隔离)以增强系统安全,防止低权限进程向高权限进程发送消息。UIPI通过消息完整性检查(MIC)等级来限制进程间通信,阻止恶意程序提升权限。ChangeWindowMessageFilterEx函数允许程序在必要时调整消息过滤规则,允许特定消息的传递。这一机制在启用UAC的系统中尤为明显,但也带来了一些限制,如DLL注入和窗口句柄验证等。
7344





