7

我有一个非托管 C++ 控制台应用程序,我在其中使用 srand() 和 rand()。我不需要它来解决特定问题,但很好奇:传递给 srand() 的原始种子是否存储在我可以查询的内存中某处?有什么办法可以知道种子是什么?

4

4 回答 4

8

种子不需要存储,只有返回的最后一个随机数是。

这是手册页中的示例:

       static unsigned long next = 1;

       /* RAND_MAX assumed to be 32767 */
       int myrand(void) {
           next = next * 1103515245 + 12345;
           return((unsigned)(next/65536) % 32768);
       }

       void mysrand(unsigned seed) {
           next = seed;
       }
于 2009-08-27T19:36:30.143 回答
3

如果你有一个简单的线性同余生成器,你有几个值,这会产生一个方程组:

 v1 = ( seed * a + b ) % m
 v2 = (   v1 * a + b ) % m;
 v3 = (   v2 * a + b ) % m;
... 

如果您知道第一个值,则可以按顺序倒退:

seed = (v1 - b)/a (mod m)

你不知道唯一的种子,你只知道它 mod m (这通常很好,因为 (0 < seed < m) 反正)如果 v1 - b 是负数,你需要添加 m's 直到它再次为正数。

您还可以查看中国剩余定理,尽管它并不完全匹配。

于 2009-08-27T19:42:43.797 回答
0

从理论上讲,不是 - 种子值用于计算下一个随机值,并且该值(理论上)用于为下一个随机数提供种子,依此类推。

安全方面,能够窥视种子(无论是原始种子还是新种子)是一个严重的安全问题,所以我希望即使它必须存储在某个地方,您也不应该能够查看它。

于 2009-08-27T19:39:47.000 回答
0

我不知道您的汇编熟练程度是多少,或者您是否可以访问非托管应用程序的源代码/调试符号,但除了那种诡计之外,没有可行的方法来确定原始种子值。随机数生成器的全部目的是想出一种方法来给你不可预测的数字——任何两个给定的 rand() 调用之间的关系不应该是可推断的。在加密性强的伪随机数生成器中,能够根据生成的随机数猜测种子将被认为是一个严重的缺陷。

最简单的方法是在调试器下启动应用程序并在srand()调用的位置设置断点 - 然后只需查看传递的参数。

接下来是反汇编应用程序并找出 srand 调用的情况。它完全有可能是用当前时间播种的 - 然后你可以尝试一堆猜测(你可能可以将它缩小到几千左右),看看是否有任何给出应用程序正在使用的相同随机数序列. (当然,这假设您有某种方式知道生成的随机值是什么)。种子也有可能一直像“0”一样愚蠢。

于 2009-08-27T20:02:02.150 回答