
Виртуализатор кода X86-64 для запугивания на основе виртуальной машины.
*Поддержка PE тестируется только на двоичных файлах, скомпилированных через Mingw-W64
CMake принесет все эти зависимости, поэтому установить их самостоятельно не нужна.
| Имя | Версия |
|---|---|
| Cmake | 3.25+ |
| Зидис | 4.1.0+ |
| зазорный | Последний |
| Лиф | 0,15,1+ |
Для построения требуется совместимый компилятор C++23 .
git clone https://github.com/dmaivel/covirt.git
cd covirt
mkdir build
cd build
cmake ..
cmake --build . --config Release Если вы компилируете Windows через Visual Studio, вы должны использовать 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 Чтобы covirt знала, какие функции должны быть виртуализированы, вы должны добавить маркеры начала и конечного кода, например, так:
#include "covirt_stub.h"
int my_function (...)
{
int result = 0 ;
__covirt_vm_start ();
// ...
__covirt_vm_end ();
return result ;
}Важный
__covirt_vm_end в недоступных местах (т.е. после возврата), так как это предотвратит излучение конечного заглушки__covirt_vm_...(); Заглушки не будут работать с использованием MSVC , потому что они используют встроенную сборкуSSE4 
#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 );
} Пример приложения выше был виртуализирован с использованием covirt a.out -d , который выводит дамп инструкций виртуальной машины после запутывания и виртуализации. Текущая реализация виртуальной машины подталкивает большинство операндов в стек для их обработки, уменьшая сложность кодирования инструкций VM. Для инструкций, у которых нет определенного обработчика виртуальной машины, они будут выполнены изначально ( vm_exit -> native instruction -> vm_enter ). Вызовые функции следует за тем же трубопроводом, в котором мы выходим, называем функцию и возвращаем виртуальную машину. Все вместе, преобразования заставляют двоичные файлы значительно расти в размерах:
a.out как ELF : 15,5 кб -> 1,0 МБa.out As PE : 259,3 КБ -> 1,3 МБ | Описание | ИДА |
|---|---|
Декомпиляция IDA vm_entry , которая была запутана только через проход MBA. Более 27 тыс. Лок был создан декомпилятором. | ![]() |
Разборка IDA vm_entry , которая была запутана с помощью проходов MBA & SMC. Декомпиляция не работает. | ![]() |