我知道有这样的程序:
#include <iostream>
#include <string>
int main() {
const std::string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::string temp = "1234567890";
srand(MAGICNUMBER);
for (int i = 0;; ++i) {
for (int j = 0; j < 10; ++j)
temp[j] = alphabet[rand() % alphabet.size()];
std::cout << temp << std::endl;
}
}
基本上是随机10符号字符串生成器。
我也知道124660967生成的字符串是“2lwd9JjVnE”。有没有办法找到MAGICNUMBER
是什么,或者至少是序列中的下一个字符串?
UPD 即可。找到下一个项目已经非常有用了;我可以在合理的时间内做到这一点(特别是没有种子)吗?
答案 0 :(得分:3)
是的,鉴于典型的rand()
实施,这很可能,相当容易,甚至。
rand()
通常是linear congruential generator,使得发生器的每个内部状态由先前状态的简单算术方程形成:x1 =(a * x0 + c)%m。您需要知道您要定位的特定实施所使用的常量a
,c
和m
,以及从州生成输出值的方法(通常值是整个州,或州的上半部分)。同样重要的是状态通常只有32位。一个更大的国家将更加困难。
因此,您需要为pRNG找到一个状态,以便接下来的十个状态产生特定的索引序列,这些索引产生您正在寻找的10个字符:2lwd9JjVnE。因此,假设整个状态由rand()
输出,您需要找到一些32位数x
,以便:{/ p>
x % 62 = 54
(x1 = (a*x + c) % m) % 62 == 11
(x2 = (a*x1 + c) % m) % 62 == 22
(x3 = (a*x2 + c) % m) % 62 == 3
(x4 = (a*x3 + c) % m) % 62 == 61
(x5 = (a*x4 + c) % m) % 62 == 35
(x6 = (a*x5 + c) % m) % 62 == 9
(x7 = (a*x6 + c) % m) % 62 == 47
(x8 = (a*x7 + c) % m) % 62 == 13
(x9 = (a*x8 + c) % m) % 62 == 30
通过尝试所有2 ^ 32个可能的状态值(假设典型的32位状态),可以毫不费力地完成。但是,由于可能选择使用的常量来确保RNG运行完整的32位周期,因此您可以简单地选择任何状态并运行它直到找到此序列。
无论哪种方式,一旦你知道产生这些值的状态,你就必须向后运行124660967 * 10步骤,以便找到哪个状态被用作原始种子。为此,您需要计算模型的congruence multiplicative inverse。或者,您可以向前运行(period - 124660967*10)
步。
答案 1 :(得分:2)
不,这几乎是不可能的。正如@chux中指出的their comment,c ++标准中没有指定确切的实现。
您需要检查将使用所有可能的种子生成的所有序列。这将在不必要的计算时间内运行。
虽然如果编译器是众所周知的,并且实现是开源的(在您的特定情况下),可能有办法找出初始种子值,知道特定的rand()
结果迭代通话。
答案 2 :(得分:0)
如果您有权访问该程序,请将其反汇编以尝试了解该数字是什么。
否则标准没有指定有关存储srand
值的任何内容,因此您会遇到其他方法,例如强制所有种子,或者可能尝试存储查找随机数的序列连续十个生成你感兴趣的字符串。