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.
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.
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:
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.
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]