我希望在代码中“隐藏”一些信息,但我不确定这是否能达到目的。我知道字符串文字很容易在编译的应用程序中找到和查看,但是整数呢?假设我定义了一个数字
#define kHiddenNumber 1234567
,然后在我的代码中使用 kHiddenNumber
作为整数来引用它。这会在编译后的代码中可见,还是会有效隐藏该数字?
#define
由预处理器处理,预处理器只是强力替换东西。它不会试图“隐藏”任何东西。
考虑简单的程序:
#define kHiddenNumber 1234567
int main(void)
{
int i = kHiddenNumber;
return(i & 0xFF);
}
编译:
gcc -o xx xx.c
请注意 123456710 = 0x12D687
现在以十六进制打印程序并搜索 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
$
您可以在输出的中间行看到 0x12D687。 它的格式很有趣,但仍然存在于代码中。 请注意,编译未优化。 当程序被优化时,证据就会丢失——可能是因为常量在如此简单的上下文中使用,“i”可以被优化掉,并且返回表达式减少到值 0x87。 字节 0x87 确实出现在优化代码中的优化版本中的大约相同位置 - 您需要执行适当的反汇编工作来证明它确实是该值的最后一个字节,尽管我认为这很可能。
$ 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
$
在更复杂的程序中 - “i”被传递给函数(可能是“printf()”),无法完成优化。
因此,您不能依赖编译器来隐藏该值。 该值的名称很可能会缺失。 但该值很可能存在于待找到的程序中。
顺便说一句,您有时可以通过类似但更复杂的方式找到加密密钥。 数据太随机,不自然 - 所以它在程序中显得很突出。
这不会隐藏任何东西。预编译器只是将“kHiddenNumber”的每个实例替换为 1234567,编译后的代码没有引用 kHiddenNumber。
kHiddenNumber 只是让你的代码更具可读性和可维护性。 C 编译器只看到 1234567。
在编译后的目标代码中出现字符串“1234567”的可能性极小。 然而,它可能以二进制形式出现 - 作为字节序列,很可能是
0x00 0x12 0xD6 0x87
或 0x87 0xD6 0x12 0x00
。
这些字节可以位于代码使用的其他常量中的单独部分中,也可以在指令流本身中进行编码。
有很多方法可以混淆这些常量,但正如其他人指出的那样,你真的是在试图玩这样的游戏。 经验丰富的逆向工程师以前已经见过这一切。
我认为这在编译的二进制文件中是不可见的,因为数字被编译为二进制格式,但这可以通过使用黑客工具来解决。
看如何隐藏二进制代码中的字符串?
也许对你有帮助
取决于你如何使用它。如果编译器无法优化它,它将是可见的。 如果您执行诸如将用户的序列号与内置编号进行比较之类的操作,就很容易跟踪。