At the xman summer camp, the big man brought us cryptography courses. Among them, the random number part feels deeply and records several scripts.
1. Time as the Random Number of Seeds
https://www.jarvisoj.com/ [xman 2019] babyrpd
Server-side code
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
Solution:
Predict time seeds, attack
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)) #Add a delay so+2 second 11 s.connect((host, port)) 12 s.send(str(random.randint(0,2**64))+'\n') 13 print s.recv(1024)
2. Random Numbers of Java
https://www.jarvisoj.com/ [xman 2019] mediumrpd
Server-side code:
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 }
Attack methods
Two random numbers V1 and V2 are obtained from the title. Through the known formula, v3 can be calculated.
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's random
Source: Mersenne Twister
The big guy said that php's mt_rand (can be attacked with php_mt_seed), ruby's rand(), python's random can be attacked, but I only got the version of python.
The title is https://www.jarvisoj.com/ [xman 2019] hardrpd
Server-side code:
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()
Attack script: (rewritten to 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 No>>>Operator, which is used as a substitute 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 #Local test code 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)