local digits = {'1', '2', '3', '4', '5', '6', '8', '9'}
math.randomseed(os.time())
local result = digits[math.random(8)]
for i = 2, 50 do
result = result..digits[math.random(8)]
end
print(result)
--> 88854243421464255299891111895292628431988589634664
这是一个Lua脚本,旨在吐出五十个随机数字,不包括0和7.我似乎无法找到Lua随机性算法。是否可以找到os.time()返回的值?
用外行的术语来说,这里的脚本是如何工作的:
因为遗漏了七个,随机算法真的吐了出来:
77754243421464255288781111785282627431877578634664
但是因为七个失踪了,七个和八个失去了八个和九个,产生了这个:
88854243421464255299891111895292628431988589634664
为了澄清,我试图弄清楚随机算法如何工作以找到作为随机种子输入的密钥。
此处也问到:https://forum.roblox.com/Forum/ShowPost.aspx?PostID=215349554 在这里:https://scriptinghelpers.org/questions/42360/can-this-script-be-reverse-engineered-to-find-the-random-seed 在这里:https://crypto.stackexchange.com/questions/47027/can-this-code-be-reverse-engineered-to-find-the-random-seed
答案 0 :(得分:4)
可以对此代码进行反向工程以找到随机种子吗?
也许,也许不是。这取决于itertools.izip_longest
的实现。
是否可以找到os.time()返回的值?
当然。 os.time()
is defined为(强调我的)
math.random
函数在不带参数的情况下调用时,返回当前日期和时间,编码为数字。 (在大多数系统中,该数字是自某个纪元以来的秒数。)
我们谈论的是32位整数。这很容易被暴力强迫。你甚至可以假设一些界限。这可能是在过去一个月左右产生的,并且没有必要搜索未来的种子。在过去的30天里,只有22位不同的秒数。
您可以简单地遍历从现在到过去的种子,并且每次都生成50位长的随机值。然后你只需要将它与你拥有的那个进行比较,并在找到匹配时停止。这不应该超过一分钟。
以下是完整代码:
time
输出
1493400000 1493300000 1493200000 1493100000 1493000000 1492900000 1492800000 1492700000 1492600000 1492500000 1492400000 1492300000 1492200000 1492100000 1492000000 1491900000 1491800000 1491700000 1491600000 1491500000 found: 1491404649
答案 1 :(得分:3)
这不是对您的问题的完整答案,但它可能会帮助您开始。您可以找到Lua的math.random
函数here的C源代码(适用于Lua 5.1,但其他版本类似)。 Lua本身不会尝试生成伪随机数,而是将该任务外包给C标准库。
具体来说,math.random
使用C的rand
函数生成数字,而math.randomseed
使用C的srand
函数设置伪随机数生成器的种子(包含在与rand
相同的手册页。这些功能在每个系统上的实现方式不同(例如x86 Windows版本与x86 Linux版本不同,不同的芯片组会有不同的版本等),因此您必须分析每个系统的算法。感兴趣的。
有关rand
如何实施的信息,this question应该为您提供一个开始。
你应该注意的一件事是,如果有人可以猜到你叫什么秒os.time
(或者如果他们只是和你一样叫它),那么他们就可以生成通过将该值传递给math.randomseed
,与您完全相同的伪随机数。如果有一个可用的种子,最好使用具有更高熵的种子。