美文网首页
windows权限管理

windows权限管理

作者: MagicalGuy | 来源:发表于2018-10-09 00:19 被阅读0次
    // 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;
    }
    

    相关文章

      网友评论

          本文标题:windows权限管理

          本文链接:https://www.haomeiwen.com/subject/kbwlaftx.html