在我们进行某些操作的时候,常常会提示权限不足的提示,这时就需要提升自己进程到系统权限。
原理:
windows的每个用户登录系统后,系统会产生一个访问令牌(access token),其中关联了当前用户的权限信息,用户登录后创建的每一个进程都含有用户access token的拷贝,当进程试图执行某些需要特殊权限的操作或是访问受保护的内核对象时,系统会检查其acess token中的权限信息以决定是否授权操作。
Administrator组成员的accesstoken中会含有一些可以执行系统级操作的特权(privileges),如终止任意进程、关闭/重启系统、加载设备驱动和更改系统时间等(这里的特权和UAC中的不一样,UAC主要是读写一些敏感的文件等,安装程序等,这些是管理员权限,绕过UAC主要是不弹出那个提示框;这里的这些特权即使是管理员权限也需要调用代码获取(或者叫开启),像一些注入里,经常会用到这些特权提升代码),不过这些特权默认是被禁用的,当Administrator组成员创建的进程中包含一些需要特权的操作时,进程必须首先打开这些禁用的特权以提升自己的权限,否则系统将拒绝进程的操作。注意,(貌似win7以后)非Administrator组成员创建的进程无法提升自身的权限,因此下面提到的进程均指Administrator组成员创建的进程。Windows以字符串的形式表示系统特权,如“SeCreatePagefilePrivilege”表示该特权用于创建页面文件,“SeDebugPrivilege”表示该特权可用于调试及更改其它进程的内存,为了便于在代码中引用这些字符串,微软在winnt.h中定义了一组宏,如
#define SE_DEBUG_NAME TEXT(“SeDebugPrivilege”)。完整的特权列表可以查阅msdn的security一章。
实现原理:
对一个任意进程(包括系统安全进程和服务进程)进行指定了写相关的访问权的OpenProcess操作,只要当前进程具有SeDeDebug权限就可以了。
要是一个用户是Administrator或是被给予了相应的权限,就可以具有该权限。可是,就算我们用Administrator帐号对一个系统安 全进程执行OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)还是会遇到“访问拒绝”的错误。什么原因呢?原来在默认的情况下进程的一些访问权限是没有被使能(Enabled)的,所以我们 要做的首先是使能这些权限。
实现流程:
1.GetCurrentProcessID 得到当前进程的ID
2.OpenProcessToken 得到进程的令牌句柄
BOOL OpenProcessToken(
HANDLE ProcessHandle, //要修改访问权限的进程句柄
DWORD DesiredAccess,
PHANDLE TokenHandle//返回的访问令牌指针
);
3.LookupPrivilegeValue 查询进程的权限 取得特权的LUID值
BOOL LookupPrivilegevalue(
LPCTSTR lpSystemName, // system name
LPCTSTR lpName, // privilege name 权限的名称
PLUID lpLuid // locally unique identifier 返回LUID的指针
);
4.AdjustTokenPrivileges 判断修改令牌权限
BOOL AdjustTokenPrivileges(
HANDLE TokenHandle, // handle to token 访问令牌的句柄
BOOL DisableAllPrivileges, // disabling option进行权限修改还是除能
PTOKEN_PRIVILEGES NewState, // privilege information修改的权限
DWORD BufferLength, // size of buffer
PTOKEN_PRIVILEGES PreviousState, // original state buffer
PDWORD ReturnLength // required buffer size
);
实现代码:
BOOL EnableSeDebugPrivilege(HANDLE ProcessHandle, BOOL IsEnable,LPCTSTR RequireLevel)
{
DWORD LastError;
HANDLE TokenHandle = 0;
if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
{
LastError = GetLastError();
if (TokenHandle)
CloseHandle(TokenHandle);
return LastError;
}
TOKEN_PRIVILEGES TokenPrivileges;
memset(&TokenPrivileges, 0, sizeof(TOKEN_PRIVILEGES));
LUID v1;
if (!LookupPrivilegeValue(NULL, RequireLevel, &v1))
{
LastError = GetLastError();
CloseHandle(TokenHandle);
return LastError;
}
TokenPrivileges.PrivilegeCount = 1; //要提升的权限个数
TokenPrivileges.Privileges[0].Luid = v1;
if (IsEnable)
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
TokenPrivileges.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
LastError = GetLastError();
CloseHandle(TokenHandle);
return LastError;
}