The Encrypted Pointer module implements a compile time C/C++ pointer encryption and obfuscation to hide your static C/C++ pointers.

All encrypted pointers 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 pointer and build.

Encrypted Pointer Example

#include <antispy/libantispy.h>

class test_class
{
public:
   test_class () {}

   virtual ~test_class () {
      printf ("Should not print in destructors.\n");
   }

   void do_something () {
      printf ("Let's use antispy.\n");
   }
};

int main(int, char **)
{
    printf ("Initialize..\n");
    {
       libantispy::encrypted_pointer<test_class> ptr;
       ptr = new test_class ();
       ptr->do_something ();
    }
    printf ("Leaving scope and destroy the pointer...\n");
    return 0;
}

Encrypted Pointer Assembly Output

Using the antispy::encrypted_pointer<> template class here makes sure the given pointer is encrypted and all access is decrypted on the stack.

 ; int __cdecl main(int argc, const char **argv, const char **envp)
mov     [rsp+arg_8], rdx
mov     [rsp+arg_0], ecx
sub     rsp, 1C8h
lea     rcx, aInitialize__ ; "Initialize..\n"
call    sub_1400032A0
lea     rax, [rsp+1C8h+var_1A0]
mov     [rsp+1C8h+var_148], rax
mov     [rsp+1C8h+var_180], 0
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+1C8h+var_178], rax
mov     rax, [rsp+1C8h+var_180]
mov     [rsp+1C8h+var_170], rax
lea     rax, [rsp+1C8h+var_158]
mov     [rsp+1C8h+var_168], rax
mov     rax, [rsp+1C8h+var_178]
mov     rcx, [rsp+1C8h+var_170]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+1C8h+var_160], rax
mov     rax, [rsp+1C8h+var_168]
mov     rcx, [rsp+1C8h+var_160]
mov     [rax], rcx
mov     rax, [rsp+1C8h+var_158]
mov     [rsp+1C8h+var_150], rax
mov     rax, [rsp+1C8h+var_150]
mov     [rsp+1C8h+var_140], rax
mov     rax, [rsp+1C8h+var_148]
mov     rcx, [rsp+1C8h+var_140]
mov     [rax], rcx
mov     ecx, 8          ; Size
call    sub_14000333C
mov     [rsp+1C8h+var_1A8], rax
cmp     [rsp+1C8h+var_1A8], 0
jz      short loc_1400011C3
mov     rax, [rsp+1C8h+var_1A8]
lea     rcx, off_140005418
mov     [rax], rcx
mov     rax, [rsp+1C8h+var_1A8]
mov     [rsp+1C8h+var_188], rax
jmp     short loc_1400011CC

loc_1400011C3:                          
mov     [rsp+1C8h+var_188], 0

loc_1400011CC:                          
mov     rax, [rsp+1C8h+var_188]
mov     [rsp+1C8h+var_138], rax
mov     rax, [rsp+1C8h+var_138]
mov     [rsp+1C8h+var_130], rax
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+1C8h+var_128], rax
mov     rax, [rsp+1C8h+var_130]
mov     [rsp+1C8h+var_120], rax
lea     rax, [rsp+1C8h+var_108]
mov     [rsp+1C8h+var_118], rax
mov     rax, [rsp+1C8h+var_128]
mov     rcx, [rsp+1C8h+var_120]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+1C8h+var_110], rax
mov     rax, [rsp+1C8h+var_118]
mov     rcx, [rsp+1C8h+var_110]
mov     [rax], rcx
mov     rax, [rsp+1C8h+var_108]
mov     [rsp+1C8h+var_100], rax
mov     rax, [rsp+1C8h+var_100]
mov     [rsp+1C8h+var_F8], rax
mov     rax, [rsp+1C8h+var_F8]
mov     [rsp+1C8h+var_F0], rax
mov     rax, [rsp+1C8h+var_F0]
mov     [rsp+1C8h+var_1A0], rax
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+1C8h+var_E8], rax
mov     rax, [rsp+1C8h+var_1A0]
mov     [rsp+1C8h+var_E0], rax
lea     rax, [rsp+1C8h+var_C8]
mov     [rsp+1C8h+var_D8], rax
mov     rax, [rsp+1C8h+var_E8]
mov     rcx, [rsp+1C8h+var_E0]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+1C8h+var_D0], rax
mov     rax, [rsp+1C8h+var_D8]
mov     rcx, [rsp+1C8h+var_D0]
mov     [rax], rcx
mov     rax, [rsp+1C8h+var_C8]
mov     [rsp+1C8h+var_C0], rax
mov     rax, [rsp+1C8h+var_C0]
mov     [rsp+1C8h+var_B8], rax
mov     rax, [rsp+1C8h+var_B8]
mov     [rsp+1C8h+var_18], rax
lea     rcx, aLetSUseAntispy ; "Let's use antispy.\n"
call    sub_1400032A0
nop
lea     rax, [rsp+1C8h+var_1A0]
mov     [rsp+1C8h+var_190], rax
cmp     [rsp+1C8h+var_190], 0
jz      scope_exit
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+1C8h+var_B0], rax
mov     rax, [rsp+1C8h+var_190]
mov     rax, [rax]
mov     [rsp+1C8h+var_A8], rax
lea     rax, [rsp+1C8h+var_90]
mov     [rsp+1C8h+var_A0], rax
mov     rax, [rsp+1C8h+var_B0]
mov     rcx, [rsp+1C8h+var_A8]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+1C8h+var_98], rax
mov     rax, [rsp+1C8h+var_A0]
mov     rcx, [rsp+1C8h+var_98]
mov     [rax], rcx
mov     rax, [rsp+1C8h+var_90]
mov     [rsp+1C8h+var_88], rax
mov     rax, [rsp+1C8h+var_88]
mov     [rsp+1C8h+var_80], rax
mov     rax, [rsp+1C8h+var_80]
mov     [rsp+1C8h+var_78], rax
mov     rax, [rsp+1C8h+var_78]
mov     [rsp+1C8h+var_198], rax
cmp     [rsp+1C8h+var_198], 0
jz      short loc_140001412
mov     rax, [rsp+1C8h+var_198]
mov     rax, [rax]
mov     rax, [rax]
mov     [rsp+1C8h+var_70], rax
mov     edx, 1
mov     rcx, [rsp+1C8h+var_198]
call    [rsp+1C8h+var_70]
mov     [rsp+1C8h+var_68], rax
jmp     short loc_14000141E

loc_140001412:
mov     [rsp+1C8h+var_68], 0

loc_14000141E:
mov     [rsp+1C8h+var_60], 0
mov     rax, 0BB9B649EA326CBDBh
mov     [rsp+1C8h+var_58], rax
mov     rax, [rsp+1C8h+var_60]
mov     [rsp+1C8h+var_50], rax
lea     rax, [rsp+1C8h+var_38]
mov     [rsp+1C8h+var_48], rax
mov     rax, [rsp+1C8h+var_58]
mov     rcx, [rsp+1C8h+var_50]
xor     rcx, rax
mov     rax, rcx
mov     [rsp+1C8h+var_40], rax
mov     rax, [rsp+1C8h+var_48]
mov     rcx, [rsp+1C8h+var_40]
mov     [rax], rcx
mov     rax, [rsp+1C8h+var_38]
mov     [rsp+1C8h+var_30], rax
mov     rax, [rsp+1C8h+var_30]
mov     [rsp+1C8h+var_28], rax
mov     rax, [rsp+1C8h+var_28]
mov     [rsp+1C8h+var_20], rax
mov     rax, [rsp+1C8h+var_190]
mov     rcx, [rsp+1C8h+var_20]
mov     [rax], rcx

scope_exit:                             
lea     rcx, aLeavingScopeAn ; "Leaving scope and destroy the pointer.."...
call    sub_1400032A0
xor     eax, eax
add     rsp, 1C8h
retn
main            endp

As you can see in the compiled binary and assembly output the pointer is decrypted just before it is used. Here, we see a simple XOR which is one of multiple encryption / decryption algorithms we support. Although this already adds some overhead in all references where you are accessing your pointer we still recommend to use even more advanced techniques that are shipped including antispy.

As alternative you can always extend antispy to include your own encryption and decryption.

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 buffer 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.