Batata
Batata

Reputation: 133

Encrypt Variables

I want to know if there is any way that I can encrypt the .data section of my process to prevent external programs like Cheat Engine to read or write data from my program.

I know how to do this in the .text section using packers, but now I want to protect the variables of my program to be accessed.

Anyone know if this is possible or if there is another way to protect the memory?

Other ways to protect memory are welcome!

Upvotes: 0

Views: 2067

Answers (3)

Rick C. Hodgin
Rick C. Hodgin

Reputation: 503

You can allocate pages with VirtualAlloc() and protect them with VirtualProtect(), and there are Ex() versions of those functions as well. You can then set and unset the flags to the correct memory protection constant values to prevent any kind of access without going through a protocol which changes the access, accesses, and changes it back.

In my opinion, at startup, it's best to have your .data section already encrypted from some pre-build compiler pass run on the source code, so that at startup everything's already encrypted, and then you decrypt inside main(), or on an as needed basis through some protocol.


As an example for doing this at compilation time, a pre-build step with a custom developed parser can look for some flag in your source code and replace the original code with a comment holding the original code, and then have the encrypted code enter the compiler in a pre-build step. A post-build step can then undo the changes made in a pre-build step allowing for the original source code in the editor. You should copy the encrypted version to the build folder so it can be documented and debugged if need be.

Something like this: Wrap each variable you want encrypted in some kind of flag, like (C++ code shown):

// Define a macro that does nothing from the compiler's point of view
#define encrypt_me(a) a

// And then in your code, wrap variables in the macro
const char my_data[] = encrypt_me("Hi, mom!");

The pre-build compiler would see the encrypt_me() reference, and change it to something like:

const char my_data[] = encrypt_me(/*"Hi, mom!"*/ "encrypted version here");

In that way, you have a cue your custom parser can pick up on for encryption, or decryption. You can encode all of your data using some kind of mime64 or if you want to use anything, encode it as octal \377 or \xFF hexadecimal escape sequences, or whatever your needs require.

For every variable you encrypt like this, you create a function including the decrypt code, or a series of #define statements that can be referenced for each one. That way, the decode logic is baked into your program, every encrypted variable is documented, along with the code to decrypt it.

If you need it at a special place, then a second stage custom pre-build parser can go through and move or comment out the code that's in that generated file.

You just need to think through the steps you need and make it happen for your specific needs.

Upvotes: 0

josh poley
josh poley

Reputation: 7479

You will want to use CryptProtectMemory to encrypt the data while not in use (use the CRYPTPROTECTMEMORY_SAME_PROCESS flag). Then call CryptUnprotectMemory to when you need to access it.

As stated by David, this just reduces the window in which an attacker can view/modify your memory, but given that limitation, this is the right way to do it.

Edit: Example encrypting an int. Error checking removed for brevity. The important part to note is that it works on CRYPTPROTECTMEMORY_BLOCK_SIZE sized chunks (for the sample we just use one chunk as that will hold an int on 32 or 64 bit platforms):

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

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

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

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

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

Output:

Before encryption: 1234
After encryption: -2594087
After decryption: 1234

Upvotes: 1

David Heffernan
David Heffernan

Reputation: 613053

You can certainly encrypt the .data section. If you wish to encrypt the entire .data section then you'd probably need to adopt the same policy as the packers do. Encrypt the entire executable. Add a stub that performs the decryption at startup, and then transfer control to the decrypted executable. But then you'd be no better off of course. The cheat engines can read the memory of the process just as before.

And you won't be able to have the process executing with the .data section encrypted. That way you'll break every bit of library code that uses global variables, constants etc. What you might do is encrypt just the sensitive information and decrypt on the fly just before use, and then throw away immediately. This at least makes it a little harder for the hackers. They have to be looking at exactly the right moment. But anyone that really wants to get at your data will be able to. At some point you'll have to decrypt the data to use it, and then the cheat engines can gain access to the values.

The bottom line here is that if you find yourself in the situation where another process can read from and write to the memory your process, then you have lost the battle.

Upvotes: 1

Related Questions