ac3ss0r / cvm.h

CVM is a header-only turing-complete virtual machine engine made in pure C.
Apache License 2.0
11 stars 3 forks source link
code-virtualizer obfuscation virtualization vm vmprotect

CVM

CVM is a header-only turing-complete virtual machine engine made in pure C and based on x86-64. It's not fully replicating the architecture, but can be used to implement any existing algorithm. It's created as an example of a VM for code protection purposes.

⚠️ The VM is still in developement and might be unstable. Be sure to report any problems you encounter in issues, that will be very helpful.

Examples

Here's an example of a pow method implementation before and after virtualization. You can find more examples in main.c.

static int pow_normal(int n, int b) {
    int r = n;
    for (int i = 1; i < b; i++)
        r*=n;
    return r;
}

static int pow_virt(int n, int b) {
    struct vm_context * ctx = vm_makectx();
    char code[] = {
        // Load params into registers
        // mov rax, n
        JOINBITS(11, VM_VAL2REG),
        VM_MOV,
        JOINBITS(0, 0),
        ENCODE_QWORD((qword)n), 
        // mov rbx, b
        JOINBITS(11, VM_VAL2REG),
        VM_MOV,
        JOINBITS(1, 0),
        ENCODE_QWORD((qword)b), 
        // int i = 0;
        // mov rdx, 1 
        JOINBITS(11, VM_VAL2REG),
        VM_MOV, JOINBITS(3, 0),
        ENCODE_QWORD(1), 

        // result
        // mov rcx, rax
        JOINBITS(3, VM_REG2REG), 
        VM_MOV,
        JOINBITS(2, 0),

        // loop start
        // cmp rdx, rbx
        JOINBITS(3, VM_REG2REG),
        VM_CMP,
        JOINBITS(3, 1),

        //  jge end_loop if (b >= i) jmp end_loop
        // out of scope 
        JOINBITS(10, VM_REG2REG),
        VM_JGE,
        ENCODE_QWORD(34), // jump to end_loop

        // mul rcx, rax
        JOINBITS(3, VM_REG2REG),
        VM_MUL,
        JOINBITS(2, 0),

         // add rdx, 1
        JOINBITS(11, VM_VAL2REG),
        VM_ADD, JOINBITS(3, 0),
        ENCODE_QWORD(1), 

        // jmp loop_start
        JOINBITS(10, VM_VAL2REG),
        VM_JMP,
        ENCODE_QWORD(-27),

        // end_loop
        // mov rax, rcx to return in rax
        JOINBITS(3, VM_REG2REG),
        VM_MOV,
        JOINBITS(0, 2)
    };
    vm_exec(ctx, code, sizeof(code));
    qword retval = ctx->rax;
    vm_destroyctx(ctx);
    return retval;
}

Execution flow (The results are the same)

Usage

To use the VM you will have to write the bytecode manually which can be hard and challenging, but remember it will be double as painful to reverse-engineer. Include the header into your projects by simply including the header.

TODO