1. Introdução
As mídias USB, e em especial os pen drives, são responsáveis por boa parte das infecções por vírus e malwares nas estações de trabalho e até servidores utilizados por usuários incautos. Um simples “espetar” de um pen drive USB pode passar por cima de todas as medidas segurança implementadas no ambiente de rede. Pensando nisso, resolvi buscar uma forma de imunizar uma mídia USB, de forma passiva, de modo que a proteção fique na mídia e não na máquina. Não existe milgare, mas é possível diminuir bastante o risco de infecção com a técnica que apresentarei.
2. Como a infecção ocorre
Quando uma mídia USB é inserida numa máquina com Windows, o recurso de autoreprodução é iniciado. Se na raiz da mídia existir um arquivo autorun.inf, este é lido pelo sistema e suas instruções são processadas, tudo de forma automática. A técnica mais eficiente para infectar uma mídia USB é, então, copiar para a mídia o malware em si (geralmente um binário PE) e criar também um autorun.inf na raiz da mídia que execute o malware toda vez que a mídia é inserida numa máquina com Windows. Este processo é explicado no texto “Como remover vírus de pen drive” [1], que escrevi em janeiro de 2010.
3. A ideia da proteção
Há várias tentativas de evitar essas infecções, desde programas simples que tentam remover indícios de vírus nas mídias USB até softwares mais complexos, apelidados de “firewalls” USB, que permitem controlar todo o tráfego. O problema é que a máquina é protegida, mas não a mídia USB. Se você usa o pen drive, por exemplo, em outra máquina, ele pode ser infectado e servir de meio de disseminação, pois os softwares que protegem a USB estão na sua máquina e não no pen drive.
Como todos os malwares que analisei criam um autorun.inf para se autoreproduzir, a ideia é criar um autorun.inf sadio no raíz da mídia USB, que seja “inalterável”, “indeletável”. Dessa forma, o malware não conseguirá sobrescrever o autorun.inf saudável pelo seu malicioso e o executável do malware pode até ser copiado para a mídia, mas não será inicializado quando a mídia for inserida num Windows qualquer, ou seja, ficará simplesmente armazenado na mídia, mas inofensivo (a não ser que algum usuário encontre manualmente o executável e o execute). Mas será possível? Vamos aos testes. Verificando a possibilidade
Depois de algumas buscas sobre criação de arquivos “indeletáveis”, encontrei o Panda USB Vaccine [2], que promete fazer exatamente o proposto. Ele realmente funciona e cria um autorun.inf “indeletável” no raíz da mídia USB. O inconveniente, para mim, é que ele é um software de código fechado e não há documentação sobre como ele faz isso, além de rodar somente em Windows. Eu estava desenvolvendo o USBForce [3], um software livre para proteção contra pragas em mídias USB quando encontrei o Vaccine. Naturalmente eu gostaria de implementar essa funcionalidade de criação de um autorun.inf “indeletável” no meu software. Além disso, não conseguiria dormir sem saber como (tecnicamente) este arquivo é criado e se era mesmo indeletável.
4. Revertendo a técnica do Vaccine:
Utilizei algumas ferramentas para saber como o Vaccine funciona, começando pelo RDG Packer Detector [4], que além de outras funcionalidades, consegue saber qual o compilador utilizado para gerar o binário, informação muito útil antes do debugging: O RDG informa que não há packer e que o software foi escrito no Borland C++. Não se pode tomar tudo como verdade, mas é um bom ponto de partida. Além disso, o RDG detecta uma chamada à função IsDebuggerPresent [5]. Alguns softwares se encerram ao perceberem que estão sendo debugados e esta função é uma das formas de ter essa percepção. Geralmente o compilador coloca algumas informações interessantes na seção .data do executável gerado. Não custa olhar rapidamente o que tem lá. Para isso eu usei o pev [6] com a opção “-s”, para exibir informações sobre as seções do executável:
> pev -s USBVaccine.exe | more Sections: Name: .text Virtual size: 0xd9000 Virtual address: 0x1000 Data size: 0xd8600 Data offset: 0x600 Characteristics: 0x60000020 (01100000000000000000000000100000) contains executable code is executable is readable Name: .data Virtual size: 0x1d000 Virtual address: 0xda000 Data size: 0x12c00 Data offset: 0xd8c00 Characteristics: 0xc0000040 (11000000000000000000000001000000) contains initialized data is readable is writable
Sabendo o offset (posição) onde a seção .data começa, usei o hdump [7] para espiar os bytes:
> hdump USBVaccine.exe | findstr “d8c[0-9]0″ 000d8c00 43 6f 64 65 47 65 61 72 20 43 2b 2b 20 2d 20 43|CodeGear C++ –C| 000d8c10 6f 70 79 72 69 67 68 74 20 32 30 30 38 20 45 6d|opyright 2008Em| 000d8c20 62 61 72 63 61 64 65 72 6f 20 54 65 63 68 6e 6f|barcaderoTechno| 000d8c30 6c 6f 67 69 65 73 00 00 00 10 40 00 b2 12 40 00|logies….@…@.| 000d8c40 b2 12 40 00 22 15 40 00 01 00 00 00 00 00 00 00|..@.”.@………| 000d8c50 fc 64 40 00 00 00 00 00 00 00 00 00 00 00 00 00|.d@………….| 000d8c60 30 99 4e 00 4c ad 4e 00 50 ad 4e 00 68 d0 4b 00|0.N.L.N.P.N.h.K.| 000d8c70 c0 d1 4b 00 50 d2 4b 00 e4 d3 4b 00 b0 93 4e 00|..K.P.K…K…N.| 000d8c80 00 00 f8 ac 4e 00 74 ad 4e 00 ec aa 4e 00 00 00|….N.t.N…N…| 000d8c90 00 00 00 00 00 00 00 00 00 00 00 90 00 00 00 00|…………….|
De fato, parece que o binário foi escrito em Borland C++, mas com uma versão mais atual (a Embarcadero comprou a divisão CodeGear da Borland).
Vamos à execução do software:
O que procuramos é o código do evento “click” do botão “Vaccinate USB”, certo? Existem ferramentas específicas para se trabalhar com binários gerados em versões específicas de compiladores. No caso do BC++, há uma ferramenta particularmente interessante chamada E2A (Event To Address), que consegue dizer o endereço de cada evento do software, o que facilita muito a vida:
O endereço da função que o evento “click” do botão chama é 0x404C58. Agora é debugar. Usei o OllyDbg [8] para isso. A ideia é colocar um breakpoint neste endereço, rodar o Vaccine no debugger, clicar no botão para vacinar a mídia e seguir passo a passo o que o software faz, a partir do breakpoint.
5. Entendendo a proteção:
Conforme é mostrado no vídeo, o Vaccine cria um arquivo AUTORUN.INF normal na raíz da mídia, mas depois busca pela entrada deste arquivo na FAT para localizar o byte que controla os atributos. Segundo a documentação [9], é o byte depois da extensão do arquivo. Para facilitar a compreensão, usei o Hex Workshop [10], que tem o recurso de editar discos e volumes lógicos. Além disso, ele permite a criação de estruturas personalizadas para interpretar os bytes visualizados. Criei uma estrutura simples (fat32-directory-table.hsl) para reproduzir a Directory Table da FAT-32.
O byte em questão é um bitfield, onde cada bit corresponde a um atributo:
Bit Máscara Atributo
0 0x01 Somente leitura
1 0x02 Oculto
2 0x04 Sistema
3 0x08 Nome de volume
4 0x10 Subdiretório
5 0x20 Arquivo
6 0x40 Não usado 1
7 0x80 Não usado 2
Lembrando que no vídeo mostrei que o Vaccine grava esse byte como 0x20 (Arquivo) e depois o busca em disco e altera para 0x42 (Não usado 1 + Oculto). É aí que mora a mágica. Não sei o motivo, mas quando o atributo 0x40 está setado, não é possível ler, executar, modificar ou excluir o arquivo. Fiz testes com os outros atributos mas o comportamento esperado só se dá com este bit 6 setado mesmo. Tentativas de implementação Eu tentei, ingenuamente, implementar o recurso no USBForce, que foi escrito em VBScript, mas a propriedade “Attributes” é um enum de valores pré-definidos e não aceita qualquer valor, portanto não aceitou o 0x42:
Set objFSO = CreateObject(“Scripting.FileSystemObject”) Set objFile = objFSO.GetFile(“F:AUTORUN.INF”) objFile.Attributes = &H20 ‘Arquivo WScript.Echo “0x” + Hex(objFile.Attributes) objFile.Attributes = &H40 ‘Não usado 1 WScript.Echo “0x” + Hex(objFile.Attributes)
O código acima prevê que já haja um arquivo autorun.inf no volume F. Ele imprime 0x20 e depois 0x0, ou seja, a tentativa de ativar o atributo não usado falha.
Tentei também usando a API do Windows diretamente, em ?
#include <windows.h> int main(void) { HANDLE out = CreateFile(“f:\autorun.inf”, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0x40, NULL); CloseHandle(out); return 0; }
O resultado foi um arquivo criado com 0x20 (Arquivo) e não com o 0x40 que pedi. Por enquanto vou adotar como solução possível a busca diretamente na FAT pela entrada do arquivo e modificação bruta do byte de atributos, como o Vaccine faz.
6. Prova de Conceito
Como incentivador do software livre, não poderia deixar de implementar esta técnica em código aberto e para funcionar no GNU/Linux. Por isso escrevi um programa para realizar o trabalho, que batizei de OpenVaccine [11]. Por enquanto ele é só uma prova de conceito e seu uso não é encorajado em ambientes de produção.
Referências
[1] https://www.mentebinaria.com.br/artigos/segurança/como-remover-vírus-de-pen-drive-r5/
[2] http://www.pandasecurity.com/homeusers/downloads/usbvaccine
[3] https://github.com/merces/usbforce
[4] http://www.rdgsoft.net
[5] http://msdn.microsoft.com/en-us/library/ms680345(VS.85).aspx
[6] https://github.com/merces/pev
[7] https://github.com/merces/hdump
[8] http://www.ollydbg.de
[9] http://www.nationmaster.com/encyclopedia/VFAT#Directory_Table
[10] http://www.hexworkshop.com
[11] http://openvaccine.sf.net