Pular para o conteúdo
Novo

DeepSeek V4.1 Flash grátis por 7 dias: 10M tokens por dia após qualquer recarga. Até 30/11.

Como funciona

Escreva uma regra YARA contra um arquivo de teste inofensivo

Escreva uma primeira regra YARA que case com um arquivo inofensivo e não com outro, e aprenda por que toda regra precisa de testes positivos e negativos.

Iniciante10 min de leituraPor NotHoly

Para que serve uma regra YARA

YARA é uma ferramenta de correspondência de padrões. Você escreve uma regra que descreve como um arquivo é, e o YARA lista os arquivos que se encaixam na descrição. Analistas de malware são quem mais usa. Eles escrevem regras para strings, estruturas de arquivo e sequências de bytes, e depois varrem pastas, imagens de disco e dumps de memória. O mesmo mecanismo funciona em qualquer arquivo que você controla, por exemplo um modelo que nunca pode carregar um marcador interno, ou um arquivo de configuração que nunca pode conter um token.

O YARA não sabe o que é perigoso. Ele compara o que a regra diz. Uma regra é uma afirmação sobre bytes, e ela só vale o que vale essa afirmação.

O projeto fica no GitHub, na organização da VirusTotal. O guia oficial de escrita, hospedado no Read the Docs, é a referência de sintaxe. A VirusTotal também mantém o YARA-X, uma reescrita em Rust que mantém a maior parte da linguagem de regras. Os dois se sobrepõem, mas não são idênticos, então leia as notas de compatibilidade antes de levar uma regra de um para o outro.

Por que as regras importam

Um hash de arquivo responde a uma pergunta estreita: este arquivo exato já é conhecido? Mude um byte e o hash muda. O artigo sobre hashes de arquivo explica isso com detalhes. Uma regra YARA faz uma pergunta mais ampla: este arquivo contém as partes que esperamos? Uma regra pode casar com muitos arquivos que compartilham uma string, uma estrutura ou um padrão de bytes, mesmo que nenhum deles tenha o mesmo hash.

É justamente aí que mora o problema. Um hash quase nunca casa com um arquivo que não deveria. Uma regra descuidada pode casar com metade do seu servidor de arquivos. Por isso, o que você precisa aprender não é tanto a sintaxe. É escrever uma regra que case com o que você quer, e somente com isso, e depois provar que ela faz isso com arquivos que você controla.

Anatomia de uma regra

Toda regra tem um nome e, dentro de chaves, até três seções:

yara
rule Exemplo_De_Regra {
  meta:
    description = "Para que serve esta regra"

  strings:
    $texto = "algum texto"

  condition:
    $texto
}

Nomes de regra usam letras, números e sublinhados, e não podem começar com número. O nome aparece em todo relatório de correspondência, então escolha um que diga ao leitor do que a regra trata.

meta

A seção meta guarda pares chave-valor para as pessoas: uma descrição, um autor, uma data, um link para a pesquisa que originou a regra. O YARA nunca usa a meta para decidir uma correspondência. Mantenha-a correta mesmo assim, porque a próxima pessoa a abrir o arquivo vai confiar nela.

strings

Cada string recebe um identificador que começa com $. A condição se refere às strings por esse identificador. Há três tipos.

Strings de texto ficam entre aspas duplas:

yara
$marcador = "LAB-TRAINING-MARKER"

Modificadores mudam a forma como o texto é comparado. nocase ignora maiúsculas e minúsculas. wide casa com texto UTF-16LE, em que cada caractere ASCII é seguido de um byte zero, algo comum em binários do Windows. fullword exige que a ocorrência apareça sozinha, e não dentro de uma palavra maior.

Strings hexadecimais ficam entre chaves e casam com bytes crus:

yara
$mz = { 4D 5A }

Esses dois bytes são a assinatura MZ no início de muitos executáveis do Windows. ?? casa com qualquer byte, [2-4] aceita um intervalo de dois a quatro bytes desconhecidos, e ( 90 | 91 ) casa com um ou com outro.

Expressões regulares ficam entre barras:

yara
$versao = /LAB-[A-Z]+ v[0-9]+/

Regex é o tipo mais flexível e também o mais fácil de deixar amplo demais. Use uma string de texto ou hexadecimal sempre que ela der conta do padrão.

condition

A condição é uma expressão booleana. Ela combina strings e propriedades do arquivo em uma resposta só: casa ou não casa.

  • $marcador é verdadeiro quando a string aparece pelo menos uma vez.
  • any of them e all of them valem para todas as strings da regra. 2 of ($a, $b, $c) exige duas de três.
  • $marcador at 0 exige a string no primeiro byte. $marcador in (0..512) exige que ela esteja nos primeiros 512 bytes.
  • #marcador > 3 conta as ocorrências.
  • filesize < 2KB verifica o tamanho do arquivo.
  • uint16(0) == 0x5A4D lê os dois primeiros bytes como um inteiro little-endian e confere a assinatura MZ.

Toda regra precisa de uma condição. Uma regra com strings e sem condição sensata está quebrada ou não serve para nada.

Como o YARA lê uma regra

  1. O YARA interpreta o arquivo de regras e o compila. Um erro de sintaxe interrompe a execução antes de qualquer arquivo ser lido.
  2. Para cada arquivo que vai varrer, o YARA procura todas as strings da seção strings.
  3. Ele avalia a condição com os resultados do passo 2.
  4. Se a condição for verdadeira, o arquivo casa. Com -s, o YARA também imprime cada string encontrada, com o deslocamento em bytes onde ela apareceu.

As strings vêm primeiro e a condição depois. Uma condição como $a and $b é estrita, porque as duas strings precisam ser encontradas antes de a regra casar.

Laboratório: um arquivo positivo e um negativo

A saída esperada abaixo é descrita, não colada, porque o formato exato pode variar entre versões do YARA. Compare o que aparecer no seu terminal com essas descrições.

Trabalhe em uma pasta vazia. No Windows, rode os comandos no Git Bash. O heredoc do passo 3 não funciona da mesma forma no PowerShell.

1. Instale o yara

No Debian e no Ubuntu:

bash
sudo apt install yara

No macOS, com Homebrew:

bash
brew install yara

No Windows, baixe o zip da release em https://github.com/VirusTotal/yara/releases, extraia e coloque o executável no seu PATH. O arquivo pode se chamar yara64.exe. Renomeie para yara.exe, ou copie com esse nome, para que os comandos abaixo funcionem como estão.

Confira a instalação:

bash
yara --version

Você deve ver um número de versão. Este artigo não fixa uma versão, então use a release mais recente que o seu método de instalação entregar.

2. Crie um arquivo positivo e um negativo

bash
mkdir yara-lab && cd yara-lab
printf 'LAB-TRAINING-MARKER v1\n' > match.txt
printf 'arquivo de texto comum\n' > nomatch.txt

Os dois arquivos são texto puro que você escreveu. O primeiro deve casar com a regra. O segundo não deve.

3. Escreva a regra

As aspas em volta de EOF importam. Sem elas, o shell troca $m por uma variável vazia antes de o YARA ler o arquivo, e a regra deixa de compilar.

bash
cat > lab.yar <<'EOF'
rule Lab_Training_Marker {
  meta: description = "Casa com o marcador do laboratório"
  strings: $m = "LAB-TRAINING-MARKER"
  condition: $m
}
EOF

Leia em três partes. A meta diz para que serve a regra. A string diz que o arquivo precisa conter o texto do marcador. A condição diz que o arquivo casa quando essa string é encontrada pelo menos uma vez.

4. Rode o teste positivo

bash
yara -s lab.yar match.txt

O YARA deve imprimir o nome da regra e o caminho do arquivo. Por causa do -s, ele também imprime uma linha para a string encontrada, com o deslocamento em bytes e o texto achado. O marcador começa no primeiro byte de match.txt, então o deslocamento deve ser 0x0.

5. Rode o teste negativo

bash
yara lab.yar nomatch.txt

Saída esperada: nada. O YARA imprime apenas as correspondências, então o silêncio significa que o arquivo não casou.

O silêncio só diz alguma coisa se o teste positivo funcionou. Rode o passo 4 primeiro. Se o passo 4 não imprimiu nada, a regra ou a instalação está errada, e o silêncio do passo 5 não prova nada.

6. Adicione um quase-casamento

Um quase-casamento é o arquivo negativo mais útil, porque ele falha por um motivo específico e estreito.

bash
printf 'LAB-TRAINING\n' > near.txt
yara lab.yar near.txt

Saída esperada: nada. O arquivo tem o começo do marcador, mas não a string completa, então a string não é encontrada e a condição é falsa.

7. Varra a pasta inteira

bash
yara -r lab.yar .

A flag -r varre a pasta recursivamente. Espere ver match.txt na saída. Provavelmente você também verá lab.yar, o próprio arquivo de regra. Ele contém o texto do marcador, então a regra casa com o próprio código-fonte. Esse é um erro comum, e a próxima seção trata dele. Mantenha as regras em uma pasta diferente dos dados que você varre.

Deixe a regra mais estrita

A regra do laboratório serve para um marcador de treino. Regras reais costumam precisar de uma restrição que a string sozinha não dá. Suponha que você queira apenas arquivos pequenos que carreguem o marcador:

yara
rule Lab_Training_Marker_Pequeno {
  strings: $m = "LAB-TRAINING-MARKER"
  condition: $m and filesize < 1KB
}

Teste do mesmo jeito. match.txt deve casar. nomatch.txt e near.txt não devem. Toda mudança nas strings ou na condição exige rodar os dois arquivos de teste de novo.

Evite regras que casam com tudo

Esta regra parece razoável:

yara
rule Muito_Amplo {
  strings: $a = "texto"
  condition: $a
}

Ela vai casar com nomatch.txt, porque a frase arquivo de texto comum contém a palavra texto. Você pode confirmar com o arquivo negativo que já criou. Uma regra que casa com ele falhou no próprio teste.

Padrões que casam demais:

  • Strings curtas, ou palavras comuns como texto, erro, copyright ou este programa.
  • Um byte só ou um padrão hexadecimal muito curto, como { 00 } ou { 90 }.
  • nocase em uma palavra comum.
  • any of them sobre uma lista de strings que aparecem em arquivos comuns.
  • Uma condição que é só checagem de tamanho, como filesize < 10KB, que casa com a maioria dos arquivos pequenos.
  • Uma regex frouxa, como /.+/.

Formas de apertar a regra:

  • Escolha strings mais longas e distintivas. Pergunte se a string apareceria em um documento que sua organização escreve todo dia. Se apareceria, escolha outra.
  • Exija mais de uma string com and, ou com 2 of (...), para que nenhuma string comum decida sozinha.
  • Ancore a busca com at ou in quando souber onde a string deve aparecer.
  • Combine o teste de conteúdo com uma checagem de cabeçalho ou de tamanho, como uint16(0) == 0x5A4D.

Erros comuns

  1. Testar só o arquivo positivo. Uma regra que casa com o arquivo para o qual foi escrita prova pouco. Ela pode casar com tudo.
  2. Pular os quase-casamentos. Arquivos comuns raramente falham de um jeito interessante. Um arquivo que quase casa é o teste que pega uma string frouxa demais.
  3. Esquecer as aspas no heredoc. O shell troca $m antes de o YARA ler o arquivo. Veja o passo 3.
  4. Varrer a pasta onde estão as regras. O arquivo de regra casa com o próprio texto.
  5. Confiar na meta. Uma descrição que diz "detecta X" não detecta X. Só os arquivos de teste mostram isso.
  6. Editar sem testar de novo. Qualquer mudança nas strings ou na condição pode mudar o resultado. Rode os dois testes depois de cada edição.

Testes positivos e negativos antes de qualquer implantação

Esta é a regra que mais importa neste artigo. Toda regra YARA precisa dos dois tipos de arquivo de teste antes de alguém implantá-la.

  • Arquivos positivos são arquivos que a regra precisa casar. No laboratório, é o match.txt. No trabalho real, vêm de amostras que você está autorizado a guardar, seguindo as regras de manuseio da sua organização.
  • Arquivos negativos são arquivos que a regra não pode casar. Inclua documentos comuns, os tipos de arquivo mais usados no seu ambiente, arquivos limpos dos sistemas que você pretende varrer e quase-casamentos como o near.txt.

Uma regra passa quando casa com todos os arquivos positivos e com nenhum negativo. Guarde os dois conjuntos ao lado da regra, no controle de versão se sua equipe usar um, e rode de novo a cada edição. Uma regra que passou no teste positivo, mas nunca foi rodada contra negativos, não foi testada.

Como seguir em frente

  • Leia o guia de escrita de regras do início ao fim. Ele cobre módulos como pe, que permite a uma regra testar cabeçalhos e seções de um executável do Windows em vez de bytes crus.
  • Rode a mesma regra do laboratório com o YARA-X e compare os resultados. A documentação do YARA-X lista o que é e o que não é compatível.
  • Monte um corpus limpo: uma pasta com arquivos comuns de máquinas que você controla. Toda regra nova precisa passar nele antes de ir para qualquer lugar.
  • Leia em seguida o artigo sobre SIEM. Ele trata do outro lado da detecção: regras que rodam sobre logs, e não sobre arquivos.

Fontes

Fontes

  1. YARA: Writing rules
  2. VirusTotal/yara on GitHub
  3. YARA-X documentation (VirusTotal)

Mais em Malware e forense