一 、random study
这个题目中共给出了三个challenge。
1. challenge 1
服务器将python中的random模块的种子设置为int(time()),然后生成随机数让我们猜,只要我们猜对一次就可以通关了。
题目中给了200次机会,应该是考虑到服务器与我们机器的时间不同步的问题(可能相差几秒)。我这里假定服务器时间与本地时间相差不超过10秒,然后对这20种情况进行枚举就好了。相应代码如下:
2.challenge 2
服务器自己调用了一个Java程序生成了三个随机数,然后将前两个告诉我们,让我们猜第三个。
用Java Decompiler对提供的Java程序进行反编译得到源码如下:
public class Main {
public static void main(String[] paramArrayOfString) {
Random random = new Random();
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
}
}
可以看出这个Java程序是使用了Random类的nextInt函数来生成随机数的。百度一下这个类,可以查到官方文档。从官方文档中可以知道:
Random的nextInt函数就是直接调用next(32)并将得到的值返回。
next(int n)会通过以下方式更新内部存储的seed值,并返回下一个随机数。
//seed乘一个数,然后取低48位。
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
// 48位种子的前n位。
return seed>>(48-n);
setSeed(long n)会将n做一些变化,然后存储到内部的seed中。
seed = (n^ 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
根据以上知识,我们可以发现,如果我们用nextInt获得了一个随机数
,那么生成这个随机数时的种子就是
,其中x是一个16位的整数。
因此我们根据题目中给出的第一个随机数可以推断出生成第二个随机数的种子的前32位,然后我们通过对低16位进行枚举就可以得到生成第二个随机数的种子是多少了。
3. challenge3
这一题就没什么了,只要challenge1通过了,这里直接调函数得到随机数,然后发过去就好了。
代码如下:
from pwn import *
import time
from aux import *
import tqdm
import random
import subprocess
conn = remote('119.3.245.36', 23456)
def solveChaleneg1(conn):
conn.recvuntil('[-]')
cur_time = int(time.time())
for i,j in (enumerate(range(cur_time-10,cur_time+10)),initial=0,total=20):
random.seed(j)
for k in range(i):
random.randint(0,2**64)
conn.sendline(str(random.randint(0,2**64)))
if 'fail' not in conn.recvline():
break
def solveChalenge2():
conn.recvuntil('[-]')
x1 = conn.recvline()
print x1
x1 = int(x1)
print(x1)
conn.recvuntil('[-]')
x2 = int(conn.recvline(),10)
o = subprocess.check_output(["java", "MyMain",str(x1),str(x2)])
x3 = int(o.split('\n')[0],10)
print "x1=%d,x2=%d,x3=%d"%(x1,x2,x3)
conn.recvuntil('[-]')
conn.sendline(str(x3))
if 'fail' in conn.recvline()[:-1]:
print "challenge2 fails"
def solveChalenge3():
target = random.getrandbits(32)
conn.recvuntil('[-]')
conn.sendline(str(target))
conn.recvuntil("[++++++++++++++++]challenge 3 completed[++++++++++++++++]")
solveSHA(conn)
solveChaleneg1(conn)
solveChalenge2()
solveChalenge3()
conn.interactive()
import java.util.Random;
public class MyMain {
public static void main(String[] paramArrayOfString) {
long x1 = (long)(Long.parseLong(paramArrayOfString[0])&((1L<<32)-1));
long x2 = (long)(Long.parseLong(paramArrayOfString[1])&((1L<<32)-1));
// = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
//seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
for(int i= 0;i
Random random = new Random(((x1<<16)+i)^0x5DEECE66DL);
if(random.nextInt() == x2){
System.out.println(random.nextInt());
}
}
}
}
CopperStudy
里面包含6个challenge.
1. challenge1
[+]teamtoken:[++++++++++++++++]proof completed[++++++++++++++++]
[+]Generating challenge 1
[+]n=0x931a21e45b8c30eb30f1b9767c724f57dd770432df414a5969d770e5cf41d86aa8c198baba3709d602b6de17003406b3ba9190e99c4c9aaa470afe052fa2aec57a7c448bf1a887c5c4776a789b51bf4f76b334fc27a59469d6b4fb76af90ec2ec56a4c83f0cabfcb3669c2e24243c9dfe32cc817fd2196452df47e92eeb06eb5L
[+]e=3
[+]m=random.getrandbits(512)
[+]c=pow(m,e,n)=0x842683283571aeb5d8716f2a4667ff7e61fc63bb5a4cd89858c02881e0d536e344167e06e44ef5e276253563486c3b05971acfb96f8ed1a9e8c3143c026889ab11d5f72973bf6907f773ad0d570436cc64daf16e35ffff1fb48c66b36d9a8bfc568de1407b19f621ead2fa572fce24a921d742128a7b321f381e81bae0cb9f70L
[+]((m>>72)<<72)=0xb74706a05587a42246ed7ff2f03c4edf180f5248cfb7a8b86757ea456ba134c8a81f146b3172d1b59437efeb2e59b41e8dbb9cf2ac3254000000000000000000L
给定了明文的高位,低72位未知。思考了一会,发现不会,于是直接百度copper