Encrypted Buffer - Documentation

TL;TR

The Encrypted Buffer module implements a compile time C/C++ buffer encryption and obfuscation to hide your static C/C++ buffers such as encryption keys, primes, initialization vectors or any sort of static resources.

Every encrypted buffer uses unique generated keys and primes in every single software build. This sort of protection guarantees a high hurdle and wall against potential attackers, since the protection is unique by buffer and build.

Problem: buffers.

We are referring to a buffer as a constant and static block of memory in your program. Whenever you use such a block of memory in your application the compiler and linker will place this most likely to a constant data segment in your program. A very common use case includes storing encryption keys, hashes or signatures in your program. 

The following code illustrates this.

char buf[4] = { 0x10, 0x20, 0x30, 0x40 }

int main(int argc, char**)
{
    LOG("initialize decryption");

    // Call some library function to initialize some decryption and sensitive information..
    if (!library_function_init(buf, 4)) { return -1; }
    LOG("decryption initialized");

    LOG("reading all sensitive information now")
    library_function_read_data(...)
} 

As you can see – in this code we initialize some function and pass a buffer including 4 bytes. Let it be some kind of password to decrypt some very sensitive information.

How is this code an issue?

While you can do this – or similar things – and it is absolutely fine – it is easy for attackers to automatically extract your buffer that is used to decrypt your sensitive information.

This code becomes an issue because you attempted to protect your information but it is fairly simple to extract the key to decrypt the buffer.

Solution: encrypted buffers.

As discussed earlier in this page we provide a compile-time obfuscation to all kinds of static buffers.

This compile-time buffer obfuscation brings the following advantages:

  • Compiler generates code on the stack and it is obfuscated on the stack.
  • Even if you don’t change your buffers’ content the obfuscated buffer will change on every single compilation of your software.
  • It gives an extra hurdle to attackers since the generated code makes common disassemblers and attackers busy.

 

Below is a minimal example that shows how to use antispy SDK – Encrypted Buffer module.

auto buf = ANTISPY_OBFUSCATED_BUFFER("\x00\x10\x20\x30", 4)

int main(int argc, char**)
{
    LOG("initialize decryption");

    // Call some library function to initialize some decryption and sensitive information..
    if (!library_function_init(buf, 4)) { return -1; }
    LOG("decryption initialized");

    LOG("reading all sensitive information now")
    library_function_read_data(...)
} 

We have changed one line of code that changes the initialization of the buffer and everything else just works ‘as is’, though the code that the compiler is about to generate is totally different since the buffer is put on the stack – obfuscated.

P.S.: Never use plain text strings in sensitive-information code paths. We have you covered with String Encryption.

Disassembly

Using the default encryption strategy the compiler generates an obfuscated buffer on the stack and decrypts it while accessing.

mov     r8d, dword ptr cs:aJcj         ; "åûåÂ"
mov     [rsp+78h+var_54], r8d
xor     r8b, 86h                       ; decrypt 1st -> 0x00
movzx   edx, byte ptr [rsp+78h+var_54+1]
xor     dl, 86h                        ; decrypt 2nd -> 0x10
movzx   ecx, byte ptr [rsp+78h+var_54+2]
xor     cl, 86h                        ; decrypt 3rd -> 0x20
movzx   eax, byte ptr [rsp+78h+var_54+3]
xor     al, 86h                        ; decrypt 4th -> 0x30
mov     byte ptr [rsp+78h+var_58], r8b
mov     byte ptr [rsp+78h+var_58+1], dl
mov     byte ptr [rsp+78h+var_58+2], cl
mov     byte ptr [rsp+78h+var_58+3], al
mov     qword ptr [rsp+78h+var_40+8], 0Fh
mov     qword ptr [rsp+78h+var_40], 4
mov     eax, [rsp+78h+var_58]
mov     dword ptr [rsp+78h+var_50], eax
mov     byte ptr [rsp+78h+var_50+4], 0
movups  xmm0, [rsp+78h+var_50]
movups  [rsp+78h+var_30], xmm0
movups  xmm1, [rsp+78h+var_40]
movups  [rsp+78h+var_20], xmm1
xor     edi, edi
lea     rbx, [rsp+78h+var_30]
db      66h, 66h
nop     word ptr [rax+rax+00000000h]