用于基于虚拟机的混淆的x86-64代码虚拟化器。
*PE支持仅在通过MinGW-w64编译的二进制文件上测试过
CMake 会自动获取所有这些依赖项,因此您无需自行安装。
需要兼容 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;
}
[!IMPORTANT]
- 请勿将
__covirt_vm_end放置在无法到达的位置(例如 return 之后),否则会阻止输出结束存根- 使用
MSVC时__covirt_vm_...();存根无法工作,因为它们使用了内联汇编- 需要
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 = %d\n", result);
__covirt_vm_end();
return result;
}
int main()
{
calculate(5, 12);
}
上面的示例应用程序使用了 covirt a.out -d 进行虚拟化,该命令会在混淆和虚拟化后输出虚拟机指令的转储。当前的虚拟机实现将大多数操作数压入堆栈进行处理,从而降低了编码虚拟机指令的复杂性。对于没有定义虚拟机处理器的指令,它们将被本地执行(vm_exit -> native instruction -> vm_enter)。函数调用遵循同样的流程,即退出虚拟机、调用函数、重新进入虚拟机。总的来说,这些转换会使二进制文件的大小显著增加:
a.out 作为 ELF:15.5 kB -> 1.0 MBa.out 作为 PE:259.3 kB -> 1.3 MB| 描述 | IDA |
|---|---|
IDA 对仅通过 MBA 过程混淆的 vm_entry 的反编译结果。反编译器生成了超过 27k 行代码。 | ![]() |
IDA 对通过 MBA 和 SMC 过程混淆的 vm_entry 的反汇编结果。反编译无法工作。 | ![]() |