redpwnCTF 2020 Writeup

この大会は2020/6/22 5:00(JST)~2020/6/26 5:00(JST)に開催されました。
今回もチームで参戦。結果は7026点で1494チーム中105位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity-check (misc)

問題にフラグが書いてあった。

flag{54n1ty_ch3ck_f1r5t_bl00d?}

discord (misc)

Discordに入り、ピン止めメッセージを見ると、フラグが書いてあった。

flag{w3lc0me_t0_r3dpwnctf_d1sc0rd}

hackerone-survey (misc)

アンケートを送信すると、フラグが表示された。

flag{rac3_f0r_H@ck3rOne_surv3y!}

base646464 (crypto)

JavaScriptコードを見ると、25回base64エンコードしていることがわかる。25回base64デコードする。

with open('cipher.txt', 'r') as f:
    data = f.read()

for i in range(25):
    data = data.decode('base64')

print data
flag{l00ks_l1ke_a_l0t_of_64s}

ropes (rev)

$ strings ropes 
__PAGEZERO
__TEXT
__text
__TEXT
__stubs
__TEXT
__stub_helper
__TEXT
__cstring
__TEXT
__unwind_info
__TEXT
__DATA
__nl_symbol_ptr
__DATA
__la_symbol_ptr
__DATA
__LINKEDIT
/usr/lib/dyld
/usr/lib/libSystem.B.dylib
Give me a magic number: 
First part is: flag{r0pes_ar3_
Second part is: just_l0ng_str1ngs}
@dyld_stub_binder
@_printf
@_puts
@_scanf
_mh_execute_header
!main
__mh_execute_header
_main
_printf
_puts
_scanf
dyld_stub_binder

2つに分断されたフラグを結合する。

flag{r0pes_ar3_just_l0ng_str1ngs}

login (web)

SQLインジェクション。添付のjsファイルを見ると、userテーブルは、id, username, passwordの構成のようなので、以下のように入力してみると、フラグが表示された。

Username: a
Password: ' union all select 1, 'admin', 'pass' --
flag{0bl1g4t0ry_5ql1}

pseudo-key (crypto)

ascii_lowercaseのインデックスで足して、26で割ったあまりを出し、そのインデックスで文字にすると暗号になる。keyもkeyで暗号化しているので、2で割れば元のkeyを出せるが、各文字で2パターンある。候補を出したら、keyが推測できたので、その前提でflagを復元する。

from string import ascii_lowercase

def decrypt(ctxt, key):
    key = ''.join(key[i % len(key)] for i in range(len(ctxt)))
    ptxt = ''
    for i in range(len(ctxt)):
        if ctxt[i] == '_':
            ptxt += '_'
            continue
        x = chr_to_num[ctxt[i]]
        y = chr_to_num[key[i]]
        ptxt += num_to_chr[(x - y) % 26]
    return ptxt

ctxt = 'z_jjaoo_rljlhr_gauf_twv_shaqzb_ljtyut'
enc_key = 'iigesssaemk'

chr_to_num = {c: i for i, c in enumerate(ascii_lowercase)}
num_to_chr = {i: c for i, c in enumerate(ascii_lowercase)}

key_list = []
for i in range(len(enc_key)):
    x = chr_to_num[enc_key[i]]
    x1 = x // 2
    x2 = (x + 26) // 2
    key_list.append([num_to_chr[x1], num_to_chr[x2]])

print key_list

# guess
key = 'redpwwwnctf'
ptxt = decrypt(ctxt, key)
flag = 'flag{%s}' % ptxt
print flag

実行結果は以下の通り。

[['e', 'r'], ['e', 'r'], ['d', 'q'], ['c', 'p'], ['j', 'w'], ['j', 'w'], ['j', 'w'], ['a', 'n'], ['c', 'p'], ['g', 't'], ['f', 's']]
flag{i_guess_pseudo_keys_are_pseudo_secure}
flag{i_guess_pseudo_keys_are_pseudo_secure}

4k-rsa (crypto)

nをfactordbで素因数分解する。

n = 9353689450544968301 * 9431486459129385713 * 9563871376496945939 * 9734621099746950389
  * 9736426554597289187 * 10035211751896066517 * 10040518276351167659 * 10181432127731860643
  * 10207091564737615283 * 10435329529687076341 * 10498390163702844413 * 10795203922067072869
  * 11172074163972443279 * 11177660664692929397 * 11485099149552071347 * 11616532426455948319
  * 11964233629849590781 * 11992188644420662609 * 12084363952563914161 * 12264277362666379411
  * 12284357139600907033 * 12726850839407946047 * 13115347801685269351 * 13330028326583914849
  * 13447718068162387333 * 13554661643603143669 * 13558122110214876367 * 13579057804448354623
  * 13716062103239551021 * 13789440402687036193 * 13856162412093479449 * 13857614679626144761
  * 14296909550165083981 * 14302754311314161101 * 14636284106789671351 * 14764546515788021591
  * 14893589315557698913 * 15067220807972526163 * 15241351646164982941 * 15407706505172751449
  * 15524931816063806341 * 15525253577632484267 * 15549005882626828981 * 15687871802768704433
  * 15720375559558820789 * 15734713257994215871 * 15742065469952258753 * 15861836139507191959
  * 16136191597900016651 * 16154675571631982029 * 16175693991682950929 * 16418126406213832189
  * 16568399117655835211 * 16618761350345493811 * 16663643217910267123 * 16750888032920189263
  * 16796967566363355967 * 16842398522466619901 * 17472599467110501143 * 17616950931512191043
  * 17825248785173311981 * 18268960885156297373 * 18311624754015021467 * 18415126952549973977

あとはMuti-prime RSAとして復号する。

from Crypto.Util.number import *

n = 5028492424316659784848610571868499830635784588253436599431884204425304126574506051458282629520844349077718907065343861952658055912723193332988900049704385076586516440137002407618568563003151764276775720948938528351773075093802636408325577864234115127871390168096496816499360494036227508350983216047669122408034583867561383118909895952974973292619495653073541886055538702432092425858482003930575665792421982301721054750712657799039327522613062264704797422340254020326514065801221180376851065029216809710795296030568379075073865984532498070572310229403940699763425130520414160563102491810814915288755251220179858773367510455580835421154668619370583787024315600566549750956030977653030065606416521363336014610142446739352985652335981500656145027999377047563266566792989553932335258615049158885853966867137798471757467768769820421797075336546511982769835420524203920252434351263053140580327108189404503020910499228438500946012560331269890809392427093030932508389051070445428793625564099729529982492671019322403728879286539821165627370580739998221464217677185178817064155665872550466352067822943073454133105879256544996546945106521271564937390984619840428052621074566596529317714264401833493628083147272364024196348602285804117877
e = 65537
c = 3832859959626457027225709485375429656323178255126603075378663780948519393653566439532625900633433079271626752658882846798954519528892785678004898021308530304423348642816494504358742617536632005629162742485616912893249757928177819654147103963601401967984760746606313579479677305115496544265504651189209247851288266375913337224758155404252271964193376588771249685826128994580590505359435624950249807274946356672459398383788496965366601700031989073183091240557732312196619073008044278694422846488276936308964833729880247375177623028647353720525241938501891398515151145843765402243620785039625653437188509517271172952425644502621053148500664229099057389473617140142440892790010206026311228529465208203622927292280981837484316872937109663262395217006401614037278579063175500228717845448302693565927904414274956989419660185597039288048513697701561336476305496225188756278588808894723873597304279725821713301598203214138796642705887647813388102769640891356064278925539661743499697835930523006188666242622981619269625586780392541257657243483709067962183896469871277059132186393541650668579736405549322908665664807483683884964791989381083279779609467287234180135259393984011170607244611693425554675508988981095977187966503676074747171

primes = [9353689450544968301, 9431486459129385713, 9563871376496945939, 
    9734621099746950389, 9736426554597289187, 10035211751896066517, 
    10040518276351167659, 10181432127731860643, 10207091564737615283, 
    10435329529687076341, 10498390163702844413, 10795203922067072869, 
    11172074163972443279, 11177660664692929397, 11485099149552071347, 
    11616532426455948319, 11964233629849590781, 11992188644420662609, 
    12084363952563914161, 12264277362666379411, 12284357139600907033, 
    12726850839407946047, 13115347801685269351, 13330028326583914849, 
    13447718068162387333, 13554661643603143669, 13558122110214876367, 
    13579057804448354623, 13716062103239551021, 13789440402687036193, 
    13856162412093479449, 13857614679626144761, 14296909550165083981, 
    14302754311314161101, 14636284106789671351, 14764546515788021591, 
    14893589315557698913, 15067220807972526163, 15241351646164982941, 
    15407706505172751449, 15524931816063806341, 15525253577632484267, 
    15549005882626828981, 15687871802768704433, 15720375559558820789, 
    15734713257994215871, 15742065469952258753, 15861836139507191959, 
    16136191597900016651, 16154675571631982029, 16175693991682950929, 
    16418126406213832189, 16568399117655835211, 16618761350345493811, 
    16663643217910267123, 16750888032920189263, 16796967566363355967, 
    16842398522466619901, 17472599467110501143, 17616950931512191043, 
    17825248785173311981, 18268960885156297373, 18311624754015021467, 
    18415126952549973977]

phi = 1
for p in primes:
    phi *= p - 1
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m)
print flag
flag{t0000_m4nyyyy_pr1m355555}

12-shades-of-redpwn (crypto)

ASCIIコードで12進数になっていて色で表現していると推測できる。

文字 10進数 12進数
f:  102   86
l:  108   90
a:  97   81
g:  103   87

合っているようだ。これを元に復号する。

codes = ['86', '90', '81', '87', 'a3', '49', '99', '43', '97', '97', '41',
    '92', '49', '7b', '41', '97', '7b', '44', '92', '7b', '44', '96', '98',
    'a5']

flag = ''
for code in codes:
    flag += chr(int(code, 12))
print flag
flag{9u3ss1n9_1s_4n_4rt}

primimity (crypto)

与えられたコードのp, q, rの生成部分に注目する。

def prime_gen():
    i = getRandomNBitInteger(1024)
    d = getRandomNBitInteger(8)
    for _ in range(d):
        i = find_next_prime(i)
    p = find_next_prime(i)
    d = getRandomNBitInteger(8)
    for _ in range(d):
        i = find_next_prime(i)
    q = find_next_prime(i)
    d = getRandomNBitInteger(8)
    for _ in range(d):
        i = find_next_prime(i)
    r = find_next_prime(i)
    return (p,q,r)

高々256回の次の素数という差なので、nの3乗根から次の素数というように進んでいけばqになり、さらに進んでいけばrになるはず。p, q, rを割り出したら、あとは通常通り、復号すればよい。

import gmpy
from Crypto.Util.number import *

def find_next_prime(n):
    if n <= 1:
        return 2
    elif n == 2:
        return 3
    else:
        if n % 2 == 0:
            n += 1
        else:
            n += 2
        while not isPrime(n):
            n += 2
        return n

n = 2739699434633097765008468371124644741923408864896396205946954196101304653772173210372608955799251139999322976228678445908704975780068946332615022064030241384638601426716056067126300711933438732265846838735860353259574129074615298010047322960704972157930663061480726566962254887144927753449042590678730779046154516549667611603792754880414526688217305247008627664864637891883902537649625488225238118503996674292057904635593729208703096877231276911845233833770015093213639131244386867600956112884383105437861665666273910566732634878464610789895607273567372933766243229798663389032807187003756226177111720510187664096691560511459141773632683383938152396711991246874813205614169161561906148974478519987935950318569760474249427787310865749167740917232799538099494710964837536211535351200520324575676987080484141561336505103872809932354748531675934527453231255132361489570816639925234935907741385330442961877410196615649696508210921
e = 65537
c = 2082926013138674164997791605512226759362824531322433048281306983526001801581956788909408046338065370689701410862433705395338736589120086871506362760060657440410056869674907314204346790554619655855805666327905912762300412323371126871463045993946331927129882715778396764969311565407104426500284824495461252591576672989633930916837016411523983491364869137945678029616541477271287052575817523864089061675401543733151180624855361245733039022140321494471318934716652758163593956711915212195328671373739342124211743835858897895276513396783328942978903764790088495033176253777832808572717335076829539988337505582696026111326821783912902713222712310343791755341823415393931813610365987465739339849380173805882522026704474308541271732478035913770922189429089852921985416202844838873352090355685075965831663443962706473737852392107876993485163981653038588544562512597409585410384189546449890975409183661424334789750460016306977673969147

p = gmpy.root(n, 3)[0]
primes = [0]
while True:
    p = find_next_prime(p)
    if n % p == 0:
        primes.append(int(p))
        if len(primes) == 3:
            break

primes[0] = n // (primes[1] * primes[2])
p = primes[0]
q = primes[1]
r = primes[2]

phi = (p - 1) * (q - 1) * (r - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m)
print flag
flag{pr1m3_pr0x1m1ty_c4n_b3_v3ry_d4ng3r0u5}

itsy-bitsy (crypto)

$ nc 2020.redpwnc.tf 31284
Enter an integer i such that i > 0: 44
Enter an integer j such that j > i > 0: 67
Ciphertext: 0000101101010111101000100110100011000011010111100001001111010100100110001000001001001101111100100110110010011110100010001100010100011000110001010011111001011111111010111101000011111001010110101000000100101010110010000101000011000011110101001011010000001000000100000110111011111000110111101111100100010

コードからサーバの処理概要は以下のようになっていることがわかる。

flagの各文字のビット数は7で最上位は1
flag_bits: flagを2進数にした文字列(1文字あたり7bit)
i, j: 入力(j > i > 0)
lb: 2**i
ub: 2**j - 1
n = len(flag_bits)
random_bits = generate_random_bits(lb, ub, n)
encrypted_bits = random_bitsとflag_bitsのxor
||>
このことから以下のようになる。
>||
i=1, j=2の場合、random_bitsは10,11の組み合わせ文字列で2ビットごとに確定できる。
i=2, j=3の場合、同様に3ビットごとに確定できる。
2ビット目は理論的に確定できないが、flagから始まることを考えると、'1'になる。
あとは、2ビット目以外で確定できていないところのi, jを決めていく。jが素数でiはj-1にすればよい。
・i=4, j=5の場合、5ビットごと
・i=6, j=7の場合、7ビットごと

0000101101010111101000100110100011000011010111100001001111010100100110001000001001001101111100100110110010011110100010001100010100011000110001010011111001011111111010111101000011111001010110101000000100101010110010000101000011000011110101001011010000001000000100000110111011111000110111101111100100010
1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1
1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1****1
1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******1******
import socket
import gmpy2

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def check_finish(ary):
    for elm in ary:
        if elm == '':
            return False
    return True

flag_bits = [''] * 301
flag_bits[1] = '1'

i = 1
j = 1
while True:
    j = gmpy2.next_prime(j)
    i = j - 1

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('2020.redpwnc.tf', 31284))

    data = recvuntil(s, ': ')
    print data + str(i)
    s.sendall(str(i) + '\n')

    data = recvuntil(s, ': ')
    print data + str(j)
    s.sendall(str(j) + '\n')

    data = recvuntil(s, '\n').rstrip()
    print data

    ct = data.split(': ')[1]
    for k in range(0, len(ct), j):
        flag_bits[k] = str(int(ct[k]) ^ 1)

    if check_finish(flag_bits):
        break

flag_bits = ''.join(flag_bits)

flag = ''
for i in range(0, len(flag_bits), 7):
    flag += chr(int(flag_bits[i:i+7], 2))
print flag

実行結果は以下の通り。

Enter an integer i such that i > 0: 1
Enter an integer j such that j > i > 0: 2
Ciphertext: 0110011100001100111001011101010011010111010010100101101101011101100001001100100010110110100101010100101000000101001000011100000010010101101101010011100001001001100100000100000000000001000101001110001110110111110100000100110100101000011110011100000010010000010001110100001010000101010100010010110000000
Enter an integer i such that i > 0: 2
Enter an integer j such that j > i > 0: 3
Ciphertext: 0011001101101110001110111000110010000001010110110000111100001110110110101011010100100101110001010110001100010001111000111110110010000110001100100100010010101101000000110111010001000011000110101011111101110110000100110010110000001000011001101011100011000010010010100000001000100100100011110100000000100
Enter an integer i such that i > 0: 4
Enter an integer j such that j > i > 0: 5
Ciphertext: 0111001001001100011000010001100010000100000000001100000111101111101100000001010010000010100010111001110000011001101100111100101011011100110100011100000110100011111010001100111001000100101100000001100011100110100010101001110000011100110010111110100000000110000101010010001110111110001111110011011011110
Enter an integer i such that i > 0: 6
Enter an integer j such that j > i > 0: 7
Ciphertext: 0101011010110000100000101111010110101010010101011000010100010100111101010111001101100001001010011101011000001110000011100011010000000010000101100010000000010110100010110100000010000001110110010001000010001110010100010010100000110100110111011110101000000001101010010000010010000001010010000011000100101
Enter an integer i such that i > 0: 10
Enter an integer j such that j > i > 0: 11
Ciphertext: 0000011011101000100010000001101110101111010110001111011111110111010110001011101000100001111010001100101111001001011000011001111100010000011100011001000111001100000100000001010101110110101010001001101110100010100111011110100011001110001011000001100011110100001010000001001101010010011000010111110100001
Enter an integer i such that i > 0: 12
Enter an integer j such that j > i > 0: 13
Ciphertext: 0000010010111110101101000101000111000101010100101010100010110000101011001101110101010100110001011110111001010101110110011001010101011010101011111000110011111010111111101001011001011000011001011111011011110010101101001011000001000110101110001110001011000010100101100011101100100000111111001011011010110
Enter an integer i such that i > 0: 16
Enter an integer j such that j > i > 0: 17
Ciphertext: 0111111101001101011111111001011001010001101010001100100100100101101100000011100100100011010110111001101010111101000100101000101101001011100001100001011110101010101001110100011010000111101000101011111110110100001101110010001110000000010000000101111010100000101111100101101111111101101101110010110111010
Enter an integer i such that i > 0: 18
Enter an integer j such that j > i > 0: 19
Ciphertext: 0100101110011110001110000111111110111111010111001001001100101111101011101101110010011010000101111110101001111001111111110110010010100001000101110100010001010110011100100101101000100110010110000101111100001011000010000001011001001000001100101010100001001010010101111000001011111011001111110010100011110
Enter an integer i such that i > 0: 22
Enter an integer j such that j > i > 0: 23
Ciphertext: 0101011001010010111001010110110010010101000100100010101111110110111000100001010011110001101100100111101001000011000101101010101001011110001011100110100110101010101100100101110111010001000011010110101110100010011000011100001001111101001100010101000110111100110101010111100000000000100101011011100110110
Enter an integer i such that i > 0: 28
Enter an integer j such that j > i > 0: 29
Ciphertext: 0001110100100011010111101110100010111111110110011001101110011101010100100000110010110111001100111011100000000100101000111111111111111100011010000101110011001100010111100100010110010001010001011001010001100101111000011100010010100100011010001111000110001110011010110101111100011111101010001010100110011
Enter an integer i such that i > 0: 30
Enter an integer j such that j > i > 0: 31
Ciphertext: 0100100100111001111000000000000010000001011011111001111010001000110101100000000010100101001111011110000110111011011011111001001111010011111100000101010000100110010111000100000110001000000001101100000011000010001011100001010110100001000101101010111110000100101010111011110110001110001000101010011000011
Enter an integer i such that i > 0: 36
Enter an integer j such that j > i > 0: 37
Ciphertext: 0110010111001011110111110001010100111100001100000011110000000011001001001001101010101010100001101100010001110011011110110000011100100110110110101111101111001010010010010101100101011110001011001010110001100000000000100010000011001000000100010111000001001110100001010000000110110111010000000110100001000
Enter an integer i such that i > 0: 40
Enter an integer j such that j > i > 0: 41
Ciphertext: 0101101010101101111010111001101010100000111010111110001100111100000101011010100001100011110111010100111110101101001101010010101000111000111101100011001010111110110101001011010011011110101010100101010100111100000101001100010010010111100000010000110000110010111101110110111110011010110111000011011010010
Enter an integer i such that i > 0: 42
Enter an integer j such that j > i > 0: 43
Ciphertext: 0010010101010100000011010001010001011001111001001011101011010100011010101011101010101010100110011111110000110111110010111000010010010110010001011110000011010111001110001000011001010110010011111110001111100110110101001001011101011110100110000000000101101010010110111000000111011111110101001101011001111
Enter an integer i such that i > 0: 46
Enter an integer j such that j > i > 0: 47
Ciphertext: 0100011110100101000010111100010101100101100111011011010001010111101010100110100011000000110000010010110111100110101011011000101000000001010110011011011111000001110010001111000100101010011001001010110111111110101000110100111111010010011000101101010110111000100101101000111011111000010010010000000111011
Enter an integer i such that i > 0: 52
Enter an integer j such that j > i > 0: 53
Ciphertext: 0111110100110101010000010010011111111110110010111101000010100111110001010101111100100010100100011001110010001001110100010101110111000100110010011000100011011111011011100000110100001010011010101001000111110011001000111100100010110010000110010110000111110000000100000010111111111110011100001101000111001
Enter an integer i such that i > 0: 58
Enter an integer j such that j > i > 0: 59
Ciphertext: 0001001111100010101101111011101110101010111001110011001011010110010100101011100010011001010001000011010000110101010011010101101111110000010111001101110010101010010100000100100011011000101010100111010011000101011110000111101000011100010111010110101110110111110000011001001010101010011000100000110000011
Enter an integer i such that i > 0: 60
Enter an integer j such that j > i > 0: 61
Ciphertext: 0000010111001100111010100010110010101111011101111111011111011000000100110000110110001000110101001111010111111011110000110100011011111110110001001011111010101000111100000001010000011011100110011101011001010010000100000110001011100100000100000011000001101101101000101011111111001010011110000111001011000
Enter an integer i such that i > 0: 66
Enter an integer j such that j > i > 0: 67
Ciphertext: 0111001001110111011110100100000001100101101011111001000011011100001011010011011000001001001000111001100011110101001100011010100110001101011111010100010000100110101110011000011001101100100100110111100101100110111000100011001100000011100000101100000011010001011011010100001111101010101001101110110111010
Enter an integer i such that i > 0: 70
Enter an integer j such that j > i > 0: 71
Ciphertext: 0100111011000000000110101101101001010100001101101011000010111101100101100100110001010110111110011100101001100101101101110011001010010100101110010100010010111111100010001101111000001000001011101101100100001110111000101111111000010110001111110111010100101010111101111010000011111001110001011010011100100
Enter an integer i such that i > 0: 72
Enter an integer j such that j > i > 0: 73
Ciphertext: 0001101000000101000110110111111010010011010111001101010010100010100011110001111011011011100010110010001001101000101001100010111111001111111001010010110010010100000100011101111101000000010010011111000011111000100110011110010100000011111111011010110110011110111011000110101110110100100000111000100000101
Enter an integer i such that i > 0: 78
Enter an integer j such that j > i > 0: 79
Ciphertext: 0101101000001010001100001101011011011000001111011100011010111100110111110001011111110011111101110110111101101110001000011100000011101011101111101000111010110100011110111001010110111000000110111011100111000011110110101010000000010100101011001011011110110101010001111011110001100001000101011000100010001
Enter an integer i such that i > 0: 82
Enter an integer j such that j > i > 0: 83
Ciphertext: 0100000010000101110110011011010111110101010100110010001010010001000010001110001010000001010010001010100000100000101011100110001010001111011001101101010101001111110010010101000000101111101010011111000011100011011011010001110000111001000011110000100011100010101001011000111111111010001010111000100100000
Enter an integer i such that i > 0: 88
Enter an integer j such that j > i > 0: 89
Ciphertext: 0011001001101101000110011001011110001101011000111101111100101111001011000101100110111101110110110010001000111011110100001001111111011011010101111110100000111011000100101110111000011101110111000010111101111001010000010000010010100110110000011111101011011010111110100100111110110100010101101101100010110
Enter an integer i such that i > 0: 96
Enter an integer j such that j > i > 0: 97
Ciphertext: 0101111000100010101101001010001011100000000001101010100011100101000001101000001001010000100000001001000110110110011111100001001100101101110000101000011111101000010011100000010101111100000001111010100001011100010001011001010000110111111000001000001101111101011011101000110000001011000101101000011110101
Enter an integer i such that i > 0: 100
Enter an integer j such that j > i > 0: 101
Ciphertext: 0001010000110010101010100100101111001010001011001001110011011001110111100011110100100110111101010001100001110100110010111011101000001000010110001001111110010100001010110111100010101000101010101010000101100010100111010100010010100000010011111100011101100000100110011001011000000011010110011010001000010
Enter an integer i such that i > 0: 102
Enter an integer j such that j > i > 0: 103
Ciphertext: 0001100010101110000111001010111111101000001010000110011110000110011000101100100101110110111101110001001110100000100010001010010000011111100101111001110010010100100001001110111111101001001010000101100101111110010010101110110001000101010110100010100001111011001110010100110010111110000000101100110001100
Enter an integer i such that i > 0: 106
Enter an integer j such that j > i > 0: 107
Ciphertext: 0001010000001100111000100100000110101010110111000011100101101011000000011001101111100000010110011001010001011110010010110101100001110100101101000101010110000010001000110010000001100110100011111000100110100110100000000101100101000101101111100011011010111110010100001111011100001010111011001101010011011
Enter an integer i such that i > 0: 108
Enter an integer j such that j > i > 0: 109
Ciphertext: 0000100100111010111100100000111001110000100010100011001001100011010010100001011101111001110111001110110110111001110100111110101010110111110001011011111101001011000000010010101011111110001101011110101000001100011110111100110010001101010110001100111101001101011010110000110000001001011111111011110001010
Enter an integer i such that i > 0: 112
Enter an integer j such that j > i > 0: 113
Ciphertext: 0001111011110100110110110111011101111001010000001010100111111001100100101100111010001110101110000110000010011100001011010000100010110001000111111001101011100110101010111100010110111010100100110100010010010010001010011111111101111100000000101111000111001101010000000111111101110010101111101110000100011
Enter an integer i such that i > 0: 126
Enter an integer j such that j > i > 0: 127
Ciphertext: 0110101001010110110101101010101100101010100011000110101110010100110100110111001100001101010000110001000001001101111001001010100001000010000111000011100111101011010010000011000110000001010011110111001010001011110011000000010100101111011100010111011100001001011110010000101011100010000001000101011100010
Enter an integer i such that i > 0: 130
Enter an integer j such that j > i > 0: 131
Ciphertext: 0100101000000011100100001100100001111010110000000100100010111110010100000111001111010111110011011100100101101100111000011100100000101110010110100001010000000100111000111010010010011100010011011101011000000100101100100100110000111101111100000000000000111101111101111110001010111010101100001001101010000
Enter an integer i such that i > 0: 136
Enter an integer j such that j > i > 0: 137
Ciphertext: 0010000001101101110010000001111101111010111001111110010000000101011110100000011100110111000000010001001001000001000101011110011111110101100010101011101000111110110111000111000110110001100010111010000011111010000011010111101111011011011011110000010110001111001001110010001011011001100000011110101001101
Enter an integer i such that i > 0: 138
Enter an integer j such that j > i > 0: 139
Ciphertext: 0111011111101001101011100101100110000001111110111001111101010100011101001110100111100010110011101000010001011000001010000111101011010010010001100011111001010111100000001111111011010001000110000011001010000101000010001000010011011111001011110100100100110100001010101011100110110101011110000111111111100
Enter an integer i such that i > 0: 148
Enter an integer j such that j > i > 0: 149
Ciphertext: 0011110100000101000011101000111101011100001100010101101101101111010001001001000001111001111010111111010000011110111000110001110110011011010110110110000100001100000000001100000000011101100100110001001010010110111000111110011011010100111101110110101101000001000101000101111100110011000000010011101001011
Enter an integer i such that i > 0: 150
Enter an integer j such that j > i > 0: 151
Ciphertext: 0000100111001001111001010100101100011110110001011001101011111010001110000110111110001100110000010011111010101100100010111010100111101000001001001111000010111001110100100010111100111011111000110101111011001000110111001100000110101011011000001011001111101011101011110010111110100011101110111101100101101
Enter an integer i such that i > 0: 156
Enter an integer j such that j > i > 0: 157
Ciphertext: 0110110011111011100100010001010101001110001101000110110010100101101111011111000110010010101110100101001111000011011111001110100110111011011000010011101010111111010100111101000101101111000010000010100111010110110111001110100101111011011000001000010101100100010010000100111110011101011111011000011001100
Enter an integer i such that i > 0: 162
Enter an integer j such that j > i > 0: 163
Ciphertext: 0011101010101010010001110001110111111000111010101001001001011101010001100000101110110110100010000110010010001101011001111111111101011011110111111110100000101001011110011110110100001111001111010110111111001011111011000000100101001111101010100100101000110011010111000111001100010010100010011100000000111
Enter an integer i such that i > 0: 166
Enter an integer j such that j > i > 0: 167
Ciphertext: 0111011001001001111111001010101100101101000100011110000100100111101001011100101110101111010111011001101100101001110111101110010011100000010011100101101001001000111111001101011001011011011111011010110011100110101110001110101011001000100010000100100010001011001010011001110101111010110100010100110100001
Enter an integer i such that i > 0: 172
Enter an integer j such that j > i > 0: 173
Ciphertext: 0110011011001001100110000001111101100110010101010010010011011001100110110000111011101110100111110110011100011010001100001111100111011110111111011000111011010110100011011001100001011101010010010010000011101011010101011110000101101101100011001011100111011101111110000010000111111101101001011000110010110
Enter an integer i such that i > 0: 178
Enter an integer j such that j > i > 0: 179
Ciphertext: 0101101010000001001010000110001001111001000110000000111011010011011011110001111010101101110100100010100001110100111011101111000110001101010010111101111110111111101010101110100000000011011111100011100110111110111011101100111110101010111001101110100000000000010011111001111000010010100111010000100111110
Enter an integer i such that i > 0: 180
Enter an integer j such that j > i > 0: 181
Ciphertext: 0001010100010010010101001000010000001100000001011101100101001001111110100100010001111001101110110001110000100100100000001111111111011111001010101000110111110101011111110101100011111101111010000011101010011100110000101110001111101100100100000010111000000001100110001101011001001110001110111011010111010
Enter an integer i such that i > 0: 190
Enter an integer j such that j > i > 0: 191
Ciphertext: 0011111001100000010011101011001011111101011110100000001010010010011011010100100010000100101010111000000011101000010100100010111110110110011010100000000111011011010110001001010010001101110100100110100001101101101011000010100011011000100001111011001000100000001010101101011000111110011001011011011010111
Enter an integer i such that i > 0: 192
Enter an integer j such that j > i > 0: 193
Ciphertext: 0010001001010110101100110110111101001010000001100100001010011111101101000001001010100111101100010001110001110011010011000000111100111000000011010111111011010100111001001010100011000110111001100011101101100011110011110101100100110010111001101110001010010111110110100011001110100101001011001010100010010
Enter an integer i such that i > 0: 196
Enter an integer j such that j > i > 0: 197
Ciphertext: 0110110011001111101100100010110111010111000111011010011111100100001111111001110101110001010001110110100110010001001010111001111000001000101111111110100110100101001100101101001001110001010110101001101101101101101110110010101101011001001100010110110100111011111101001110001110010000011111111001110011010
Enter an integer i such that i > 0: 198
Enter an integer j such that j > i > 0: 199
Ciphertext: 0010111000010000110001100110001000100001011101111000001100011111000111011010101101101010001111000011010000101110011001001111000001100001100001100110011000010011110001010111000011011010111101011100010000110100111110000011001010110100101111000010111100010010001111110010101100011100011111100101100101100
Enter an integer i such that i > 0: 210
Enter an integer j such that j > i > 0: 211
Ciphertext: 0100000100000000110111111110110010001110000110001001001001001001010000000110111001000000111011000000100100010000100011111011101100101011011100001000011010000001100100110101111011011101000101101010000010010100101110011001101010010110000001011110101000001101000101011100011000001101100110110101111000101
Enter an integer i such that i > 0: 222
Enter an integer j such that j > i > 0: 223
Ciphertext: 0000101100000101101000111110110010000011000001101010111100100100000010110011110001000100110110110111101101010011101101001101010011100111000111110111110110000011110110010110000011110111011011011110100101101011011011100000010001011101000001111111111100010001111001011111101110011011100111001010100001110
Enter an integer i such that i > 0: 226
Enter an integer j such that j > i > 0: 227
Ciphertext: 0001111111000000000110011011100011011000000100100110000010001001011101110110011011010101000111100010001000010000000010011110011100010001010111110111100001110110100010100011011011000111100000110011110011100010010001011111100111110100010110110010001111000101001011010101100100111010110000101011001100011
Enter an integer i such that i > 0: 228
Enter an integer j such that j > i > 0: 229
Ciphertext: 0110000010010111110000010001110011011000100001010101011101100000110001001000100011010101011100101000010010101011011001000111001100100010001100010100100011010011011001010101110011010011001000101000011000010111010101000100000010010110001110000100110111111111000011000110010100110001010101101010110011111
Enter an integer i such that i > 0: 232
Enter an integer j such that j > i > 0: 233
Ciphertext: 0001111010111111101101000000100001000001000110100101101011001000110110000100100011110101100111110110101111000011111100101111110000011011011000101001101011100111111000010011101001000001001110001011011010011111110111100010111010100101001000110010001100101100010000010010010001011100110110111010000000100
Enter an integer i such that i > 0: 238
Enter an integer j such that j > i > 0: 239
Ciphertext: 0001110011110001101011101100111100001101001111101110001011111001101010111111011100011101100101011000001000010000010000101000010000100111011100000000100100111100010000111110100111010110001010100111011101101010110010100011010101100011010100001101101101111001011010101001010010000111001101111100100011100
Enter an integer i such that i > 0: 240
Enter an integer j such that j > i > 0: 241
Ciphertext: 0010111011111111100000001001010111101101010111011101001010001110110010001001001001011110110010000111001110011111000001001011000101111011101100011010010100110001000100100110111101001011101000010100100001010110000011010110110110011110000010010100100100000010011100011001010011000100110110101001111100011
Enter an integer i such that i > 0: 250
Enter an integer j such that j > i > 0: 251
Ciphertext: 0111100011100011100010010110101110110110000111100100100001100011111101101100010001010000101100101110101010000010100010000101111100100110000000011001010011100011101100001000001010010110001100000110110101011111000000110101111111110100011000111110100111010100111001100100000100100011001101100100001001010
Enter an integer i such that i > 0: 256
Enter an integer j such that j > i > 0: 257
Ciphertext: 0100101001011100010000010110110001111001000101110011011101100000000011011110111001110001100010001110101100000111011111000011000000111001001100011010011100100101000111010111000011110100111100100011110000001001101000110010001000100101100111111100001010000010101010111111101101100000001101101101110101111
Enter an integer i such that i > 0: 262
Enter an integer j such that j > i > 0: 263
Ciphertext: 0101100100011100001110010101100100100001010111101110100101001011001000011010110100000000100101001000001111000100011110001001010011111101001101010010100011001100000100110110101011010010100101001001000100000010110000010100000001000111000101100111111001101001001110011100111100011100100011100011111000100
Enter an integer i such that i > 0: 268
Enter an integer j such that j > i > 0: 269
Ciphertext: 0001110000011001001010010011111001111101011100111110011000011111010100110010000101111110010001001111000001101100101101001100111100010110101001100101101011101011110101011001100101000111010010111001111011111101001100001011011100111100001000001101010010111001011111110001110011100100011011100011001100110
Enter an integer i such that i > 0: 270
Enter an integer j such that j > i > 0: 271
Ciphertext: 0101010011110011101100011111000001011011011110110101011011010001111110001111100011001100001011101000010001101010101101010100100001011001101000111000101100001011110110101011010000110010101101010011101001101010001100011101000111101010010011100101111011011100010111000111110100010011010011011010001110101
Enter an integer i such that i > 0: 276
Enter an integer j such that j > i > 0: 277
Ciphertext: 0101011101110101001001011000001111110000110101111110111000011110100001001010110101110110011000100000011101000111100000100100000101111110100110001010001010010001100110001101011001101100100001010011011011001000010111000000100111100110000010000101001100101100001100001100100001110010110010010001110011101
Enter an integer i such that i > 0: 280
Enter an integer j such that j > i > 0: 281
Ciphertext: 0100100011110001001110100101110001010010001100101011001011111101000001000010010000001111101000110100111100110010010010000000101100101100110011001010010101011101001001110110101000011111100101011110011100001010110100110111100111010010111101010100101000110110100111110001100000011110101000111111011100010
Enter an integer i such that i > 0: 282
Enter an integer j such that j > i > 0: 283
Ciphertext: 0111010111111011100101000001110010100001011000101001010110111100001110010111101101010011001100101111001000010110101010011010010100110010101110110000101001001110110110010110110001100010101110000111110000001010101100110101111100111101111111001111110101000000101100001100010101000110100101011001001100000
Enter an integer i such that i > 0: 292
Enter an integer j such that j > i > 0: 293
Ciphertext: 0111101100111111100101011000000011111001101101100011110000101101001100010000011001001010011101101000011111000111101101111101110101011101111110110010001000011110000011111101100110000111011001010101111011011011100111100100010000111111110100000010100011001110110101011000111110100110110101011000010000001
flag{bits_leaking_out_down_the_water_spout}
flag{bits_leaking_out_down_the_water_spout}

alien-transmissions-v2 (crypto)

いろいろ試した結果、平文はprintableとは限らなく、意味のある文字列にもならないようだ。
以下の条件のみを使って、鍵を見つける必要がある。

・This alien language consists of words delimitated by the character represented as 481
・The two keys appear to be of length 21 and 19
・The value of each character in these keys does not exceed 255

この条件から、鍵は21の長さのものと19のものがあるため、19と21の最小公倍数が周期になる。また、481が区切り文字になっているとのことで、頻度が高く出現すると推測する。試しにindex: 0 から19*21ごとのコードの頻度を調べる。

with open('encrypted.txt', 'r') as f:
    ct = [int(code.rstrip()) for code in f.readlines()]

index = 0

codes = {}
for i in range(index, len(ct), 19 * 21):
    c = ct[i]
    if c in codes:
        codes[c] += 1
    else:
        codes[c] = 1

for c in codes:
    if codes[c] > 10:
        print c, codes[c]

10個より多く出現するコードと出現数は以下の通り。

[index: 0]
31 11
74 12
78 12
91 11
267 11
470 250
485 11

index:1, 2も同様に調べると、以下のようになった。

[index: 1]
182 12
331 11
422 246

[index: 2]
26 12
27 15
57 12
401 11
501 11
507 244

1つだけ群を抜いて多いものがあるので、考え方は合っていそう。この多いコードを481とXORしたものが鍵2つの該当するインデックス同士のXORになるはず。key1[0]が決まると、他も決まる。

                11111111112222222222333333333344444444445555555555
      012345678901234567890123456789012345678901234567890123456789
key1  abcdefghijklmnopqrstuabcdefghijklmnopqrstuabcdefghijklmnopqr
key2  ABCDEFGHIJKLMNOPQRSABCDEFGHIJKLMNOPQRSABCDEFGHIJKLMNOPQRSABC

例)
key1[0] = 'f'
key2[0%19] = key1[0] ^ X[0]
key2[21%19] = key1[0] ^ X[21]
     :
def is_printable(s):
    for c in s:
        if ord(c) < 32 or ord(c) > 126:
            return False
    return True

def get_max_count_code(ct, index):
    codes = {}
    for i in range(index, len(ct), 19 * 21):
        if ct[i] in codes:
            codes[ct[i]] += 1
        else:
            codes[ct[i]] = 1
    max_count_code = max(codes, key=codes.get)
    return max_count_code

with open('encrypted.txt', 'r') as f:
    ct = [int(code.rstrip()) for code in f.readlines()]

len_key1 = 21
len_key2 = 19

xor_key = []
for i in range(len_key1 * len_key2):
    xor_key.append(get_max_count_code(ct, i) ^ 481)

for code in range(32, 127):
    key1_0 = chr(code)
    key2_0 = chr(code ^ xor_key[0])

    key1 = [''] * len_key1
    for i in range(len_key1):
        index = (i * len_key2) % len_key1
        key1[index] = chr(ord(key2_0) ^ xor_key[i * len_key2])
    key1 = ''.join(key1)

    key2 = [''] * len_key2
    for i in range(len_key2):
        index = (i * len_key1) % len_key2
        key2[index] = chr(ord(key1_0) ^ xor_key[i * len_key1])
    key2 = ''.join(key2)

    key = key1 + key2

    if is_printable(key):
        print '[+] key1:', key1
        print '[+] key2:', key2
        print '[+] key :', key

実行結果は以下の通り。

[+] key1: `;z;/=W|`;Wn9z=|W`<dn
[+] key2: W|`;W=;k8flW9=W|`9=
[+] key : `;z;/=W|`;Wn9z=|W`<dnW|`;W=;k8flW9=W|`9=
[+] key1: a:{:.<V}a:Vo8{<}Va=eo
[+] key2: V}a:V<:j9gmV8<V}a8<
[+] key : a:{:.<V}a:Vo8{<}Va=eoV}a:V<:j9gmV8<V}a8<
[+] key1: b9x9-?U~b9Ul;x?~Ub>fl
[+] key2: U~b9U?9i:dnU;?U~b;?
[+] key : b9x9-?U~b9Ul;x?~Ub>flU~b9U?9i:dnU;?U~b;?
[+] key1: d?~?+9Sxd?Sj=~9xSd8`j
[+] key2: Sxd?S9?o<bhS=9Sxd=9
[+] key : d?~?+9Sxd?Sj=~9xSd8`jSxd?S9?o<bhS=9Sxd=9
[+] key1: f=|=);Qzf=Qh?|;zQf:bh
[+] key2: Qzf=Q;=m>`jQ?;Qzf?;
[+] key : f=|=);Qzf=Qh?|;zQf:bhQzf=Q;=m>`jQ?;Qzf?;
[+] key1: g<}<(:P{g<Pi>}:{Pg;ci
[+] key2: P{g<P:<l?akP>:P{g>:
[+] key : g<}<(:P{g<Pi>}:{Pg;ciP{g<P:<l?akP>:P{g>:
[+] key1: h3r3'5_th3_f1r5t_h4lf
[+] key2: _th3_53c0nd_15_th15
[+] key : h3r3'5_th3_f1r5t_h4lf_th3_53c0nd_15_th15
[+] key1: i2s2&4^ui2^g0s4u^i5mg
[+] key2: ^ui2^42b1oe^04^ui04
[+] key : i2s2&4^ui2^g0s4u^i5mg^ui2^42b1oe^04^ui04
[+] key1: j1p1%7]vj1]d3p7v]j6nd
[+] key2: ]vj1]71a2lf]37]vj37
[+] key : j1p1%7]vj1]d3p7v]j6nd]vj1]71a2lf]37]vj37
[+] key1: k0q0$6\wk0\e2q6w\k7oe
[+] key2: \wk0\60`3mg\26\wk26
[+] key : k0q0$6\wk0\e2q6w\k7oe\wk0\60`3mg\26\wk26
[+] key1: l7v7#1[pl7[b5v1p[l0hb
[+] key2: [pl7[17g4j`[51[pl51
[+] key : l7v7#1[pl7[b5v1p[l0hb[pl7[17g4j`[51[pl51
[+] key1: m6w6"0Zqm6Zc4w0qZm1ic
[+] key2: Zqm6Z06f5kaZ40Zqm40
[+] key : m6w6"0Zqm6Zc4w0qZm1icZqm6Z06f5kaZ40Zqm40
[+] key1: n5t5!3Yrn5Y`7t3rYn2j`
[+] key2: Yrn5Y35e6hbY73Yrn73
[+] key : n5t5!3Yrn5Y`7t3rYn2j`Yrn5Y35e6hbY73Yrn73
[+] key1: o4u4 2Xso4Xa6u2sXo3ka
[+] key2: Xso4X24d7icX62Xso62
[+] key : o4u4 2Xso4Xa6u2sXo3kaXso4X24d7icX62Xso62
[+] key1: p+j+?-Glp+G~)j-lGp,t~
[+] key2: Glp+G-+{(v|G)-Glp)-
[+] key : p+j+?-Glp+G~)j-lGp,t~Glp+G-+{(v|G)-Glp)-
[+] key1: r)h)=/Enr)E|+h/nEr.v|
[+] key2: Enr)E/)y*t~E+/Enr+/
[+] key : r)h)=/Enr)E|+h/nEr.v|Enr)E/)y*t~E+/Enr+/
[+] key1: u.o.:(Biu.B{,o(iBu)q{
[+] key2: Biu.B(.~-syB,(Biu,(
[+] key : u.o.:(Biu.B{,o(iBu)q{Biu.B(.~-syB,(Biu,(
[+] key1: v-l-9+Ajv-Ax/l+jAv*rx
[+] key2: Ajv-A+-}.pzA/+Ajv/+
[+] key : v-l-9+Ajv-Ax/l+jAv*rxAjv-A+-}.pzA/+Ajv/+
[+] key1: w,m,8*@kw,@y.m*k@w+sy
[+] key2: @kw,@*,|/q{@.*@kw.*
[+] key : w,m,8*@kw,@y.m*k@w+sy@kw,@*,|/q{@.*@kw.*
[+] key1: x#b#7%Odx#Ov!b%dOx$|v
[+] key2: Odx#O%#s ~tO!%Odx!%
[+] key : x#b#7%Odx#Ov!b%dOx$|vOdx#O%#s ~tO!%Odx!%
[+] key1: z!`!5'Mfz!Mt#`'fMz&~t
[+] key2: Mfz!M'!q"|vM#'Mfz#'
[+] key : z!`!5'Mfz!Mt#`'fMz&~tMfz!M'!q"|vM#'Mfz#'
[+] key1: |'f'3!K`|'Kr%f!`K| xr
[+] key2: K`|'K!'w$zpK%!K`|%!
[+] key : |'f'3!K`|'Kr%f!`K| xrK`|'K!'w$zpK%!K`|%!
[+] key1: }&g&2 Ja}&Js$g aJ}!ys
[+] key2: Ja}&J &v%{qJ$ Ja}$
[+] key : }&g&2 Ja}&Js$g aJ}!ysJa}&J &v%{qJ$ Ja}$
[+] key1: ~%d%1#Ib~%Ip'd#bI~"zp
[+] key2: Ib~%I#%u&xrI'#Ib~'#
[+] key : ~%d%1#Ib~%Ip'd#bI~"zpIb~%I#%u&xrI'#Ib~'#

この候補の中からフラグになりそうな文字列を選択する。

flag{h3r3'5_th3_f1r5t_h4lf_th3_53c0nd_15_th15}

worst-pw-manager (crypto)

暗号処理の概要は以下の通り。

・passwords: passwords.txtの一覧
・passwordsの各パスワードについて以下の処理を実施
 ・masked_file_name:
  c: 各文字のASCIIコード
  小文字以外:chr((c - ord('0') + i) % 10 + ord('0'))
  小文字  :chr((c - ord('a') + i) % 26 + ord('a'))
  上記を結合
  ⇒passwords/[index]_{結合].enc

Keyの作り方がよくなく、8バイトの鍵を作成しているように見えて、8バイトの最後の文字を8バイト分使っている。このため、ブルートフォースが可能。フラグ文字列の長さでどうループるするかわからないので、全ファイルについて、鍵を求めてみる。

import os
import string

class KeyByteHolder(): # im paid by LoC, excuse the enterprise level code
    def __init__(self, num):
        assert num >= 0 and num < 256
        self.num = num

    def __repr__(self):
        return hex(self.num)[2:]

def rc4(text, key): # definitely not stolen from stackoverflow
    S = [i for i in range(256)]
    j = 0
    out = bytearray()

    #KSA Phase
    for i in range(256):
        j = (j + S[i] + key[i % len(key)].num) % 256
        S[i] , S[j] = S[j] , S[i]

    #PRGA Phase
    i = j = 0
    for char in text:
        i = ( i + 1 ) % 256
        j = ( j + S[i] ) % 256
        S[i] , S[j] = S[j] , S[i]
        out.append(ord(char) ^ S[(S[i] + S[j]) % 256])

    return out

def get_password(s):
    password = ''
    for i in range(len(s)):
        if s[i] not in string.ascii_lowercase:
             password += chr((ord(s[i]) - ord('0') - i) % 10 + ord('0'))
        else:
             password += chr((ord(s[i]) - ord('a') - i) % 26 + ord('a'))
    return password

def get_key(fname, password):
    with open(DIR + fname, 'rb') as f:
        enc = f.read()
    for k in range(256):
        key = [KeyByteHolder(k)] * 8
        try_enc = rc4(password, key)
        if try_enc == enc:
            return chr(k)
    return ''

DIR = 'passwords/'

files = os.listdir(DIR)
keys = {}
for file in files:
    index = int(file.split('_')[0])
    fname = file.split('_')[1].split('.')[0]
    password = get_password(fname)
    key = get_key(file, password)
    keys[index] = key

for k, v in sorted(keys.items()):
    print k, v

実行結果は以下の通り。

0 y
1 s
2 n
3 n
10 l
11 t
12 u
13 _
14 i
15 d
16 r
17 _
18 a
19 o
20 u
21 g
22 _
23 i
24 y
25 _
26 f
27 p
28 t
29 d
30 _
31 i
32 c
33 s
34 _
35 h
36 t
37 a
38 o
39 p
100 i
101 d
102 r
103 _
104 a
105 o
106 u
107 g
108 _
109 i
110 y
111 _
112 f
113 p
114 t
115 d
116 _
117 i
118 c
119 s
120 _
121 h
122 t
123 a
124 o
125 p
126 p
127 s
128 }
129 y
130 s
131 n
132 n
133 p
134 {
135 i
136 d
137 t
138 s
139 l
140 t
141 u
142 _
143 i
144 d
145 r
146 _
147 a
148 o
149 u
150 g
151 _
152 i
153 y
154 _
155 f
156 p
157 t
158 d
159 _
160 i
161 c
162 s
163 _
164 h
165 t
166 a
167 o
168 p
169 p
170 s
171 }
172 y
173 s
174 n
175 n
176 p
177 {
178 i
179 d
180 t
181 s
182 l
183 t
184 u
185 _
186 i
187 d
188 r
189 _
190 a
191 o
192 u
193 g
194 _
195 i
196 y
197 _
198 f
199 p
200 t
201 d
202 _
203 i
204 c
205 s
206 _
207 h
208 t
209 a
210 o
211 p
212 p
213 s
214 }
215 y
216 s
217 n
218 n
219 p
220 {
221 i
222 d
223 t
224 s
225 l
226 t
227 u
228 _
229 i
230 d
231 r
232 _
233 a
234 o
235 u
236 g
237 _
238 i
239 y
240 _
241 f
242 p
243 t
244 d
245 _
246 i
247 c
248 s
249 _
250 h
251 t
252 a
253 o
254 p
255 p
256 s
257 }
258 y
259 s
260 n
261 n
262 p
263 {
264 i
265 d
266 t
267 s
268 l
269 t
270 u
271 _
272 i
273 d
274 r
275 _
276 a
277 o
278 u
279 g
280 _
281 i
282 y
283 _
284 f
285 p
286 t
287 d
288 _
289 i
290 c
291 s
292 _
293 h
294 t
295 a
296 o
297 p
298 p
299 s
300 }
301 y
302 s
303 n
304 n
305 p
306 {
307 i
308 d
309 t
310 s
311 l
312 t
313 u
314 _
315 i
316 d
317 r
318 _
319 a
320 o
321 u
322 g
323 _
324 i
325 y
326 _
327 f
328 p
329 t
330 d
331 _
332 i
333 c
334 s
335 _
336 h
337 t
338 a
339 o
340 p
341 p
342 s
343 }
344 y
345 s
346 n
347 n
348 p
349 {
350 i
351 d
352 t
353 s
354 l
355 t
356 u
357 _
358 i
359 d
360 r
361 _
362 a
363 o
364 u
365 g
366 _
367 i
368 y
369 _
370 f
371 p
372 t
373 d
374 _
375 i
376 c
377 s
378 _
379 h
380 t
381 a
382 o
383 p
384 p
385 s
386 }
387 y
388 s
389 n
390 n
391 p
392 {
393 i
394 d
395 t
396 s
397 l
398 t
399 u
400 _
401 i
402 d
403 r
404 _
405 a
406 o
407 u
408 g

{のインデックスを見てみると、以下になっていることがわかる。

134, 177, 220, 263, 306, 349, 392

さらに以下のようになっている。

flagのインデックス = (index * 8 + 7) % len(flag)

43ごとに登場するので、フラグの長さは43である。これを踏まえ、フラグを構成する。

import os
import string

class KeyByteHolder(): # im paid by LoC, excuse the enterprise level code
    def __init__(self, num):
        assert num >= 0 and num < 256
        self.num = num

    def __repr__(self):
        return hex(self.num)[2:]

def rc4(text, key): # definitely not stolen from stackoverflow
    S = [i for i in range(256)]
    j = 0
    out = bytearray()

    #KSA Phase
    for i in range(256):
        j = (j + S[i] + key[i % len(key)].num) % 256
        S[i] , S[j] = S[j] , S[i]

    #PRGA Phase
    i = j = 0
    for char in text:
        i = ( i + 1 ) % 256
        j = ( j + S[i] ) % 256
        S[i] , S[j] = S[j] , S[i]
        out.append(ord(char) ^ S[(S[i] + S[j]) % 256])

    return out

def get_password(s):
    password = ''
    for i in range(len(s)):
        if s[i] not in string.ascii_lowercase:
             password += chr((ord(s[i]) - ord('0') - i) % 10 + ord('0'))
        else:
             password += chr((ord(s[i]) - ord('a') - i) % 26 + ord('a'))
    return password

def get_key(fname, password):
    with open(DIR + fname, 'rb') as f:
        enc = f.read()
    for k in range(256):
        key = [KeyByteHolder(k)] * 8
        try_enc = rc4(password, key)
        if try_enc == enc:
            return chr(k)
    return ''

DIR = 'passwords/'

files = os.listdir(DIR)
keys = {}
for file in files:
    index = int(file.split('_')[0])
    fname = file.split('_')[1].split('.')[0]
    password = get_password(fname)
    key = get_key(file, password)
    keys[index] = key

flag = [''] * 43
for k, v in sorted(keys.items()):
    index = (k * 8 + 7) % 43
    flag[index] = v

flag = ''.join(flag)
print flag
flag{crypto_is_stupid_and_python_is_stupid}

seekrypt (crypto)

暗号化の処理概要は以下の通り。

■gen()
・alpha, beta: 1024bit素数
・mod = alpha * beta
・x: 1~modのランダム整数
・y = alpha^(bytes_to_long(flag[len(flag)//2:])<<0x1f0)
・以下の条件を満たす。
 pow(beta**2*x,(alpha-1)//2,alpha) + pow(alpha**2*x,(beta-1)//2,beta) == alpha+beta-2
・(x,y), modを返却

■encrypt()
・m: flagの前半の2進数
 x, a = x, y
・mの各bitについて、以下の処理を行う。
 ・y: 1~kのランダム整数
 ・以下の条件を満たす。
  GCD(y, k) == 1
 ・c.append((x**int(b)*y**2)%k)
  b: 0 ⇒ (y**2) % k
  b: 1 ⇒ (x * y**2) % k
・cを返却

cの配列、gen()のy、modを出力

alphaとyの関係は以下のようになる。

y: aaaa....aaaaxxxx....xxxxaaaa....aaaa
   [  128bit  ][  400bit  ][ 0x1f0bit ]

alphaの上128bitと下0x1f0bitはyと同じ。modはわかっているため、Coppersmithの定理でalpha、betaを求めることができる。

pow((beta**2)*x, (alpha-1)//2, alpha) + pow((alpha**2)*x, (beta-1)//2, beta) == alpha + beta - 2
    ↓
pow((beta**2)*x, (alpha-1)//2, alpha) = alpha - 1
pow((alpha**2)*x, (beta-1)//2, beta) = beta - 1
    ↓
(pow(beta**2, (alpha-1)//2, alpha) * pow(x, (alpha-1)//2, alpha)) % alpha = alpha - 1
(pow(alpha**2, (beta-1)//2, beta) * pow(x, (beta-1)//2, beta)) % beta = beta - 1
    ↓
pow(x, (alpha-1)//2, alpha) = ((alpha - 1) * inverse(pow(beta**2, (alpha-1)//2, alpha), alpha)) % alpha
pow(x, (beta-1)//2, beta) = ((beta - 1) * inverse(pow(alpha**2, (beta-1)//2, beta), beta)) % beta

alphaとbetaは素数なので、RSA暗号の復号の仕方でx % alpha, x % betaの値を求めることが可能。あとは中国の剰余定理でxを求めることができる。
encryptの方は、c[i]を各ビットの暗号とすると、以下の判定で0か1かを割り出すことができる。

・pow(c[i], (alpha - 1) // 2, alpha) == alpha -1 → 1
・pow(c[i], (alpha - 1) // 2, alpha) == 1 → 0
※alphaでなく、betaでもよい。
#!/usr/bin/env sage
from Crypto.Util.number import *
import functools

def chinese_remainder(n, a):
    sum = 0
    prod = functools.reduce(lambda a, b: a*b, n)
    for n_i, a_i in zip(n, a):
        p = prod // n_i
        sum += a_i * mul_inv(p, n_i) * p
    return sum % prod

def mul_inv(a, b):
    b0 = b
    x0, x1 = 0, 1
    if b == 1: return 1
    while a > 1:
        q = a // b
        a, b = b, a%b
        x0, x1 = x1 - q * x0, x0
    if x1 < 0: x1 += b0
    return x1

def get_bit(c, p):
    if int(pow(c, (p - 1) // 2, p)) == 1:
        return '0'
    else:
        return '1'

with open('output', 'r') as f:
    data = f.read().rstrip()

encrypted = eval(data.split(']')[0] + ']')
y = int(data.split(' ')[-2])
mod = int(data.split(' ')[-1])

abits = 1024
kbits1 = 128
kbits2 = 0x1f0

a0 = y & ((2^abits - 1) - (2^(abits - kbits1) - 1) + (2^kbits2 - 1))

PR.<x> = PolynomialRing(Zmod(mod))
f = 2^kbits2*x + a0
f = f.monic()

x0 = f.small_roots(X=2^(abits-kbits1-kbits2), beta=0.3)[0]
alpha = int(2^kbits2 * x0 + a0)
beta = mod // alpha
assert alpha * beta == mod

print '[+] alpha =', alpha
print '[+] beta  =', beta

flag2 = long_to_bytes((y ^^ alpha)>>0x1f0)
print '[+] flag2 =', flag2

phi = alpha - 1
A = int(pow(beta^2, (alpha - 1) // 2, alpha))
c = ((alpha - 1) * inverse(A, alpha)) % alpha
d = inverse((alpha - 1) // 2, phi)
x1 = int(pow(c, d, alpha))

phi = beta - 1
B = int(pow(alpha^2, (beta - 1) // 2, beta))
c = ((beta - 1) * inverse(B, beta)) % beta
d = inverse((beta - 1) // 2, phi)
x2 = int(pow(c, d, beta))

x = chinese_remainder([alpha, beta], [x1, x2])

bin_flag = '0'
for c in encrypted:
    bin_flag += get_bit(c, alpha)

flag1 = ''
for i in range(0, len(bin_flag), 8):
    flag1 += chr(int(bin_flag[i:i+8], 2))
print '[+] flag1 =', flag1

flag = flag1 + flag2
print '[!] flag =', flag

実行結果は以下の通り。

[+] alpha = 136437248584749771882310599149278388531535057166399265926387706469408766646754256272579824337507311270141846388413460068357591608585943215991636909883491826121544218636098300792976192313647146944748229438407801334865956608317244973051161890353895660399085055691697783021603089766899505767068206163163800347041
[+] beta  = 111465177805937770092447538469179445774366193827194740607135429566055472211468222381549404082890700206235027215272837920897816155607239237735456964466540345357023816176790307723190964931868944349012990770951977325326303518466212160620425490277981375362357314987300481362988133278120883358082360890689404217367
[+] flag2 = r3ts.....th3_fl4g_1ts3lf!!!!}
[+] flag1 = flag{y0u_f0und_m0re_th4n_s3c
[!] flag = flag{y0u_f0und_m0re_th4n_s3cr3ts.....th3_fl4g_1ts3lf!!!!}
flag{y0u_f0und_m0re_th4n_s3cr3ts.....th3_fl4g_1ts3lf!!!!}

ratification (crypto)

$ nc 2020.redpwnc.tf 31752
107077696267508129416175585963108422803463901358416542220944291963416818941164057377524278964572559510466566832891858203815902423475841414131914044575494257478490098662998784378647808956512371334406416587258923155401309634308046892117356683094976105481647263616346379311825857354314994113076534677933152952029

[1] Sign
[2] Verify
[3] Exit
1
Message: abcdefgh
4317209832999496269930676428010987925036451302344516666719893836724091562912752811969515522526275829075211015320168100805560016665826392659236144113329530741356138646197538246769827743983264745514640609231575381504240047051322250720510052676986165357464930869844787991484640238903342378801671555981006022407247710759060322443710269617148716354569798623148214519206583565919408342715247875934926504551741225536964012607663827514138005332761072495563820321919497380243941613814149924674878938338721837687076419678573780774729875739700622074607435494608607229301133683192030307384880420476045405129098639547359274760049 1445950663427396821660083035453051200028705681115648038303477382928268067472349842204582247459620393954241771526556214397547741851639280443863333114927295578079432565752908733549765360637421841102395349387009340406978651247494667862083939685607817300954481739955578931927543296090586752769733890247770956821439186382002746322468211701782389786770624548874898961793376112701070037762305420086360490078056839530888819068231283516596154905691170065421018287826546633311648909655475440645590502588711480811605808728102311295768109615441971114606243889742570722862496787138318845458688715627209297045162001266111610850209
8941915950037096606539592476544880377840131080244735613623712307828602758771909598786591379886333031504366196952470317131235860111744800380090464489403867840891929106258087389722104016811673204035008607666897176311580981080434723973891267300210754567443872393128157963497656022970232995415032196216153785700359770450789095233410624365717203933709115711213105649428630962961001027012251824539272678528973361349861713486940063638404720115862853116880374950229009289566381311632845574670561647082135829834112535966506203655723321888168042328044056351181956417760368782743712200515757755398541889381103809444775406392347
Signed!

[1] Sign
[2] Verify
[3] Exit
2
Message: abcdefgh
Signature: 8941915950037096606539592476544880377840131080244735613623712307828602758771909598786591379886333031504366196952470317131235860111744800380090464489403867840891929106258087389722104016811673204035008607666897176311580981080434723973891267300210754567443872393128157963497656022970232995415032196216153785700359770450789095233410624365717203933709115711213105649428630962961001027012251824539272678528973361349861713486940063638404720115862853116880374950229009289566381311632845574670561647082135829834112535966506203655723321888168042328044056351181956417760368782743712200515757755398541889381103809444775406392347
Verified!

[1] Sign
[2] Verify
[3] Exit

サーバの処理概要は以下の通り。

・p: 1024bit素数
・q: 1024bit素数
・n: p*q
・e: 65537

・p表示

■1: Sign
・msg: メッセージ入力⇒数値化
 messageと同じものは指定できない。
・n1: 29個の0-11のランダム整数値の配列
・n2: 29個の0-(2**(max(p/qのbit長)-11)-1)のランダム整数値の配列
・a: n1[i]*n2[i]の合計値(i: 0-28)

・enc: pow(msg, n2[i], n)の配列
・P: pow(enc[i], n1[i], p)の積
・Q: pow(enc[i], n1[i], q)の積

・b = inverse(e,(p-1)*(q-1))-a
・sig1 = b%(p-1)+[0~q-2ランダム整数]*(p-1)
・sig2 = b%(q-1)+[0~p-2ランダム整数]*(q-1)
・sig1, sig2表示

・sp = pow(msg,sig1,n)*P%p
・sq = pow(msg,sig2,n)*Q%q
・s = (q*inverse(q,p)*sp + p*inverse(p,q)*sq) % n
 →Signatureとして表示

■2: Verify
・msg: メッセージ入力⇒数値化
・sig: Signature入力(数値)
・pow(sig,e,n) == msgでチェックを行う。
・msgがmessageである場合、フラグが表示される。

Signで以下が言える。
・P = [pow(msg, n1[i]*n2[i], p) for i in range(29)]の要素の積
 → P = pow(msg, a, p)
・Q = [pow(msg, n1[i]*n2[i], q) for i in range(29)]の要素の積
 → Q = pow(msg, a, q)
・sp = pow(msg, sig1, n) * pow(msg, a, p) % p
     = pow(msg, sig1 + a, p)
・sq = pow(msg, sig2, n) * pow(msg, a, q) % q
     = pow(msg, sig2 + a, q)

s % p = sp
→ pow(msg, a, p) = (s % p) * inverse(pow(msg, sig1, p), p)
s % q = sq
→ pow(msg, a, q) = (s % q) * inverse(pow(msg, sig2, q), q)

...とここまで考えて、詰まってしまっていたが、sig1, sig2の値は使わず、\x02, \x04, \x10の場合のsigからnを算出する。あとはpがわかっているので、qがわかり、署名(=復号)に必要な情報がそろうので、目的のメッセージのSignatureを算出できる。

import socket
from Crypto.Util.number import *

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

e = 65537
message = bytes_to_long('redpwnCTF is a cybersecurity competition hosted by the redpwn CTF team.')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('2020.redpwnc.tf', 31752))

data = recvuntil(s, 'Exit\n').rstrip()
print data

p = int(data.split('\n')[0])

#### calculate n, q ####
try_rsa_sig = []
for c in [2, 4, 16]:
    print '1'
    s.sendall('1\n')
    data = recvuntil(s, ': ')
    print data + chr(c)
    s.sendall(chr(c) + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    data = recvuntil(s, '\n').rstrip()
    print data
    sig = int(data)
    try_rsa_sig.append(sig)
    data = recvuntil(s, 'Exit\n').rstrip()
    print data

diff1 = (try_rsa_sig[0]) ** 2 - try_rsa_sig[1]
diff2 = (try_rsa_sig[1]) ** 2 - try_rsa_sig[2]

n = GCD(diff1, diff2)
for i in range(100, 1, -1):
    if n % i == 0:
        n = n / i

assert n % p == 0
q = n // p

#### signing ####
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
sig = str(pow(message, d, n))

#### verify ####
print '2'
s.sendall('2\n')
data = recvuntil(s, ': ')
print data + long_to_bytes(message)
s.sendall(long_to_bytes(message) + '\n')
data = recvuntil(s, ': ')
print data + sig
s.sendall(sig + '\n')
data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

96632838554935267465023013449939167781571527340246441232587635416380685567856532206904444623615438810981777270598625763994108860362972217997828906733802442444092675741385397370855315552376601210544570668873398069407674549054039329327690668023711488128859052256881956138074848316784784838581018449365569013857

[1] Sign
[2] Verify
[3] Exit
1
Message: 
1543614857601641396621680529863184519735299074516654321453486486538502658878055644199360036067858037396308120005545113832764001986989643149384738092565269727575601538708267442096849174036499151090416000115778337003806946622913422745557209618241263175348200079654635663295075689154870712644118607993999934885951281670269812377093721751493990112692423126768779721348910822089407265637695261235726930435465217930476102772232215267783027001791803151068119912112582286869987353529156158220837195097016920349338120473269955961080574899418271801504516488435498494910157633583956302724837255663872129426865428860469176756821 4178041875918812178570678986411539481080823150893547053732111658228099563026664443932239383007607691817860595934427474376072238173974493948741894797373458650250263534438043661711384169097442788089119201310584872883498625983802721488028999208384019215001104222809750791004888552200808067704470785784898076343420488600966943327688456234468912533989736101995096936829734646802323702747979511278247360495665942040398870855636601746510568394177739390478129040338514524112266480480137249583802602465866289348354929435157077313760941800455366390821028182011487297677980300469453026811508418682246267779446975472057687630409
10198430841746618751917070406214674493789694585116304143473055701643909462887081422518110820301425785935574268567346428236570151516332479434557785924427351553002826622789631215328506021755793841556119687767934061790160246228050861925803862282275947677207606035196857619940380940046419715415998280002068788605909612764464952476774135750375335023919123610663795019118614586542869472790734107491664561168311948295440338878489216804484828541384833610066852637625544109001852771869585016904786236660175092858185271144632196840451153860009656908253884920484043416191123071532297351607822991446427224795973724161845464615206
Signed!

[1] Sign
[2] Verify
[3] Exit
1
Message: 
6660241895074592597209729594612450405564494719041974713186165851564110373995928472489991083256501688841262940484868548588928097872059039770340971383065159387656457405364742367110547001293160251014423025866044792007133579621589054523327349336866115021444057184931843119308485620454349346048596321457666219612932601600667121080067113707931724862520667308767754243105823134735738549667855477296484981314870709755938073952090063600677143988413784671364509767091588135098222925039459574533842806314025636480700009818413470662769778956765124643438919615423832091256241722852823714670463298546143334287000508475491934303737 9047004317267492738907050403532691261284390028814555531692992335633773143042066671965842401934034404910785663240917488615569303931989144087128568104950501615842481699757104961146850305154662485335829123979766040774225968729983724116218224915675780149676312901131900424052934369372032160269853830589455329760738671802022845478706281375707800521237838815039596615261113857756111857137266949718831637382976799387854653892371972412929865099673492664401918550211376012809558530960939970349376720875799516153734434864835452272991497361577691625113955721507286739300128002392320309990978092823772528546395523524414429406153
7117034537284807945742187637806026575167189721915053721598366919183855678942904354100709676706266939987239784636517792765098186691320027952760129640600043110457061247950276300699673730974142889985775745067008215978127363446244067211331065425887900476400645979318670437602368253467708451553311503194719326191064426287789511648871280741907163685803438413525611639511127857327717637478826770192926449531152248176721924066673649830894705875875821071334985547799225547429288740385677845949184073408535192433745657787749143778154225763717556041539568362882041531006931566481778379872702497773143744698911835183934554574390
Signed!

[1] Sign
[2] Verify
[3] Exit
1
Message: 
1236392049112485472517172643536022400925824772641043407869226681283042560774119392444305888650047054704048337401911085765622422384453486847807211487320808767227069132711032572035031957069494755199469374415707038584938864339351834352925345321562390601253705880053243908223973115998003254683287172055891957678792027272696235469930818794030445398520326434216211997988108139313008166153045904799327259025667875476801795432052609223536382288909786950161220724119821953712653263255077713496502531369387565996240231934338188145281857459162911394796676676744762080702873042937848289391260294968489340235226832763955766993937 10319287694575719163750057188873121584639993569361323151402585611925103396498198488162396930817472409241110504366439123512978428183667434816849513797014186591558654725044138526989795304093205689883280526867683161991263554383103619859708304278630422921788105315173783465886559986696034819853553263203730095625615750263103194955378198897745293245056477494652571985089565287694283544393377868939347171679506307362974590350460314034228146379820903299186359824847995582580032929588329824818140583079654784039728339235507614551588737423270668556403712290868286994270806660246477877145443408568383151967255368817833505707769
7087844101109445737669255068411371588031372410901195273489022792132901324468694772450118553724072462952293036192720518079266107550861167519787550247873202636828774027473029866790785047099950067875935390794167896182373511217303041510086050933697588050743726054123142838576032264384857810857400067239604522385491644685318895265892977824252941084878599232705280285081159682153518470377289902303714955226781333497310168076179517060761658871171877609122168168887479768071433684958889819037457088842714323642735945600492740626719851431296390048482411255044724888205871640312809110387883054355557516820432198690598440860105
Signed!

[1] Sign
[2] Verify
[3] Exit
2
Message: redpwnCTF is a cybersecurity competition hosted by the redpwn CTF team.
Signature: 7121897894433052450135945980027633697004175418380148075114797438722955196365495432465329167727618797456803690417832370656112287274725560957826664570839367805251208593306450954965856271388508770551551097485601353147910947150979605132009419181165996910218471209266706719702262336112947078452989375242791676184465957243264234498559486932008194584376740025075684625088082604040873796699399765134078976692826448087630242162115355375710410399345657145287118593515466876949105047559926668626521207050840120891562458958955053916638523502093610396829812656402462916651979969309839915348702683863007925295129646275119176717273
Verified!
Here's your flag: b'flag{random_flags_are_secure-2504b7e69c65676367aef1d9658821030011f8968a640b504d320846ab5d5029b}'
flag{random_flags_are_secure-2504b7e69c65676367aef1d9658821030011f8968a640b504d320846ab5d5029b}

redpwnctf-survey (misc)

アンケートに答えたら、フラグが表示された。

flag{thank5_f0r_p1ay1ng_r3dpwnCTF2020}