
Ein X86-64-Code-Virtualizer für VM-basierte Verschleierung.
*PE-Unterstützung nur auf Binärdateien getestet, die über Mingw-W64 zusammengestellt wurden
CMake wird all diese Abhängigkeiten abrufen, sodass es nicht erforderlich ist, sie selbst zu installieren.
| Name | Version |
|---|---|
| Cmake | 3.25+ |
| Zydis | 4.1.0+ |
| Zasm | Letzte |
| Lief | 0,15.1+ |
Ein C++23 kompatibler Compiler ist erforderlich, um zu erstellen.
git clone https://github.com/dmaivel/covirt.git
cd covirt
mkdir build
cd build
cmake ..
cmake --build . --config Release Wenn Sie über Visual Studio unter Windows kompilieren, müssen Sie 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 Damit covirt wissen kann, welche Funktionen virtualisiert werden müssen, müssen Sie den Start- und Endmarkierungen in Ihren Quellcode hinzufügen, wie Sie:
#include "covirt_stub.h"
int my_function (...)
{
int result = 0 ;
__covirt_vm_start ();
// ...
__covirt_vm_end ();
return result ;
}Wichtig
__covirt_vm_end an nicht erreichbaren Stellen (dh nach einer Rückkehr), da dies verhindert__covirt_vm_...(); Stubs funktioniert nicht mit MSVC , da sie Inline -Montage verwendenSSE4 -Unterstützung ist erforderlich 
#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 );
} Die obige Beispielanwendung wurde unter Verwendung von covirt a.out -d virtualisiert, wodurch nach der Verschleierung und Virtualisierung eine Dump der VM -Anweisungen ausgegeben wird. Die aktuelle VM -Implementierung drückt die meisten Operanden auf den Stapel, um sie zu verarbeiten, wodurch die Komplexität der Codierung der VM -Anweisungen verringert wird. Für Anweisungen, die keinen definierten VM -Handler haben, werden sie nativ ausgeführt ( vm_exit -> native instruction -> vm_enter ). Das Aufrufen von Funktionen folgt derselben Pipeline, in der wir die Funktion beenden, die Funktion aufrufen und die VM wiedergeben. Insgesamt wachsen die Binärdateien erheblich in der Größe:
a.out als ELF : 15,5 kb -> 1,0 MBa.out als PE : 259.3 kb -> 1,3 mb | Beschreibung | Ida |
|---|---|
IDA -Dekompilierung von vm_entry , die nur über den MBA -Pass verschleiert wurde. Über 27K wurden vom Dekompiler erzeugt. | ![]() |
IDA -Demontage von vm_entry , die über die MBA & SMC -Pässe verschleiert wurde. Die Dekompilierung funktioniert nicht. | ![]() |