有人知道是否有时间或事件有人使用兰德()的弱点来预测利用它?在电子游戏中产生代币或作弊的东西?
自PHP 7之前,rand()很容易破解。事实上,这里有一些C代码,归功于Peter Selinger,它预测了种子的价值:
#include <stdio.h>
#define MAX 1000
#define seed 1
main() {
int r[MAX];
int i;
r[0] = seed;
for (i=1; i<31; i++) {
r[i] = (16807LL * r[i-1]) % 2147483647;
if (r[i] < 0) {
r[i] += 2147483647;
}
}
for (i=31; i<34; i++) {
r[i] = r[i-31];
}
for (i=34; i<344; i++) {
r[i] = r[i-31] + r[i-3];
}
for (i=344; i<MAX; i++) {
r[i] = r[i-31] + r[i-3];
printf("%d\n", ((unsigned int)r[i]) >> 1);
}
}
再一次,有没有时间使用这个弱点来预测下一个随机数并利用某些东西?
谢谢!
答案 0 :(得分:0)
在PHP 7之前,PHP使用Linear Congruential Generator算法生成随机数或简短的LCG。该算法的工作原理如下:
next_random = (previous_random * a + c) % m
previous_random = next_random
当你第一次随机出现时,显然没有previous_random数字。这就是我们提供种子的原因。因此,种子只是第一个previous_random值。
现在,我们知道算法,但我们需要知道PHP使用的a
,c
和m
的值。我相信每个版本的PHP都使用不同的值。但是,让我们说我们不知道那些价值,我们如何猜测这个价值。就我而言,我使用的是PHP 5.6.15 Windows。
srand(0);
var_dump(rand()); // 12345
var_dump(rand()); // 5758
所以,m = getrandmax () + 1
。由于我们的种子是0,所以我们c = 12345
。要获得值a
,我们可以使用简单循环来猜测a
。
$m = getrandmax () + 1;
for($a = 0; $a < $m; $a++)
if ((($a * 12345 + 12345) % $m) == 5758)
var_dump($a); // in my case, 20077
或者您可以像这样获得价值a
srand(0); rand(); // 12345
srand(1); rand(); // 32422
// so a = 32422 - 12345 = 20077
现在,我可以编写与当前PHP版本相同的随机函数。
class visal_rnd
{
function __construct($seed = 0) {
$this->seed = $seed;
}
function rnd() {
$this->seed = ($this->seed * 20077 + 12345) % 32768;
return $this->seed;
}
}
我能够预测自己的PHP版本,因为我对当前的环境有如此多的了解,我之前知道一些随机的,我知道种子。如果攻击者的知识几乎为零,那么攻击就不容易了。
默认情况下,PHP 7.0+使用Mersenne Twister。与线性同余生成器相比,有更多参数需要猜测。所以,它需要更多的知识。
取决于您向公众公开了多少信息。如果您只生成一个随机数且攻击者不了解a
,previous_random
,c
和m
。攻击者无法预测下一个随机数。