我有一个未经管理的C++控制台应用程序,在其中使用了srand()和rand()函数。虽然我不需要解决特定问题,但我很好奇:在我可以查询的内存中,srand()函数传递的原始种子是否被存储?是否有任何方法可以确定种子是什么?
不需要存储种子,只需存储返回的最后一个随机数。
以下是man页上的示例:
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;
}
v1 = ( seed * a + b ) % m
v2 = ( v1 * a + b ) % m;
v3 = ( v2 * a + b ) % m;
...
seed = (v1 - b)/a (mod m)
你无法唯一地知道种子,你只知道它对m取模(通常这样做是没有问题的,因为(0 < seed < m))如果v1-b为负数,则需要加上m直到再次变成正数。
你也可以看看中国剩余定理,尽管它不是完全匹配的。
我不知道你的汇编熟练程度如何,或者你是否可以访问未管理应用程序的源代码/调试符号,但除了这种诡计之外,没有可行的方法来确定原始种子值。随机数生成器的整个目的是想出一种给你不可预测的数字的方法 - 任何两个rand()调用之间的关系都不应该是可推断的。在密码学强伪随机数生成器中,如果能够根据生成的随机数猜测种子,那将被认为是一个严重的缺陷。
最简单的方法是,在调试器下启动应用程序并设置一个断点,其中包含srand()的调用 - 然后只需查看传递的参数即可。
接下来是反汇编应用程序并找出srand调用的情况。它完全有可能使用当前时间进行播种 - 然后您可以尝试一堆猜测(您可能可以将其缩小到几千个左右),看看是否有任何一个给出与应用程序正在使用的相同的随机数序列。 (当然,这假设您有某种方式知道正在生成的随机值是什么)。也有可能种子始终是像“0”这样的愚蠢东西。