Ofuscação de Códigos

A ofuscação de um código pode ser definida como um conjunto de técnicas que dificultam a legibilidade ou análise do código-fonte ou da execução de um programa. Simplificadamente é assegurar-se que o código pareça ser diferente do que de fato é para que seja difícil entendê-lo. Existem diversos motivos para a ofuscação, como a segurança por obscuridade, proteção de direitos autorais, a dissuasão de usuários maliciosos e até mesmo uma certa “garantia de emprego” com um código que só o desenvolvedor entende [1] – prática essa intolerável no mundo real e que deve permanecer como um texto humorístico.

Técnicas de ofuscação não visam impossibilitar a engenharia reversa de um programa, já que eventualmente alguém irá fazê-lo e descobrirá como o programa funciona. O objetivo é dificultar essa descoberta até mesmo para aqueles que já são experientes nisso. Um exemplo seria um programa comercial com ofuscação para dificultar a sua adulteração de forma maliciosa ou uma cópia ilegal. No entanto, há alguns questionamentos quanto aos seus custos em performance, manutenção e usabilidade do programa. [2, 3]

Quanto a efetividade da ofuscação, há um paper disponibilizado pela IEEE que analisou essa questão e concluiu que de fato essas técnicas afetam significativamente a eficiência dos ataques contra o software [4]. Um estudo mais recente afirma que mesmo a ofuscação mais simples pode ser tão efetiva quanto a ofuscação mais complexa, dependendo de como o ataque é efetuado [5]. Além disso, conclui que o código ofuscado apenas atrasa a engenharia reversa, já que o programa pode ser entendido e adulterado após um certo tempo. De qualquer forma, esses estudos não analisam o impacto das técnicas de ofuscação na performance, manutenção, usabilidade e auditoria do código – o que com certeza seria avaliado no desenvolvimento de um programa comercial.

E quando falamos de ofuscação muitos podem lembrar de minificação, técnica muito utilizada no JavaScript para deixar os arquivos mais leves e aumentar a sua performance. A minificação remove espaços em branco e caracteres desnecessários, mas seu propósito é diferente da ofuscação, seu processo é simples e a manutenção do código minificado é muito menos trabalhosa. Uma certa dificuldade de leitura num código minificado acaba sendo apenas uma consequência da minificação – que, no fim, pode ser facilmente revertida. As únicas semelhanças que as técnicas possuem são os benefícios da remoção de caracteres adicionais, quebra de linha e espaços em branco, sendo que a ofuscação faz muito mais que isso.

Ofuscação de Malwares

Apesar do seu uso legítimo para proteção de programas e direitos autorais, a ofuscação de códigos é mais utilizada em malwares. Nesse caso, não temos preocupação com performance, usabilidade ou manutenção e o objetivo, além de dificultar a engenharia reversa, é dificultar a detecção do software malicioso.

Enquanto há um esforço para que o malware seja executado, há também o esforço para que ele não seja detectado pelos usuários, pesquisadores e softwares de detecção, como os IDS. Quanto ao usuário, dependendo do nível técnico e familiaridade com o sistema, o trabalho e o cuidado com a detecção pode ser mínimo. Um exemplo seria um programa mal intencionado camuflar-se de um serviço no Windows, como o svchost.exe. Outro exemplo seria um malware em PHP com prefixo ‘wp-‘, como wp-signin.php, em uma hospedagem com um WordPress instalado, onde o usuário tomará por certo que é um arquivo do próprio WordPress.

E dentro desse serviço svchost.exe malicioso ou do arquivo wp-signin.php podemos ter técnicas de ofuscação para que um usuário mais experiente não entenda o que ele está fazendo ou que um pesquisador tenha que fazer um pouco mais de esforço para isso. No caso do svchost.exe, técnicas de ofuscação de binários seriam utilizadas, e no do arquivo em PHP, sendo esta uma linguagem interpretada, apenas uma ofuscação do código seria necessária, como exemplificado mais abaixo.

Apesar de saber que os pesquisadores vão, eventualmente, fazer uma engenharia reversa independente da técnica de ofuscação utilizada [5], essas técnicas também são úteis para que os softwares de IDS ou anti-vírus não consigam detectar a presença de um conteúdo malicioso, principalmente quando são baseados em assinatura. Esses sistemas de detecção precisam de uma assinatura já existente para serem efetivos, o que é difícil com malwares ofuscados já que vários usam técnicas de oligomorfismo ou polimorfismo.

Simplificadamente, ambas as técnicas fazem com que um mesmo código possa ser escrito de diversas formas diferentes. Expandindo brevemente as definições, o oligomorfismo é uma técnica que partiu da criptografia dos malwares. Os malwares criptografados são compostos por um decriptador e um corpo criptografado e para cada infecção uma chave diferente é usada tendo assim o corpo criptografado sempre único. O problema aqui é que o decriptador é constante em cada geração do malware, o que acaba por permitir que os scanners detectem o malware baseado nos padrões desse decriptador. A partir daí temos o oligomorfismo, onde o decriptador é mutável e criado a partir de formas pré-definidas mas com um limite – só é possível gerar algumas centenas de decriptadores diferentes, o que permite a detecção por assinaturas. O polimorfismo é um pouco mais avançado, criando inúmeros decriptadores ainda mantendo seu algoritmo original intacto. A forma de gerar uma assinatura desse tipo de malware é a partir da emulação do malware em ambiente seguro para identificá-lo a partir de sua execução [6].

Independente da chave criptográfica aplicada ou da técnica de ofuscação usada, a função do malware é sempre a mesma e o que muda é a sua apresentação. Existem muitos estudos quanto a teoria da ofuscação e muito do conteúdo acadêmico é baseado em malwares, geralmente focando em métodos de classificar um programa como malicioso, e uma análise da funcionalidade do programa ofuscado normalmente é deixada de fora [7].

Exemplos de Ofuscação

Para exemplificar alguns casos de ofuscação de códigos maliciosos eu separei três exemplos de malwares em uma linguagem interpretada, o PHP. Um tipo de malware comum nessa linguagem é o backdoor, tendo como objetivo abrir uma “porta dos fundos” em um site para que atacantes consigam comprometê-lo ou até mesmo para atacar um servidor específico a partir de um site vulnerável – usa-se o site como vetor para comprometer o sistema do servidor em si, e não só o site. Abaixo temos justamente exemplos simples de backdoors.

ckbywxfl.php

Seu nome original era “ckbywxfl.php” e encontrei-o num site infectado que precisei investigar. Um simples backdoor ofuscado mas ao fazer uma engenharia reversa nele, pude ver que ele receberia e executaria via POST ou COOKIE um payload em hexadecimal que foi criptografado por uma operação XOR:

sirvrzof.php

Mesmo backdoor que o primeiro, mas podemos notar que algumas coisas mudaram.

Esse seria um exemplo bem básico de um malware ofuscado mutável. Os dois programas tem as mesmas funções e objetivo, mas seus códigos são diferentes e assinatura dos mesmos são diferentes, conforme podemos ver no exemplo abaixo:

Claro que essas não seriam assinaturas usadas no mundo real, para fazer um scan com o ClamAV poderíamos usar a documentação que especifica um formato padrão estendido de assinaturas [8], mas a assinatura do sample01.php só acharia malwares idênticos a ele, ignorando o sample02.php que é o mesmo malware codificado diferente.

mbil42.php

No exemplo abaixo, temos um outro tipo de backdoor, encontrado em outro site infectado com o nome de “mbil42.php” que parece ser mais complexo que o primeiro caso.

Nesse caso, a ofuscação é realizada executando múltiplas vezes operações que descomprimem dados comprimidos com DEFLATE[9] no formato base 64. Apesar da aparência, ao fazer uma engenharia reversa nele o resultado é apenas um backdoor de uma linha para executar uma simples requisição com POST.

Exemplos de ofuscação em geral (não-maliciosa) que são bem interessantes como o Dogon.c e o Hamre.c podem ser encontrados no site do International Obfuscated C Code Contest, uma competição de ofuscação de códigos que reúne programadores de C que são entusiastas dessas técnicas.

Concluindo, o post abordou brevemente o uso da ofuscação em programas comerciais e em como ele é mais utilizado por malwares para aumentar seu tempo de vida ou burlar mecanismos de detecção. Artigos futuros podem abordar mais a fundo a ofuscação de códigos e binários em aplicações benignas para proteção de direitos autorais ou de softwares proprietários, e também explorar os métodos de ofuscação utilizados por malwares e as diversas técnicas de engenharia reversa utilizadas por pesquisadores.

Referências:

1. How To Write Unmaintainable Code <https://github.com/Droogans/unmaintainable-code>

2. How to obfuscate string constants? – Resposta por: Tom Gullen. <https://stackoverflow.com/a/6018904>

3. (Why) should I use obfuscation? – Resposta por: Leigh Caldwell <https://stackoverflow.com/a/31902>

4. The effectiveness of source code obfuscation: An experimental assessment <https://ieeexplore.ieee.org/document/5090041/>

5. A family of experiments to assess the effectiveness and efficiency of source code obfuscation techniques <https://link.springer.com/article/10.1007/s10664-013-9248-x>

6. A Brief History of Malware Obfuscation <https://blogs.cisco.com/security/a_brief_history_of_malware_obfuscation_part_1_of_2>

7. Protecting Software through Obfuscation: Can It Keep Pace with Progress in Code Analysis? <http://www.cs.rhul.ac.uk/home/kinder/papers/csur16-obfuscation.pdf>

8. Creating Signatures for ClamAV <https://github.com/Cisco-Talos/clamav-faq/blob/master/manual/signatures.pdf>

9. DEFLATE Compressed Data Format <http://www.faqs.org/rfcs/rfc1951.html>