6

我的程序中有一个字符串文字,我正在尝试创建一个业余校验和以确保该字符串文字没有在可移植可执行文件中被替换。

为此,我创建了字符串文字的散列,并将其作为整数文字存储在程序中。现在我有两种文字,一种用于字符串,一种用于哈希。

在我的代码中,我通过使用以相同方式散列字符串文字的函数来实现校验和,我创建一个新的运行时散列并根据散列文字检查该散列。

问题当然是,通过编译器优化,它可能会预先计算运行时哈希,然后我会根据哈希文字检查哈希文字,并且校验和将始终返回 true。

所以我正在寻找一种技巧,让编译器认为字符串文字是一个可以是任何东西的动态字符串,这样它就不会对运行时哈希进行常量折叠优化,我的代码也能正常工作。

4

1 回答 1

9

您可能会将字符串文字声明为 a const volatile,例如

const volatile char myliteral[] = "some literal string";

您还可以在构建时计算散列,例如在构建过程中有一些东西来提取适当的字符串并单独计算散列。

最后,如果字符串及其散列位于两个不同的翻译单元中(例如 infile1.cfile2.c),您需要链接时优化以使内联在构建时发生。使用当前的GCC(即 GCC 4.9 或 5),您需要在编译时和链接时显式传递-flto以获得链接时优化,因此如果您没有明确地这样做(例如CC=gcc -flto -O2在您的 中Makefile),它不会发生.

顺便说一句,您可能会对整个可执行文件、整个共享库或某个给定的目标文件进行校验和。详细信息因操作系统而异。在 Linux 上参见dlopen(3)dlsym(3)dladdr(3)dl_iterate_phdr(5)elf(5)proc(5)

此外,您可以散列初始文字的一些随机后缀子字符串(例如myliteral+random()%strlen(myliteral)运行时的散列),并保留并与此类部分散列的常量数组进行比较。编译器不太可能内联所有这些!

我实际上认为这在实践中不是一个真正的问题:没有人会关心您的可执行文件,也没有人会花时间反编译它。

顺便说一句,您可以生成一个__timestamp.c包含时间戳和校验和信息的单独文件(我正在2018 年夏天的bismon项目中这样做),并将其与您的可执行文件链接。

于 2015-09-06T17:04:32.933 回答