Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
YARA-Performance-Guidelines — Um guia sobre como escrever regras YARA rápidas e com baixo consumo de memória | Kitploit
Ferramentas/GitHubGitHub/neo23x0/yara-performance-guidelines
Análise EstáticaAnálise de MalwareAprendizado e Educação
GitHubneo23x0/yara-performance-guidelines

YARA-Performance-Guidelines

Um guia sobre como escrever regras YARA rápidas e com baixo consumo de memória

Ver Repositório

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
17423há 1 anoRevisado pelo Kitploit

Diretrizes de Desempenho do YARA

Escrever regras YARA eficientes é essencial para manter um desempenho de varredura rápido e preciso. Este guia fornece princípios-chave e melhores práticas para ajudar você a otimizar suas regras, reduzir computação desnecessária e evitar armadilhas comuns. Ele incorpora insights de especialistas do setor, incluindo Victor M. Alvarez, WXS, e contribuições da comunidade YARA.

  • Revisão 1.6, fevereiro de 2025, aplica-se a todas as versões do YARA superiores a 3.7

Principais Conclusões

Esta seção fornece um resumo conciso das melhores práticas de desempenho do YARA. Para explicações detalhadas e exemplos, consulte o guia completo abaixo.

Entendendo o Processo de Varredura do YARA

"Pense no YARA como um processo de duas etapas: primeiro, buscar todos os padrões listados nas strings e, segundo, avaliar as condições. Você não pode usar condições bem formadas para compensar strings mal escolhidas."
— Wesley Shields

O YARA segue quatro etapas principais ao varrer um arquivo:

  1. Compilando as regras – Extraindo átomos (substrings de 4 bytes) das strings definidas.
  2. Busca Aho-Corasick – Varrendo arquivos em busca desses átomos.
  3. Mecanismo de bytecode – Verificando correspondências completas de strings.
  4. Avaliação de condições – Verificando lógica adicional da regra.

Seleção de Strings – O Fator Mais Importante

O YARA busca strings primeiro, tornando a seleção de strings o fator mais importante para a eficiência da regra.

✅ Melhores Práticas para Strings:

  • Evite strings curtas (<4 bytes) – Elas criam muitos falsos positivos.
  • Use átomos de 4 bytes únicos – O YARA depende deles para uma varredura rápida.
  • Minimize curingas em strings hexadecimais – Mantenha pelo menos um segmento concreto longo.
  • Use regex com moderação – Se necessário, inclua uma âncora fixa de 4 bytes para melhorar a eficiência.
  • Evite padrões repetidos de um único byte – Ex.: \x00\x00\x00\x00 aparece com frequência demais.
  • Use nocase com cuidado – Ele gera exponencialmente mais variações de busca.

Otimizando Condições e Avaliação de Curto-Circuito

O YARA avalia condições sequencialmente e para na primeira falha.

✅ Melhores Práticas para Condições:

  • Coloque verificações rápidas primeiro (ex.: filesize < X) antes de condições caras.
  • Evite loops sobre grandes volumes de dados (for all i in (1..filesize) é ineficiente).
  • Use offsets diretos (@) em vez de regex para verificações de sequência.

⚠ Nota: Condições com regex não usam curto-circuito e são sempre avaliadas por último.

Módulos – Use com Cautela

Módulos como pe, elf ou magic precisam analisar o arquivo inteiro antes da avaliação, aumentando o tempo de varredura.

✅ Alternativas:

  • Em vez de pe.is_pe, use uint16(0) == 0x5A4D para identificar arquivos PE.
  • Evite usar módulos, a menos que uma inspeção profunda do arquivo seja necessária.

Lidando com Muitas Correspondências e Varredura Lenta

Correspondências excessivas tornam a varredura mais lenta e podem acionar erros de "too many matches".

✅ Corrigindo Correspondências Ineficientes:

  • Verifique os quantificadores de regex – Evite .*, .+ ou {x,} sem limite superior.
  • Reduza curingas em strings hexadecimais.
  • Divida alternâncias em strings separadas quando possível.

Tutorial em Vídeo

@herrcore criou um tutorial em vídeo útil cobrindo os tópicos discutidos neste guia de desempenho.

Introduction Into YARA - Writing Efficient YARA Rules

O Básico

Para entender melhor o que e onde o desempenho do YARA pode ser otimizado, é útil compreender o processo de varredura. Ele é basicamente dividido em 4 etapas, que serão explicadas de forma bem simplificada usando esta regra de exemplo:

root@kitploit:~
import "math"
rule example_php_webshell_rule
{
    meta:
        description = "Just an example php webshell rule"
        date = "2021/02/16"
    strings:
        $php_tag = "<?php"
        $input1   = "GET"
        $input2   = "POST"
        $payload = /assert[\t ]{0,100}\(/
    condition:
        filesize < 20KB and
        $php_tag and
        $payload and
        any of ( $input* ) and
        math.entropy(500, filesize-500) >= 5
}

1. Compilando as regras

Esta etapa ocorre antes da varredura em si. O YARA procura os chamados atoms nas strings de busca para alimentar o autômato Aho-Corasick. Os detalhes são explicados no capítulo átomo, mas por enquanto basta saber que eles têm no máximo 4 bytes e o YARA os escolhe de forma bastante inteligente para evitar muitas correspondências. Em nosso exemplo, o YARA pode escolher os seguintes 4 átomos:

  • <?ph
  • GET
  • POST
  • sser (de assert)

2. Autômato Aho-Corasick

Aqui a varredura começa. As etapas 2.-4. serão executadas em todos os arquivos. O YARA procurará em cada arquivo os 4 átomos definidos acima usando uma árvore de prefixos chamada autômato Aho-Corasick. Quaisquer correspondências são repassadas ao mecanismo de bytecode.

3. Mecanismo de bytecode

Se houver, por exemplo, uma correspondência em sser, o YARA verificará se ela foi precedida por um a e continua com um t. Se isso for verdade, ele prosseguirá com a regex [\t ]{0,100}\(. Com essa abordagem inteligente, o YARA evita percorrer os arquivos inteiros com um mecanismo de regex lento e apenas seleciona determinadas partes para examinar mais de perto.

4. Condições

Após toda a correspondência de padrões ser concluída, as condições são verificadas. O YARA possui outro mecanismo de otimização para executar a verificação de math.entropy, que exige muita CPU, da nossa regra de exemplo somente se as 4 condições anteriores forem atendidas. Explicado em mais detalhes no capítulo Condições e Avaliação de Curto-Circuito

Se as condições forem atendidas, uma correspondência é relatada. A varredura continua com o próximo arquivo na etapa 2.

Átomos

O YARA extrai das strings substrings curtas de até 4 bytes, chamadas de "átomos". Esses átomos podem ser extraídos de qualquer lugar dentro da string, e o YARA procura por esses átomos durante a varredura do arquivo; se encontrar um dos átomos, ele verifica se a string realmente corresponde.

Por exemplo, considere estas strings:

root@kitploit:~
/abc.*cde/

=> os átomos possíveis são abc e cde, e qualquer um deles pode ser usado. O átomo abc é atualmente preferido porque ambos têm a mesma qualidade e ele é o primeiro dos dois.

root@kitploit:~
/(one|two)three/

=> os átomos possíveis são one, two, thre e hree; podemos procurar por thre (ou hree) isoladamente, ou por one e two juntos. O átomo thre é preferido porque levará a menos correspondências potenciais do que one e two (que são mais curtos) e não contém e duplo (quanto mais única a letra, melhor).

O YARA faz o melhor esforço para selecionar os melhores átomos de cada string, por exemplo:

root@kitploit:~
{ 00 00 00 00 [1-4] 01 02 03 04 }

=> aqui o YARA usa o átomo 01 02 03 04, porque 00 00 00 00 é comum demais

root@kitploit:~
{ 01 02 [1-4] 01 02 03 04 }

=> 01 02 03 04 é preferido em relação a 01 02 porque é mais longo

Portanto, o ponto importante é que as strings devem conter bons átomos. Estas são strings ruins porque contêm átomos muito curtos ou comuns demais:

root@kitploit:~
{00 00 00 00 [1-2] FF FF [1-2] 00 00 00 00}
{AB  [1-2] 03 21 [1-2] 01 02}
/a.*b/
/a(c|d)/

As piores strings são aquelas que não contêm nenhum átomo, como:

root@kitploit:~
/\w.*\d/
/[0-9]+\n/

Essa expressão regular não contém nenhuma substring fixa que possa ser usada como átomo, portanto ela deve ser avaliada em cada offset do arquivo para verificar se corresponde ali.

Muitas Iterações em Loops

Outra boa recomendação é evitar loops com muitas iterações, especialmente se a instrução dentro do loop for complexa demais, por exemplo:

root@kitploit:~
strings:
	$a = {00 00}
condition:
	for all i in (1..#a) : (@a[i] < 10000)

Esta regra tem dois problemas. O primeiro é que a string $a é comum demais; o segundo é que, por $a ser comum demais, #a pode ser muito alto e a condição pode ser avaliada milhares de vezes.

Esta outra condição também é ineficiente porque o número de iterações depende do tamanho do arquivo, que também pode ser muito alto:

root@kitploit:~
for all i in (1..filesize) : ($a at i)

Módulo Magic

Evite usar o "módulo magic", que não está disponível na plataforma Windows. O uso do módulo "magic" torna a varredura mais lenta, mas fornece correspondências exatas.

Definição personalizada de cabeçalho mágico de GIF:

root@kitploit:~
rule gif_1 {
  condition:
    (uint32be(0) == 0x47494638 and uint16be(4) == 0x3961) or
    (uint32be(0) == 0x47494638 and uint16be(4) == 0x3761)
}

Usando o módulo "magic":

root@kitploit:~
import "magic"
rule gif_2 {
  condition:
    magic.mime_type() == "image/gif"
}

Strings Curtas Demais

Evite definir strings muito curtas. Qualquer string com menos de 4 bytes provavelmente aparecerá em muitos arquivos OU como conteúdo uniforme em um arquivo submetido a XOR.

Conteúdo Uniforme

Algumas strings são longas o suficiente, mas não devem ser usadas por um motivo diferente: uniformidade. Estes são alguns exemplos de strings que não devem ser usadas, pois podem causar muitas correspondências em arquivos.

root@kitploit:~
$s1 = "22222222222222222222222222222222222222222222222222222222222222"
$s2 = "\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20"  // wide formatted spaces

A mensagem de erro seria assim:

root@kitploit:~
error scanning yara-killer.dat: string "$mz" in rule "shitty_mz" caused too many matches

Recomendações para Strings

Tente definir strings da forma mais restrita possível. Evite o atributo "nocase" se possível, pois muitos átomos serão gerados e pesquisados (maior uso de memória, mais iterações). Lembre-se de que, na ausência de modificadores, "ascii" é assumido por padrão. As combinações possíveis são:

BAIXO - apenas um átomo é gerado

root@kitploit:~
$s1 = "cmd.exe"		       // (ascii only)
$s2 = "cmd.exe" ascii          // (ascii only, same as $s1)
$s3 = "cmd.exe" wide           // (UTF-16 only)
$s4 = "cmd.exe" ascii wide     // (both ascii and UTF-16) two atoms will be generated 
$s5 = { 63 6d 64 2e 65 78 65 } // ascii char code in hex

ALTO - Todas as combinações de letras maiúsculas e minúsculas para os 4 bytes escolhidos pelo YARA serão geradas como átomos

root@kitploit:~
$s5 = "cmd.exe" nocase      (all different cases, e.g. "Cmd.", "cMd.", "cmD." ..)

Se você quiser corresponder a comandos de script, verifique se a linguagem é realmente insensível a maiúsculas/minúsculas (ex.: php, batch do Windows) antes de usar nocase. Se você precisar apenas de variações de caixa para uma ou duas letras, é melhor usar uma regex, ex.:

root@kitploit:~
$re = /[Pp]assword/

Tenha cuidado ao trabalhar com alternâncias como:

root@kitploit:~
$re = /(a|b)cde/
$hex = {C7 C3 00 (31 | 33)}

Essas strings geram átomos curtos que podem tornar a varredura mais lenta. Nos casos em que há um pequeno número de variantes, é recomendável escrever as strings separadamente:

root@kitploit:~
$re1 = /acde/
$re2 = /bcde/
$hex1 = {C7 C3 00 31}
$hex2 = {C7 C3 00 33}

Expressões Regulares

Use expressões regulares somente quando necessário. A avaliação de expressões regulares é inerentemente mais lenta do que a correspondência simples de strings e consome uma quantidade significativa de memória. Não as use se strings hexadecimais com saltos e curingas puderem resolver o problema.

Se você precisar usar expressões regulares, evite quantificadores gananciosos .* e até mesmo quantificadores relutantes .*?. Em vez disso, use números exatos como .{1,30} ou até .{1,3000}. Além disso, não se esqueça do limite superior (evite, por exemplo, .{2,}).

Ao usar quantificadores, duas situações podem ocorrer:

Se o início da expressão regular estiver ancorado em uma posição e apenas o sufixo puder variar, o YARA corresponderá à correspondência mais longa possível. Em casos como .* e .+ ou .{2,}, isso pode gerar strings grandes e problemas de lentidão na varredura.

Se houver mais possíveis inícios para a expressão regular, o YARA corresponderá a todos eles.

root@kitploit:~
$re1 = /Tom.{0,2}/		// will find Tomxx in "Tomxx"
$re2 = /.{0,2}Tom/      // will find Tom, xTom, xxTom in "xxTom"

O número de correspondências mais curtas pode facilmente ultrapassar o limite e criar o erro "too many matches".

O exemplo a seguir é a expressão regular para um endereço de e-mail. Ao usar [-a-z0-9._%+] com quantificadores, o YARA corresponderá a um mesmo endereço várias vezes, o que não é ideal. Nesse caso, é recomendável encontrar um subconjunto razoavelmente pequeno de endereços que forneça informações suficientes para a análise.

USE

root@kitploit:~
/[-a-z0-9._%+]@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
OR
/@[-a-z0-9.]{2,10}\.[a-z]{2,4}/ 

AVOID

root@kitploit:~
/[-a-z0-9._%+]*@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
/[-a-z0-9._%+]+@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
/[-a-z0-9._%+]{x,y}@[-a-z0-9.]{2,10}\.[a-z]{2,4}/

Se você quiser garantir que, por exemplo, exec seja seguido por /bin/sh, você pode usar os offsets fornecidos pelo símbolo @. Esta seria a versão lenta com regex:

root@kitploit:~
$ = /exec.*\/bin\/sh/

Esta é a forma mais rápida usando offsets:

root@kitploit:~
strings:
  $exec = "exec" 
  $sh   = "/bin/sh"
conditions:
  $exec and $sh and
  @exec < @sh

Tente também incluir sequências longas de strings que possam servir como âncoras no processo de correspondência. Novamente, quanto mais longo, melhor.

RUIM

root@kitploit:~
$s1 = /http:\/\/[.]*\.hta/	// greedy [.]*

MELHOR

root@kitploit:~
$s1 = /http:\/\/[a-z0-9\.\/]{3,70}\.hta/ 	// better, with an the upper bound

MELHOR AINDA

root@kitploit:~
$s1 = /mshta\.exe http:\/\/[a-z0-9\.\/]{3,70}\.hta/

Erros de Muitas Correspondências e Lentidão na Varredura

Os erros de "too many matches" são causados por strings muito genéricas que aparecem com frequência demais na entrada, ou pelo YARA correspondendo a uma mesma ocorrência várias vezes.

A lentidão na varredura é causada por strings que geram átomos curtos demais, ou nenhum átomo. Como resultado, o YARA usa um algoritmo ingênuo de correspondência de padrões, o que causa a lentidão.

Ambos os problemas podem, em alguns casos, ser corrigidos com estas etapas:

  1. Verifique os quantificadores .* e .+, .*?
  2. Verifique quantificadores sem limite superior, como x{14,}
  3. Verifique intervalos grandes demais (ex.: x{1,300000})
  4. Verifique saltos grandes nas strings hexadecimais
  5. Verifique caracteres curinga - eles podem ser especificados com mais precisão, ou a string poderia ser dividida em 2, omitindo o caractere curinga?
  6. Verifique alternâncias: elas podem ser divididas em 2 ou mais strings?
  7. Tente adicionar especificações para correspondência de palavras (fullword, \b,...)

Observe que, no próximo capítulo Condições e Avaliação de Curto-Circuito, algumas dicas para condições são mencionadas. No entanto, as alterações nelas não resolverão os erros de "too many matches" e lentidão na varredura.

Condições e Avaliação de Curto-Circuito

Tente escrever declarações de condição nas quais os elementos com maior probabilidade de serem "False" sejam colocados primeiro. A condição é avaliada da esquerda para a direita. Quanto mais cedo o mecanismo identificar que uma regra não foi satisfeita, mais cedo ele poderá pular a regra atual e avaliar a próxima. A melhoria de velocidade causada por essa forma de ordenar as declarações de condição depende da diferença nos ciclos de CPU necessários para processar cada uma delas. Se todas as declarações tiverem custo mais ou menos igual, reordená-las não causa melhoria perceptível. Se uma das declarações puder ser processada muito rapidamente, é recomendável colocá-la primeiro, a fim de evitar a avaliação da declaração cara nos casos em que a primeira declaração for FALSE.

Alterar a ordem na declaração a seguir não causa melhoria significativa:

root@kitploit:~
$string1 and $string2 and uint16(0) == 0x5A4D

No entanto, se o tempo de execução das declarações for muito diferente, reordená-las para acionar o curto-circuito melhorará significativamente a velocidade da varredura:

LENTO

root@kitploit:~
// EXPENSIVE and CHEAP
math.entropy(0, filesize) > 7.0 and uint16(0) == 0x5A4D

RÁPIDO

root@kitploit:~
// CHEAP and EXPENSIVE
uint16(0) == 0x5A4D and math.entropy(0, filesize) > 7.0

A avaliação de curto-circuito foi introduzida para ajudar a otimizar sentenças caras, particularmente sentenças "for". Algumas pessoas usavam condições como a do exemplo a seguir:

root@kitploit:~
strings:
	$mz = "MZ"
	...
condition:
	$mz at 0 and for all i in (1..filesize) : ( whatever )

Como filesize pode ser um número muito grande, "whatever" pode ser executado muitas vezes, tornando a execução mais lenta. Agora, com a avaliação de curto-circuito, a sentença "for" será executada somente se a primeira parte da condição for atendida; portanto, esta regra será lenta apenas para arquivos MZ. Uma melhoria adicional poderia ser:

root@kitploit:~
$mz at 0 and filesize < 100KB and for all i in (1..filesize) : ( whatever )

Dessa forma, um limite superior para o número de iterações é definido.

A partir da versão 3.10, os loops de faixa de inteiros também foram otimizados:

root@kitploit:~
for all i in (0..100): (false)
for any i in (0..100): (true)

Both of these loops will stop iterating after the first time through.

Sem Curto-Circuito para Expressões Regulares

Infelizmente, isso não funciona com expressões regulares porque todas elas são inicialmente alimentadas no mecanismo de correspondência de strings. O exemplo a seguir tornará a busca mais lenta para qualquer arquivo, e não apenas para aqueles com tamanho menor que 200 bytes:

root@kitploit:~
strings:
  $expensive_regex = /\$[a-z0-9_]+\(/ nocase
conditions:
  filesize < 200 and
  $expensive_regex

Essa avaliação de "curto-circuito" é aplicada desde a versão 3.4 do YARA.

Metadados

Quaisquer dados na seção de metadados são lidos na RAM pelo YARA. (Você pode testar isso facilmente inserindo 100.000 hashes em uma regra e verificando o uso de RAM da varredura do YARA antes e depois.) É claro que você não quer remover permanentemente os metadados das regras, mas se estiver com pouca RAM, você pode remover algumas partes desnecessárias deles em seu fluxo de trabalho imediatamente antes da varredura.

Baixar ferramenta