// 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!");
预编译编译器会看到encrypt_me()引用,并将其更改为如下内容:
const char my_data[] = encrypt_me(/*"Hi, mom!"*/ "encrypted version here");
3条答案
按热度按时间hlswsv351#
您将需要使用
CryptProtectMemory
在不使用时加密数据(使用CRYPTPROTECTMEMORY_SAME_PROCESS
标志)。然后在需要访问它时调用CryptUnprotectMemory
。正如大卫所说,这只是减少了攻击者可以查看/修改内存的窗口,但考虑到这个限制,这是正确的方法。
编辑:加密int的示例。为简洁起见,删除了错误检查。需要注意的重要部分是,它适用于CRYPTPROTECTMEMORY_BLOCK_SIZE大小的块(对于示例,我们只使用一个块,因为它将在32或64位平台上保存一个int):
输出:
zi8p0yeb2#
您当然可以加密
.data
部分。如果您希望加密整个.data
部分,那么您可能需要采用与打包程序相同的策略。加密整个可执行文件。添加一个在启动时执行解密的存根,然后将控制转移到解密的可执行文件。但那样的话你当然也不会好到哪里去。作弊引擎可以像以前一样读取进程的内存。并且您将无法让进程在
.data
部分加密的情况下执行。这样你就可以破坏使用全局变量、常量等的库代码。你可以做的是只加密敏感信息,在使用前即时解密,然后立即丢弃。这至少让黑客们更难下手了。他们必须在正确的时间寻找。但是任何真正想得到你的数据的人都可以。在某些时候,您必须解密数据才能使用它,然后作弊引擎可以访问这些值。这里的底线是,如果您发现自己处于另一个进程可以读取和写入您的进程的内存的情况下,那么您已经输掉了这场战斗。
yduiuuwa3#
您可以使用VirtualAlloc()分配页面,并使用VirtualProtect()保护它们,这些函数也有Ex()版本。然后,您可以将标志设置和取消设置为正确的memory protection constant values,以防止任何类型的访问,而不需要通过改变访问,访问,并将其更改回来的协议。
在我看来,在启动时,最好让你的.data部分已经从一些预编译编译器传递加密,并在源代码上运行,这样在启动时一切都已经加密,然后你在main()内部解密,或者根据需要通过一些协议解密。
作为在编译时这样做的一个示例,使用自定义开发的解析器的预构建步骤可以在源代码中查找某个标志,并将原始代码替换为保留原始代码的注解,然后在预构建步骤中将加密的代码输入编译器。然后,构建后步骤可以撤消在构建前步骤中所做的更改,从而允许编辑器中的原始源代码。您应该将加密版本复制到构建文件夹中,以便在需要时对其进行记录和调试。
就像这样:用某种标志 Package 你想要加密的每个变量,比如(C++代码):
预编译编译器会看到encrypt_me()引用,并将其更改为如下内容:
这样,您就有了自定义解析器可以接收加密或解密的提示。您可以使用某种mime64编码所有数据,或者如果您想使用任何东西,可以将其编码为八进制
\377
或\xFF
十六进制转义序列,或者任何您需要的。