• 7.4 通过API枚举进程权限


    GetTokenInformation 用于检索进程或线程的令牌(Token)信息。Token是一个数据结构,其包含有关进程或线程的安全上下文,代表当前用户或服务的安全标识符和权限信息。GetTokenInformation函数也可以用来获取这些安全信息,通常用于在运行时检查某个进程或线程的权限或安全信息。

    该函数原型如下:

    BOOL GetTokenInformation(
      HANDLE TokenHandle,
      TOKEN_INFORMATION_CLASS TokenInformationClass,
      LPVOID TokenInformation,
      DWORD TokenInformationLength,
      PDWORD ReturnLength
    );
    

    参数说明:

    • TokenHandle:当前进程或线程令牌的句柄。
    • TokenInformationClass:表示要检索的Token信息类别,是TOKEN_INFORMATION_CLASS枚举类型的值之一。这个参数的值确定TokenInformation参数的方案,以及返回的信息类型。
    • TokenInformation:指向要接收信息的缓冲区的指针。
    • TokenInformationLength:要接收的缓冲区的大小(以字节为单位)。
    • ReturnLength:实际缓冲区的大小(以字节为单位)。

    常见的TokenInformationClass值包括:

    • TokenUser:用户标识信息;
    • TokenGroups:组信息;
    • TokenOwner:所有者信息;
    • TokenPrimaryGroup:主组信息;
    • TokenPrivileges:特权信息;
    • TokenSessionId:会话ID信息。

    该函数的返回值为BOOL类型。如果函数执行成功,则返回非零值,否则返回零。如果函数返回零,则可以调用 GetLastError() 函数获取错误代码。

    #include 
    #include 
    #include 
    
    void ShowPrviliges(HANDLE process)
    {
      // 通过进程句柄获取到进程令牌
      HANDLE hToken;
      OpenProcessToken(process, TOKEN_QUERY, &hToken);
    
      // 获取查询到的令牌信息
      DWORD dwSize;
      GetTokenInformation(hToken, TokenPrivileges, NULL, NULL, &dwSize);
    
      // 根据令牌中的大小分配空间
      char* pBuf = new char[dwSize] {};
      GetTokenInformation(hToken, TokenPrivileges, pBuf, dwSize, &dwSize);
    
      // 将内存中的内容用要查询数据结构体解析
      TOKEN_PRIVILEGES* pTp = (TOKEN_PRIVILEGES*)pBuf;
      DWORD dwCount = pTp->PrivilegeCount;               // 解析出权限个数
      LUID_AND_ATTRIBUTES* pluid = pTp->Privileges;      // 具备的权限类型
    
      for (int i = 0; i < dwCount; i++, pluid++)
      {
        char szName[100] = {};
        DWORD dwLen = sizeof(szName);
        LookupPrivilegeNameA(0, &pluid->Luid, szName, &dwLen);
        switch (pluid->Attributes)
        {
        case 0:
          printf("ID => %3d \t 状态 => 关闭 \t\t 类型 => %s \n", i, szName); break;
        case 1:
          printf("ID => %3d \t 状态 => 默认 \t\t 类型 => %s \n", i, szName); break;
        case 2:
          printf("ID => %3d \t 状态 => 开启 \t\t 类型 => %s \n", i, szName); break;
        case 3:
          printf("ID => %3d \t 状态 => 默认开启 \t\t 类型 => %s \n", i, szName); break;
        }
      }
      delete pBuf;
    }
    
    int main(int argc, char* argv[])
    {
      // 拿到自身程序的句柄
      HANDLE LocalProcess = GetCurrentProcess();
      ShowPrviliges(LocalProcess);
    
      system("pause");
      return 0;
    }
    

    如下所示代码同样是一段权限检索的实现,函数EnumOwner()接受一个指向进程令牌的句柄,并使用它来检索有关令牌用户的信息。使用GetTokenInformation()获取一个包含令牌用户的安全标识符(SID)指针的TOKEN_USER结构。然后,它使用LocalAlloc()SID分配内存,并使用CopySid()SID复制到该内存中。最后使用LookupAccountSid()检索与SID相关联的用户账户的名称。函数返回指向包含账户名称的字符字符串的指针。

    main()函数中使用OpenProcess()PROCESS_QUERY_INFORMATION标志检索当前进程的句柄。然后,它使用OpenProcessToken()TOKEN_QUERY标志检索进程令牌的句柄。将该句柄传递给EnumOwner()以检索与令牌相关联的用户账户名称。最后使用printf()打印账户名称,使用CloseHandle()关闭令牌句柄,使用CloseHandle()关闭进程句柄。

    #include 
    #include 
    #include 
    
    // 通过进程Token获取进程权限类型
    char * __stdcall EnumOwner(HANDLE htoken)
    {
      DWORD dwLen;
      PSID pSid = 0;
      TOKEN_USER* pWork;
      SID_NAME_USE use;
      TCHAR User[256], Domain[256];
    
      GetTokenInformation(htoken, TokenUser, NULL, 0, &dwLen);
      pWork = (TOKEN_USER*)LocalAlloc(LMEM_ZEROINIT, dwLen);
      if (GetTokenInformation(htoken, TokenUser, pWork, dwLen, &dwLen))
      {
        dwLen = GetLengthSid(pWork->User.Sid);
        pSid = (PSID)LocalAlloc(LMEM_ZEROINIT, dwLen);
        CopySid(dwLen, pSid, pWork->User.Sid);
        dwLen = 256;
        LookupAccountSid(NULL, pSid, &User[0], &dwLen, &Domain[0], &dwLen, &use);
        // printf("\t 主机 => %s \t 权限用户 => %s ", Domain, User);
        return User;
      }
      return NULL;
    }
    
    int main(int argc, char* argv[])
    {
      HANDLE ProcessHandle, hToken;
    
      ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE,GetCurrentProcessId());
      if (ProcessHandle != NULL)
      {
        if (OpenProcessToken(ProcessHandle, TOKEN_QUERY, &hToken))
        {
          char *token = EnumOwner(hToken);
          printf("[+] 当前进程身份: %s \n", token);
          CloseHandle(hToken);
          CloseHandle(ProcessHandle);
        }
      }
    
      system("pause");
      return 0;
    }
    

    本文作者: 王瑞
    本文链接: https://www.lyshark.com/post/136e2c9d.html
    版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

  • 相关阅读:
    ChatGPT工作提效之使用python开发对接百度地图开放平台API的实战方案(批量路线规划、批量获取POI、突破数量有限制、批量地理编码)
    AUTOSAR EcuM休眠阶段的具体实现详解
    【23种设计模式】组合模式(八)
    MFC中如何自动调整CCombobox宽度
    携手亚信安慧AntDB,在数智化浪潮中乘风破浪
    2--OpenCV:图形基础
    Vue中使用Echarts封装为公用组件(简单复制粘贴)
    java-php-python-ssm基于内容的校园热点新闻推送网站计算机毕业设计
    Redis单线程为什么还能这么快
    【附源码】Python计算机毕业设计汽车出租平台
  • 原文地址:https://www.cnblogs.com/LyShark/p/17723951.html