xman随机数相关题目

参加xman夏令营,大佬给我们带来了密码学课程。其中随机数部分感受颇深,记录下几个脚本。

1. 以时间作为种子的随机数

https://www.jarvisoj.com/ 的[xman2019]babyrpd

服务端代码

 1 class Unbuffered(object):
 2    def __init__(self, stream):
 3        self.stream = stream
 4    def write(self, data):
 5        self.stream.write(data)
 6        self.stream.flush()
 7    def __getattr__(self, attr):
 8        return getattr(self.stream, attr)
 9 import sys
10 sys.stdout = Unbuffered(sys.stdout)
11 import signal
12 signal.alarm(600)
13 
14 import random
15 import time
16 flag=open("/root/level0/flag","r").read()
17 
18 random.seed(int(time.time()))
19 def check():
20     recv=int(raw_input())
21     if recv==random.randint(0,2**64):
22         print flag
23         return True
24     else:
25         print "atum tql"
26         return False
27 
28 while 1:
29     if check():
30         break

解决方法:

预测时间种子,进行攻击

 1 #coding=utf-8
 2 import socket               
 3 import random
 4 import time
 5 
 6 while True:
 7     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 8     host = '47.97.215.88'
 9     port = 20000
10     random.seed(int(time.time()+2))  #加上延迟所以+2秒
11     s.connect((host, port))
12     s.send(str(random.randint(0,2**64))+'\n')
13     print s.recv(1024)

2. java的Random随机数

https://www.jarvisoj.com/ 的[xman2019]mediumrpd

服务端代码:

 1 class Unbuffered(object):
 2    def __init__(self, stream):
 3        self.stream = stream
 4    def write(self, data):
 5        self.stream.write(data)
 6        self.stream.flush()
 7    def __getattr__(self, attr):
 8        return getattr(self.stream, attr)
 9 import sys
10 sys.stdout = Unbuffered(sys.stdout)
11 import signal
12 signal.alarm(600)
13 import os
14 os.chdir("/root/level1")
15 
16 flag=open("flag","r").read()
17 
18 import subprocess
19 o = subprocess.check_output(["java", "Main"])
20 tmp=[]
21 for i in o.split("\n")[0:3]:
22     tmp.append(int(i.strip()))
23 
24 
25 v1=tmp[0] % 0xffffffff
26 v2=tmp[1] % 0xffffffff
27 v3=tmp[2] % 0xffffffff
28 print v1
29 print v2
30 v3_get=int(raw_input())
31 if v3_get==v3:
32     print flag
1 import java.util.Random;
2 public class Main {
3     public static void main(String[] args) {
4         Random random = new Random();
5         System.out.println(random.nextInt());
6         System.out.println(random.nextInt());
7         System.out.println(random.nextInt());
8     }
9 }

攻击方法

从题目获取到两个随机数v1,v2,通过已知公式,可以计算出v3

 1 import socket               
 2 import random
 3 import time
 4 def liner (seed):
 5     return ((seed*25214903917+11)&0xffffffffffff)
 6 
 7 while True:
 8     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 9     host = '47.97.215.88'
10     port = 20001
11     s.connect((host, port))
12     v1=int(s.recv(1024))
13     v2=int(s.recv(1024))
14     for i in range(65536):
15         seed=v1*65536+i
16         if liner(seed)>>16==v2:
17             print seed
18             v3=liner(liner(seed))>>16
19             s.send(str(v3)+'\n')
20             print s.recv(1024)

3. python的random

来源是:Mersenne Twister

大佬说php的mt_rand(可以用php_mt_seed攻击),ruby的rand(),python的random都可以攻击,但我只弄出python的版本

题目为https://www.jarvisoj.com/ 的[xman2019]hardrpd

参考文章:https://ddaa.tw/30c3ctf_2013_number_100_guess.html

服务端代码:

 1 class Unbuffered(object):
 2    def __init__(self, stream):
 3        self.stream = stream
 4    def write(self, data):
 5        self.stream.write(data)
 6        self.stream.flush()
 7    def __getattr__(self, attr):
 8        return getattr(self.stream, attr)
 9 import sys
10 sys.stdout = Unbuffered(sys.stdout)
11 import os
12 os.chdir("/root/level2")
13 
14 from random import *
15 
16 
17 while 1:
18     a=raw_input("#")
19     target=getrandbits(32)
20     if a!=str(target):
21         print target
22     else:
23         print open("flag","rb").read()

 

攻击脚本:(改写至TokyoWestern CTF WriteUp by r3kapig

 1 #coding=utf-8
 2 import socket               
 3 import random
 4 import time
 5 
 6 
 7 def unBitshiftRightXor (value,shift):
 8     i = 0
 9     result = 0
10     while i * shift < 32:
11          partMask = right((-1 << (32 - shift)) , (shift * i))
12          part = value & partMask
13          value ^= right(part , shift)
14          result |= part
15          i+=1
16     return result
17 def unBitshiftLeftXor(value, shift, mask):
18     i = 0;
19     result = 0;
20     while i * shift < 32:
21         partMask = right(-1 , (32 - shift)) << (shift * i)
22         part = value & partMask
23         value ^= (part << shift) & mask
24         result |= part
25         i += 1
26     return result
27 
28 def rev(nums):
29     state=[]
30     for i in nums:
31         value = i;
32         value = unBitshiftRightXor(value, 18)
33         value = unBitshiftLeftXor(value, 15, 0xefc60000)
34         value = unBitshiftLeftXor(value, 7, 0x9d2c5680)
35         state.append(unBitshiftRightXor(value, 11))
36     return state
37 
38 def sign(iv):
39     if(iv&0x80000000):
40         iv = -0x100000000 + iv
41     return iv
42 
43 def nextState(state):
44     for i in range(624):
45         y = (state[i] & 0x80000000) + (state[(i + 1) % 624] & 0x7fffffff)
46         next = right(y,1);
47         next ^= state[(i + 397) % 624]
48         if ((y & 1L) == 1L):
49             next ^= 0x9908b0df
50         state[i] = next
51 
52 def nextNumber(state):
53     currentIndex=0
54     tmp = state[currentIndex];
55     tmp ^= right(tmp , 11)
56     tmp ^= (tmp << 7) & 0x9d2c5680
57     tmp ^= (tmp << 15) & 0xefc60000
58     tmp ^= right(tmp , 18)
59     return tmp
60 
61 def right(n,bit): #python没有>>>运算符,这个函数用作代替
62     x=n
63     if n<0 and bit>0:
64         n=(2147483648*2+n)>>bit
65     else:
66         n=n>>bit
67     return n
68 
69 def crack_prng(outputs_624_list):
70     state=rev(outputs_624_list)
71     stateList = state[:]
72     nextState(state)
73     r = random.Random()
74     state = (3, tuple(stateList + [624]), None)
75     r.setstate(state)
76     return r
77 '''
78 #本地测试代码
79 n=[random.getrandbits(32) for i in range(625)]
80 r=crack_prng(n[:-1])
81 print n[-1],r.getrandbits(32)
82 '''
83 n=[]
84 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
85 host = '47.97.215.88'
86 port = 20002  
87 s.connect((host, port))
88 for i in range(624):
89     print s.recv(1024),i,
90     s.send('\n')
91     n.append(int(s.recv(1024)))
92 r=crack_prng(n)
93 s.send(str(r.getrandbits(32))+'\n')
94 print s.recv(1024),s.recv(1024)

 

posted @ 2019-08-05 17:27  ~kagi~  阅读(859)  评论(0编辑  收藏  举报