Em junho deste ano, pesquisadores da ESET identificaram um exploit que se aproveita de uma vulnerabilidade 0-day que estava sendo usada em ataques altamente direcionados na Europa Oriental.

O exploit abusa de uma vulnerabilidade de escalonamento de privilégio local no Microsoft Windows, mais especificamente um desreferenciamento de ponteiro NULL (nulo) no componente win32k.sys. Depois que o exploit foi descoberto e analisado, a informação foi comunicada ao Microsoft Security Response Center, que rapidamente corrigiu a vulnerabilidade e lançou um patch.

A vulnerabilidade afeta as seguintes versões do Windows:

  • Windows 7 for 32-bit Systems Service Pack 1
  • Windows 7 for x64-based Systems Service Pack 1
  • Windows Server 2008 for 32-bit Systems Service Pack 2
  • Windows Server 2008 for Itanium-Based Systems Service Pack 2
  • Windows Server 2008 for x64-based Systems Service Pack 2
  • Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1
  • Windows Server 2008 R2 for x64-based Systems Service Pack 1

Este artigo está enfocado nos detalhes técnicos da vulnerabilidade e sua exploração. Em outro artigo que publicaremos amanhã (12), nos aprofundaremos com informações sobre o malware e suas implicações.

Exploração

Tal como acontece com outras vulnerabilidades no Microsoft Windows win32k.sys que foram reveladas nos últimos anos, este exploit usa objetos do tipo de menu pop-up. Por exemplo, os exploits de escalonamento de privilégios local do grupo Sednit que analisamos em 2017 usavam objetos de menu e técnicas muito semelhantes com as deste exploit.

Este exploit cria duas janelas: uma para a primeira etapa e outra para a segunda etapa da exploração. Para a primeira janela, cria objetos de menu pop-up e adiciona itens de menu usando as funções CreatePopupMenu e AppendMenu. Além disso, o exploit configura os hooks WH_CALLWNDPROC e EVENT_SYSTEM_MENUPOPUPSTART.

Em seguida, o exploit exibe um menu usando a função TrackPopupMenu. Nesse momento, o código hookeado a EVENT_SYSTEM_MENUPOPUPSTART é executado. Este código tenta abrir-se como o primeiro item disponível no menu enviando a sequência de mensagens MN_SELECTITEM, MN_SELECTFIRSTVALIDITEM e MN_OPENHIERARCHY para o menu.

O próximo passo é muito importante para acionar essa vulnerabilidade. O exploit deve capturar o momento em que o menu inicial é criado e o submenu está prestes a ser criado. Para isso, o exploit conta com código que manipula a mensagem WM_NCCREATE no hook WH_CALLWNDPROC. Quando o código do exploit detecta que o sistema está nesse estado, ele envia a mensagem MN_CANCELMENUS (0x1E6) para o primeiro menu, que cancela esse menu. No entanto, seu submenu ainda deve ser criado.

Agora, se verificarmos o objeto submenu no modo kernel, veremos que tagPOPUPMENU> ppopupmenuRoot é igual a 0. Esse estado permite que o atacante use esse elemento nessa estrutura de kernel como um desreferenciamento de ponteiro NULL. O exploit atribui uma nova página no endereço 0x0 e este endereço será tratado como um objeto tagPOPUPMENU (veja a Figura 1) pelo kernel.

Figura 1. A estrutura do kernel tagPOPUPMENU

Neste ponto, os atacantes usam a segunda janela. O objetivo principal do exploit é transformar o bit bServerSideWindowProc na estrutura tagWND da segunda janela. Isso causa a execução de um procedimento WndProc no modo kernel.

Para realizar essa ação, os atacantes filtram o endereço de memória do kernel da estrutura tagWND da segunda janela chamando a função HMValidateHandle não exportada na biblioteca user32.dll. Em seguida, o exploit cria um objeto tagPOPUPMENU falso na página nula e envia uma mensagem MN_BUTTONDOWN para um submenu.

Depois disso, o kernel irá eventualmente executar a função win32k!xxxMNOpenHierarchy.

Figura 2. Código desmontado da função win32k!xxxMNOpenHierarchy

Esta função passa um objeto criado para a página nula ao win32k!HMAssignmentLock. O bit bServerSideWindowProc está configurado dentro da função win32k!HMDestroyUnlockedObject, que está localizada em algumas chamadas mais profundas dentro do win32k!HMAssignmentLock.

Figura 3. Código desmontado da função win32k!HMDestroyUnlockedObject

Tudo está pronto! Agora, o exploit pode enviar uma mensagem específica para a segunda janela com o objetivo de executar o WndProc no modo kernel.

Como etapa final, o exploit substitui o token do processo atual pelo token do sistema.

O patch publicado, entre outros, adiciona a revisão de um ponteiro NULL na função win32k!xxxMNOpenHierarchy.

Figura 4. Diferenças de código entre duas versões do win32k.sys - original (à esquerda) e corrigido (à direita)

Conclusão

O exploit funciona apenas em versões antigas do Windows, pois desde o lançamento do Windows 8, um processo do usuário não tem permissão para mapear a página nula. A Microsoft implementou essa atenuação no Windows 7 para sistemas baseados em x64.

Aqueles que continuam usando o Windows 7 Service Pack 1 em sistemas de 32 bits devem considerar a atualização para um sistema operacional mais novo, já que a extensão do suporte para o Windows 7 Service Pack 1 terminará em 14 de janeiro de 2020. Isso significa que os usuários do Windows 7 não receberão atualizações de segurança críticas, portanto, vulnerabilidades como essas permanecerão sem correção para sempre.

Indicadores de Comprometimento (IoCs)

SHA-1 hash ESET detection name
CBC93A9DD769DEE98FFE1F43A4F5CADAF568E321 Win32/Exploit.CVE-2019-1132.A