从安全角度来看,将变量初始化为 NULL 或 0 或 -1 是一种不好的做法吗?

信息安全 逆向工程 安全编码
2021-08-18 17:28:11

我正在尝试学习一些有关针对逆向工程的装甲应用程序。在一篇文章中,我读到将变量初始化为 NULL 或 0 或 -1 与在应用程序中使用通用密码一样安全(相对于 RE)。简而言之,据说我们应该使用 RNG 来生成我们最初“存储”到新声明的变量的随机数据。其他方法是使用 XOR 运算符。不幸的是,我忘记为这篇文章添加书签,而且我没有时间完整阅读它。

问题是 - 如果我们在初始化变量时使用随机数据和/或 XOR 运算符,我们是否会添加到应用程序对逆向工程的防御中?

编辑:看来我的问题还不够清楚。我要问的是哪个更好(或者根本没有区别)

  • int variable = 0;

或者

  • int variable = random(seed);

让我们假设,为了这个问题,random(seed)确实是真正的随机性。

关于 XOR 运算符。正如我所说,我只是部分阅读了这篇文章。我看到两段,一段名为“使用随机数生成器”,另一段为“使用异或初始化变量”。我不清楚 XOR 是如何使用的,如果有人对此有所了解,我只在此处提及它以引起人们的注意。

3个回答

在许多编程语言中,局部变量的初始化是强制的,否则引擎将断然拒绝读取未初始化的数据。即使在您可以读取未初始化变量并因此获得该位置内存中剩余内容的副本的语言中,您也不能指望它是“随机的”;它将倾向于包含始终相同的值,具体取决于应用程序之前所做的事情。事实上,在 C 语言中,局部变量来自堆栈和/或缓存在 CPU 寄存器中,这些是在整个应用程序中不断重用的资源。

如果您阅读的文章建议不要初始化局部变量,然后阅读它们,期望这会产生“随机性”,那么本文将被烧毁,原因有很多:

  • 读取未初始化的数据明显违反规范;在 C 编程语言标准中,这称为“未定义行为”,可能会产生问题结果,包括应用程序崩溃,或者更糟糕的是,无声内存损坏。

  • 这种随机性不会有任何好处,任何值得一提的“随机性”概念。

  • 重现性通过试图从局部变量中获取不可重现的值,文章只是提倡使代码无法调试,这只能被描述为愚蠢的事情特别是为了安全。这几乎可以保证存在长期存在的、难以检测的安全漏洞。

如果您想要随机性,请使用操作系统提供的内容,例如/dev/urandom. 从各个角度来看,它都比旨在安抚随机之神的非理性自制仪式要好得多。


编辑:正如@TerryChia 指出的那样,您的问题可能是关于从 PRNG强制随机初始化变量(本地或非本地),而不是在那里保留默认值(当然,如果有默认值;在许多编程语言中,局部变量根本没有默认值)。在这种情况下,您所说的“XOR”尚不清楚。

在这种情况下,您要么在将有意义的值存储在其中之前不读取所述变量,在这种情况下,变量最初包含的内容完全不相关:它不会影响代码的行为。或者您确实读取了变量,然后从中获取这些或多或少的随机值,从而使应用程序代码不可重现并导致上述问题;也就是说,代码将难以调试,从而增加了实际漏洞的概率和密度。

您似乎混合了两个安全目标:保护代码免受逆向工程和保护应用程序免受攻击。这些目标通常是相互矛盾的:针对逆向工程的保护会增加代码的复杂性,因此代码更容易受到攻击,因为它在某些情况下会以意想不到的方式运行。

恰当的例子:如果将变量初始化为随机值,则在逆向工程时更难以确定一块内存未初始化。另一方面,跟踪对 RNG 的调用将显示变量被初始化的位置。因此,将变量初始化为随机值没有任何好处。

在安全性方面,将变量初始化为随机值是不好的。零点更安全。如果事实证明该变量在没有被初始化的情况下被使用,那么零通常危害较小:您可以仔细检查该值是否不应该为 0,如果它是一个指针,它将导致一个干净的崩溃第一次取消引用。相反,一个随机值会导致不可预知的行为,一个潜在的安全漏洞。

防止逆向工程的成本如此之高(因为调试比编程更难,而且对于混淆来说是双倍的),以至于它是非常有价值的。如果您确定需要在混淆方面付出努力,那么您可能低估了难度。如果您仍然选择混淆,将变量初始化为随机值并不是一种非常有用的技术,因为在静态或动态分析下很容易看出无论如何都没有使用随机值。混淆将要求您使用随机值来执行计算,但最终结果不依赖于该值。

安全的角度来看,将变量初始化为 NULL、0 或其他安全且可重现的值是一种很好的做法。

初始化变量提供一致的行为。您应该使用本身就足够随机的 RNG。将您的随机输出与实际发生在该内存位置的任何内容进行异或运算实际上不会带来任何好处。

通常不建议依靠这种解决方案来增加值的随机性。

但要小心,不要通过修复它们来破坏它们