-2

I have written a C++ code for application, in which there are some variables that must have different values for every user will use it ( lets call it the variable X for simplicity)

X have different values for different user. This (X)should be not changed and also embedded in the exe itself ( so I can't read it from a file or any other similar solution)

I don't want to distribute the source code then compile. Instead, I want a method that makes me edit the final exe directly without need to compile ( it is just value of variable X which differs !) Is this possible ?

My idea to do this is if I can force this (X) at a constant memory location, I can then edit its value easily from Hex-editor as example. ( I mean the same ideas when hackers writes cheat tool for a certain game )

  1. Is the mechanism of fixed memory position possible?
  2. Is there any other idea to make what I want?

I hope my question is clear enough

melpomene
  • 84,125
  • 8
  • 85
  • 148
CodeLOL
  • 35
  • 5
  • 5
    I would put the values for the variables into a separate file that the application reads when it starts up. Much more manageable and maintainable than doing hex editing on an executable. – Jerry Coffin Sep 08 '18 at 06:23
  • Why can't you just change it in the code and recompile? That seems easier than trying to hex-edit it. – Retired Ninja Sep 08 '18 at 06:23
  • @RetiredNinja Because then you'd have to recompile the whole application for every user / download. – melpomene Sep 08 '18 at 06:24
  • 2
    @melpomene And that is different than having to edit the executable for every user in what way? – Retired Ninja Sep 08 '18 at 06:24
  • @RetiredNinja Writing some bytes to a file at a fixed offset is much easier (algorithmically and performance-wise) than doing a structural edit on source code and invoking a compiler. – melpomene Sep 08 '18 at 06:26
  • You declare the variable in an .h file and assign the value in a .cpp file, so that changing the value would only require a brief recompilation. – rsjaffe Sep 08 '18 at 06:28
  • 1
    If your application runs on Windows, you might consider using resources. I believe there're APIs you can use to modify the resources and thus the executable. https://learn.microsoft.com/en-us/windows/desktop/menurc/adding-deleting-and-replacing-resources – Tianjiao Huang Sep 08 '18 at 06:29
  • 1
    The quick and dirty way of doing this is to define a global `char special_data[] = "XXX a unique string XXX";`, compile it, then search the binary for `XXX a unique string XXX` and replace it by whatever you want (as long as it has the same number of bytes). – melpomene Sep 08 '18 at 06:31
  • @melpomene: That's what I'd do too, if someone forced me to hack something together like this. It doesn't need to be the same number of bytes either, fewer bytes would be fine. You could make the dummy string size 1000 or more with little downside. – John Zwinck Sep 08 '18 at 06:35
  • @melpomene If you say so. It can easily be automated as with anything. Build scripts that automatically increment version numbers are nothing special and this seems the same to me. – Retired Ninja Sep 08 '18 at 06:35
  • @RetiredNinja This sounds more like an embedded per-user license key or serial number to me. – melpomene Sep 08 '18 at 06:37
  • There are plenty of utilities for patching executables. Essentially, distribute the (relatively small) patch program along with data about the deltas to apply to your actual executable (s). Although you need to recompile the program on your development machine, the only data distributed is a description of changes to apply, not the entire executables. More advanced patch programs do include capabilities to recognise particular versions of an executable (e.g. to ensure you don't apply the 1.2 to 1.3 patch to version 1.1 of the program). – Peter Sep 08 '18 at 07:32
  • Why not to simply append your data to the end of the executable and then open the executable as a binary file and read this data? – Evg Sep 08 '18 at 07:35
  • 1
    You can exports symbols from an exe. However C++ doesn't have a standard mechanism for that. With VS it suffices to use `__declspec(dllexport)` (the name is deceiving) on the variable *declaration*. You can then process the PE to retrieve the offset of the variable through the EAT and eventually remove the entry. What compiler are you using? – Margaret Bloom Sep 08 '18 at 07:48
  • 2
    There's a strong smell of an XY problem. Why do you need this? You also contradict yourself, first saying the value should not be embedded in an executable, and then that you want to edit it with a hex editor. – n. m. could be an AI Sep 08 '18 at 07:56
  • @melpomene That is good ! what if more bytes than the stored old variable ? Can I shift all the bytes with the difference in both ? – CodeLOL Sep 08 '18 at 15:34
  • @n.m. No contradiction, I want a method such that me or even the users (not all for sure ) can edit this (X) without having the compiled code to recompile – CodeLOL Sep 08 '18 at 15:37
  • So what does this mean "so I can't read it from a file or any other similar solution"? You cannot read it but you can edit it? – n. m. could be an AI Sep 08 '18 at 15:44
  • not totally right X value will be changed form a user to another and it should be embedded in exe itself not read from another files,...etc Me + some users should be able to edit it using this method I am asking about without re-compiling it. The other users ( who are for sure non-technical users) won't edit. They only use I hope it is clearer now – CodeLOL Sep 08 '18 at 19:28
  • You could use a linker script to choose where in the data segment it goes, and where the data segment of the executable goes in the file. Or it would be easier to have a symbol-table entry for it so you could use tools that know about symbol-tables. – Peter Cordes Sep 09 '18 at 00:25

1 Answers1

1

In this answer I'll use Visual Studio 2017 Community Edition because I wanted to be sure to a have a development environment fully compatible with Windows.

I'll present five methods, from the most maintainable to the less. Of course the focus of this answer in strictly limited to the goal of "sharing" a C++ variable with an external tool.
Security of such an operation is a different topic and ultimately a futile attempt anyway.


Method 1 - Resources

Windows APIs1 and the PE2 support embedding resources in an executable3.
Resources are typically images, icons or localized strings but they can be anything - including raw binary data.

With Visual Studio is quite easy to add a resource: In the Solution Explorer > Resource files > Add > New item > Resource > Resource file (.rc)

This will open the Resource view, right-click on Resource.rc and select Add resource....
It's possible to create the standard resources but we need a Custom... type that we can call RAW.
This will create a new binary resource, gives it an ID and makes a few files in the solution.
Switching back to the Solution explorer we can see these new files and eventually edit the .bin file with a better hex editor than the VS's integrated one.
Of particular interest is the resource.h file that we can include to have the definition for the resource id, in my case it was IDR_RAW1.

After the bin file has been crafted we are ready to read it in the application, the pattern to use is the usual one - I don't feel like going over these API one more time a new answer so I'll link the Official documentation and provides a sample code:

#include <Windows.h>
#include "resource.h"

int WINAPI WinMain(HMODULE hModule, HMODULE hPrevModule, LPSTR lpCmdLine, int showCmd)
{
    //Get an handle to our resource
    HRSRC hRes = FindResource(hModule, MAKEINTRESOURCE(IDR_RAW1), "RAW");

    //Load the resource (Compatibility reasons make this use two APIs)
    HGLOBAL hResData = LoadResource(hModule, hRes);
    LPVOID ptrData = LockResource(hResData);

    /*
      ptrData is out binary content. Here is assumed it was a ASCIIZ string
    */
    MessageBox(NULL, (LPCSTR)ptrData, "Title", MB_ICONINFORMATION);

    return 0;
}

Resources are good because they allow for an easy integration with other automatic build tools: it's easy to add a build step before the resources are compiled to generate them on the fly.

It is also very easy to alter them after the exe file as been generated - CFF Explorer III is a simple and effective tools to edit a PE module's resources.
It's even possible to replace a resource entirely thereby not limiting ourselves to keeping the new resource the same size as the old one.

Just open the module in CFF, select Resource editor, browse to the raw resource and edit/replace it. Then save.

Method 2 - PE exports

Executable are ordinary PE module just like Dlls, the difference is really a batter of a bit.
Just like Dlls can exports functions and variables4 so can exes.

With VC++ the way to tag a symbol as exported is __declspec(dllexport):

#include <Windows.h>

__declspec(dllexport) char var[30] = "Hello, cruel world!";

int WINAPI WinMain(HMODULE hModule, HMODULE hPrevModule, LPSTR lpCmdLine, int showCmd)
{
    MessageBox(NULL, var, "Title 2", MB_ICONINFORMATION);

    return 0;
}

The C++ side of the matter is little affected.
The editing of the PE module is less user friendly but still very easy for everyone to follow.

With CFF open the export directory, all the exports will be listed.
C++ compilers have to mangle variables names when they can be shared due to the C++ features they support - so you won't find a nice name like var in the exports but something like ?var@@3PADA.
The export name doesn't really fulfil any goal in this context but you must be able to identify the correct export. This should be easy since it's very likely to be only one.
CFF will show you the function RVA, this is the RVA (relative to the image base) of the variable, you can easily convert it into a file offset or simply use the Address converted integrated in CFF.
This will open an hex editor and points you at the right bytes.

Method 3 - Map files

If you don't want to have a PE exports pointing right at your variable you can tell VS to generate a MAP file.

Map files will list all the symbols exported by an object file (note: an object file, not a PE module).
So you must make sure a variable, in this case, is exported by your translation unit - this is the default case for "global" variables but make sure to remember to not attach the static linkage modified to it and eventually make it volatile to prevent the compiler from eliminating it during the constants folding step.

#include "Windows.h"

//extern is redundant, I use it only for documenting the intention
//volatile is a hack to prevent constant folding in this simple case
extern volatile int var2 = 3;


int WINAPI WinMain(HMODULE hModule, HMODULE hPrevModule, LPSTR lpCmdLine, int showCmd)
{
    //A simple use of an int
    return var2;
}

A MAP file will be generated in the output dir, along with the exe, inside it's present a row like this one:

 0003:00000018       ?var2@@3HC                 00403018     Source.obj

This gives you the VA of the variable (403018) that you can use in CFF Address translator.

Method 4 - PE scan

You can initialise the variable with an unique value.
To be able to do so the variable size must be big enough that the probability that a random sequence of bits of equal size end up with the same value is negligible.
For example, if the var is a QWORD the probability of finding, in the PE module, another QWORD with the same value is very low (one in 264) but if the var is a byte then the probability is just one in 256.

Eventually, add a marker variable (I'd use a random array of 16 bytes) before the variable to mark it (i.e. act as the unique value).

To modify the PE use an hex editor to look for that unique value, this will give you the offset of the var to edit.

Method 5 - Reverse engineering

After each release, reverse engine the application (this is easy as you can debug it with VS along with the sources) and look where the compiler allocated the variable.
Take note of the RVA (nota bene: RVA not VA, the VA is variable) and then use CFF to edit the exe.

This requires a reverse engineering analysis each time a new release is built.


1 To be correct, "Win32" APIs.
2 I strongly advice the reader to be at least accustomized with the PE file format as I must assume so to keep this answer in topic and short. Having no understanding of the PE file format will likely result in no understanding of the question as a whole.
3 Actually, in any PE module.
4 Symbols in general.

Community
  • 1
  • 1
Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124
  • Good ! I have a simple question as I still new, why Global variables ? If I made the same with local variables won't I see them or I got something wrong ? – CodeLOL Sep 10 '18 at 05:53
  • @CodeLOL Local vars only exists for the time the function is executing - i.e. they are allocated at the beginning of a function and then deallocated at the end. They are allocated on the stack and hence they don't have a fixed address and are much more difficult to find. – Margaret Bloom Sep 10 '18 at 06:41
  • But at least, if I initialized a local variable with a unique string as example, won't me find it if I search with this string ? – CodeLOL Sep 10 '18 at 15:33
  • @CodeLOL Maybe - Maybe not. The compiler can store the string in the rodata section and copy it in the local var or embed it in the instruction stream between the opcodes. In the latter case you won't find it with a simple search. – Margaret Bloom Sep 10 '18 at 17:23
  • I have tried making a global variable ( string ) string x = "mytest.exe" in my example, x points to an exe near my main exe. the code runs this (mytest,exe) I successfully located the string in hex editor. when I modified it to point to another name ( "another.exe") from Hex edit, and ran my main exe, windows didn't open it at all ! I am sure I edited only the string no more no less – CodeLOL Sep 10 '18 at 20:21
  • @CodeLOL For one thing `another` is one more letter than `mytest`. Thus may be overwriting adjacent values. Try using a name with the same number of letters or less. It's impossible to tell what's wrong from here. You aren't signing the executable or anything, are you? – Margaret Bloom Sep 10 '18 at 20:56
  • I know that sizes are different. I haven't overwritten anything, I have inserted my new name in the place of the old one , and the bytes after the name are shifted with the difference I there something wrong in this ? – CodeLOL Sep 10 '18 at 22:40
  • Also, what is signing the exe or anything u are asking about ? sorry but I am still new can u explain – CodeLOL Sep 10 '18 at 22:41
  • @CodeLOL You can't shift bytes in a PE module! A lot of fields in the file are offsets, if you shift bytes those offsets becomes wrong. Try changing the string with another one with the same length. If you need to change the length of string, I suggest to declare it with a lot of null terminators in the C code so that you can overwrite those. Signing is a process to authenticate an executable, to securely affirm it's identity. If you don't know that it is then you are not using it :) Actually it's rare for user mode programs but it was worth checking. – Margaret Bloom Sep 11 '18 at 06:30
  • I tried a simple trial code, the code opens an exe of name specified in a global variable.Let it as example "Google Chrome.exe" I located it successfully in the Hex file, modified it with "Opera.exe", the difference in length is put null (to keep the same length) Running again the exe (after renaming target exe), nothing happens! Opera.exe didn't run at all When I only kept the same length( i.e:length of Google Chrome.exe ) but changed one letter only (Toogle Chrome.exe ) and renamed the target exe with (Toogle Chrome.exe). Now it runs! Why something like this happens ?! – CodeLOL Sep 13 '18 at 20:22
  • @CodeLOL Is Opera in your path? Maybe the system doesn't know where to find it. It's hard to say without code. Does it work if you use Opera.exe in the source code. – Margaret Bloom Sep 13 '18 at 21:53