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;
}
上一篇下一篇

猜你喜欢

热点阅读