0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

picoCTF Writeup picoGym Practice Challenges Easy Peasy (注意<spoiler>)

Posted at

Easy Peasy

Description
A one-time pad is unbreakable, but can you manage to recover the flag? (Wrap with picoCTF{}) nc mercury.picoctf.net 64260 otp.py

ncで接続されたサービスに接続すると、最初に暗号化フラグを取得し、必要なだけのデータを暗号化できる。

$ nc mercury.picoctf.net 20266
******************Welcome to our OTP implementation!******************
This is the encrypted flag!
5b1e564b6e415c0e394e0401384b08553a4e5c597b6d4a5c5a684d50013d6e4b

What data would you like to encrypt? test
Here ya go!
15532f0c

What data would you like to encrypt?

サービスの実装から、長さ 50000 の XOR パッドを使用して入力を暗号化していることがわかる。ワンタイムパッドとして使用する場合、これは壊れないはずですが、この場合、サービスはラップアラウンドを実行し、50000 文字ごとに同じパッドを再利用する。

したがって、フラグの暗号化に使用された XOR 値を取得するには、ラップアラウンドを発生させて、既知の入力を同じXOR値で再暗号化する必要があります。入力がわかっているので、それを暗号化された結果と XOR してキーを取得できます。次に、暗号化されたフラグを使用してキーを XOR するだけです。

実際、同じ暗号化フラグを、最初に暗号化するために使用された XOR ストリームで再暗号化することで、これをもう少し効率的にすることもできる。これにより、平文フラグが生成されます。

decrypt.py
from pwn import *
from tqdm.auto import tqdm
import binascii
import string
KEY_LEN = 50000

encrypted = "51466d4e5f575538195551416e4f5300413f1b5008684d5504384157046e4959"


def get_message(slide, encrypted):
    io = remote("mercury.picoctf.net", 64260)
    for i in range(4):
        io.recvline()
    io.sendline("1"*(50000-slide))
    io.recvline()
    io.recvline()

    io.sendline(deconvert(encrypted))
    io.recvline()
    io.recvline()
    message = io.recvline().strip()
    return message


def convert(message):
    key = (chr(0)*len(message)).encode()
    result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), message, key))
    return "".join(result)

def deconvert(message):
    dec = b""
    for i in range(0,len(message),2):
        dec+=chr(int(message[i:i+2],16)).encode()
    return dec

print(deconvert(encrypted))

message = get_message(32, encrypted)
message_dec = deconvert(message)
print(message_dec)
decrypt2.py
from pwn import *

KEY_LEN = 50000
MAX_CHUNK = 1000

r = remote("mercury.picoctf.net", 64260)
r.recvuntil("This is the encrypted flag!\n")
flag = r.recvlineS(keepends = False)
log.info(f"Flag: {flag}")
bin_flag = unhex(flag)

counter = KEY_LEN - len(bin_flag)

with log.progress('Causing wrap-around') as p:
    while counter > 0:
        p.status(f"{counter} bytes left")
        chunk_size = min(MAX_CHUNK, counter)
        r.sendlineafter("What data would you like to encrypt? ", "a" * chunk_size)
        
        counter -= chunk_size

r.sendlineafter("What data would you like to encrypt? ", bin_flag)
r.recvlineS()
log.success("The flag: {}".format(unhex(r.recvlineS())))

picoCTF{3a16944dad432717ccc3945d3d96421a}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?