在枚举/结束系统进程或操作系统服务时,会出现权限不足而失败的情况,因此需要提升进程的权限。
1 BOOL SystemRestart() 2 { 3 EnableXXXPrivilege(SE_SHUTDOWN_NAME); 4 return ExitWindowsEx(EWX_REBOOT, 0); 5 }
windows的每个用户登录系统后,系统会产生一个访问令牌(access token),其中关联了当前用户的权限信息,用户登录后创建的每一个进程都会有用户access token的拷贝,当进程试图执行某些需要特殊权限的操作或是访问受保护的内核对象,系统会检查其access token的权限信息以决定是否授权操作。Administrator组成员的access token中会含有一些可以执行系统级操作的特权(privilege),如终止任意进程,关闭、重启系统、加载设备驱动和更改系统时间等,不过这些特权默认是被禁用的,当administrator组成员创建的进程中包含一些需要特权的操作时,进程必须首先打开这些禁用的特权以提升自己的权限,否则系统将拒绝进程的操作。注意,非administrator组成员创建的进程无法提升自身的权限。
Windows以字符串的形式表示系统特权,如”SeCreatePagefilePrivilege”表示该特权用于创建页面文件,“SeDebugPrivilege”表示该特权可用于调试及更改其他进程的内存。为了方便在代码中引用这些字符串,微软在winnt.h中定义了一组宏,如#define SE_DEBUG_NAME TEXT(“SeDebugPrivilege”)。完整的特权列表可以查阅MSDN(Privilege Constants)一章。虽然Windows使用字符串表示特权,但查询或更改特权的API需要LUID来引用相应的特权,LUID表示local unique identifier,它是一个64位值,在当前系统中是唯一的。为了提升进程权限到指定的特权,我们必须先找到该特权对应的LUID,这时要调用LookupPrivilegeValue函数。然后,我们需要调用AdjustTokenPrivileges函数,通知操作系统将指定的access token权限中的特权置为打开状态。
1 BOOL EnableXXXPrivilege( LPCTSTR pszPrivilegeName ) 2 { 3 HANDLE hToken; 4 LUID seXXXNameValue; //本地唯一标识符结构变量 5 TOKEN_PRIVILEGES tkp; //访问令牌权限结构变量 6 7 //获得进程访问令牌的句柄 8 if ( ! OpenProcessToken( GetCurrentProcess(), 9 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) 10 { 11 return FALSE; 12 } 13 14 //查询SE_SHUTDOWN_NAME权限所对应的luid值 15 //NULL:本地系统 pszPrivilegeName:SE_SHUTDOWN_NAME 16 if ( !LookupPrivilegeValue( NULL, pszPrivilegeName, &seXXXNameValue)) 17 { 18 CloseHandle( hToken ); 19 return FALSE; 20 } 21 22 //填充Token_Privileges结构 23 tkp.PrivilegeCount = 1; 24 tkp.Privileges[0].Luid = seXXXNameValue; 25 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 26 27 //提升权限 28 if ( !AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL )) 29 { 30 CloseHandle( hToken ); 31 return FALSE; 32 } 33 34 CloseHandle( hToken ); 35 36 return TRUE; 37 }
参考:https://blog.csdn.net/chenyonken/article/details/78290810