tags:

views:

127

answers:

7

I'm looking to "hide" some information in my code, and I'm not sure if this will do the trick or not. I know string literals are easily found and viewed in a compiled app, but what about integers? Lets say I define a number #define kHiddenNumber 1234567 and then in my code reference it using kHiddenNumber as an integer. Would that be visible in the compiled code, or would the number be effectively hidden?

Thanks!

A: 

i think that won't be visible in the compiled binary, as the number is compiled to binary format, but that can be figured out by using hacking tool.

Benny
+3  A: 

That won't hide anything. The pre-compiler just replaces every instance of "kHiddenNumber" with 1234567 and the compiled code has no reference to kHiddenNumber.

kHiddenNumber just makes your code more readable and maintainable. The C-compiler just sees 1234567.

chrissr
+5  A: 

#define is handled by the preprocessor, and the preprocessor just brute-force replaces things. It makes no attempt to "hide" anything.

Ignacio Vazquez-Abrams
+1: #define is not C code, it's a separate language that feeds the C compiler. The `kHiddenNumber` no longer exists at compile time; it is totally replaced by the cpp and is gone forever. The number 1234567 is the only thing that's left.
S.Lott
I know how #define works (at least I was pretty sure I did, and you've confirmed that) and I'm not relying on the #define to hide it for me, I just know that if I were to put "12345" as a string in my program and 12345 as an integer in my program, the string would stick out in plaintext and the integer would at least be in binary form. I just wanted to make sure that #define didn't do something funny and leave that value somewhere as a string.
Cory Imdieke
A: 

depends how you use it. if compiler is not able to optimize it out, it will be visible. if you do something like comparing serial number from user against built-in numbers, it's easy to track.

aaa
+1  A: 

It is extremely unlikely to appear in the compiled object code as the string "1234567". It will, however, likely appear in binary form - as a sequence of bytes, quite probably either 0x00 0x12 0xD6 0x87 or 0x87 0xD6 0x12 0x00.

These bytes could be located in a separate section among other constants used by your code, or they could be encoded within the instruction stream itself.

There are ways of obfuscating such constants, but as others have pointed out, you're really on a hiding to nothing trying to play such games. Experienced reverse-engineers have seen it all before.

caf
+3  A: 

Consider the simple program:

#define kHiddenNumber 1234567

int main(void)
{
    int i = kHiddenNumber;
    return(i & 0xFF);
}

Compile it:

gcc -o xx xx.c

Note that 123456710 = 0x12D687

Now print the program in hex and search for D6:

$ od -x xx | grep d6
0002700      6d65    422e    642e    6c79    6269    0000    0000    0000
0007460      45c7    87fc    12d6    0f00    45b6    c9fc    00c3    25ff
0020140      7265    4700    705f    6f72    6e67    6d61    0065    026c
$

You can see the 0x12D687 in there, in the middle line of output. It's in a funny format, but nonetheless present in the code. Note that the compilation was not optimized. When the program is optimized, the evidence is lost - probably because the constant is used in such a simple context that 'i' can be optimized out and the return expression reduced to the value 0x87. The byte 0x87 does appear in the optimized code at about the same place in the optimized version - you'd need to do a proper disassembly job to prove that was definitively the last byte of the value, though I regard it as likely.

$ od -x xx | grep -i d6
0002320      e500    60d6    fdf5    ee77    10b8    e3d5    5834    7377
0002700      6d65    422e    642e    6c79    6269    0000    0000    0000
0020140      7265    4700    705f    6f72    6e67    6d61    0065    026c
$ od -x xx | grep -i 87
0007460      0000    f400    4855    e589    87b8    0000    c900    00c3
$

In more complex programs - where 'i' was passed to a function (perhaps 'printf()'), the optimization could not be done.

Consequently, you cannot rely on the compiler to hide the value. The name for the value will be absent, most likely. But the value may well be present in the program to be found.

Incidentally, you can sometimes find encryption keys in a similar - though more complex way. The data is too random to be natural - so it stands out like a sore thumb in the program.

Jonathan Leffler