We have an innovative seesaw!
ソースコードとoutput.txtが配布されます。
flagをビット列に変換したものとランダムなビット列を用意し、flagの各ビットに対して1/2の確率でランダムビット列とのANDを取ったものに書き換えているらしい。
その試行の16回分の出力がoutput.txtに入ってます。
from Crypto.Util.number import *
from random import random, getrandbits
from flag import flag
flag = bytes_to_long(flag.encode("utf-8"))
length = flag.bit_length()
key = getrandbits(length)
while not length == key.bit_length():
key = getrandbits(length)
flag = list(bin(flag)[2:])
key = list(bin(key)[2:])
cipher_L = []
for _ in range(16):
cipher = flag[:]
m = 0.5
for i in range(length):
n = random()
if n > m:
cipher[i] = str(eval(cipher[i] + "&" + key[i]))
cipher_L.append("".join(cipher))
print("cipher =", cipher_L)
ビット同士でANDを取るとき、1が0になることはあれど0が1になることはありません。
つまり0は16回試行しようがその全てで0となっているはず。
逆に1は1になったり0になったりしてますが16回も試行すりゃ1回くらい1になってるはず。
つまり出力の全パターンに対してORを取ればflagが復元できるはず。
inp=[]
ans=0
with open("output_.txt") as f:
l = [s.strip() for s in f.readlines()]
for i in l:
ans=ans|(int("0b"+i,0))
print(bin(ans))
(output.txtはリスト形式での出力だったのを1行ずつに書き換えたoutput_.txtを入力に用いています)
これでビット列が復元できたわけですがutf-8へのデコードはまだです。
Pythonでのデコードわかんないよ~~!!とプログラミング能力の低さを露呈させていたところ↓のサイトを見つけて事なきを得ました。
https://dencode.com/ja/
みんなはプログラミングができるようになろうね!
ctf4b{Sh3_54w_4_SEESAW,_5h3_54id_50}