Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
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.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
VMProtect-devirtualization — Brincando com a proteção de software VMProtect. Desofuscação automática de funções puras usando execução simbólica e LLVM. | Kitploit
Ferramentas/GitHubGitHub/jonathansalwan/vmprotect-devirtualization
Análise EstáticaAnálise Dinâmica (Sandboxing)Engenharia ReversaFuzzingAnálise de Binários
GitHubjonathansalwan/vmprotect-devirtualization

VMProtect-devirtualization

Brincando com a proteção de software VMProtect. Desofuscação automática de funções puras usando execução simbólica e LLVM.

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 →
1.5k20816há 4 anosRevisado pelo Kitploit
Compartilhar

Desvirtualização do VMProtect

Uma abordagem dinâmica experimental para desvirtualizar funções puras protegidas por VMProtect 3.x

 

 

  • Resumo
  • Introdução
  • A abordagem
    • Exemplo 1: Uma operação bitwise simples protegida
    • Exemplo 2: Uma operação MBA protegida
    • Exemplo 3: Mais de um bloco básico
  • Conclusão e limitações
  • Referências

 

 

TL;DR

Estou compartilhando algumas notas sobre uma abordagem dinâmica para desvirtualizar funções puras protegidas pelo VMProtect. Essa abordagem mostrou resultados muito bons se a função virtualizada contém apenas um bloco básico (independentemente de seu tamanho). Este é um cenário comum quando binários protegem operações aritméticas. No entanto, esta abordagem é um pouco mais experimental quando a função alvo contém mais de um bloco básico. Ainda assim, conseguimos desvirtualizar e reconstruir o código binário de amostras que contêm 2 blocos básicos, o que sugere que é possível desvirtualizar completamente pequenas funções de forma dinâmica.

Introduction

VMProtect é uma proteção de software que protege o código executando-o em uma máquina virtual com arquitetura não padrão. Essa proteção é um ótimo playground para os amantes de assembly [0, 1, 2, 3, 4, 5, 6, 11]. Além disso, já existem inúmeras ferramentas que atacam essa proteção [7, 8, 9, 12, 13]. Em 2016, analisamos a solução de proteção de software Tigress e conseguimos derrotar sua virtualização usando execução simbólica e LLVM. Essa abordagem foi apresentada no DIMVA 2018 [10] e quis testá-la no VMProtect. Observe que não existe uma solução mágica que funcione em todos os binários, sempre há compensações dependendo do alvo e dos seus objetivos. Esta modesta contribuição visa fornecer um exemplo de um ataque dinâmico contra funções puras que são virtualizadas pelo VMProtect. A principal vantagem de um ataque dinâmico é que ele derrota por design algumas proteções estáticas do VMProtect, como código automodificável, criptografia de chaves e operandos etc.

Consideramos uma função pura como uma função com um número finito de caminhos e que não possui efeitos colaterais. Pode haver várias entradas, mas apenas uma saída. Abaixo está um exemplo de uma função pura:```cpp int secret(int x, int y) { int r = x ^ y; return r; }

# A abordagem

Baseamo-nos na intuição chave de que um trace ofuscado T' (do código ofuscado P') combina instruções
originais do código original P (o trace T correspondente a T' no código original) e
instruções da máquina virtual VM de modo que T' = T + VM(T). Se formos capazes de distinguir entre
essas duas subsequências de instruções T e VM(T), então seremos capazes de reconstruir um caminho do
programa original P a partir de um trace T'. Repetindo esta operação para cobrir todos os caminhos do
programa virtualizado, seremos capazes de reconstruir o programa original P. No nosso exemplo prático, o código
original tem um número finito de caminhos executáveis, o que é o caso em muitas situações envolvendo proteção
de propriedade intelectual. Para isso, procedemos com os seguintes passos:

1. Identificar a função virtualizada e seus argumentos
2. Gerar um trace VMProtect do alvo
3. Reproduzir o trace VMP e construir expressões simbólicas para obter a relação entre entradas e saída
4. Aplicar otimizações nas expressões simbólicas para evitar o máximo possível instruções da VM
5. Elevar nossa representação simbólica para LLVM-IR para construir uma nova versão desprotegida do alvo

## Exemplo 1: Uma operação bitwise simples

Vamos tomar como primeiro exemplo a seguinte função: ela recebe duas entradas e retorna `x ^ y` que é protegida por VMProtect.```cpp
int secret(int x, int y) {
  VMProtectBegin("secret");
  int r = x ^ y;
  VMProtectEnd();
  return r;
}

Começamos identificando onde as funções estão usando VMProtect e quantos argumentos elas têm. Para nosso exemplo, podemos ter algo como abaixo:

Apenas lendo o código, sabemos que a função começa no endereço 0x4011c0, tem dois argumentos de 32 bits (edi e esi) e retorna em 0x4011ef. Isso é tudo o que precisamos em engenharia reversa. As próximas partes serão automáticas. Agora temos que gerar uma execução de rastreamento desta função virtualizada. Para isso, usamos um Pintool. Ele precisa apenas de um endereço start e um end (para nosso exemplo, 0x4011c0 e 0x4011ef) que representam o intervalo da instrumentação. Note que qualquer tipo de DBI ou emulador poderia fazer esse trabalho.``` $ ./pin/pin -t ./pin/source/tools/VMP_Trace/obj-intel64/VMP_Trace.so -start 4198848 -end 4198895 -- ./vmp_binaries/binaries/sample2.vmp.bin 1 2 &> ./vmp_traces/sample2.vmp.trace

Você pode ver o resultado [here](https://github.com/jonathansalwan/vmprotect-devirtualization/blob/main/vmp_traces/sample2.vmp.trace). O formato de rastreamento usa três tipos de operações: `mr`, `r` e `i`. `mr` é um acesso de leitura à memória feito pela instrução `i`, e `r` são os registradores da CPU. Por exemplo:```
mr:0x7ffda459d718:8:0x227db4f8
r:0x40200a:0x0:0x7ffda459f571:0x2:0x40200a:0x0:0x0:0x7ffda459d688:0x0:0x0:0x7feee9b80ac0:0x7feee9b8000f:0xad1c3e:0x0:0x0:0x0
i:0x89173e:8:488BB42490000000

Temos uma leitura de memória que carrega uma constante de 8 bytes 0x227db4f8 do endereço 0x7ffda459d718. A instrução é executada no endereço 0x89173e e seu opcode de 8 bytes é 488BB42490000000, que é um mov rsi, qword ptr [rsp + 0x90]. O estado dos registradores antes da execução é o seguinte:```python (1) RAX = 0x40200a (9) R8 = 0 (2) RBX = 0 (10) R9 = 0 (3) RCX = 0x7ffda459f571 (11) R10 = 0x7feee9b80ac0 (4) RDX = 0x2 (12) R11 = 0x7feee9b8000f (5) RDI = 0x40200a (13) R12 = 0xad1c3e (6) RSI = 0 (14) R13 = 0 (7) RBP = 0 (15) R14 = 0 (8) RSP = 0x7ffda459d688 (16) R15 = 0

Uma vez que o trace VMP foi gerado, nós o reproduzimos usando o script [attack_vmp.py](https://github.com/jonathansalwan/vmprotect-devirtualization/blob/main/attack_vmp.py). Este script utiliza o [Triton](https://github.com/jonathansalwan/Triton) para construir o predicado de caminho do trace. Note que todas as expressões que envolvem variáveis simbólicas (entradas da função) são mantidas simbólicas, enquanto todas as expressões não relacionadas às entradas são concretizadas. Em outras palavras, nossas expressões simbólicas não contêm nenhuma operação relacionada à máquina virtual (a própria maquinaria não depende do usuário), mas apenas operações relacionadas ao programa original.

Por exemplo, abaixo está um exemplo de concretização. À esquerda temos uma AST que contém subexpressões que não envolvem variáveis simbólicas (`1 + 2` e `6 ^ 3`). Então, esses ramos são concretizados e substituídos por constantes `3` e `5`, o que resulta na AST à direita. **É assim que desvirtualizamos o código.**

<p align="center">
  <img src="https://assets.kitploit.com/production/public/readmes/8096/857ed50cfe9cb2347f816ece1d8dc4c13174c971dcb65ebc5621be14269a5ca8.png">
</p>
Baixar ferramenta