zoukankan      html  css  js  c++  java
  • 如何修改线程的Access Token

    1.  什么是Access Token

    Access Token用来标识一个用户,其中包括用户的SID和用户所属组的SID,还包括这个用户和所属用户组的所拥有的权限列表。

    当用户输入用户名和密码登陆到Windows之后,Windows会创建一个Acess Token,用来标识这个用户。 在这个用户下创建的进程都将得到一份这个Access Token的备份。当进程需要访问一个可以加密的对象(如文件,事件等)时,windows利用这个Access Token来跟对象的Security Descriptor进行比较,以确认这个进程是否有权限来访问这个对象。(关于SIDSecurity Descriptor请参阅其他资料)

     

    2.  线程的Access Token

    进程被创建时,从系统中得到Access Token是属于进程,线程刚开始创建的时候并没有Access Token。我们可以通过一个叫Impersonate的方法赋予线程一个Access Token,这样就使得线程具有跟进程不同的Access Token,用来完成一些使用进程的Access Token无法完成的任务。

    Impersonate一般用于Client/Server模式中,Client发送一个请求访问服务期内的资源,如果Server接到请求后直接去访问资源的话,可能会导致Server无法控制Client可以访问哪些资源。Windows提供了Impersonate这种解决方案,Server的一个线程可以Impersonate Client,这样这个线程就将以Client的身份来访问资源,从而可以直接控制Client是否可以访问资源。

     

    3.  Impersonate的方法

    有以下几个函数可以实现Impersonate

    a)         DdeImpersonateClient 用于在DDEImpersonate

    b)        ImpersonateNamedPipeClient 用于在NamedPipeImpersonate

    c)         ImpersonateLoggedOnUser 利用Access TokenImpersonate

    d)        ImpersonateSelf           利用进程的Access TokenImpersonate

    e)         SetThreadToken   使用Access TokenImpersonate其他的线程

    f)         RpcImpersonateClient 用于在RPCImpersonate

    g)        ImpersonateSecurityContext      用于在security package Impersonate

     

    4.  利用ImpersonateLoggedOnUser来实现Impersonate

    其他的一些Impersonate的方法大都是使用在特定的环境下,ImpersonateLoggedOnUser则仅需要有用户的Access Token就可以。

    获取用户的Access Token有两种方法

    a)       利用LogonAsUser,通过输入用户名,密码,域信息来获取用户的Access Token

    b)      利用OpenProcessToken来直接进程的Access Token

     

    5.  例子

    下面一个利用ImpersonateLoggedOnUser来实现Impersonate的例子。BOOL Impersonate(LPCSTR szFileName)函数中,输入参数为需要Impersonate的进程名,比如说explorer.exe

    Int main()

    {     

    OSVERSIONINFO os = {sizeof(OSVERSIONINFO)};

    GetVersionEx(&os);

    if(os.dwMajorVersion >= 6 ){//Only Impersonate when it is vista and later

            Impersonate(_T("explorer.exe"));

            //now this thread have the Access Token of explorer.exe

    }

    }

     

    BOOL Impersonate(LPCSTR szFileName)

    {

    BOOL bResult = FALSE;

    HANDLE hProcess = NULL;

    HANDLE hToken = NULL;

     

    for(DWORD dw=0; dw<0xFFFFFF; Sleep((++dw)*100)){//loop until success

            DWORD dwSessionID = 0;//GetActiveConsoleSessionId();

            if(!ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionID))

                   continue;

            DWORD dwPID = GetPIDOFSpecifiedSession(dwSessionID, szFileName, NULL);

            hProcess = OpenProcess(PROCESS_ALL_ACCESS,

                   TRUE, dwPID);

            if(hProcess == NULL)

                   continue;

           

            if(!OpenProcessToken(hProcess,

                   TOKEN_READ | TOKEN_DUPLICATE | TOKEN_QUERY|TOKEN_ASSIGN_PRIMARY ,

                   &hToken ))

            {

                   CloseHandle(hProcess);

                   hProcess = NULL;

                   DbgPrint("In CreateProcessAsActiveWinlogon, Open Process Failed");

                   continue;

            }

     

            bResult = ImpersonateLoggedOnUser(hToken);

            break;

    }

    return bResult;

    }

     

    DWORD GetActiveConsoleSessionId()

    {

    DWORD dwResult = 0;

    HINSTANCE hKernal32 = NULL;

    do {

            OSVERSIONINFO os = {sizeof(OSVERSIONINFO)};

            GetVersionEx(&os);

            if(os.dwMajorVersion == 5 && os.dwMinorVersion==0){//2000

                   break;

            }

            else{//xp and vista

                   typedef DWORD (WINAPI* PWTSActiveSessionID)();

                   hKernal32 = LoadLibrary(_T("kernel32.dll"));

                   if(hKernal32 == NULL)

                          break;

     

                   PWTSActiveSessionID pWTSActiveSessionID =

                          (PWTSActiveSessionID)GetProcAddress(hKernal32,

                          _T("WTSGetActiveConsoleSessionId"));

                   if(pWTSActiveSessionID == NULL)

                          break;

                   dwResult = pWTSActiveSessionID();

            }

    } while(FALSE);

    if(hKernal32 != NULL)

            FreeLibrary(hKernal32);

    return dwResult;    

    }

     

     

    DWORD GetPIDOFSpecifiedSession(DWORD dwSessionID, LPCTSTR lpProcessName,

                                                      LPCTSTR lpUserName)

    {

    DWORD dwRet = 0;

    PWTS_PROCESS_INFO lpProcessInfo = NULL;

    do {

            if (lpProcessName==NULL)

                   break;

           

            DWORD dwProcessCount = 0;

            if(!WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &lpProcessInfo,

                   &dwProcessCount))

            {//This functions will fail if it is run in windows 2000

            //and in windows 2000, I can just using the process id of current process instead

                   DbgPrint("In CCheckPIN::GetPIDOFSpecifiedSession, WTSEnumerateProcesses returns FALSE,\

                          Last Error:%d", GetLastError());

                   dwRet = GetCurrentProcessId();//using current process id

                   break;

            }

           

            // dump each process description

            for (DWORD dwIndex = 0; dwIndex < dwProcessCount;

            dwIndex++)

            {

                   if(lpProcessInfo[dwIndex].SessionId != dwSessionID)

                          continue;

                  

                   if(lstrcmpi(lpProcessInfo[dwIndex].pProcessName, lpProcessName) != 0 )

                          continue;

                  

                   if(lpUserName != NULL){

                          TCHAR szUser[MAX_PATH] = {0};

                          DWORD chUser = MAX_PATH;

                          TCHAR szDomain[MAX_PATH] = {0};

                          DWORD chDomain = MAX_PATH;

                          SID_NAME_USE   snu;

                         

                          if(!LookupAccountSid(NULL, lpProcessInfo[dwIndex].pUserSid, szUser,

                                 &chUser, szDomain, &chDomain, &snu))

                          {

                                 DbgPrint("LookupAccountSid returns FALSE, LastError:%d", GetLastError());

                                 break;

                          }

                          DbgPrint("szUser:%s, lpUserName:%s", szUser, lpUserName);

                          if(lstrcmpi(szUser, lpUserName) != 0)

                          {

                                 break;

                          }

                   }

                  

                   dwRet = lpProcessInfo[dwIndex].ProcessId;

                   break;

            }//end of for loop

    }while(FALSE);

     

    if(lpProcessName != NULL){

            WTSFreeMemory(lpProcessInfo);

    }

    return dwRet;

    }

     

  • 相关阅读:
    关于在windows10中的vmware9.0里面安装的ubuntukylin15.04和windows共享目录的一些反思
    关于最近工程的一些心得
    关于springMVC中component-scan的问题以及springmvc.xml整理
    初学node.js有感三
    初学node.js有感二
    初学node.js有感一
    编译原理——算符优先分析文法(附源代码)
    数据结构与算法系列研究九——排序算法的一些探讨
    LeetCode: Same Tree
    LeetCode: Symmetric Tree
  • 原文地址:https://www.cnblogs.com/ahuo/p/1997289.html
Copyright © 2011-2022 走看看