HSCTF 6 Writeup

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

Discord (Miscellaneous)

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

hsctf{hi_welcome_to_discord}

Hidden Flag (Miscellaneous)

pngファイルの最後にkey is invisibleと書いてある。"invisible"をXOR鍵として復号する。

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

key = 'invisible'
enc = enc[:-len('key is invisible')-1]

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

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

f:id:satou-y:20190608104448p:plain

hsctf{n0t_1nv1s1bl3_an5m0r3?-39547632}

64+word (Miscellaneous)

Base64文字が100×100に敷き詰められている。フラグがBase64で縦横斜めのどれかに隠れていると推測できる。検索しても横には無かったので、とりあえず縦上からと斜め左上からで検索するスクリプトを組む。

import base64

with open('64word.txt', 'r') as f:
    rows = f.read().split('\n')

def disp_lu_rd(rows, x, y):
    s = ''
    m = max(x, y)
    for i in range(len(rows) - m):
        s += rows[y+i][x+i]
        if len(s) % 4 == 0:
            if '}' in base64.b64decode(s):
                break
    return s

target = base64.b64encode('hsctf{')

## Vertical ##
for y in range(len(rows)-len(target)):
    for x in range(len(rows[0])):
        s = ''
        for i in range(len(target)):
            s += rows[y+i][x]
        if s == target:
            print x, y

## Left Up to Right Down ##
for y in range(len(rows)-len(target)):
    for x in range(len(rows[0])-len(target)):
        s = ''
        for i in range(len(target)):
            s += rows[y+i][x+i]
        if s == target:
            b64 = disp_lu_rd(rows, x, y)
            flag = b64.decode('base64')
            flag = flag[:flag.index('}')+1]
            print flag

左上から斜めに右下方向に隠されていた。

hsctf{b4s3_64_w0rd_s3arch3s_ar3_fu9?}

Inspect Me (Web)

HTMLソースを見ると、コメントにフラグの一部がある。

<!-- The first part of the flag is: hsctf{that_was_ -->

style.cssを見ると、コメントにフラグの一部がある。

body {
    font-family: Arial, Helvetica, sans-serif;
    background-color: #000;
}

main {
    max-width: 70ch;
    padding: 2ch;
    margin: auto;
}

/* The second part of the flag is: pretty_easy_ */

script.jsを見ると、コメントにフラグの一部がある。

document.addEventListener('contextmenu', function(e) {
    e.preventDefault();
});

// The last part of the flag is: right}

全部結合すると、フラグになる。

hsctf{that_was_pretty_easy_right}

Agent Keith (Web)

HTMLソースを見ると、コメントにこう書いてある。

<!-- DEBUG (remove me!!): NCSA_Mosaic/2.0 (Windows 3.1) -->

UserAgentをこのデータにしてアクセスする。

$ curl  -H "User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)" https://agent-keith.web.chal.hsctf.com/
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
        <title>agent-keith</title>
        <link rel="stylesheet" href="http://localhost:8002/static/style.css">
    </head>
    <body>
        <main>
            <h2>If you're not Keith, you won't get the flag!</h2>
            <p><b>Your agent is:</b> NCSA_Mosaic/2.0 (Windows 3.1)</p>
            <p><b>Flag:</b> hsctf{wow_you_are_agent_keith_now}</p>
            <!-- DEBUG (remove me!!): NCSA_Mosaic/2.0 (Windows 3.1) -->
        </main>
    </body>
</html>

レスポンスにフラグが入っていた。

hsctf{wow_you_are_agent_keith_now}

S-Q-L (Web)

問題はSign-inのぺージ。SQLインジェクションをしてみる。

Username: ' or 1=1 #
Password: a

上記入力してサインインすると、フラグが表示された。

Hello Keith!
The flag is hsctf{mysql_real_escape_string}
hsctf{mysql_real_escape_string}

Cool Image (Forensics)

pdf拡張子のファイルが添付されている。

$ file cool.pdf
cool.pdf: PNG image data, 1326 x 89, 8-bit/color RGBA, non-interlaced

pdfではなかったようだ。拡張子をpngにして開く。
f:id:satou-y:20190608112036p:plain

hsctf{who_uses_extensions_anyways}

Cool Image 2 (Forensics)

PNGファイルのシグネチャの前に以下のゴミが入っている。

I found this cool file. Its really cool!

このゴミを取り除き、ファイルを開く。
f:id:satou-y:20190608112429p:plain

hsctf{sorry_about_the_extra_bytes}

Logo Sucks Bad (Forensics)

PNGファイルが添付されている。StegsolveのData ExtractでRGBのLSBをテキストで見る。

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non velit rutrum, porttitor est a, porttitor nisi. Aliquam placerat nibh ut diam faucibus, ut auctor felis sodales. Suspendisse egestas tempus libero, efficitur finibus orci congue sit amet. Sed accumsan mi sit amet porttitor pellentesque. Morbi et porta lacus. Nulla ligula justo, pulvinar imperdiet porta quis, accumsan et massa. In viverra varius eleifend. Ut congue feugiat leo a ultrices.

Ut risus ipsum, dictum id euismod nec, mattis eu dolor. In aliquam viverra congue. Mauris lacinia lectus quis erat porttitor, vitae iaculis mauris ultrices. Donec quis imperdiet mi, et fermentum purus. Mauris rhoncus sit amet ex quis gravida. In tempor, libero vel finibus tristique, velit est vestibulum est, non semper leo mauris vel enim. Nulla non orci pharetra, bibendum quam a, pharetra felis. Morbi tincidunt, mauris nec aliquam maximus, eros justo rutrum odio, in dapibus sem arcu blandit nunc. Mauris dapibus sem lorem, quis lacinia nunc consectetur pulvinar. Donec sapien erat, pulvinar non fermentum tempor, auctor pellentesque tortor.

Suspendisse id vehicula enim. Cras ut enim sollicitudin, aliquam mauris eget, vehicula arcu. Morbi convallis sed nulla et pellentesque. Cras risus justo, fermentum eget ex ac, dictum dignissim magna. Nullam nec velit vel nulla varius gravida. Aliquam ac lorem tempor, venenatis nibh sed, ultricies urna. In fringilla hendrerit purus, tristique aliquam ipsum molestie vitae. Sed efficitur auctor lacus ac luctus.

Donec id viverra augue. Vivamus nullhsctf{th4_l3est_s3gnific3nt_bbbbbbbbbbbbb}a neque, iaculis quis urna eget, gravida commodo quam. Vestibulum porttitor justo in suscipit rutrum. Sed id tristique ipsum. Nulla vel porta nisl. Quisque leo quam, placerat id neque eu, ullamcorper facilisis lacus. Maecenas magna eros, sollicitudin id est a, fermentum elementum leo. Vestibulum porttitor urna eget bibendum interdum. Mauris eget consequat est. Aenean hendrerit eleifend finibus. Sed eu luctus nulla, non tristique nunc. Cras aliquet vehicula tincidunt. Maecenas nec semper ipsum.

Proin pulvinar lacus id malesuada bibendum. Mauris ac sapien eros. Sed non neque id ante porta finibus eget eget enim. Pellentesque placerat, neque sit amet dictum eleifend, tortor dolor porttitor ex, in vestibulum lacus tortor id purus. Phasellus varius nulla sed magna finibus aliquet. Proin eros metus, sodales vel enim eu, imperdiet pulvinar erat. Nunc quis iaculis dui. In cursus a urna in dapibus. Sed eu elementum quam. Vivamus ornare convallis leo sed mollis. Aenean sit amet nulla vel leo cursus dictum ac nec sem. Morbi nec ultrices felis.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

この長文の中にフラグが含まれていた。

hsctf{th4_l3est_s3gnific3nt_bbbbbbbbbbbbb}

Reverse Search Algorithm (Cryptography)

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

p = 29
q = 19378812610208711050554891591368513578428260883630885898953907471497427917962675301070084754463193723428901453

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

from Crypto.Util.number import *

n = 561985565696052620466091856149686893774419565625295691069663316673425409620917583731032457879432617979438142137
e = 65537
c = 328055279212128616898203809983039708787490384650725890748576927208883055381430000756624369636820903704775835777

p = 29
q = 19378812610208711050554891591368513578428260883630885898953907471497427917962675301070084754463193723428901453

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

flag = long_to_bytes(m)
print flag
hsctf{y3s_rsa_1s_s0lved_10823704961253}

Super Secure System (Crypto)

$ nc crypto.hsctf.com 8111
* * * SUPER SECURE SYSTEM * * *
My encryption system is impossible to crack if used once!
You can use this system to encrypt any of your messages with my super special key!!!
Here is my super secret message: 09321f276a3f475b137455033254233e281740131b3f024701711c2c496c030f6d5e686536496539487d692b3706715d2f5d550609

Enter the message you want to encrypt: aaa

Encrypted: 00201d

Enter the message you want to encrypt: bbb

Encrypted: 03231e

XORが固定になっているように見える。XORキーを求め、復号する。

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))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.hsctf.com', 8111))

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

data = recvuntil(s, 'encrypt: ')
try_text = 'a' * (len(enc_flag) / 2)
print data + try_text
s.sendall(try_text + '\n')

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

key = str_xor(enc.decode('hex'), try_text)
flag = str_xor(enc_flag.decode('hex'), key)
print flag

実行結果は以下の通り。

* * * SUPER SECURE SYSTEM * * *
My encryption system is impossible to crack if used once!
You can use this system to encrypt any of your messages with my super special key!!!
Here is my super secret message: 470f1d53247123393b6a2a5347551a7b5b3c5d064b4630552d7a047d6573005f48564e7252534e01596b5a364a6b6b091305396177

Enter the message you want to encrypt: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Encrypted: 4e1d1f46236b2a682d542f01426b02294f0258021944234d1c2f3a686c213e4d18471c416c411c034d58080846393f5d135d3d3f6b
hsctf{h0w_d3d_y3u_de3cryP4_th3_s1p3R_s3cuR3_m355a9e?}
hsctf{h0w_d3d_y3u_de3cryP4_th3_s1p3R_s3cuR3_m355a9e?}

A Lost Cause (Crypto)

文字列の後ろに行くにつれ、シフト数が減っていくとのことで、26パターン総当たりする。

def decrypt(s, n):
    dec = ''
    for i in range(len(s)):
        code = ord(s[i]) - n + i
        while True:
            if code < ord('A'):
                code += 26
            elif code > ord('Z'):
                code -= 26
            else:
                break
        dec += chr(code)
    return dec

enc = 'CGULKVIPFRGDOOCSJTRRVMORCQDZG'

for i in range(26):
    dec = decrypt(enc, i)
    print dec

実行結果は以下の通り。

CHWOOAOWNAQOABQHZKJKPHKOAPDAI
BGVNNZNVMZPNZAPGYJIJOGJNZOCZH
AFUMMYMULYOMYZOFXIHINFIMYNBYG
ZETLLXLTKXNLXYNEWHGHMEHLXMAXF
YDSKKWKSJWMKWXMDVGFGLDGKWLZWE
XCRJJVJRIVLJVWLCUFEFKCFJVKYVD
WBQIIUIQHUKIUVKBTEDEJBEIUJXUC
VAPHHTHPGTJHTUJASDCDIADHTIWTB
UZOGGSGOFSIGSTIZRCBCHZCGSHVSA
TYNFFRFNERHFRSHYQBABGYBFRGURZ
SXMEEQEMDQGEQRGXPAZAFXAEQFTQY
RWLDDPDLCPFDPQFWOZYZEWZDPESPX
QVKCCOCKBOECOPEVNYXYDVYCODROW
PUJBBNBJANDBNODUMXWXCUXBNCQNV
OTIAAMAIZMCAMNCTLWVWBTWAMBPMU
NSHZZLZHYLBZLMBSKVUVASVZLAOLT
MRGYYKYGXKAYKLARJUTUZRUYKZNKS
LQFXXJXFWJZXJKZQITSTYQTXJYMJR
KPEWWIWEVIYWIJYPHSRSXPSWIXLIQ
JODVVHVDUHXVHIXOGRQRWORVHWKHP
INCUUGUCTGWUGHWNFQPQVNQUGVJGO
HMBTTFTBSFVTFGVMEPOPUMPTFUIFN
GLASSESAREUSEFULDONOTLOSETHEM★
FKZRRDRZQDTRDETKCNMNSKNRDSGDL
EJYQQCQYPCSQCDSJBMLMRJMQCRFCK
DIXPPBPXOBRPBCRIALKLQILPBQEBJ

英文になりそうなものがフラグになる。

hsctf{GLASSESAREUSEFULDONOTLOSETHEM}

Massive RSA (Crypto)

nを素因数分解しようとしたら、n自身が素数であるとわかる。このため phi = n - 1 になる。あとはそのまま復号する。

from Crypto.Util.number import *

n = 950687172821200540428729809153981241192606941085199889710006512529799315561656564788637203101376144614649190146776378362001933636271697777317137481911233025291081331157135314582760768668046936978951230131371278628451555794052066356238840168982528971519323334381994143826200392654688774136120844941887558297071490087973944885778003973836311019785751636542119444349041852180595146239058424861988708991060298944680661305392492285898022705075814390941667822309754536610263449507491311215196067928669134842614154655850281748314529232542980764185554607592605321212081871630106290126123668106453941684604069442637972979374182617204123679546880646955063471680804611387541602675808433185504968764805413712115090234016146947180827040328391684056285942239977920347896230959546196177226139807640271414022569186565510341302134143539867133746492544472279859740722443892721076576952182274117616122050429733446090321598356954337536610713395670667775788540830077914016236382546944507664840405622352934380411525395863579062612404875578114927946272686172750421522119335879522375883064090902859635110578120928185659759792150776022992518497479844711483878613494426215867980856381040745252296584054718251345106582780587533445417441424957999212662923937862802426711722066998062574441680275377501049078991123518677027512513302350533057609106549686502083785061647562269181863107725160293272971931807381453849850066056697913028167183570392948696346480930400320904644898839942228059188904225142187444604612121676565893284697317106343998167640380023972222033520190994951064491572372368101650142992876761420785551386138148283615194775971673577063363049929945959258097086463812469068598955485574579363616634109593903116561526921965491646400040600138481505369027344295330767163087489333402201631708610718911106905154471963379233672543874307197342217544783263700843246351822145605839955798639016346308363889766574606793652730311687899415585873892778899179927359964882217066947566799298173326850382334054179474389651499891117938361854701587568363867264590395711833275763832842002504433841816245069655064326325306033334336469743800464944131049874472540605264250854258280373869113420817955012823462838351481855289027030577957168468047751024562853260494808998446682723835213272609799649864902376137320638444968430858790173696935815430513690803796736064125183005539073920032869713201073105497655763097638587404309062750746064609677994654409535743453776560694719663801069746654445359756195253816544699551
e = 65537
c = 358031506752691557002311547479988375196982422041486602674622689505841503255891193495423484852537391230787811575487947331018616578066891850752360030033666964406349205662189685086812466246139857474435922486026421639388596443953295273675167564381889788905773472245885677132773617051291379731995063989611049809121305468803148551770792609803351375571069366930457307762595216806633327492195442616272627113423143562166655122764898972565860928147259322712805600875994388377208017608434714747741249858321487547543201109467214209112271771033615033493406609653861223917338109193262445432032609161395100024272041503554476490575517100959892951805088735483927048625195799936311280172779052715645263075391841840633949032397082918665057115947698884582406130793211266028238396814146117158924884049679536261009188784571232730683037831940224049822081316216826346444136538278601803972530054219050666898301540575647763640218206611889707353810593843233814867745903144987805142815936160730054575462147126944741419094810558325854901931279755547624294325463528887326262902481099025253153222985717157272371423956465138892784879439141174797253720403065191378958340033965895823856879711180993895832306970105743588207727415495184380531676665121800713201192348940665501790550763379781627493441276077597720109700408848080221149485596419299548121287851605588246207568970548444975309457244824469026820421430723018384050095117420646392648577894835705672984626936461419833136418809219064810002991383584690376016818146065548853387107821627387061145659169570667682815001659475702299150425968489723185023734605402721950322618778361500790860436305553373620345189103147000675410970964950319723908599010461359668359916257252524290941929329344189971893558606572573665758188839754783710992996790764297302297263058216442742649741478512564068171266181773137060969745593802381540073397960444915230200708170859754559500051431883110028690791716906470624666328560717322458030544811229295722551849062570074938188113143167107247887066194761639893865268761243061406701905009155852073538976526544132556878584303616835564050808296190660548444328286965504238451837563164333849009829715536534194161169283679744857703254399005457897171205489516009277290637116063165415762387507832317759826809621649619867791323227812339615334304473447955432417706078131565118376536807024099950882628684498106652639816295352225305807407640318163257501701063937626962730520365319344478183221104445194534512033852645130826246778909064441514943

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

flag = long_to_bytes(m)
print flag
hsctf{forg0t_t0_mult1ply_prim3s}

Really Secure Algorithm (Crypto)

nを素因数分解しようとしたら、n は平方数(=p*p)であることがわかる。このため phi = p * (p -1) になる。あとはそのまま復号する。

from Crypto.Util.number import *

n = 263267198123727104271550205341958556303174876064032565857792727663848160746900434003334094378461840454433227578735680279553650400052510227283214433685655389241738968354222022240447121539162931116186488081274412377377863765060659624492965287622808692749117314129201849562443565726131685574812838404826685772784018356022327187718875291322282817197153362298286311745185044256353269081114504160345675620425507611498834298188117790948858958927324322729589237022927318641658527526339949064156992164883005731437748282518738478979873117409239854040895815331355928887403604759009882738848259473325879750260720986636810762489517585226347851473734040531823667025962249586099400648241100437388872231055432689235806576775408121773865595903729724074502829922897576209606754695074134609
e = 65537
c = 63730750663034420186054203696069279764587723426304400672168802689236894414173435574483861036285304923175308990970626739416195244195549995430401827434818046984872271300851807150225874311165602381589988405416304964847452307525883351225541615576599793984531868515708574409281711313769662949003103013799762173274319885217020434609677019589956037159254692138098542595148862209162217974360672409463898048108702225525424962923062427384889851578644031591358064552906800570492514371562100724091169894418230725012261656940082835040737854122792213175137748786146901908965502442703781479786905292956846018910885453170712237452652785768243138215686333746130607279614237568018186440315574405008206846139370637386144872550749882260458201528561992116159466686768832642982965722508678847

p = 16225510719965861964299051658340559066224635411075742500953901749924501886090804067406052688894869028683583501052917637552385089084807531319036985272636554557876754514524927502408114799014949174520357440885167280739363628642463479075654764698947461583766215118582826142179234382923872619079721726020446020581078274482268162477580369246821166693123724514271177264591824616458410293414647
assert n == p * p

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

flag = long_to_bytes(m)
print flag
hsctf{square_number_time}

Spooky ECC (Crypto)

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

myPubKey = g * myPrivKey
bobPubKey * myPrivKey がAES共通鍵

SSSA AttackでmyPrivKeyを求めることができれば、AES共通鍵がわかる。あとはそのまま復号すればよい。

from ecpy import *
from hashlib import sha256
from Crypto.Cipher import AES
import binascii

def computeSharedSecret(pubkey, privkey):
    return pubkey * privkey

p = 0xb09700d3d1c7123f0b0336474c18c3f3f60002d480a4bce33f007c08b498197ed832687c47c2bc76b7eb199d3a420fcf77d3e5a32389fefb1032744bb473a4bd
A = 0x1b2a886d1cfcaecd03954657956cd03df56ec7709fbb0de738fb073ed20b92b6fa3d72f771618c5e2060a23c33b586a6046993894fd4950db2c12776e77fdbd1
B = 0x303bde5e945d46949b8c9986519a9a1f0301f61ff043b3bf2785fd85e365e4caa163c64ad307db8dbbac0087fd8562273ee61aac095815030cc73c7495b46ddb
g_x = 0x9f12acd5b74cc67e03506be8f904087863ce7fd8ed1de6404f26e8e96bea3761fca1f5b21def5298e7adbbf8787ea431a43d241fda6bc9fbaddeaff35ab4f7c3
g_y = 0x51f33f0e5c36e1bf91ac78b04c7e4f819bfad8db291fc2e20c10ee00e98525927719ecf0e8b96c5e62e3f48a38b94e72dddee1109bfdad9c7dfd3f566da69eb4
h_x = 1177058043549358413014554258002815119079001682731148396776662750875463733619059415667987598866208023692880799135159888362631239206873676420277546691755222
h_y = 6042132606876152754155047441818131810928517366269481359146510190883638121779596002132009344517568983680414721512960291321687246617263491498797986759689315
flag_enc = 'd5cb4f93aa95af738bbcf5cbc1d4f1b66c9c9f84b4257035cf19e3ee41e2b79384fed7ef7d9fb58f6dfb86fefc95429b9f87b5b8a330aa082681fd140b8156bd'

F = FiniteField(p)
E = EllipticCurve(F, A, B)

G = E(g_x, g_y)
H = E(h_x, h_y)

myPrivKey = SSSA_Attack(F, E, G, H)

bob_pub_x = 0x993cf91c25dd287e30cb8f6a0d4fa70e89e90ac0953e7ee876b1ef190a6a442235479162b5ac61beb1d1a5aca03313ff5c53c2e3c81df2fbedf3b0add0b20d18
bob_pub_y = 0x4e75b39de8d5daa3f5f489c02b8fa2cce6f2cfb406bb4a5a0d75d29a3021dcd61df697ef485743e7f8a1b9cc60879bc808e74f9c909b2f0cecb1df0a03c771f5

bobPubKey = E(bob_pub_x, bob_pub_y)

DH_secret = computeSharedSecret(bobPubKey, myPrivKey)
DH_secret_str = '(%d, %d)' % (DH_secret.x, DH_secret.y)
AES_secret = sha256(DH_secret_str).digest()
obj = AES.new(AES_secret, AES.MODE_ECB)
ciphertext = binascii.unhexlify(flag_enc)
plaintext = obj.decrypt(ciphertext)
flag = plaintext.rstrip(' ')
print flag
hsctf{Anomalous curves, m0ar like anom00se curves}

Marginally More Spooky ECC (Crypto)

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

myPubKey = g * myPrivKey
bobPubKey * myPrivKey がAES共通鍵

「Spooky ECC」と同様にSSSA AttackでmyPrivKeyを求めることができれば、AES共通鍵がわかる。あとはそのまま復号すればよい。

from ecpy import *
from hashlib import sha256
from Crypto.Cipher import AES
import binascii

def computeSharedSecret(pubkey, privkey):
    return pubkey * privkey

N = 0x5f455eda519035fc8968cd1827931584553b826d33d6aa28553df93381878cc0f0d9ff60184251aa2624e10f79aa2a952a4e5ef06f03b5439af62db1cbc4832024757a21d1bdc0ceb6ac996a6c8258b2f28979f48b989bd90c30aa14a59adec286e2019bccdcae6e92fefcd7e9734b4c2f2d41489f771e58e0903e85f327c930e479c628281a5da73fd18e203f96c60a0738182ce0a137ba6c7a603f66f30e26ef37ddefd14b2787679daf8b040241fa971037b3eff67fe2f021abf62c5e765e1a8d44c62225c7768a8baa602eb06c03d2b79c7c25dc68cd2392432533bb780ba2d4b822b9098d45d28ee83e05e85fc965ef2ca6169c51b5da77a80207a7cfd4ea8471b42ae3093b29702bf62ee9fd16d97928e4da46b9f7564682ce684eab3183b232a2bf64fa9bb39a8e3e45378730432d51f67be725a7cd874c2d065dc5d0b5e8e3fd8d2aeeeb78abb837a08ca7a019e1856e43caf310176c72690bbcd20933fc48f3e3c90793a5c0ec1a5082c366524ffd30430e350079844c0588cf2497
A = 0x22f8e75e46ae5938f376ede629ae4b0c409e95df47addb399d0b7976d9127cecc21690737ff65821f6265418586861137e05c9ac1b5bab058de197b2871a8658b78d725e2a2ed195679748b8d3a01702f823a840ed8b8ab687faf75c3b25e617fd1fb746232380310a402e35ca9b3f5f261cfd4220219a7c8f8e1d8f1df1ee8172ab4096ad673179a06525e824ae63e3ebee83c86371050e805ecb919657deb1bebbf2ab786c75f65473b4c19a2a96aa5b5803eeb9883a46e97bf98d23045853fb628eb76c07936f23733e8661c080a5b09176d9d8696410a8347b4a52e5fb839db70780eecdd4453112e7310624b49ec3240c8b2a280276b409beab0765e1f220158e13e81614c927e982bf265c2626f0b8cc7300071c1b7c6ba6d09533a53c736b0890872b081759d8717964f1d7c659025f3c6b3a1bacb9dfc0847e971aa14c82d174376ddaffa598f3a54d4e2b75c07e80c6f448fbd0cdce5f52bad11adf4245b36664d9ea5a6644679ba9c17453bb7008a57a64b2e0a8527ddb81848cb1
B = 0x1fcb5c6d1ce86a8b6a23bf62b97ba31d9a5944ecc7fdc14de93b4abc62db794b7e1550ed9c2dc3501f2e6256d20e4c96fee5e3ae93069d35acee3644ec75ace6f6626f6d1ab8f48cfb8a05f6cb7409cddac6afe0762732beb1f2ad06f92738790bb805c710a574eb64ce6da4ac304a240fb783290bb30947aed2dab52344f9093067d53c83f800d25a49d263c8a20d389a850b11a4518a9d4fad16f011278617df63304a55f5d9d4c8c5866ace275faf0fcbe2003bf7ff3ae40338c889ac8bf6334ba924ce1b4e146a159453aa7a5bbb85e19932072ca23ee2680e857a713e572c9de3bf675d7f1cf3e4d9838e619558b41373b715e151f759ce721f32beb6e1f0e0b6696989370a9990d2a7653d06dc7b65af2aa90adf3ed68ce74c414066a0ed5a163b0a76e5db4259cc2d28a8de96e43fd939fb53f2a882da9e3ec983860a76607636b9885e00a6a8fb0beba28cada7882a979c5cd2c4577edd4ff5abc93d2ab53b73df724539d1c89449c98f34ee2ad33da21b97625f683ed8a33d5ac6b0
g_x = 0x3f66670d68519cbe0057246a150b34c579e34ec8880bbc4863a9e3cb4794f90ab5efaf00a9ddd323eeb3eb654e1d508be16f5ba3411ab929553fbb0b1c76e9e897055ec094d8747d5cdd47161296547442d8fd63a798d385490ea57aaa3af4af8a75a2495aeda31da47bc1a890abe142784f8743a71861a8c1aab547999acae9e6f72f320b6f550bca5222936b3cc1dfbd657c9cd655121d2a0c83047621f20e65fdba41ec098c6b51269ab8fe22938c292ae199ff49ad9afcc6e99f8d462ee0499c7e58eae6861d593426790fb6d747695e0f93dd3e00e29bb37911e88c13543467444a3ba90d7c9a4eb30aa2b7fd37fb209e034a15ff40b08ea4916311b22e54015fa1772b12dae675780a87546b8cda2bdc324be8b83a1b99a5c151339445a66a2828554b611a4257026d9c20c90617412a85f2786a45fb590c444a3c88d6b8ff38fc2e8972ebc1492c248add99c48f2ec70db4d2460da32d064d58aeeb895cf4e9a20a2b8ce12e426b3f62795adee331b1b61afa2e43884e35818ebe80d6
g_y = 0x38ba31ae0253a3a4070ef7e4380f40684f5a061f49d6591661ad5b4ff57deda46923bdc8185fcda5942f404030516ca5d1c7cf7ec9b43e4cbcdeed0296906988fa054a18d5a7f70f06692a140cf69e669884889bc778d72bd9a1e5c1dcdfba16121461a221dcdac7287ad5b6d3710c00fd100ef89c038baf23c621766e470501aa86de194539fb087dddc3ad5c0f3c78a79d0f4a981850af7c3cb86f392286fe075b10f5761d923cdfcd92cc1017bdee4e83ac64692ac76c40057735122813b2003b19422dc3adaf0f502eb254685ae88161fbde92027d8f419f4f939c988ee7ec34a05736e105d647baf2b84304caf006f39f85096419a11801f2402e02791f3d9813bdd50d8a0a7aaeade853d7b17e75f68612467cc59f7ec3e63ddb3551a697ba02f772671c4569acd5edec0e1e8e6f73fcb032d99789cefb572deb8b6ff330ddd48a2bcf77b47862925a155670679fc9acfd7900d4250a20821eb52a86819daec526f31bfd27cc26d46dfe71da188efde1cbdb115b2cacd910f3f4fb0c63
h_x = 437071643139846376174570991796635821556515973629140637974881910713809347474907708565664978550023080253628563436981461136240187164218943955473906962427621588751133571536263233128379933305722755097642938222821729992112928292343709506067984904756673958537023071586963031303778873355502404560858525640218412720622373369824098745839367743073545069145335781750997022711031566712394148013463290094808515199272554914216404105860245097476566116111286301652851468677715923578954629435631529176601375057076486686319987081515732244810707537343009005070717978425223526163538923468401194292605591320411183706696317193017854195733313461440688247150235910596818920488351049708819811858751684500436391333903440323475318106920865373152352052176746206454328646354342334742517809741676585846785744248199296743482652484393544744906275391431743950732816017334306485823146135060569081401399868784435172595669863476450094990358575115579475893309208
h_y = 1129749802565185627834158659553807502912216175360213456254075674481088988433443479576096556714622648959392819034084284852916959478876546195923213995294956323268527231581766047828610029859113248478558662868743044337554958806463167785068464444239137312628465183766940740668064934990938102926858847015457403169279134366635216151257462869638958624971531184853170344683049422552732473598742118914767190141609028327074078277290367090610634101108300855280065814455390630761148497086654130386459756495733281280347492148461347415812198075975619307315113752254659557316385115639576216222522363256407482949179689085285199590385738252375535519944626298197399005839337752193084119312960497435211490324941382907224728563381320712225158253541488668785632485406927982563839147149734593198947641619638737854288142722191014592471804685884172858025758753635315661266804801339190058215957655776800114139349071970424218949196308458641913657267781
flag_enc = 'f84a130d288fd200e5564253a7ea34e7dda3ccd28f18440fa06c92a3076ccc6746b8b95734c87177e2cc8759e0b00365'

F = FiniteField(N)
E = EllipticCurve(F, A, B)

G = E(g_x, g_y)
H = E(h_x, h_y)

myPrivKey = SSSA_Attack(F, E, G, H)

bob_pub_x = 0x35c7220105e55ae41a7098f528d4b25a4fb9840bae5e1489645be43d3d76853160ddc9afe04a53aef2b400f85b91272e71941c192cf49cbe2b4f73ce8e715da1986e40253eea400ef7b0e6c60aee5cd6984d29bcdd32a53cec2f47fd0f30d4fdf2f46c59a46d2d54c7766558c318230d4265d25ee72b6d8eff54403f36db684236a80dca118d464bd31eff3cb3a30fdd30c6924100960b8fbda2f6b64e7a04332b2ff481788e9ef26516d21d4b10afbbb59519c0bab71d84ff2df56cf29756e169a61a54800761ac4f9ef562f685ec004ff5c26917e28d914c8f3274f9effbc388c8151e46b490256325d9843d1d09f17059bcad949e75ffaa30027d13fcf169689c84f67693d0f12d8ec46a4bda3c9f8e0f61edd1c1525e0b55bf879ec6b3c53c45bc6f76a705de7554a40717e36150ba44ec1a52ae98587055129a02d211da8d18c74f0b69edb020d89325c1a41cdacdc4a7609527b6791407e2a2e79b8f0eb8f581f3317c47eb6a1afda3f8888b3580e4552ed5ab0030487b77b3e87db495
bob_pub_y = 0x17ab49ada83cbac774f8e9d48a9190ce2cde27d20981894526a4f7a151863a78c791d3cabcbe2d720fe9ae75549b685d5d068d61cfc31725ea3e1ee62417e977024e069d5f559c0e706ddeec7609a0ded60b694f638911996b872715ef0aca5b6d0b6652991bd37163885a60842e009794c03a56de47f107ae1b9c3de750d7e479c30836bdbc72f206991388812ace1dc11f03b5e9f96d5f3b80464389d9f137b62ea6d063b866424a4b04605fa2e7c9e2816fe19f98cbafed371711fc0923a234c194996004cf1fae0934a96d54f3dde1aa6d6fe68e84cb1ad2795b969b36b333cae0ac82c4010c12ffcedffc670859135ad0058ffff60f511946e44bc8f5295e85798c0466b2fc89a252797d65a338b37151385355b89adf70f2014667f1374c1508f30165e8b16bf9fd9f789499438db5fa725769a73844306afe2a99344c9fac0954bf3355318b0ba8283c9b45a29714968ee6b05cb381ecf6282d5ee27a4e57a9a646b87661fe3f605228d2326903051a32a3470515a40463d5084b614

bobPubKey = E(bob_pub_x, bob_pub_y)

DH_secret = computeSharedSecret(bobPubKey, myPrivKey)
DH_secret_str = '(%d, %d)' % (DH_secret.x, DH_secret.y)
AES_secret = sha256(DH_secret_str).digest()
obj = AES.new(AES_secret, AES.MODE_ECB)
ciphertext = binascii.unhexlify(flag_enc)
plaintext = obj.decrypt(ciphertext)
flag = plaintext.rstrip(' ')
print flag
hsctf{Y_does_4lice_have_such_weird_cuRV3s?}

Tux's Kitchen (Crypto)

$ nc crypto.hsctf.com 8112

				TUX's KITCHEN
                    ..- - .              
                   '        `.           
                  '.- .  .--. .          
                 |: _ | :  _ :|          
                 |`(@)--`.(@) |          
                 : .'     `-, :          
                 :(_____.-'.' `          
                 : `-.__.-'   :          
                 `  _.    _.   .         
                /  /  `_ '  \    .       
               .  :          \   \      
              .  : _      __  .\   .     
             .  /             : `.  \    
            :  /      '        : `.  .   
           '  `      :          : :  `.  
         .`_ :       :          / '   |  
         :' \ .      :           '__  :  
      .--'   \`-._    .      .' :    `).  
    ..|       \   )          :   '._.'  : 
   ;           \-'.        ..:         / 
   '.           \  - ....-   |        '  
      -.         :   _____   |      .'   
        ` -.    .'--       --`.   .'     
            `--                --    
[94502238958180, 3239939113188L, 36316791069768L, 74074574741772L, 66168572136316L, 80623467427418L, 75026654356284L, 50623013930716L, 14521993191832L, 1043830470864L, 9198516838638L, 12614129459328L, 19390428682606L, 50551489441974L, 23163695523340L, 32930787907352L, 64273717132804L, 2308552454540L, 23927252424676L, 4912213340334L, 48608335665180L, 17825781568022L, 59492604464762L, 61049515860332L, 28121911611052L, 70718923063032L, 6188788875442L, 50884233066568L, 50785141535028L, 38001261855484L, 9087790989292L, 10639550205734L, 6534967064988L, 25391516747560L, 33768565198062L, 16229074586954L, 8835287258924L, 10506577178492L, 9979169202152L, 14220693695642L, 41247903800840L, 41507250686812L, 1601286609988L, 70083909145228L, 31814590623406L, 50377900745900L, 14912013039884L, 35580271413072L, 11077521806466L, 53051496283116L, 18090007827476L, 38902288369748L, 24119603003596L, 26321069617516L, 27262655778060L, 29165495157296L, 28788848037938L, 31099248532660L, 5497383893232L, 48470151532048L, 25946791922962L, 25460577127462L, 24691906525312L, 21699741615156L, 30529196924104L, 5142675176780L, 56902352320640L, 24695196850078L, 16999993798690L, 65447783457532L]

スクリプトの処理概要は以下のようになっている。

■key = bake_it()
・10000以上99999以下の回数だけ以下実行
 s = random.randint(100000000000,999999999999)
・s -= random.randint(232,24895235)
・random.randint(100000000000,999999999999)を返却

■final_baking(flag,key)
・baked = rand0m_mess(food,key)
 mess = [key]
 (foodの長さ-1)回以下実行
 ・a=(a*b+c)%d
 ・messにaをappend
 messを返却
・treasureにflagの長さだけ以下をappend
 ord(flag[i])*baked[i]
・treasure = prepare(treasure)
・treasureを表示

ランダム値は何になるかはわからないが、prepare前のtreasureは算出できる。また、prepare前のtreasureの各要素はord(flag[i])*baked[i]になっているため、必ずord(flag[i])の倍数になる。この値を取り、最大公約数を取れば、フラグの各文字のASCIIコードになる。

import socket

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

def rev_prepare(food):
    org_food = food
    for i in range(len(org_food)):
        org_food[-1] -= MY_LUCKY_NUMBER
    for i in range(len(org_food)):
        org_food[i] = org_food[i] ^ MY_LUCKY_NUMBER
    return org_food

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
    gcd = b
    return gcd, x, y

MY_LUCKY_NUMBER = 29486316

codes = []
for i in range(10):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('crypto.hsctf.com', 8112))
    data = recvuntil(s, '--    \n').rstrip()
    print data
    data = recvuntil(s, ']')
    print data
    treasure = rev_prepare(eval(data))
    if i == 0:
        codes = treasure
    else:
        for j in range(len(codes)):
            gcd, _, _ = egcd(codes[j], treasure[j])
            codes[j] = gcd

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

print flag

実行結果は以下の通り。

    :
                                TUX's KITCHEN
                    ..- - .
                   '        `.
                  '.- .  .--. .
                 |: _ | :  _ :|
                 |`(@)--`.(@) |
                 : .'     `-, :
                 :(_____.-'.' `
                 : `-.__.-'   :
                 `  _.    _.   .
                /  /  `_ '  \    .
               .  :          \   \
              .  : _      __  .\   .
             .  /             : `.  \
            :  /      '        : `.  .
           '  `      :          : :  `.
         .`_ :       :          / '   |
         :' \ .      :           '__  :
      .--'   \`-._    .      .' :    `).
    ..|       \   )          :   '._.'  :
   ;           \-'.        ..:         /
   '.           \  - ....-   |        '
      -.         :   _____   |      .'
        ` -.    .'--       --`.   .'
            `--                --
[81118554797092, 7547416817262L, 13924726641214L, 24608708806052L, 20427372177504L, 4752740762539L, 25685977718996L, 6587661423732L, 6387324995677L, 2779701188569L, 1996595265884L, 10244439233919L, 22440974883832L, 17437990453970L, 4906410834476L, 4633172239142L, 10569490399219L, 6343329221262L, 14609369031062L, 4042647881186L, 23115014471738L, 8643276090734L, 14351992012611L, 20538335765384L, 5654620504828L, 22864776681506L, 9808285250767L, 21882865717333L, 8401998681094L, 20393585938440L, 4493085708140L, 12732130156075L, 18738761835793L, 18689672713854L, 6832347691292L, 12320314719526L, 5600302004409L, 12692625054340L, 20271109605100L, 9486494930594L, 14858167076081L, 10711897536764L, 6740004248652L, 7064890768756L, 10955238662235L, 9420096213164L, 1695027316220L, 8815883981882L, 3359624516498L, 3210261582694L, 4838126713825L, 5415903477176L, 1430472167156L, 16972867365502L, 14937265628996L, 353527285145L, 3861324095989L, 5791399138428L, 16645079816928L, 5130270927668L, 1659285419958L, 1903779832800L, 15454714302078L, 2270784256068L, 11695285242083L, 648658065248L, 8724789270003L, 1406023999045L, 2169124259302L, 1943044899939L]
hsctf{th1s_1s_0ne_v3ry_l0ng_fl@g_b3ca8s3_t5x_l0v3z_vveR9_LOn9_flaGs7!}
hsctf{th1s_1s_0ne_v3ry_l0ng_fl@g_b3ca8s3_t5x_l0v3z_vveR9_LOn9_flaGs7!}

Survey (Miscellaneous)

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

hsctf{come_back_next_year!}