Executar operações privilegiadas usando C++

Aplicativos cliente especiais podem invocar operações privilegiadas. Por exemplo, um aplicativo pode permitir que um gerente reinicie um computador do escritório sem resposta. Usando a WMI (Instrumentação de Gerenciamento do Windows), você pode executar uma operação privilegiada chamando o provedor WMI para a operação privilegiada.

O procedimento a seguir descreve como chamar um provedor para uma operação privilegiada.

Para chamar um provedor para uma operação privilegiada

  1. Obtenha permissões para o processo do cliente a fim de executar a operação com privilégios.

    Normalmente, um administrador define as permissões usando ferramentas administrativas do sistema antes de executar o processo.

  2. Obtenha permissão para o processo do provedor para habilitar a operação privilegiada.

    Normalmente, você pode definir permissões de provedor com uma chamada para a função AdjustTokenPrivileges.

  3. Obtenha permissão para o processo do cliente para habilitar a operação privilegiada.

    Essa etapa só será necessária se o provedor for local em relação ao cliente. Se o cliente e o provedor existirem no mesmo computador, o cliente deverá habilitar especificamente a operação privilegiada usando uma das seguintes técnicas:

    • Se o cliente for proprietário do processo, o cliente poderá usar AdjustTokenPrivileges para ajustar o token de processo antes de chamar o WMI. Nesse caso, você não precisa de nenhum código adicional.
    • Se o cliente não puder acessar o token do cliente, o cliente poderá usar o procedimento a seguir para criar um token de thread e usar AdjustTokenPrivileges nesse token.

O procedimento a seguir descreve como criar um token de thread e usar AdjustTokenPrivileges nesse token.

Para criar um token de thread e usar AdjustTokenPrivileges nesse token

  1. Crie uma cópia do token de processo chamando ImpersonateSelf.

  2. Recupere o token de thread recém-criado chamando GetTokenInformation.

  3. Habilite a operação privilegiada com uma chamada para AdjustTokenPrivileges no novo token.

  4. Obtenha um ponteiro para IWbemServices.

  5. Camufle o ponteiro para IWbemServices com uma chamada para CoSetProxyBlanket.

  6. Repita as etapas de 1 a 5 em cada chamada ao WMI.

    Observação

    Você deve repetir as etapas porque o COM armazena tokens em cache incorretamente.

     

O exemplo de código neste tópico requer a instrução #include a seguir para compilar corretamente.

#include <wbemidl.h>

O exemplo de código a seguir mostra como habilitar privilégios em um computador local.

// Get the privileges 
// The token has been obtained outside the scope of this code sample
// ================== 
DWORD dwLen;
bool bRes;
HANDLE hToken;

// obtain dwLen
bRes = GetTokenInformation(
  hToken, 
  TokenPrivileges, 
  NULL, 
  0,
  &dwLen
); 

BYTE* pBuffer = new BYTE[dwLen];
if(pBuffer == NULL)
{
  CloseHandle(hToken);
  return WBEM_E_OUT_OF_MEMORY;
} 

bRes = GetTokenInformation(
  hToken, 
  TokenPrivileges, 
  pBuffer,     
  dwLen,        
  &dwLen
);

if (!bRes)
{
  CloseHandle(hToken);
  delete [] pBuffer;
  return WBEM_E_ACCESS_DENIED;
} 

// Iterate through all the privileges and enable them all
// ====================================================== 
TOKEN_PRIVILEGES* pPrivs = (TOKEN_PRIVILEGES*)pBuffer;
for (DWORD i = 0; i < pPrivs->PrivilegeCount; i++)
{
  pPrivs->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED;
} 
// Store the information back in the token
// ========================================= 
bRes = AdjustTokenPrivileges(
  hToken, 
  FALSE, 
  pPrivs, 
  0, NULL, NULL
);

delete [] pBuffer;
CloseHandle(hToken); 

if (!bRes)
  return WBEM_E_ACCESS_DENIED;
else
  return WBEM_S_NO_ERROR;