题目
import random, time
import string
import base64
import os
def otp(a, b):
r = ""
for i, j in zip(a, b):
r += chr(ord(i) ^ ord(j))
return r
def genSample():
p = ''.join([string.ascii_letters[random.randint(0, len(string.ascii_letters)-1)] for _ in range(random.randint(1, 30))])
k = ''.join([string.ascii_letters[random.randint(0, len(string.ascii_letters)-1)] for _ in range(len(p))])
x = otp(p, k)
return x, p, k
random.seed(int(time.time()))
print("Welcome to my one time pad service!\nIt's so unbreakable that *if* you do manage to decrypt my text, I'll give you a flag!")
print("You will be given the ciphertext and key for samples, and the ciphertext for when you try to decrypt. All will be given in base 64, but when you enter your answer, give it in ASCII.")
print("Enter:")
print("\t1) Request sample")
print("\t2) Try your luck at decrypting something!")
while True:
choice = int(input("> "))
if choice == 1:
x, p, k = genSample()
print(base64.b64encode(x.encode()).decode(), "with key", base64.b64encode(k.encode()).decode())
elif choice == 2:
x, p, k = genSample()
print(base64.b64encode(x.encode()).decode())
a = input("Your answer: ").strip()
if a == p:
print(os.environ.get("FLAG"))
break
else:
print("Wrong! The correct answer was", p, "with key", k)
分析
本题的关键在于random.seed(int(time.time()))
,找到执行时的种子,再算出p,就可以得到flag
新学到的点
用pwn库nc连接
之前都是在终端nc,这次学到了pwn库中的一些方法
conn=remote("misc.2020.chall.actf.co", 20301)//连接
conn.sendlineafter(">","2")//发送
xx=conn.recvline()//接收
时间戳
时间戳是指格林威治时间自1970年1月1日(00:00:00 GMT)至当前时间的总秒数。它也被称为Unix时间戳(Unix Timestamp)。通俗的讲,时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据
由于程序执行到交互的时间很短,所以爆破时只需要调30秒的时差
解题
from pwn import *
import random,time,string,base64,os
def otp(a, b):
r = ""
for i, j in zip(a, b):
r += chr(ord(i) ^ ord(j))
return r
def genSample():
p = ''.join([string.ascii_letters[random.randint(0, len(string.ascii_letters)-1)] for _ in range(random.randint(1, 30))])
k = ''.join([string.ascii_letters[random.randint(0, len(string.ascii_letters)-1)] for _ in range(len(p))])
x = otp(p, k)
return x, p, k
seed=int(time.time())
random.seed(seed)
conn=remote("misc.2020.chall.actf.co", 20301)
x,p,k=genSample()
conn.sendlineafter(">","2")
xx=conn.recvline().strip()
d=base64.b64decode(xx).decode()
offset=-30
while d!=x:
random.seed(int(time.time())+offset)
x,p,k=genSample()
offset+=1
conn.sendlineafter(":",p)
print(conn.recvline().strip())
需要注意的问题
b64decode()可以直接解密字符串,b64encode必须要把需要解密的内容转为Byte类型