[angstromctf]one time bad

题目

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类型

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容