The Encrypted Primitive module implements a compile time C/C++ value encryption and obfuscation to hide your primitives.

All encrypted values use unique generated keys with every single build. This sort of protection gurantees a high hurdle and wall against potential attackers, since the protection is unique by value and build.

Encrypted Primitive Example

uint64_t add (uint64_t a, uint64_t b)
{
   return a + b;
}

uint64_t GetMagicNumber ()
{
   return rand () % 255;
}

int main(int, char **)
{
    srand (time (NULL));
    
    ANTISPY_ENCRYPTED_VALUE (uint64_t, number, 0x1010101010101010);
    
    uint64_t result = add(number, GetMagicNumber());
    printf ("result is %llu\n", result);
    return 0;
}

Encrypted Primitive Assembly Output

Using the ANTISPY_ENCRYPTED_VALUE macro makes sure the given primitive is encrypted and all access is decrypted on the stack.

main proc near

mov     [rsp+arg_8], rdx
mov     [rsp+arg_0], ecx
sub     rsp, 0C8h
xor     ecx, ecx        ; Time
call    cs:_time64
mov     ecx, eax        ; Seed
call    cs:srand
mov     rax, 1010101010101010h
mov     [rsp+0C8h+var_A0], rax
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+0C8h+var_98], rax
mov     rax, [rsp+0C8h+var_A0]
mov     [rsp+0C8h+var_90], rax
lea     rax, [rsp+0C8h+var_78]
mov     [rsp+0C8h+var_88], rax
mov     rax, [rsp+0C8h+var_98]
mov     rcx, [rsp+0C8h+var_90]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+0C8h+var_80], rax
mov     rax, [rsp+0C8h+var_88]
mov     rcx, [rsp+0C8h+var_80]
mov     [rax], rcx
mov     rax, [rsp+0C8h+var_78]
mov     [rsp+0C8h+var_70], rax
mov     rax, [rsp+0C8h+var_70]
mov     [rsp+0C8h+var_68], rax
mov     rax, [rsp+0C8h+var_68]
mov     [rsp+0C8h+var_60], rax
call    GetMagicNumber
mov     [rsp+0C8h+var_20], rax
mov     rax, [rsp+0C8h+var_10]
mov     [rsp+0C8h+var_A8], rax
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+0C8h+var_58], rax
mov     rax, [rsp+0C8h+var_60]
mov     [rsp+0C8h+var_50], rax
lea     rax, [rsp+0C8h+var_38]
mov     [rsp+0C8h+var_48], rax
mov     rax, [rsp+0C8h+var_58]
mov     rcx, [rsp+0C8h+var_50]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+0C8h+var_40], rax
mov     rax, [rsp+0C8h+var_48]
mov     rcx, [rsp+0C8h+var_40]
mov     [rax], rcx
mov     rax, [rsp+0C8h+var_38]
mov     [rsp+0C8h+var_30], rax
mov     rax, [rsp+0C8h+var_30]
mov     [rsp+0C8h+var_28], rax
mov     rax, [rsp+0C8h+var_28]
mov     [rsp+0C8h+var_A8], rax
mov     rdx, [rsp+0C8h+var_20]
mov     rcx, [rsp+0C8h+var_A8]
call    add
mov     [rsp+0C8h+var_18], rax
mov     rdx, [rsp+0C8h+var_18]
lea     rcx, aResultIsLlu ; "result is %llu\n"
call    sub_140002EA0
xor     eax, eax
add     rsp, 0C8h
retn
sub_140001150 endp

As you can see in the compiled binary and assembly output the primitive is decrypted just before it is used.

If you protect that code block with Control Flow Obfuscation and Anti-Debugging techniques the attacker has almost no chance to easily extract the decrypted primitive since it is not present in the binary.

Example Binaries

You want to have a look at the result in your favorite Disassembler? Please request example binaries here.