
รหัส X86-64 Virtualizer สำหรับการทำให้งงงวยตาม VM
*การสนับสนุน PE ทดสอบเฉพาะในไบนารีที่รวบรวมผ่าน MingW-W64
CMake จะดึงการพึ่งพาทั้งหมดเหล่านี้ดังนั้นการติดตั้งด้วยตัวคุณเองจึงไม่จำเป็น
| ชื่อ | รุ่น |
|---|---|
| cmake | 3.25+ |
| zydis | 4.1.0+ |
| สิ่งเปลี่ยนสี | ล่าสุด |
| lief | 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 ปัจจุบันจะผลักดันให้ตัวถูกดำเนินการส่วนใหญ่ไปยังสแต็กเพื่อประมวลผลลดความซับซ้อนของการเข้ารหัสคำสั่ง VM สำหรับคำแนะนำที่ไม่มีตัวจัดการ VM ที่กำหนดไว้พวกเขาจะถูกดำเนินการโดยธรรมชาติ ( vm_exit -> native instruction -> vm_enter ) ฟังก์ชั่นการโทรติดตามไปป์ไลน์เดียวกันซึ่งเราออกจากการเรียกใช้ฟังก์ชั่นและป้อน VM อีกครั้ง ทั้งหมดเข้าด้วยกันการเปลี่ยนแปลงทำให้ไบนารีมีขนาดมากขึ้นอย่างมีนัยสำคัญ:
a.out เป็น ELF : 15.5 kb -> 1.0 mba.out เป็น PE : 259.3 kb -> 1.3 mb | คำอธิบาย | IDA |
|---|---|
การสลายตัวของ IDA ของ vm_entry ซึ่งได้รับการทำให้งงงวยผ่าน MBA Pass เท่านั้น LOC มากกว่า 27K ถูกสร้างขึ้นโดย decompiler | ![]() |
IDA ถอดชิ้นส่วนของ vm_entry ซึ่งได้รับการทำให้งงผ่าน MBA & SMC ผ่าน การสลายตัวไม่ทำงาน | ![]() |