1. 背景
UAC(User Account Control,用户帐户控制)是微软在Windows Vista及其之后版本系统新增的一项技术,此项技术是通过“令牌(Token)”来限定进程的权限。
在Windows Vista之前的系统(如:Windows XP),用户如果使用管理员(Administrator)帐号登录系统,那将创建一个安全令牌(Security Token),这个安全令牌会与包括第一个应用进程Windows资源管理器(explorer.exe)在内及后来所创建的新进程相关联,Windows资源管理器会将它的令牌传递给它的子进程。因此,相当于子进程(有可能是恶意程序或恶意脚本)就会继承Administrator帐号的高权限,访问受保护的资源。
在Windows Vista系统中,用户如果使用管理员(Administrator)帐号登录系统,除了创建一个安全令牌(Security Token),还会创建一个经过筛选的令牌(Filtered Token),经过筛选的令牌(Filtered Token)将仅授予标准用户(Standard User)的权限,Filtered Token将会与包括第一个应用进程Windows资源管理器(explorer.exe)在内及后来所创建的新进程相关联,那么这些进程在试图访问系统受保护的资源时将受限,如果想让其具备访问权限则需对其进行提升权限。
以一个表格来总结以上的内容:
系统 | 帐户 | 访问资源权限 |
---|---|---|
XP | Administrator (Security Token) | 几乎无限制 |
Vista | Administrator (Security Token) | 几乎无限制 |
Standard User (Filter Token) | 受限 (无法访问受保护的资源) |
2.应用场景
编写一个权限受限的测试工具,用于执行样本程序(可能是恶意程序或恶意脚本),以验证样本程序是否可以攻破系统防护软件的能力,访问系统受保护的资源。
3.实现方法
创建一个权限受限进程的大致思路(这里只是举例其中一种): 获取Windows资源管理器(explorer.exe)的令牌信息,以该令牌信息来启动目标进程;
伪代码流程:
#include <Tlhelp32.h>
#include <Userenv.h>
#pragma comment(lib, "Userenv.lib")
BOOL CreateProcessAsStandardUser(LPWSTR lpCmdLine)
{
//枚举进程,找到explorer.exe,获取其Token
HANDLE hToken = NULL;
HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
PROCESSENTRY32 pe32 = {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return FALSE;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
do
{
if(!_tcsicmp(pe32.szExeFile, _T("explorer.exe")))
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,pe32.th32ProcessID);
if(!hProcess)
{
CloseHandle (hProcessSnap);
return FALSE;
}
bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS, &hToken);
CloseHandle(hProcess);
break;
}
}
while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle (hProcessSnap);
if(NULL == hToken)
return FALSE;
//获取环境变量信息
LPVOID lpEnv = NULL;
if(!CreateEnvironmentBlock(&lpEnv, hToken, FALSE))
return FALSE;
//根据令牌、环境变量,启动进程
OSVERSIONINFO info = { 0 };
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");
BOOL bResult = CreateProcessAsUser(hToken, NULL, lpCmdLine, NULL, NULL,
FALSE,NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, lpEnv, NULL, &si, &pi);
if(lpEnv)
DestroyEnvironmentBlock(lpEnv);
if(hToken)
CloseHandle(hToken);
if(pi.hThread)
CloseHandle(pi.hThread);
if(pi.hProcess)
CloseHandle(pi.hProcess);
return bResult;
}
}