1

Despite various ways to scrub sensitive data in volatile memory (see Survive DSE or Zeroing buffers), programs tend to perform transparent memory copies (such as a Garbage Collection). The newly generated duplicates are no longer referenced and then they're exposed to memory attacks, thus the above mentioned solutions are not applicable in this case.

My questions are:

  1. When and why would such memory copy occur (in C and C++)?

  2. Are there any solutions to prevent it? Both on the program level and the compiling level.

1 Answer 1

3

When and why would such memory copy occur (in C and C++)?

By no means an exhaustive list, but examples would include:

  • Calls for explicit copies like strncpy(), memcpy()
  • Passing arguments by value causes them to duplicated (generally on the stack)
  • Variable assignments for structs and classes (not pointers) cause a copy.
  • You also have no guarantee what the runtime's memory manager does or doesn't do. Memory that has been freed might still be sitting there, in whole or in part.
  • Data can be also swapped from memory out to disk by the operating system (virtual memory), cause a copy on disk.

Is there any solutions to prevent it? Both on program level and compiling level

Probably the most scientific answer is: No. If the user has full access to the machine (including physical access) you can't entirely prevent someone from finding a way to get at memory of your program. But you certainly can make it harder.

One approach that comes to mind is the keep the information obfuscated in some way until the last possible moment and decode only the specific thing you need one piece at a time, being careful to fill that memory with garbage afterward.

If someone is trying to scrape the memory of your program to look for sensitive information, you can probably slow them down a lot by making it (nearly) all random-looking bytes that are only decoded in very small pieces. This would basically force them to decompile/disassemble your program to figure out exactly what encoding you were doing and how in order to get at the data. Combine this with a binary code obfuscation tool and this becomes a major hassle.

Again, it's not impossible to circumvent this approach, but it's definitely harder.

7
  • 1
    Another important source for copies is when a continuous storage container (std::vector, std::string) resizes. Commented Sep 18, 2019 at 6:39
  • 2
    Yep, this also appears while using realloc sometimes. For memory swap, we can leverage mlock() to avoid it.
    – weir007
    Commented Sep 18, 2019 at 7:08
  • 1
    If you've got a secret, you need to protect that secret. Obfuscation does not protect a secret. mlock() the memory for the secret into RAM before writing the secret into it, make sure you don't use anything fancy on that buffer, and explicitly clear the buffer when you are done before calling munlock(). (Not doing anything fancy means: Treat it as a plain old C array, don't use C++ containers and stuff on it, and, most importantly, don't use a language like Java that won't allow you any control over what the runtime does with your memory. You want every access to the secret explicit.) Commented Sep 18, 2019 at 9:18
  • 1
    @cmaster And then look at the assembly output to make sure the C compiler has not optimised out the 'clear the buffer' bit on the grounds that it can prove the memory is not used elsewhere... Volatile sometimes helps here, but compilers are getting too clever by half.
    – Dan Mills
    Commented Sep 22, 2019 at 14:31
  • @DanMills Full ACK. Another way to avoid destructive optimization by the compiler is to put a memset() wrapper into a shared library, and then use that wrapper to clear the secret. Since the wrapper is in a shared library, the compiler does not know its implementation, and the linker cannot optimize the call away because the lib version loaded at runtime may not be the same as the one that the program was linked against (LD_PRELOAD). This is the most robust way I know to keep the optimizer from exploiting some specific knowledge without deactivating it fully via volatile. Commented Sep 22, 2019 at 17:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.