4

EDIT: I've considered this more and decided it would be better and easier to just encrypt the variable in the memory and when I want to use it just decrypt it. I've tried using the following code:

DWORD blockSize = CRYPTPROTECTMEMORY_BLOCK_SIZE;
int* protectedBlock = (int*)LocalAlloc(LPTR, (SIZE_T)blockSize);

protectedBlock[0] = 1234;
printf("Before encryption: %d\n", protectedBlock[0]);
// OUTPUT: 1234

CryptProtectMemory(protectedBlock, blockSize, CRYPTPROTECTMEMORY_SAME_PROCESS);
printf("After encryption: %d\n", protectedBlock[0]);
// OUTPUT: The encrypted string

CryptUnprotectMemory(protectedBlock, blockSize, CRYPTPROTECTMEMORY_SAME_PROCESS);
printf("After decryption: %d\n", protectedBlock[0]);
//OUTPUT: 1234

SecureZeroMemory(protectedBlock, blockSize);
LocalFree(protectedBlock);

It works fine when I want to encrypt an integer, but when I try to use a string (LPCSTR) the string still stays in the memory. This is the code I use:

DWORD blockSize = CRYPTPROTECTMEMORY_BLOCK_SIZE;
LPTSTR* protectedBlock = (LPTSTR*)LocalAlloc(LPTR, (SIZE_T)blockSize);

protectedBlock[0] = (LPTSTR)"Test String";
printf("Before encryption: %d\n", protectedBlock[0]);

CryptProtectMemory(protectedBlock, blockSize, CRYPTPROTECTMEMORY_SAME_PROCESS);
printf("After encryption: %d\n", protectedBlock[0]);
// OUTPUT: The encrypted string

CryptUnprotectMemory(protectedBlock, blockSize, CRYPTPROTECTMEMORY_SAME_PROCESS);
cout << "After decryption: " << (char*)protectedBlock[0] << endl;
//OUTPUT: Test String

SecureZeroMemory(protectedBlock, blockSize);
LocalFree(protectedBlock);
  • 1
    It's not clear if the C++ `std::string` implementation is compelled to do this. If it's truly sensitive, manage the memory yourself and call `bzero`. Remember this can and will be lodged in various caches, possibly your swap file, and so on, so you'll need to do additional work to truly expunge it. – tadman Mar 22 '19 at 22:06
  • Overwrite the contents with zeros (or whatever). –  Mar 22 '19 at 22:06
  • Might be worth reading: https://stackoverflow.com/questions/13268657/is-it-possible-to-guarantee-code-doing-memory-writes-is-not-optimized-away-in-c – MFisherKDX Mar 22 '19 at 22:13
  • 3
    [Perhaps you should not store sensitive information in memory in plain text](https://stackoverflow.com/a/13286547/10147399) – Aykhan Hagverdili Mar 22 '19 at 22:17
  • 1
    @tadman: `bzero` is non-standard. `memset` is standard. – Keith Thompson Mar 22 '19 at 22:28
  • @KeithThompson Good point. – tadman Mar 22 '19 at 22:29
  • 1
    Simply overwriting the data is not guaranteed to work. The compiler can optimize away such code if it has no effect on the visible behavior. (The result of a memory dump is not considered visible behavior.) As the answer @MFisherKDX cited suggests, you probably need to use `volatile`. – Keith Thompson Mar 22 '19 at 22:30
  • Also consider the source of the information in the variable. If, for example, it was input from the console, read from a file or entered into a control in your GUI etc. then the sensitive string will also exist in multiple locations (in memory) not under your control. – Richard Critten Mar 23 '19 at 00:21
  • I will keep these in mind but I've changed the question please read it, I've figured it would be easier to just encrypt them and then decrypt them when I want to use them and then encrypt them back. – JumpakCoding Mar 23 '19 at 00:53

2 Answers2

1

Which "memory". CPU registers, ram, cache memory, a swap disk etc. What you are asking is a complicated issue that you could probably write a book on.

In truth its probably only feasable (and thats debatable) in assembly where you can be sure the compiler isnt doing some type of optimisation you don't know about. Even this doesnt always stop cpu registers / cache etc.

The real question you should ask yourself is who or what you are trying to protect it from.

Something here to get you started on a small amount of the issues you have to address.

Safe Clearing of Private Data

I would look first at maybe encrypting variables in memory (which in itself can be a large topic).

Google and some reading is your friend here.

William Humphreys
  • 1,206
  • 1
  • 14
  • 38
  • The example given in the link does not work :(. I get this `error: ‘memset’ was not declared in this scope` –  Mar 22 '19 at 22:41
  • Try adding #include and removing what seems to be some unrequired html on the last line. Im writing this on my phone so I have no way to test. – William Humphreys Mar 22 '19 at 22:50
  • LOL I did that, :) but do not include examples that do not work, and stay away from cpluplus.com –  Mar 22 '19 at 22:51
  • When I click on the edit and run Icon (even on my phone) and make those edits it works fine. – William Humphreys Mar 22 '19 at 22:54
  • As I say above what you really have to ask is who are you hiding your data from (or what). If I have access to your software it doesnt really matter what you do to it in memory on the whole. – William Humphreys Mar 22 '19 at 23:02
  • +1 for rest of the answer, no problems there but cplusplus.com is big problem :) you should stay away from it. –  Mar 22 '19 at 23:11
  • I will keep these in mind but I've changed the question, I've figured it would be easier to just encrypt them and then decrypt them when I want to use them and then encrypt them back. – JumpakCoding Mar 23 '19 at 00:54
0
protectedBlock[0] = (LPTSTR)"Test String";

This is wrong for two reasons:

  1. By using the string literal "Test String" in your code, you make that a string literal that is part of your program. You will have to assemble the string in memory some other way.

  2. A LPSTR is a long pointer to a string. So you put in the protected block a pointer to a string. Then, by protecting the block, you protected that pointer. But the pointer wasn't what you wanted to protect, you wanted to protect the string itself. So you need to put the string data itself into the protected block, not a pointer to it.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • I didn't think of that. What would you recommend using instead of LPTSTR? I guess I need to not use a pointer, just if you would give me an example it would be good. I'm a beginner in C++ and today I will do some small research on the string types and pointers... – JumpakCoding Mar 23 '19 at 09:51
  • I would put some "encrypted" form of the string in the source code and call into a function that copied it into a buffer and "decrypts" it in place, so the "decrypted" string only ever lives in the buffer. This is an extremely advanced problem you're trying to tackle that is difficult even for experts to get right (trying to hide something from someone with physical control of the computer that holds that thing), I would suggest you consider doing something else. It requires obscuring what your code is really doing. – David Schwartz Mar 23 '19 at 18:39
  • But I mean what would you use instead of LPTSTR in this case? And I'm not trying to hide it from someone who has physical control of the computer :D, I just want to make sure it's encrypted in the memory so for example when another process injects into the process that contains the encrypted string, it shouldn't be able to read the variable. Yes I've could just keep the string encrypted but I want to do this for more strings, and I've found official Windows function (it's the one that I've posted in my question) I'm just asking what would you use instead of LPTSTR? – JumpakCoding Mar 23 '19 at 18:58
  • @JumpakCoding I would put the actual string in the buffer. The string is going to be an object of variable size, so there's no c++ type that's going to perfectly describe its contents since every c++ type has a constant size (otherwise `new` wouldn't know how much to allocate). Again, this is not a simple task but actually a very advanced one. If you're willing to limit yourself to strings that fit in 256 characters, you could use `char[256]` as your data type. But this is C++, why not make a class specifically for this? – David Schwartz Mar 23 '19 at 19:00
  • @JumpakCoding You can use a `LPTSTR` to point to the string if you want, but it should point into the protected block. You still have to figure some way to get the actual string data itself into the protected block without it already being somewhere else in memory, that is, you must assemble the string in the protected block in the first instance with some sort of string assembly code that you need to write. – David Schwartz Mar 23 '19 at 19:02
  • I've just tried using string from std but it gives me some weird exception : Exception thrown: read access violation. **_Ptr_user** was 0x0. – JumpakCoding Mar 23 '19 at 19:03
  • @JumpakCoding You didn't try to put the actual contents of the string class in the protected memory, did you? That won't work for precisely the reason I explained in my answer under part 2. How do you know the data in the string class isn't just a pointer to the string? (How can it work any other way since `sizeof(std::string)` is a constant and the actual string can be much bigger than that, right?) – David Schwartz Mar 23 '19 at 19:04
  • I don't know if I need to do it with the assembly, because this code actually works like a charm when I use a integer. – JumpakCoding Mar 23 '19 at 19:05
  • By "assembly" I don't mean assembler language. I mean you need to assemble the string in the sense of putting it together in the first place. And your `int` example won't really work because this code `protectedBlock[0] = 1234;` is visible to anyone or anything who looks in memory. You need to do something like `protectedBlock[0] = 2468; protectedBlock[0]/=2;` or something to assemble the secret in the protected block in a way that doesn't make the contents visible. – David Schwartz Mar 23 '19 at 19:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190566/discussion-between-jumpakcoding-and-david-schwartz). – JumpakCoding Mar 23 '19 at 19:07