Como o malware evita caixas de areia com o Visual Basic

Todos os dias, no JSOC CERT, encontramos eventos de diferentes caixas de proteção que funcionam como parte das soluções AntiAPT de nossos clientes e permitem que milhares de arquivos do tráfego da Web e de email passem por eles. Vale a pena notar que os modernos sistemas Sandbox em seu desenvolvimento foram muito mais além do que simplesmente interceptar chamadas do sistema no Modo Kernel e funções da API no Modo Usuário. Cada vez mais, eles usam seu próprio hypervisor, um sistema para emular a atividade do usuário, instrumentação dinâmica, hash e clustering em seções de código, análise de cobertura de código etc. Essa variedade de tecnologias cria a ilusão de que, se um arquivo não funciona na caixa de areia e não mostra sua “cara verdadeira”, então provavelmente é o APT ou uma tecnologia inovadora para detectar um ambiente virtual, do qual a comunidade IB ainda não está ciente. Mas ...


Como não conhecemos os recursos internos do trabalho de caixas de areia comerciais, em alguns casos, verificamos duas vezes - analisamos manualmente as amostras que passaram no teste. Recentemente, descobrimos várias vezes que algumas caixas de proteção comerciais (por razões objetivas, não podemos dizer quais) não detectaram determinados arquivos maliciosos durante a análise dinâmica e, se o analisador estático também estava silencioso, o arquivo foi ignorado.

A verificação da sandbox conseguiu ignorar famílias de malware conhecidas como Pony, Loki e Hawkeye. Apenas uma coisa os uniu - eles foram cobertos por um empacotador escrito em Visual Basic.

Dado que essas famílias HPE há muito não são novidade, o veredicto "positivo" da sandbox é muito deprimente. Portanto, decidimos descrever o princípio geral de operação desse empacotador e as observações feitas por nós ao longo de algum tempo.
O esquema geral do trabalho do empacotador é condicionalmente dividido em 4 etapas e é mostrado no diagrama abaixo.



O ponto de entrada de um arquivo malicioso parece típico dos aplicativos Visual Basic:



Nós encontramos várias opções para esse empacotador, e o código do VB Wrapper mudou com frequência, mas a tarefa executada permaneceu a mesma: transferir o controle para o código do Estágio 1. Em amostras anteriores, o controle foi transferido usando as funções de API da classe Enum * (por exemplo, EnumWindows, EnumCalendarInfo, etc.). e) para o qual o endereço Estágio 1 do código foi indicado como parâmetro. Recentemente, observamos que o controle é transferido diretamente.

Etapa 1


A gerência recebe o código Estágio 1. Este código não é criptografado, mas é ofuscado. Os métodos de ofuscação variam de amostra para amostra, mas o algoritmo de operação geral não muda:

  1. Um ciclo com muitas instruções (incluindo lixo) que gera a chave necessária para decodificar o código do Estágio 2. A peculiaridade desse trecho de código é que não há funções de suspensão, mas devido ao grande número de iterações, sua execução leva em média 1-2 minutos.
  2. Descriptografia (XOR regular) e transferência de controle para o código do Estágio 2.

A captura de tela abaixo mostra exemplos de métodos de ofuscação usados:



2 etapa


A principal tarefa do código no Estágio 2 é verificar o ambiente e implementar métodos anti-depuração. Algumas seções do código são criptografadas (descriptografadas antes da execução e, depois disso, criptografadas novamente com o mesmo algoritmo XOR) para dificultar a detecção por assinaturas. Após a descriptografia, os recursos característicos são visíveis, segundo os quais o código do Estágio 2 pode ser reconhecido por análise manual.



A lista de verificações é bastante grande e difere em diferentes versões do empacotador, por isso, forneceremos alguns métodos encontrados em todas as versões com capturas de tela e, no final, listaremos a lista inteira na tabela.

1) GetTickCount + Sleep


O registro de data e hora atual é obtido, o modo de suspensão é chamado por 2 segundos, após o qual outro registro de data e hora é obtido imediatamente.

Depois disso, a diferença entre as marcas é verificada (se 2 segundos realmente passaram).



2) SetErrorMode


Verifica a operação correta da chamada da API SetErrorMode. A função é chamada duas vezes seguidas com os parâmetros 0x800 e 0x0, após o qual o resultado da segunda chamada é verificado: deve ser igual a 0x800.



3) SetLastError


Primeiro, é chamado um SetLastError com um parâmetro 0x5, após o qual é verificado se o valor do último código de erro no TEB está definido corretamente (ou seja, é 0x5).



4) Verificando o movimento do cursor


O código entra em um loop sem fim, esperando o mouse se mover.



5) DbgBreakPoint e DbgUiRemoteBreakin


Essas funções são modificadas para impedir que o depurador se conecte ao processo.


Técnica


Comentário


GetTickCount + Sleep


Verificando timestamps


SetErrorMode


Verificando se a função está funcionando corretamente


SetLastError


Verificando se a função está funcionando corretamente


GetCursorPos


Verifique o movimento do cursor


Dbgbreakpoint


Modificação de função para impedir a conexão do depurador


DbgUiRemoteBreakin


Modificação de função para impedir a conexão do depurador


Exclusão de gancho


Os primeiros 5 bytes de funções são restaurados no ntdll.dll, caso haja ganchos


NtSetInformationThread


Parâmetro 0x11 (ThreadHideFromDebugger)


GetThreadContext + verifique DR


Registros de depuração DR0-DR3, DR6, DR7 são verificados.


Verificar pontos de interrupção


As instruções INT3 (0xCC), int 3 (0xCD 0x03) e ud2 (0x0F 0x0B) no início de algumas funções são verificadas


cpuid (EAX = 0x0)


Os registros EAX, ECX, EDX são verificados


cpuid (EAX = 0x40000000)


Os registros EAX, ECX, EDX são verificados


cpuid (EAX = 0x1)


31º bit ECX verificado


PEB (sendo depurado)


Verifica o valor 0x1


PEB (NtGlobalFlag)


Valor verificado 0x70


NtQueryInformationProcess


Chamado com sinalizadores ProcessDebugPort (0x7), ProcessDebugFlags (0x1F), ProcessDebugObjectHandle (0x1E)


Verificação do nome do processo


As strings "amostra", "caixa de areia", "vírus", "malware", "auto". São verificadas



Se todas as técnicas do estágio 2 forem concluídas, a linha de comandos será verificada quanto à conformidade com o formato especial. Se a verificação falhar, as seguintes ações serão executadas:

1) A função CreateProcess é chamada com o sinalizador CREATE_SUSPENDED para reiniciar o processo atual. Nesse caso, a linha de comando tem o formato necessário.
2) Usando as funções GetContextThread e SetContextThread, o ponto de entrada é alterado para um novo, localizado no código do Estágio 1.
3) Repita as etapas 1 e 2 (incluindo um ciclo longo e todas as verificações). Dessa vez, a verificação da linha de comando é bem-sucedida e o processo prossegue para a próxima etapa.

3 etapa


Nesse estágio, o corpo do vírus principal é descriptografado e a técnica Process Hollowing é executada no processo atual, após o qual o controle é transferido para o ponto de entrada do vírus principal.

Lição aprendida


Não podemos dizer exatamente o que causa essa ou aquela sandbox nesse caso, mas quero acreditar que a possibilidade de usar as técnicas descritas no artigo por malware foi fornecida pelos fornecedores por um longo tempo, e o problema está apenas no longo atraso na primeira etapa do trabalho do empacotador .

Apesar de as caixas de areia modernas serem posicionadas principalmente como parte dos sistemas de proteção contra ataques de APT, nossas observações sugerem que mesmo famílias maliciosas conhecidas pela comunidade penetram na infraestrutura com constância invejável. Como não há garantias de que a amostra que contornou o sandbox não terá algumas técnicas de desvio de antivírus em seu arsenal, você não pode confiar nesse monte de soluções protetoras. Nesses casos, um processo de monitoramento adequadamente construído, incluindo eventos de segurança da informação dos hosts finais, pode garantir uma resposta oportuna e minimizar possíveis danos.

Source: https://habr.com/ru/post/pt473086/


All Articles