参加xman夏令营,大佬给我们带来了密码学课程。其中随机数部分感受颇深,记录下几个脚本。
1.以时间作为种子的随机数
的[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 sys10 sys.stdout = Unbuffered(sys.stdout)11 import signal12 signal.alarm(600)13 14 import random15 import time16 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 flag23 return True24 else:25 print "atum tql"26 return False27 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 = 2000010 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随机数
的[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 sys10 sys.stdout = Unbuffered(sys.stdout)11 import signal12 signal.alarm(600)13 import os14 os.chdir("/root/level1")15 16 flag=open("flag","r").read()17 18 import subprocess19 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] % 0xffffffff26 v2=tmp[1] % 0xffffffff27 v3=tmp[2] % 0xffffffff28 print v129 print v230 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 = 2000111 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+i16 if liner(seed)>>16==v2:17 print seed18 v3=liner(liner(seed))>>1619 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的版本
题目为 的[xman2019]hardrpd
参考文章:
服务端代码:
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 sys10 sys.stdout = Unbuffered(sys.stdout)11 import os12 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 target22 else:23 print open("flag","rb").read()
攻击脚本:(改写至)
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 = 010 while i * shift < 32:11 partMask = right((-1 << (32 - shift)) , (shift * i))12 part = value & partMask13 value ^= right(part , shift)14 result |= part15 i+=116 return result17 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 & partMask23 value ^= (part << shift) & mask24 result |= part25 i += 126 return result27 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 state37 38 def sign(iv):39 if(iv&0x80000000):40 iv = -0x100000000 + iv41 return iv42 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 ^= 0x9908b0df50 state[i] = next51 52 def nextNumber(state):53 currentIndex=054 tmp = state[currentIndex];55 tmp ^= right(tmp , 11)56 tmp ^= (tmp << 7) & 0x9d2c568057 tmp ^= (tmp << 15) & 0xefc6000058 tmp ^= right(tmp , 18)59 return tmp60 61 def right(n,bit): #python没有>>>运算符,这个函数用作代替62 x=n63 if n<0 and bit>0:64 n=(2147483648*2+n)>>bit65 else:66 n=n>>bit67 return n68 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 r77 '''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)