UIPI – User Interface Privilege Isolation

O Windows 7 coloca uma barreira em torno de processos elevados para protegê-los de malware em execução na mesma área de trabalho com direitos de usuário padrão. Sem uma barreira, o malware poderia obter direitos administrativos pela injeção de código, por exemplo, através da troca de mensagens de janela (SendMessage).

O isolamento de privilégios de interface de usuário (UIPI - User Interface Privilege Isolation) é um recurso de segurança que impede que a maioria das mensagens sejam recebidas de um remetente que possui nível de integridade inferior. Nesse novo modelo de segurança, todos os processos e objetos possuem níveis de integridade onde a diretiva de integridade de um objeto pode restringir os acessos mesmo que estes tenham sido concedidos a um processo pelo modelo de segurança do DAC (Windows Discretionary Access Control).

O gerenciador de janelas compara o nível de integridade do remetente com o nível do destinatário e não permite processos com nível de integridade inferior enviar mensagens para processos com níveis de integridade superior

 


 

As aplicações que possuem nível de integridade baixo geralmente não pode enviar mensagens para aplicativos com privilégios mais elevados a menos que a maior aplicação privilegiada permita explicitamente a mensagem através da API ChangeWindowMessageFilter. Da mesma forma, os aplicativos com privilégios mais baixos podem ler, mas não é possível modificar um handle (HWND) possuído por um aplicativo privilegiado superior. Por razões de compatibilidade, SendMessage e outras APIs retornarão sucesso mesmo se a API foi bloqueada devido a problemas de privilégio.

Através da API ChangeWindowMessageFilter é possível permitir que um processo de integridade menor envie mensagens para um processo de integridade maior. O filtro, um pouco contrário à intuição, define a lista das mensagens que são permitidas serem enviadas por um processo de menor integridade.

BOOL WINAPI
ChangeWindowMessageFilter(

  _In_  UINT message,

  _In_  DWORD
dwFlag

);

Maiores detalhes da API ChangeWindowMessageFilter em: https://msdn.microsoft.com/en-us/library/ms632675(v=vs.85).aspx

Vamos utilizar a aplicação Broken Ping Pong, disponível em: https://msdn.microsoft.com/en-us/gg465097, como exemplo. A aplicação deve ser executada duas vezes para que existam duas telas (Windows Forms) para que a mensagens sejam trocadas com o objetivo de simular o jogo ping pong, conforme:

  
 

A aplicação funciona corretamente quando o nível de integridade dos dois processos são iguais. Execute o Process Explorer para visualizar o nível de integridade dos processos. O Process Explorer está disponível para download em: https://technet.microsoft.com/en-us/sysinternals/bb896653.aspx.

No Process Explorer habilite a visualização da coluna que exibe os níveis de integridade (Integrity Level) dos processos.


  
  
Localize as duas instâncias dos processos BrokenManagedPingPong.exe e observe que o nível de integridade dos processos são iguais. Nesse caso, o nível de integridade deverá ser médio, caso o UAC estiver
habilitado e os processos terem sido executados sem elevação.
  
  

O próximo passo é fechar as duas janelas do Ping Pong, executar normalmente a primeira instância do BrokenManagedPingPong e executar a segunda instância elevada (selecione a opção executar como administrador). Observe, através do Process Explorer, que o nível de integridade dos processos deverá ser diferente.

Quando o nível de integridades dos processos é diferente a aplicação não funciona, ou seja, a mensagem ping pong não salta de uma tela para outra. Isso ocorre, pois um processo não pode enviar mensagem para outro processo que possua um nível de integridade maior.

O problema ocorre no construtor do formulário onde o método PostMessage falha ao tentar enviar a mensagem para a janela que pertence a um processo que possui nível de integridade maior.
 

O problema pode ser corrigido através da API ChangeWindowMessageFilter que permite filtrar as mensagens que são exceção à regra e que consequentemente podem ser transmitidas entre processos com diferentes níveis de integridade.

O primeiro passo é adicionar o seguinte código para poder utilizar a API ChangeWindowMessageFilter:

E o segundo e último passo é adicionar o código abaixo para adicionar a mensagem, trafegada entre os processos, na filtro de exceção.

Após a correção a aplicação irá funcionar independentemente se as duas instâncias possuírem o mesmo nível de integridade.