本文主要解释了python random模块中的randint方法的底层原理,并做了简单的逆向,能还原出所使用的随机数的部分,这在对random模块逆向的时候会有一些帮助。
文章目录
- random模块底层原理概述
- randint分析
- 逆向
random模块底层原理概述
python的random模块底层是调用的cpython/Modules/_randommodule.c
,该模块使用的是MT19937算法,python里只是对一些方法进行简单的封装,不涉及随机数的生成,关于底层c代码在其它文章中有分析过,这里就不再详细描述,主要讲一些python应用层是怎么借助底层模块提供的随机数生成满足各种约束的随机数。
python random模块应用层的主要思想是,借助底层c模块中,生成n位随机数的能力,对这些随机数进行各种变换,使得能够满足约束。
randint分析
调用链路:randint->randrange->_randbelow->_randbelow_with_getrandbits->getrandbits->(_randommodule.c)_random_Random_getrandbits_impl
源码追踪截图:
主要思想:
- 算出边界的长度(上界+1-下界)
- 获取一个边界长度(位数)的随机数。
- 将得到的指定位数的随机数加上下边界。
逆向
random.randint()
得到的随机数a,是由一个指定位数的随机数b加上下边界得到的,这个b又是n个32位随机数通过舍弃部分位得到的。
如果我们要还原出底层模块最原始得到的那个随机数的部分,可以采取如下方法:
from Crypto.Math.Numbers import Integer
def randint(x, l, u):
one = x - l
target_bit = Integer(u + 1 - l).size_in_bits()
target_bit %= 32
target_bit = 32 - target_bit
return one << target_bit
应用场景:需要通过最原始得到的随机数去还原MT19937的内部状态
ATFWUS 2024-01-23