
Un virtualiseur de code x86-64 pour l'obscurcissement basé sur la machine virtuelle.
* Le support PE est testé uniquement sur les binaires compilés via MingW-W64
CMake rapportera toutes ces dépendances, donc les installer vous-même n'est pas nécessaire.
| Nom | Version |
|---|---|
| Cmake | 3.25+ |
| Zydis | 4.1.0+ |
| zasme | Dernier |
| Lief | 0.15.1+ |
Un compilateur compatible C++23 est requis pour construire.
git clone https://github.com/dmaivel/covirt.git
cd covirt
mkdir build
cd build
cmake ..
cmake --build . --config Release Si vous compilez sur Windows via Visual Studio, vous devez utiliser clang-cl : cmake .. -T ClangCL -A x64 .
Usage: covirt [--help] [--version] [--output OUTPUT_PATH] [--vm_code_size MAX] [--vm_stack_size SIZE] [--no_self_modifying_code] [--no_mixed_boolean_arith] [--show_dump_table] INPUT_PATH
Code virtualizer for x86-64 ELF & PE binaries
Positional arguments:
INPUT_PATH path to input binary to virtualize
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
-o, --output OUTPUT_PATH specify the output file [default: INPUT_PATH.covirt]
-vcode, --vm_code_size MAX specify the maximum allowed total lifted bytes [default: 2048]
-vstack, --vm_stack_size SIZE specify the size of the virtual stack [default: 2048]
-no_smc, --no_self_modifying_code disable smc pass
-no_mba, --no_mixed_boolean_arith disable mba pass
-d, --show_dump_table show disassembly of the vm instructions Pour que covirt sache quelles fonctions doivent être virtualisées, vous devez ajouter les marqueurs de début et de fin dans votre code source, comme ainsi:
#include "covirt_stub.h"
int my_function (...)
{
int result = 0 ;
__covirt_vm_start ();
// ...
__covirt_vm_end ();
return result ;
}Important
__covirt_vm_end dans des emplacements inaccessibles (c'est-à-dire après un retour), car cela empêchera le talon final d'émettre__covirt_vm_...(); Les talons ne fonctionneront pas en utilisant MSVC car ils utilisent l'assemblage en ligneSSE4 est requis 
#include <covirt_stub.h>
#include <stdio.h>
int calculate ( int a , int b )
{
int result = 0 ;
__covirt_vm_start ();
for ( int i = 0 ; i < 10 ; i ++ )
if ( i > 5 )
result += result + a ;
else
result += ( result >> 1 ) + b ;
printf ( "result = %dn" , result );
__covirt_vm_end ();
return result ;
}
int main ()
{
calculate ( 5 , 12 );
} L'exemple d'application ci-dessus a été virtualisé à l'aide de covirt a.out -d , qui étend un vidage des instructions VM après l'obscurcissement et la virtualisation. L'implémentation VM actuelle pousse la plupart des opérandes sur la pile pour les traiter, réduisant la complexité de l'encodage des instructions VM. Pour les instructions qui n'ont pas de gestionnaire de VM défini, ils seront exécutés nativement ( vm_exit -> native instruction -> vm_enter ). Les fonctions d'appel suivent le même pipeline, dans lequel nous quittons, appelons la fonction et réinstallerons la machine virtuelle. Tous ensemble, les transformations font croître considérablement les binaires:
a.out comme un ELF : 15,5 kb -> 1,0 Moa.out comme un PE : 259,3 Ko -> 1,3 Mo | Description | Ida |
|---|---|
La décompilation IDA de vm_entry , qui a été obscurcie via le MBA Pass uniquement. Plus de 27 000 LOC ont été générés par le décompilateur. | ![]() |
Désassement IDA de vm_entry , qui a été obscurci via les passes MBA & SMC. La décompilation ne fonctionne pas. | ![]() |