[GKCTF2021]random

本题出现了MT19937伪随机数生成算法。

题目

task.py

import random
from hashlib import md5 def get_mask():
file = open("random.txt","w")
for i in range(104): #各取104个
file.write(str(random.getrandbits(32))+"\n")
file.write(str(random.getrandbits(64))+"\n")
file.write(str(random.getrandbits(96))+"\n")
file.close()
get_mask()
flag = md5(str(random.getrandbits(32)).encode()).hexdigest()
print(flag)

random.txt

分析

感觉task.py没给啥,突破点在于这个random.getrandits()

去查一下得到:

random.getrandbits(k)

生成一个k比特长的随机整数

那也就意味着生成了32/64/96比特长的随机整数,32、64/96都是32的整数倍。

这会不会也是突破口呢?

看了wp,提到了一个算法:Mersenne Twister 梅森旋转算法

MT19937算法

产生随机数的速度快、周期长,可达到\(2^{19937-1}\)

可以产生32位整数序列,在$1\le k \le 623 $的维度之间都可以均等分布。

如上图所示,mt19937的随机数生成器结构首先需要一个uint32的种子,然后生成一个具有624个uint32数组的状态数组。生成状态数组之后,进行一次旋转,最终可以输出624个随机的uint32。然后重复执行旋转操作。

步骤

1.利用seed初始化624的状态

2.对状态进行旋转

3.根据状态提取伪随机数

代码实现

32位的MT19937的python代码如下:

def _int32(x):
return int(0xFFFFFFFF & x) class MT19937:
# 根据seed初始化624的state
def __init__(self, seed):
self.mt = [0] * 624
self.mt[0] = seed
self.mti = 0
for i in range(1, 624):
self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i) # 提取伪随机数
def extract_number(self):
if self.mti == 0:
self.twist()
y = self.mt[self.mti]
y = y ^ y >> 11
y = y ^ y << 7 & 2636928640
y = y ^ y << 15 & 4022730752
y = y ^ y >> 18
self.mti = (self.mti + 1) % 624
return _int32(y) # 对状态进行旋转
def twist(self):
for i in range(0, 624):
y = _int32((self.mt[i] & 0x80000000) + (self.mt[(i + 1) % 624] & 0x7fffffff))
self.mt[i] = (y >> 1) ^ self.mt[(i + 397) % 624] if y % 2 != 0:
self.mt[i] = self.mt[i] ^ 0x9908b0df

python中内置的Random类就是采用了MT19937算法,getrandbits(32)方法可以获得一个32位随机数

整个获取伪随机数的过程的重点就是这个self.mt[]也就是state块的状态。

在本题中,在random.txt中总共获取了312个随机数。其中有104个32位的,104个64位的,104个96位的。

解法1

因为本题随机数都是由32位整数序列产生,所以我们可以得知:

104个32位的需要产生104个随机数

104个64位的需要产生208个随机数

104个96位的需要产生312个随机数

所以总共需要产生624个随机数。

而这个数字刚刚好对应了624个state块的个数,理论上来讲,我们可以将624个state块的状态推出来,然后就可以推出下面产生的随机数,也就是flag了。

from random import Random

def invert_right(m,l,val=''):
length = 32
mx = 0xffffffff
if val == '':
val = mx
i,res = 0,0
while i*l<length:
mask = (mx<<(length-l)&mx)>>i*l
tmp = m & mask
m = m^tmp>>l&val
res += tmp
i += 1
return res def invert_left(m,l,val):
length = 32
mx = 0xffffffff
i,res = 0,0
while i*l < length:
mask = (mx>>(length-l)&mx)<<i*l
tmp = m & mask
m ^= tmp<<l&val
res |= tmp
i += 1
return res def invert_temper(m):
m = invert_right(m,18)
m = invert_left(m,15,4022730752)
m = invert_left(m,7,2636928640)
m = invert_right(m,11)
return m def clone_mt(record):
state = [invert_temper(i) for i in record]
gen = Random()
gen.setstate((3,tuple(state+[0]),None))
return gen f = open("random.txt",'r').readlines()
prng = []
j=0
for i in f:
i = i.strip('\n')
print(int(i).bit_length())
if(j%3==0):
prng.append(int(i))
elif(j%3==1):#将生成两次随机数的两个随机数分离出来
prng.append(int(i)& (2 ** 32 - 1))
prng.append(int(i)>> 32)
else:#将生成三次随机数的三个随机数分离出来
prng.append(int(i)& (2 ** 32 - 1))
prng.append(int(i)& (2 ** 64 - 1) >> 32)
prng.append(int(i)>>64)
j+=1 g = clone_mt(prng[:624])
for i in range(624):
g.getrandbits(32)#产生前624个随机数,让state状态到生成flag前 key = g.getrandbits(32)
print(key)
from hashlib import md5
flag = md5(str(key).encode()).hexdigest()
print(flag)
#14c71fec812b754b2061a35a4f6d8421
解法2

使用基于梅森算法的randcrack库。

randcrack一把梭:

from hashlib import md5
from randcrack import RandCrack with open(r'random.txt', 'r') as f:
l = f.readlines()
l = [int(i.strip()) for i in l]
t = []
for i in range(len(l)):
if i % 3 == 0:
t.append(l[i])
elif i % 3 == 1:
t.append(l[i] & (2 ** 32 - 1))
t.append(l[i] >> 32)
else:
t.append(l[i] & (2 ** 32 - 1))
t.append(l[i] & (2 ** 64 - 1) >> 32)
t.append(l[i] >> 64)
rc = RandCrack()
for i in t:
rc.submit(i)
flag = rc.predict_getrandbits(32)#在给出的随机数数量多时,predict_getrandbits()可以预测下一个随机数
print('GKCTF{'+md5(str(flag).encode()).hexdigest()+'}')

GKCTF{14c71fec812b754b2061a35a4f6d8421}

总结

有师傅的文章提到:近年来MT19937在各大CTF赛事中出现的频率越来越高。

那下次再做几道加深印象。

参考:https://www.anquanke.com/post/id/205861#h3-4

https://blog.csdn.net/m0_62506844/article/details/124278580?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-5-124278580-blog-124983179.pc_relevant_multi_platform_whitelistv1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-5-124278580-blog-124983179.pc_relevant_multi_platform_whitelistv1&utm_relevant_index=9

[GKCTF2021]random的更多相关文章

  1. Chrome V8引擎系列随笔 (1):Math.Random()函数概览

    先让大家来看一幅图,这幅图是V8引擎4.7版本和4.9版本Math.Random()函数的值的分布图,我可以这么理解 .从下图中,也许你会认为这是个二维码?其实这幅图告诉我们一个道理,第二张图的点的分 ...

  2. Math.random()

    Math.random() 日期时间函数(需要用变量调用):var b = new Date(); //获取当前时间b.getTime() //获取时间戳b.getFullYear() //获取年份b ...

  3. .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

    .Net中我们通常使用Random类生成随机数,在一些场景下,我却发现Random生成的随机数并不可靠,在下面的例子中我们通过循环随机生成10个随机数: ; i < ; i++) { Rando ...

  4. 随机数(random)

    需求 Random rd=new Random(); 需要十以内的随机数  (0---10) System.out.println((int)((rd.nextDouble()*100)/10)); ...

  5. python写红包的原理流程包含random,lambda其中的使用和见简单介绍

    Python写红包的原理流程 首先来说说要用到的知识点,第一个要说的是扩展包random,random模块一般用来生成一个随机数 今天要用到ramdom中unifrom的方法用于生成一个指定范围的随机 ...

  6. [LeetCode] Random Pick Index 随机拾取序列

    Given an array of integers with possible duplicates, randomly output the index of a given target num ...

  7. [LeetCode] Linked List Random Node 链表随机节点

    Given a singly linked list, return a random node's value from the linked list. Each node must have t ...

  8. [LeetCode] Copy List with Random Pointer 拷贝带有随机指针的链表

    A linked list is given such that each node contains an additional random pointer which could point t ...

  9. php对应js math.random

    <?php function random($min = 0, $max = 1) {     return $min + mt_rand()/mt_getrandmax()*($max-$mi ...

  10. python常用模块(模块和包的解释,time模块,sys模块,random模块,os模块,json和pickle序列化模块)

    1.1模块 什么是模块: 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文 ...

随机推荐

  1. 【RocketMQ】主从模式下的消费进度管理

    在[RocketMQ]消息的拉取一文中可知,消费者在启动的时候,会创建消息拉取API对象PullAPIWrapper,调用pullKernelImpl方法向Broker发送拉取消息的请求,那么在主从模 ...

  2. python实验报告(第11章)

    实验11:使用Python操作数据库 一.实验目的和要求 1.学会数据库编程接口: 2.学会使用SQLite: 3.学会使用MySQL. 二.实验环境 软件版本:Python 3.10 64_bit ...

  3. WCH沁恒 CH37系列芯片选型以及常见问题的处理(CH376/CH378)

    选型 型号 接口 功能 备注 电源 CH372 并口 USB_Device 全速 USB 设备接口,兼容 USB V2.0 3.1-3.6 4.2-5.4 CH374 SPI/并口 Host/Devi ...

  4. WCH以太网相关芯片资料总结

    网络产品线产品分类 1.接口控制类.CH395Q           http://www.wch.cn/search?t=all&q=395CH395LCH392F            h ...

  5. [机器学习] sklearn聚类

    聚类(Clustering)简单来说就是一种分组方法,将一类事物中具有相似性的个体分为一类,将另一部分比较相近的个体分为另一类.例如人和猿都是灵长目动物,但是根据染色体数目不同可以将人和猿分类不同的两 ...

  6. [OpenCV实战]4 OpenCV中的颜色空间

    目录 1 不同的色彩空间 1.1RGB颜色空间 1.2 Lab色彩空间 1.3  YCrCb颜色空间 1.4 HSV颜色空间 2 如何使用这些颜色空间进行分割 2.1 获取特定颜色的颜色值 2.2 应 ...

  7. 毫米波雷达 TI IWR1443 初体验

    文章目录 1 前言 2 准备工作 2.1 mmWave SDK 2.2 Code Composer Studio(CCS) 2.3 Uniflash 2.4 MATLAB runtime 2.5 TI ...

  8. 拜占庭将军问题与CAP

    1.拜占庭将军问题 拜占庭位于如今的土耳其的伊斯坦布尔,是东罗马帝国的首都.由于当时拜占庭罗马帝国国土辽阔,为了达到防御目的,每个军队都分隔很远,将军与将军之间只能靠信差传消息.在战争的时候,拜占庭军 ...

  9. 推荐一款在浏览器编辑`Blazor`的`IDE`

    不知道是否有Blazor用户羡慕过React或者Vue用户,在一些组件库中,它们就提供了在当前的组件预览对于组件的实时编辑并且预览? 比如semi-design的这种 在比如codepen这种 由于B ...

  10. Atcoder dp I Coins 题解

    Atcoder链接:Coins Luogu链接:Coins $\scr{\color{BlueViolet}{Solution}}$ 观察数据,发现$ \cal{n} \le 3000 $,说明 $ ...