windows权限管理
2018-10-09 本文已影响0人
MagicalGuy
// 17_权限管理_令牌的获取.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <shlobj.h>
int _tmain(int argc, _TCHAR* argv[])
{
// 获取本进程令牌
HANDLE hToken = NULL;
if( !OpenProcessToken( GetCurrentProcess( ) , TOKEN_QUERY , &hToken ) ) {
printf( "错误码:%x\n" , GetLastError( ) );
return 0;
}
// 用于接收令牌类型
TOKEN_ELEVATION_TYPE tokenType = TokenElevationTypeDefault ;
DWORD dwRetSize = 0; // 用于接收函数输出信息的字节数
// 获取令牌信息
GetTokenInformation( hToken ,
TokenElevationType ,// 获取令牌的当前提升等级
&tokenType ,
sizeof( tokenType ) ,
&dwRetSize // 所需缓冲区的字节数
);
// 判断是否调用成功
if( ERROR_SUCCESS != GetLastError( ) ) {
printf( "错误码:%x\n" , GetLastError( ) );
return 0;
}
// 根据令牌的类型来输出相应的信息
switch( tokenType ) {
case TokenElevationTypeDefault:
printf( "默认用户, 可能是一个普通用户, 可能是关闭UAC时登录的管理员用户\n" );
// 调用系统函数IsUserAnAdmin, 进一步确定是普通用户还是管理员用户
return IsUserAnAdmin( );
break;
case TokenElevationTypeFull:
printf( "管理员账户,并拥有全部的权限\n" );
break;
case TokenElevationTypeLimited:
{
// 判断受限制的用户是管理员
// 如果是管理员, 则这个令牌中会保存有管理员的SID
// 1. 获取系统内键管理员用户的SID
byte adminSID[ SECURITY_MAX_SID_SIZE ];
DWORD dwSize = SECURITY_MAX_SID_SIZE;
CreateWellKnownSid( WinBuiltinAdministratorsSid , // 获取SID的类型,这里是系统内键管理员
NULL , // 传NULL,获取本地计算机的管理员
adminSID ,// 函数输出的管理员SID
&dwSize // 输入结构的大小,也作为输出
);
// 获取本令牌的连接令牌(受限制的令牌都会有一个连接的令牌,受限制的令牌正是由主令牌所创建的. )
TOKEN_LINKED_TOKEN linkToken;
GetTokenInformation( hToken ,
TokenLinkedToken ,
&linkToken ,
sizeof( linkToken ) ,
&dwSize
);
// 在连接的令牌中查找是否具有管理员的SID
BOOL bIsMember = FALSE; // 用于保存是否包含.
CheckTokenMembership( linkToken.LinkedToken ,
&adminSID ,
&bIsMember );
if( bIsMember ) {
printf( "权限被阉割的受限制管理员账户, 部分权限被移处理\n" );
}
}
break;
}
system( "pause" );
return 0;
}
================
// 18_权限管理_给一个令牌增删特权.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <shlobj.h>
// 给进程添加对应的权限
// HANDLE hProcess : 要添加权限的进程
// const TCHAR* pszPrivilegeName : 要添加的特权的名称
BOOL AddPrivilege( HANDLE hProcess , const TCHAR* pszPrivilegeName );
// 判断是否是管理员权限
BOOL IsAdmin( HANDLE hProcess);
// 以管理员身份运行指定的可执行文件
void RunAsAdmin( const TCHAR* pszExeFile );
int _tmain( int argc , _TCHAR* argv[ ] )
{
// 下面这个函数可能会因为特权过低而执行失败
HANDLE hProcess = NULL;
hProcess = OpenProcess( PROCESS_ALL_ACCESS , FALSE , 12320 );
if( hProcess == NULL ) {
printf( "错误码:%x\n" , GetLastError( ) );
}
// 将特权权限提升到SeDebug特权, 就能够打开任何进程.
// 但是只有以管理员身份运行,并且不是受限制的管理员身份才能修改,因此,
// 需要判断当前是否具有管理员的全部权限
// 如果不是, 则需要以管理员身份运行本程序
// 判断当前进程是否以管理员身份运行
if( !IsAdmin( GetCurrentProcess( ) ) ) {
// 以管理员身份运行本进程
// 1 获取本进程的文件路径.
TCHAR path[ MAX_PATH ] = { 0 }; // 需要初始化
DWORD dwPathSize = MAX_PATH;
QueryFullProcessImageName( GetCurrentProcess( ) , 0 ,
path ,
&dwPathSize );
// 2 调用创建进程的API运行本进程.
ShellExecute( NULL , // 窗口句柄,没有则填NULL
_T( "runas" ) , // 以管理员身份运行的重要参数
path , // 所有运行的程序的路径(这里是本进程)
NULL , // 命令行参数
NULL , // 新进程的工作目录的路径
SW_SHOW // 创建后的显示标志(最小化,最大化, 显示,隐藏等)
);
// 退出本进程
ExitProcess( 0 );
}
// 将权限提升到SeDbug权限
if( !AddPrivilege( GetCurrentProcess( ) , SE_DEBUG_NAME/*字符串形式的权限名*/ ) ) {
printf( "提升权限失败\n" );
system( "pause" );
return 0;
}
// 打开进程句柄
hProcess = OpenProcess( PROCESS_ALL_ACCESS , FALSE , 12320 );
if( hProcess == NULL ) {
printf( "错误码:%x\n" , GetLastError( ) );
system( "pause" );
return 0;
}
printf( "打开成功\n" );
system( "pause" );
return 0;
}
BOOL AddPrivilege( HANDLE hProcess , const TCHAR* pszPrivilegeName )
{
// 进程的特权使用LUID值来表示, 因此, 需要先获取传入的权限名对应的LUID值
// 0. 获取特权对应的LUID值
LUID privilegeLuid;
if( !LookupPrivilegeValue( NULL , pszPrivilegeName , &privilegeLuid ) )
return FALSE;
// 1. 获取本进程令牌
HANDLE hToken = NULL;
// 打开令牌时, 需要加上TOKEN_ADJUST_PRIVILEGES 权限(这个权限用于修改令牌特权)
if( !OpenProcessToken( GetCurrentProcess( ) , TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , &hToken ) ) {
printf( "错误码:%x\n" , GetLastError( ) );
return 0;
}
// 2. 使用令牌特权修改函数将SeDebug的LUID特权值添加到本进程令牌
TOKEN_PRIVILEGES tokenPrivieges; // 新的特权
// 使用特权的LUID来初始化结构体.
tokenPrivieges.PrivilegeCount = 1; // 特权个数
tokenPrivieges.Privileges[ 0 ].Luid = privilegeLuid; // 将特权LUID保存到数组中
tokenPrivieges.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;// 将属性值设为启用(有禁用,移除等其他状态)
// 调用函数添加特权
return AdjustTokenPrivileges( hToken , // 要添加特权的令牌
FALSE , // TRUE是移除特权, FALSE是添加特权
&tokenPrivieges , // 要添加的特权数组
sizeof( tokenPrivieges ) ,// 整个特权数组的大小
NULL , // 旧的特权数组
NULL // 旧的特权数组的长度
);
}
BOOL IsAdmin( HANDLE hProcess )
{
HANDLE hToken = NULL;
OpenProcessToken( hProcess , TOKEN_QUERY , &hToken );
TOKEN_ELEVATION_TYPE tokenType = TokenElevationTypeDefault ; // 用于接收令牌类型
DWORD dwRetSize = 0; // 用于接收函数输出信息的字节数
// 2. 查询进程令牌中的权限提升值.( 这个值会记录当前的令牌是何种类型( 细节在17_权限管理_令牌的获取.cpp ) )
GetTokenInformation( hToken ,
TokenElevationType ,// 获取令牌的当前提升等级
&tokenType ,
sizeof( tokenType ) ,
&dwRetSize // 所需缓冲区的字节数
);
// 根据令牌的类型来输出相应的信息
if( TokenElevationTypeFull == tokenType ) {
// 3. 如果令牌是TokenElevationTypeFull , 则拥有至高无上的能力,可以给令牌添加任何特权
printf( "管理员账户,并拥有全部的权限,可以给令牌添加任何特权\n" );
return TRUE;
}
// 4. 如果是其他的, 则需要以管理员身份重新运行本进程. 这样就能以第三步的方法解决剩下的问题.
else if( TokenElevationTypeDefault == tokenType ) {
printf( "默认用户, 可能是一个普通用户, 可能是关闭UAC时登录的管理员用户\n" );
// 调用系统函数IsUserAnAdmin, 进一步确定是普通用户还是管理员用户
return IsUserAnAdmin();
}
else if( TokenElevationTypeLimited == tokenType ) {
// 判断受限制的用户是管理员
// 如果是管理员, 则这个令牌中会保存有管理员的SID
// 1. 获取系统内键管理员用户的SID
SID adminSid;
DWORD dwSize = sizeof( adminSid );
CreateWellKnownSid( WinBuiltinAdministratorsSid , // 获取SID的类型,这里是系统内键管理员
NULL , // 传NULL,获取本地计算机的管理员
&adminSid ,// 函数输出的管理员SID
&dwSize // 输入结构的大小,也作为输出
);
// 获取本令牌的连接令牌(受限制的令牌都会有一个连接的令牌,受限制的令牌正式由主令牌所创建的. )
TOKEN_LINKED_TOKEN linkToken;
GetTokenInformation( hToken ,
TokenLinkedToken , // 获取连接的令牌句柄
&linkToken ,
sizeof( linkToken ) ,
&dwSize
);
// 在连接的令牌中查找是否具有管理员的SID
BOOL bIsContain = FALSE; // 用于保存是否包含.
CheckTokenMembership( linkToken.LinkedToken , // 在这个令牌中检查
&adminSid , // 检查令牌中是否包含此SID
&bIsContain ); // 输出TRUE则包含,反之不包含
if( bIsContain ) {
printf( "权限被阉割的受限制管理员账户, 部分权限被移处理\n" );
}
return bIsContain; // 不是以管理员权限运行
}
return FALSE;
}
===================
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// 如果盾牌没有出现在按钮, 可以加入以下宏.
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#include "resource.h"
#include <shlobj.h>
BOOL IsAdmin( HANDLE hProcess );
INT_PTR CALLBACK DlgProc( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam );
BOOL IsAdmin( HANDLE hProcess );
int WINAPI WinMain( _In_ HINSTANCE hInstance , _In_opt_ HINSTANCE hPrevInstance , _In_ LPSTR lpCmdLine , _In_ int nShowCmd )
{
DialogBox( hInstance , MAKEINTRESOURCE( IDD_DIALOG1 ) , NULL , DlgProc );
}
INT_PTR CALLBACK DlgProc( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
switch( uMsg ) {
case WM_INITDIALOG:
{
HWND hButton = GetDlgItem( hWnd , BTN_RunAsAdmin );
// 判断当前是否是以管理员身份运行的进程.
if( !IsAdmin( GetCurrentProcess( ) ) ) {
// 如果不是, 则将一个按钮设置为带盾牌标志的按钮.
Button_SetElevationRequiredState( hButton , TRUE );
}
else {
// 如果已经以管理员身份运行,则将按钮隐藏
ShowWindow( hButton , SW_HIDE );
}
}
break;
case WM_COMMAND:
{
switch( LOWORD(wParam) ) {
case BTN_RunAsAdmin: // 以管理员身份运行的按钮被点击事件
{
// 1. 获取本进程路径
TCHAR path[ MAX_PATH ] = { 0 };
DWORD dwSize = MAX_PATH;
QueryFullProcessImageName( GetCurrentProcess( ) , 0 , path , &dwSize );
// 隐藏窗口
ShowWindow( hWnd , SW_HIDE );
// 2. 以管理员身份运行
ShellExecute( hWnd ,
L"runas" , /*系统命令,意思以管理运行一个进程*/
path ,
NULL , NULL , SW_SHOW );
if( ERROR_SUCCESS == GetLastError( ) ) {
// 如果创建成功则退出进程.
ExitProcess( 0 );
}
else {
// 如果创建进程失败, 则将窗口显示回来
ShowWindow( hWnd , SW_SHOW );
}
}
break;
}
}
break;
case WM_CLOSE:
EndDialog( hWnd , 0 );
break;
default:return FALSE;
break;
}
return TRUE;
}
BOOL IsAdmin( HANDLE hProcess )
{
HANDLE hToken = NULL;
OpenProcessToken( hProcess , TOKEN_QUERY , &hToken );
TOKEN_ELEVATION_TYPE tokenType = TokenElevationTypeDefault ; // 用于接收令牌类型
DWORD dwRetSize = 0; // 用于接收函数输出信息的字节数
// 2. 查询进程令牌中的权限提升值.( 这个值会记录当前的令牌是何种类型( 细节将17_权限管理_令牌的获取.cpp ) )
GetTokenInformation( hToken ,
TokenElevationType ,// 获取令牌的当前提升等级
&tokenType ,
sizeof( tokenType ) ,
&dwRetSize // 所需缓冲区的字节数
);
// 根据令牌的类型来输出相应的信息
if( TokenElevationTypeFull == tokenType ) {
// 3. 如果令牌是TokenElevationTypeFull , 则拥有至高无上的能力,可以给令牌添加任何特权,返回第0步执行代码.
return TRUE;
}
// 4. 如果是其他的, 则需要以管理员身份重新运行本进程. 这样就能以第三步的方法解决剩下的问题.
else if( TokenElevationTypeDefault == tokenType ) {
// 默认用户可能是一个没有权限的标准用户
// 也可能是UAC被关闭.
// 直接调用系统的函数IsUserAnAdmin 来判断用户是否是管理员.
return IsUserAnAdmin( );
}
else if( TokenElevationTypeLimited == tokenType ) {
return FALSE;
}
return FALSE;
}