yoshikingのがんばる日記

あたまよくないけどがんばります

SECCON Beginners CTF 2019 Writeup

 5月25~26日にSECCON Beginners CTFが開催されてました. チームzer0ptsで参加し、見事1位でした. チームメンバーのスピード感にあたふたしながらも、何とか数問通したのでWriteupを書きます. f:id:y05h1k1ng:20190526150254p:plain

チームメンバーのWriteup

st98: Beginners CTF 2019 の write-up - st98 の日記帳

theoldmoon0602: SECCON Beginners CTF 2019 writeup - ふるつき

ptr-yudai: SECCON Beginners CTF 2019のWriteup - CTFするぞ

[Crypto 363pts] Go RSA

Nだけなくしちゃったんだよなあ……。

 とりあえず、ncしてみます.

$ nc 133.242.17.175 1337
Encrypted flag is: 6344991311564553615862579427487315421208055634102890395723986371495652609153052697621268167305282339617530377087384855394685474792773022115680540686568501138450681688735527617827708821485497498334547179214866381804619441945049231222689303859605328356743173601997078352973035701358512748861024520717173066208645110545270222021655297034426926498311814336661104067007494662082645957734853033496598300417493177589227972753784432427753861158326507152049357862231911441535352804653810629357318640120796228696711675902539564632797542696587638137206651220915784909017728259256279217121403410183718987376151252076850594986072
> 0 
0
> 1
1
> 2
2862334794876318566324057598241408128109425191172133981033760448232814429877972087723511977245286558645814682054000700802565238541629306735791660770705209092054679971683689343593450904080873595244990490120345136595441331711791642822309784005850295255019360549477080451991452042485726954377888628611850312169956235832476482473468997735379482200368532387100203433537314371261639774070163736423425627779689468867325590663448606913878199332557603250135695359944006132143818989945004067114026488158760762115016145779669731641814525334761633123615342046269898802364403424297888529318077961694410182680067006220851010487693
The D was 3108589354283999881366977377816211791659702282566657492492997508648885943813044323050780847180267937096874217339239440259051280553557374969326192368619436355830441614153601856008410159305941711348272515678361389635638005453913489251292139406829869123083572863219302494814837811525563431399822598189396464260524809835126230568531180443134269028794046517626742952434891439389309802663719183434506260830073832328429505252129371886238807490334805430087834068647490477751392145402285002619521810094785728754166749922294644025726513925553921296219135200362480519946364396480504261544279372784914298890836180406341120859329

 数字を与えたら何か返ってきます.また、Encrypted flagDがもらえます.RSAと言われているので、返ってくる数字は


c = (input\ number)^e \bmod{n}

と考えられます.

 残るnさえ見つければ、復号できます. となると、mod演算の力の見せ所です...! mod演算は大雑把に説明すると、余りのことでした. 具体的に小さな値で説明すると、


10 \bmod{8} = 2

となります.つまり、0~7の値ですべての数字を表します.ではマイナスの値はどのように表せられるでしょうか. なんと、


-1 \bmod{8} = 7

となります!!! 詳細な説明はGooglemod 数学とかでググってください.(説明めんどう...)

 ここまでで、-1がn-1になることがわかりました.あとは、Encrypted flag, D, nから復号するだけです.

$ nc 133.242.17.175 1337
Encrypted flag is: 8574265495326376630715344864118702269699156118364751300483334371118983366068335837878430692194643907630947760218074636257962213901840959279695171778233952421546225414267130705377041788556040425374281913702704126363017674911378922866975795108524827197944518379304446564136766368478442131132639926373420800112390754225415097241757980287552353646752237359721950559438294762549429323083064086759103892170016208312683627723372030448129192438463592881852579263558462628295396255591387527275622328216850681535962245066287633466061728308482282796879985854086150426339364856915080205049371087944085742585047633265078786916717
> -1
15542669559227225429825537324581227774031891481936836236023168265768560509534175413897898039939875309341780656581069256476153063968087844810314599683067761887287458414581491790878409323665908229753209802327406269329874867875899296307778465317869542704169327492799825878469046825297855569668076456765118516134730535748246251497708000239072261510836367562449392851385927337215223745929318252139726812616575352609129732978704075275309551532205839627157499897379612485885734926354947463132399491683701371211067204644701324764499164101507557096214031191342098432721010724037945643454866504810914319842027997822183833426928
> 
Bye
The D was 11294445810590008451256715894011877130636049863981565968908667859208720657125830750743450207578873334636815264492070773310043387985660245681773997822701971285230906503746417520618785810004504532306435504005987399035139855466710836433795285598947451084782032325512289357709536384149184028104314710422845174670617305707095050004395521134314125412593577026243869778911744982261668051428824513145971177432162816223685859285472240021048696838191250769292549473790421401957500586651833875804831485999431831427601391163986595878453821597916628888747151831289612576792460488564806552328452459557394329005245982294646297165825
$ python3
Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from binascii import unhexlify
>>> enc_flag = 8574265495326376630715344864118702269699156118364751300483334371118983366068335837878430692194643907630947760218074636257962213901840959279695171778233952421546225414267130705377041788556040425374281913702704126363017674911378922866975795108524827197944518379304446564136766368478442131132639926373420800112390754225415097241757980287552353646752237359721950559438294762549429323083064086759103892170016208312683627723372030448129192438463592881852579263558462628295396255591387527275622328216850681535962245066287633466061728308482282796879985854086150426339364856915080205049371087944085742585047633265078786916717
>>> n_minus_1 = 15542669559227225429825537324581227774031891481936836236023168265768560509534175413897898039939875309341780656581069256476153063968087844810314599683067761887287458414581491790878409323665908229753209802327406269329874867875899296307778465317869542704169327492799825878469046825297855569668076456765118516134730535748246251497708000239072261510836367562449392851385927337215223745929318252139726812616575352609129732978704075275309551532205839627157499897379612485885734926354947463132399491683701371211067204644701324764499164101507557096214031191342098432721010724037945643454866504810914319842027997822183833426928
>>> n = n_minus_1 + 1
>>> d = 11294445810590008451256715894011877130636049863981565968908667859208720657125830750743450207578873334636815264492070773310043387985660245681773997822701971285230906503746417520618785810004504532306435504005987399035139855466710836433795285598947451084782032325512289357709536384149184028104314710422845174670617305707095050004395521134314125412593577026243869778911744982261668051428824513145971177432162816223685859285472240021048696838191250769292549473790421401957500586651833875804831485999431831427601391163986595878453821597916628888747151831289612576792460488564806552328452459557394329005245982294646297165825
>>> flag = pow(enc_flag, d, n)
>>> unhexlify(hex(flag)[2:])
b'ctf4b{f1nd_7he_p4ramet3rs}'

フラグゲット!!!ctf4b{f1nd_7he_p4ramet3rs}

[Crypto 393pts] Bit Flip

平文を1ビットランダムで反転させる能力を手に入れた!

 ソースコードも渡されます.ソースコードを読むと、問題文通りのRSAです. e = 3 は明らかにおかしい(通常はe = 0x10001)ので、low public exponet attack等をやってみますが、条件に合わないのでうまくいきません.

 うーん、これは困りました... いったんe = 3から離れてみましょう.

 ncしたとき、

$ nc 133.242.17.175 31337
11545705109146803081154196731091553481494291928457261149212388528068058378823269333768320005182187108983022445099553663343177812738205610210357260446050457617731702932090378720710803576264258475457572522292489169532629163257089936346472604268088528122978005890263575400712331754280140566518723346561592384959

というふうに、平文をランダムで1ビット反転したものの暗号文がもらえます.再度ncすると、違う場所が反転されたものの暗号文です. となると、1ビット反転後の平文をm'としたとき、m'1m'2はほとんど同じ平文であることがわかります.

 RSAでbitがわかっている(今回はわかっているとは言えない)ときの攻撃といえば、Coppersmith's Attackです. なんか、今回の条件に合う攻撃なかったかな~と調べていると、

inaz2.hatenablog.com

 ありました!!!!Coppersmith’s Short Pad Attack & Franklin-Reiter Related Message Attack(長い)みたいです!!! 攻撃条件は

二つの暗号文について平文の上位bitがnのbit数の (1-1/e2) 程度共通する場合、これらからそれぞれの平文を求めることができる。

みたいです.今回はe = 3、nのbit数が1023bitなので、平文の上位bitが967bit同じ平文m'1m'2を用意しなければなりません. これはあまり難しくなくて、1bitしか変わらないので、いくつか暗号文を用意すれば上位bitがほとんど同じペアがあります. ただ、暗号文からどこのbitが反転しているかはわからないです. そのため10個程度暗号文を用意し、数値が近いもの同士で攻撃してみます.

def short_pad_attack(c1, c2, e, n):
    PRxy.<x,y> = PolynomialRing(Zmod(n))
    PRx.<xn> = PolynomialRing(Zmod(n))
    PRZZ.<xz,yz> = PolynomialRing(Zmod(n))

    g1 = x^e - c1
    g2 = (x+y)^e - c2

    q1 = g1.change_ring(PRZZ)
    q2 = g2.change_ring(PRZZ)

    h = q2.resultant(q1)
    h = h.univariate_polynomial()
    h = h.change_ring(PRx).subs(y=xn)
    h = h.monic()

    kbits = n.nbits()//(2*e*e)
    diff = h.small_roots(X=2^kbits, beta=0.5)[0]  # find root < 2^kbits with factor >= n^0.5

    return diff

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

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

    return -gcd(g1, g2)[0]


if __name__ == '__main__':
    n = 82212154608576254900096226483113810717974464677637469172151624370076874445177909757467220517368961706061745548693538272183076941444005809369433342423449908965735182462388415108238954782902658438063972198394192220357503336925109727386083951661191494159560430569334665763264352163167121773914831172831824145331
    e = 3

    nbits = n.nbits()
    kbits = nbits//(2*e*e)
    print "upper %d bits (of %d bits) is same" % (nbits-kbits, nbits)

    # ^^ = bit-wise XOR
    # http://doc.sagemath.org/html/en/faq/faq-usage.html#how-do-i-use-the-bitwise-xor-operator-in-sage
    cs = [77806872332913639919230209971392238784617993613323608240759820467908361781292069393342282547351581556259586998986092213607990761433134090374312820694026772204652782705492033343505430039323127158238332166350733150021228707945218465461966055458055161585955918733260995686334094638272681504698713633622376505308, 56989538367235158070306311186976292179966897528478291741508067866076558453602047302097966694208295312681095728980453463065836403911062093169223760418437322965770764311509640241287759696024373113722137027468951246866660964543912817862578633166333098878995510302628735250428938293637106737039139535160299108113, 38904877077171263737628178288521508189937409452080551772429415381447030724554764139002760866443078904692197281533309765344183894882142747076974754239070945859011211448240209079404207383248263468302174482960469183459600520739134108565937096269114702664072319462367117303477702692144066942049118080262294258198, 18583489730966619030615979926193288458958202730544958951381254155250349562324597989826437296289617404778761642054183547194844953317251480423608095521453337512728025268903153005408483464432086619556754592849674435698214322639172504375579000690270700946296005084794493004273617912360198409988034062432904201443, 81779690030003209255009995980102852322918673284543406574532267172257453562542775941820716471921905724303767155906053394193722593095884543297184318525481682039383393411599467185668595266012433381398851647598176014943130868710424785320701066749455904911769968456600407617618999332917394004530335428836578511038, 32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587, 74515903266795492985898471025229269878024376884435233684330662967167738131179553721410985213658229983853042260704757838616925556197183464709236532593823846170499630895374282114622487171170087091856753282020369482187351762243468042340933214874709271883018014631321412057529269400452647011517326283977015327189, 50884193811664497731364349812345616105175266569747833161903539901598152530392727464246077616701699644190582339965644325919604108036097223534586827791663822181563764715514302285487273629970687924833993670021557569304506460830014722740930334310623881775573664519736313757433300737631028708325665330938763782184, 32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587, 32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587, 70349274946614957759744006616813137783981786796010483575643371633588262711107346355531982812397035546281065385276548490062296856185344260769924218825995217554937441693054306002310733683884013698358767818115213188542062367075206824218550649564035135625128570873259781498669780078490598700442802349177736369712, 14980967781796819388041767887889903216468297576583006138007297644760691492596305457996725733919525577152256022483859011858574079640555374613247881143820771398254213825665880164126364722955374272148086280616213121922743671360167002526131898166108921720900263044330025216410582216554968042705705297554547422768, 20084571405797864822888728924121156713191530288959443915037367599696984039639335435370481551716134617000168582476618945013400480262866044903717028607042509827672584798897176555204805945259386570000183369487279952176022447143620009290796257006795499399194469035408992268017445449883256724883866657842304577341, 82212154608576254900096226483113810717974464677637469172151624370076874445177909757467220517368961706061745548693538272183076941444005809369433342423449908965735182462388415108238954782902658438063972198394192220357503336925109727386083951661191494159560430569334665763264352163167121773914831172831824145331]
    cs.sort()
    for i in range(len(cs)-1):
        c1 = cs[i]
        c2 = cs[i+1]
    try:
            diff = short_pad_attack(c1, c2, e, n)
            print "difference of two messages is %d" % diff

            m1 = related_message_attack(c1, c2, diff, e, n)
            print m1
            print m1 + diff
    except:
        pass
$ ./sage attack.sage
upper 967 bits (of 1023 bits) is same
difference of two messages is 0
32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587
32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587
difference of two messages is 0
32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587
32723890881319186547872779402620483902697729020200348166442392175021912171894118652683887146846612929006547793375263509134656509739561177352356684588019934405564505733524922144146700314897913117036840607504607821666469911969838394487387376073261438777475081050957502547204126815797206281111078395092049286587
difference of two messages is 82212154608576254900096226483113810717974464677637469172151624370076874445177909757467220517368961706061745548693538272183076941444005809369433342423449908965735182462388415108238954782902658438063972198394192220357503336925109727386083951661191494159560430569334665763264352163167121773914831172831589264307
16260765149986038884145173876068642724013617302097779293079362876653494069932815072038851668676222848467504538570853507159925860036819304291732134150397319327193122637750054910716746167965635612837962028769149915298230040116567157454495798898178036434538204980608594381468821524975316356796051708170
16260765149986038884145173876068642724013617302097779293079362876653494069932815072038851668676222848467504538570853507159925860036819304291732134150397319327193122637750054910716746167965635612837962028769149915298230040116567157454495798898178036434538204980608594381468821524975316356795816827146

 m'1m'2が同じになってしまうペアがあったようですが、1つうまくいってます. ただ、これはどこかのbitが反転されたものなので、雑プログラムで復号します.

from binascii import unhexlify

m = 16260765149986038884145173876068642724013617302097779293079362876653494069932815072038851668676222848467504538570853507159925860036819304291732134150397319327193122637750054910716746167965635612837962028769149915298230040116567157454495798898178036434538204980608594381468821524975316356796051708170

for i in range(0, 30):
    r = 1 << i
    flag = m ^ r
    try:
        print("[+] {} : {}".format(i, unhexlify(hex(flag)[2:])))
    except:
        pass

 0~30(適当)で雑に調べてますが、特にエラーなく出力されたのでその中で1番うまくいっているのが、

[+] 28 : b'ctf4b{b1tfl1pp1ng_1s_r3lated_m3ss4ge} DUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMYDUMMY\n'

でした.後ろにDUMMYが入っていたんですね. これでフラグがとれました!ctf4b{b1tfl1pp1ng_1s_r3lated_m3ss4ge}

終わりに

 初めにCryptoのWarmupからやったのですが、全然解けなくて死んでました... theoldmoonにヘルプをだして解いてもらいました... そのときは、Warmupすら解けないの終わりでは...?と思いましたが、結果、きちんと仕事を果たせてよかったです(ほんまか).

 去年はCTFの存在を知っている程度のbabyで、linuxわからない!って感じで何も解けなかった記憶があります(笑). そう考えるとCTFを初めて約1年でよくここまで成長したな~と思います.

 まだまだ、わからないことがたくさんあるので、今後も精進していきたいです.

 最後になりましたが、 チームメンバー、運営・参加者の皆様お疲れさまでした. ここまで、読んでくださってありがとうございます.

angstromCTF 2019 Writeup

 4月20~25日にangstromCTFが開催されてました. チームzer0ptsで参加し、3730点で8位でした. 僕個人は、MiscとCryptoしかやってないです.

 今回は結構たくさんの問題を解くことができたので、うれしいです. Miscの簡単な問題を除いて以下に、Writeupを書いていきます.

チームメンバーのWriteup

theoldmoon0602 : ångstromCTF 2019 writeup - ふるつき

ptr-yudai : angstromCTF 2019 Writeup - CTFするぞ

st98 : ちょいまち angstromCTF 2019 の write-up - st98 の日記帳

[Misc 40] Paper bin

defund accidentally deleted all of his math papers! Help recover them from his computer's raw data.

 paper_bin.datというファイルが渡されます.

 recoverしてくれと言われているので、拡張子をpdfに変更してみます. 普通にpdfが見れるのですが、pdfの中を検索してもフラグが一向に見つかりません. しかし、foremostをするとpdfの中に20個ほどpdfが隠されていることがわかりました.

$ foremost paper_bin.dat  (pdfからでも取れます)
Processing: paper_bin.dat
|*|
$ cd output/pdf/
$ evince *

 雑にpdfを開けて、1つずつactfで検索するとフラグが取れます.

actf{proof_by_triviality}

 この問題は、10ページのpdfに対してサイズがやけに大きいことに感づくべきで、初めは全然気づかなかったです. 実ははじめforemostをpdfに対してしたけど、cd output/を見てpdf以外なんもないじゃんって放置してました... 気づくまで、ddとかで空白を消したりしてました(ddコマンドの練習にはなった...).

[Misc 60] Lithp

My friend gave me this program but I couldn't understand what he was saying - what was he trying to tell me?

 lithp.lispというファイルが渡されます.

;LITHP

(defparameter *encrypted* '(8930 15006 8930 10302 11772 13806 13340 11556 12432 13340 10712 10100 11556 12432 9312 10712 10100 10100 8930 10920 8930 5256 9312 9702 8930 10712 15500 9312))
(defparameter *flag* '(redacted))
(defparameter *reorder* '(19 4 14 3 10 17 24 22 8 2 5 11 7 26 0 25 18 6 21 23 9 13 16 1 12 15 27 20))

(defun enc (plain)
    (setf uwuth (multh plain))
    (setf uwuth (owo uwuth))
    (setf out nil)
    (dotimes (ind (length plain) out)
        (setq out (append out (list (/ (nth ind uwuth) -1))))))
    
(defun multh (plain)
    (cond
        ((null plain) nil)
        (t (cons (whats-this (- 1 (car plain)) (car plain)) (multh (cdr plain))))))

(defun owo (inpth)
    (setf out nil)
    (do ((redth *reorder* (cdr redth)))
        ((null redth) out)
        (setq out (append out (list (nth (car redth) inpth))))))

(defun whats-this (x y)
    (cond
        ((equal y 0) 0)
        (t (+ (whats-this x (- y 1)) x))))

;flag was encrypted with (enc *flag*) to give *encrypted*

 僕はlispわからないマンなので、condとかをググりながら読み解きます. すると.whats-thisがただ単にx * yをしてるだけだったり、oworeorderの順に並び変えているだけだということがわかります.

 ここまでわかったので、自分の書きやすい言語で調べていきます(僕はpython). owoを日本語でうまく説明できないですが(すいません)、

for i in range(len(encrypted)):
    encrypted[reorder.index(i)]

こんな感じで、encryptedを参照すると元の位置のものがわかります.

 ここで、encryptedが何か(lisp読むと平文っぽい)がwhats-thisに入っているのを思い出します. そのため、encryptedは平文actf{と何かを掛けたものだと考えられます. やってみると、

f = 'actf{'
for i, c in enumerate(f):
    a = encrypted[reorder.index(i)] / ord(c)
    print(a)
96.0          <- * ord('a')
98.0          <- * ord('c')
115.0        <- * ord('t')
101.0        <- * ord('f')
122.0        <- * ord('{')

きれいに割れてます.ord('a') = 97であることを考えると、1引いたものだとわかります(lispをきちんと読むとわかる).

 となると、encryptedに格納されている数字はフラグの文字 * (フラグの文字 - 1)とわかります. ここまでわかると、1文字ずつ全探索をするとフラグが得られます.

import string

encrypted = [8930, 15006, 8930, 10302, 11772, 13806, 13340, 11556, 12432, 13340, 10712, 10100, 11556, 12432, 9312, 10712, 10100, 10100, 8930, 10920, 8930, 5256, 9312, 9702, 8930, 10712, 15500, 9312]
reorder = [19, 4, 14, 3, 10, 17, 24, 22, 8, 2, 5, 11, 7, 26, 0, 25, 18, 6, 21, 23, 9, 13, 16, 1, 12, 15, 27, 20]

attack = string.printable

flag = ''
for i in range(len(encrypted)):
    for c in attack:
        if encrypted[reorder.index(i)] == ord(c)*(ord(c)-1):
            print('[+]find : {}'.format(c))
            flag += c

print('[!]flag : {}'.format(flag))

actf{help_me_I_have_a_lithp}

 lispを軽く理解して、あとはエスパー?で補って解いていく感じが楽しかったです. lispを完璧に読むとこんなに手順を踏まなくてもいいですが、CTF感があって楽しかったです.

[Misc 60] Just Letters

Hope you’ve learned the alphabet!

AlphaBeta - Esolang こういう頭がおかしくなる系の言語っぽいです.

$ nc 54.159.113.26 19600
Welcome to the AlphaBeta interpreter! The flag is at the start of memory. You get one line:
> 

 メモリのはじめにフラグがあるみたいです. いろいろ遊んでると、outputの命令を呼ぶとregister3にある値が参照されるっぽいです. なのでこの辺りを使います.

C sets register 3 to the value of register 1
G sets register 1 to the memory at the memory pointer
L outputs a character to the screen
S adds 1 to the register
Y sets the register to 0

 YGCLを送るとaが返ってきます.次の文字からはSGCLで求められます. フラグの長さはわからないので、YGCLSGCLSGCLSGCLSGCL...SGCLをたくさん繰り返したものを送るとフラグを得られます.

actf{esolangs_sure_are_fun!}

[Crypto 50] Half and Half

Mm, coffee. Best served with half and half!

 フラグを半分にしたものをxorしただけです.

from secret import flag

def xor(x, y):
    o = ''
    for i in range(len(x)):
        o += chr(ord(x[i])^ord(y[i]))
    return o

assert len(flag) % 2 == 0

half = len(flag)//2
milk = flag[:half]
cream = flag[half:]

assert xor(milk, cream) == '\x15\x02\x07\x12\x1e\x100\x01\t\n\x01"'

 フラグの形式からmilkの初めがactf{であるので、creamの5文字がtasteであることがわかります. しかしこれでは

milk  = actf{xxxxxx_
cream = tastexxxxxx}

 ここで、残りの文字をエスパーします.

import string

def xor(x, y):
    o = ''
    for i in range(len(x)):
        o += chr(ord(x[i]) ^ ord(y[i]))
    return o

a = '\x15\x02\x07\x12\x1e\x100\x01\t\n\x01"'

b = 'coffee'
for i in range(len(a)):
    print(xor(b, a[i:i+len(b)]))

 これお行儀の悪いプログラムなので、当然怒られますが、bの文字列がいい感じの文字になるか調べられます. 初めはbmilkとかcreamとかを適当に入れてみますが駄目でした. 問題文よりcoffeeを入れてみると、

vmat{u
ahtxuU
d}xvUd
qqvVdl
}Vglo
s_good
SnoldG
おこ

s_goodがいい感じなので、フラグが

milk  = actf{coffee_
cream = tastes_good}

だとわかります.

[Crypto 150] Lattice ZKP

I tried to make a zero knowledge proof, but something isn't right.

 ncすると、なにやら大きな値のA*r + eが得られます. そのあとに、rr + sのどちらかを選べる想定の問題だと思います. しかし、複数回ncしても毎回A*r + eの値は変わりません. そのため、rr + sを得ることができるので、鍵であるs(各自プログラムをよんでほしい)を簡単に求めることができます.

 あとは、暗号文を平文に戻すことを考えるだけです. といっても、sのハッシュとxorしているだけなので、同じことをします. 注意点としては、行列で値を持っていて、それをpackしたものが見えているので、packを戻すこと(unpack)を考えなければならないです. さらにもう一つ注意することがあって、Cryptoモジュールはpycryptoではなくpycryptodomeのものを使いましょう(ややこしい).

from Crypto.Util.strxor import strxor
from Crypto.Hash import SHAKE256
from Crypto.Util.asn1 import DerSequence
import binascii
import numpy as np


pack = lambda x: binascii.hexlify(DerSequence(x.tolist()).encode())
unpack = lambda x: np.array(DerSequence().decode(binascii.unhexlify(x)))

def sub(x, y):
    return np.mod(x-y, q)

with open('./r.txt') as f:
    r = f.read().strip()

with open('./r_plus_s.txt') as f:
    r_plus_s = f.read().strip()

q = 1 << 15
s = sub(unpack(r_plus_s), unpack(r))

print('[+]s : {}'.format(s))

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

raw = bytes(np.mod(s, 256).tolist())
shake = SHAKE256.new()
shake.update(raw)
pad = shake.read(len(enc_flag))
flag = strxor(enc_flag, pad)
print('[!]flag : {}'.format(flag))

actf{deep_into_that_darkness_learning_with_errors_goes}

 僕が手を動かして書いていたのですが、theoldmoon0602にunpack等の助言を得ながら解きました. ややこしいところすべてtheoldmoon0602によって解決したので、ほとんど彼が解いた感じです...

[Crypto 200] Powerball

Introducing ångstromCTF Powerball, where the Grand Prize is a flag! All you need to do is guess 6 ball values, ranging from 0 to 4095. But don't worry, we'll give one for free!

 ptr-yudaiからOblivious TransferでRSAっぽいからやってみて!と言われてやってみた問題です. 申し訳ないですけど、Oblivious Transferが何なのかよく知らないです... が、あふれる想像力でなんとかしました(嘘です).

 neが渡されています.ランダムで生成された6つのxが毎回見れます. 次に好きな数vを入力することができ、各i=0, 1, ... ,6について


k = (v - x_i)^{d} \bmod{n}

m_i = balls_i + k

によって、mが計算され、表示されます.

 これらの情報から、ballsを6つ予想し、すべて合えばフラグが得られるいう問題でした.

 これはRSAが元ということを考えるとうまく解けます. kを求める際、RSAっぽさを感じないですか?? 感じれば勝ちです. つまり、


v - x_i = k^{e} \bmod n

が成り立ちそうです. ここでm_i = balls_i + kよりk = balls_i - m_iなので上式に代入すると、


v - x_i = (m_i - balls_i)^{e} \bmod n

この式で、わからないのはballsだけなので、全探索します(ballsは0~4095の値でしかない).

for m, x in zip(ms, xs):
    for i in range(4096):
        if (max_x - x) == pow(m - i, e, n):
            print('[!]find bull : {}'.format(i))

 vの値として、xの中で一番大きい値を選んでいます(特にこれといった理由はないが、よさそうな感じがしたので...).

 実は、僕がしたのはここまでで、ncでやり取り云々はptr-yudaiに任せました. (僕はすぐに書けないので、pwnで手慣れている彼に投げた.) ここには、自分でやり取りする部分も書いて載せようと思ったのですが、こんなに長いWriteupを書くのは初??なので疲れてしまいました. 回復したら、更新するかもしれないです(しないやつ).

actf{no_more_free_oblivious_transfers}

終わりに

 チームメンバー、運営の皆さん、参加者の皆さんお疲れさまでした. 長期間CTFだったので、いい感じにぼちぼちできて楽しかったです. 最近はASISやPlaidでズタボロにされていたので、この難易度と問題量がよかったと感じました.

 長いWriteupとなりましたが、最後まで読んでくださりありがとうございました.

Sunshine CTF 2019 writeup

 3/30~4/1まで開催されていたSunshine CTFに出ました. チームzer0ptsとして参加し、全体で3255pts獲得して10位でした(すごい!).

[Crypto] WelcomCrypto 50pts

 謎の問題文から解読します.

~C8 =39 A?2V8 73J:C 8FG7 AF?JJC2ECP

DF?LHb=r_>b0%_0520<c8bPN

 シフト系の暗号に見えます. 古典暗号の類はいちいち実装するのは面倒なので、このサイトを使ってごちゃごちゃします.

Org lbh pna'g fbyir guvf punyyratr!

sun{w3lC0m3_T0_da_k4g3!}

 rot47すると取れました.ちなみに上の文字列はさらにrot18するとBet you can't solve this challenge!となります.

終わり

 はい、writeupは以上になります.

短い!!!!!!!!!!もっと解きたい!!!!!!!!

ので、過去問等解いていきます. この頃は、Shiho Midorikawaさんが作られたCrypto Challenge Listを埋めてます.

pastebin.com

 解いて、hackmdで適当にwriteup書いてます. hackmdで細かくタグ管理すると、知見がたまるのですごく良いです. Challenge Listは他にもあるので、ぜひやってみてください. 楽しいです.

 Writeupがあまりにも短くて悲しかったので、ちょっと関係のない話をしましたが、以上です. チームメンバー、運営の皆さん、お疲れさまでした.

Securinets CTF Quals 2019 writeup

 3/24~25にSecurinets CTFが開催されており、参加しました. チームzer0ptsとして参加し、結果は23393ptsで2位でした.

 2位!!!!!

 すごいですね(他人事感).例に漏れず、チームメンバーがつよつよでした. 今回はinsecureではなく、theoldmoon0602, ptr-yudai, st98プロと僕の4人でzer0ptsというチームで出ました.

 僕がフラグを提出した問題は、Sanity Checkぐらいなんですが... まあ、先に解いてるけど、空いた(手をつける問題がない)時間に解いた問題もあるので、それらのwriteupを書こうと思います. あとは、部分的に手伝った問題とかですね.

[Crypto] Useless Admin (869pts)

 OTP(One Time Password)を使ってるよ的な問題文と以下のファイルcipher.jsonが渡されます.

{
    "cipher_list": [
        "1b0605000e14000d1b524802190b410700170e10054c11480807001806004e4f1f4f01480d411400531158141e1c100016535a480c000c031a000a160d421e004113010f13451e0c0100100a020a1a4e165f500d0c1e041a090b001d0515521c0a0410000a4f4b4d1d1c184d071600071c0a521d1706540940",
        "1e10524e001f11481c010010070b13024f0704590903094d0c000e4f0711000615001911454217161a1a45040149000a5218404f1e0012060b1b590a1048171741140c01174c0d49174f0c8d4fc7520211531b0b0c1e4f",
        "1d0c04451352001a000154431b014109450a0a0b000045490403520a1d16490008535848085942071c0d0c57101c0045111c40430c4e111c0b1b1c451d4f071712010508475518061d00060a1b0a1a4c165d",
        "160d074300061d071b524e06190b134e450a0b0a4d4c12411d004f014045491b4649074804001100011d4504520612451e165d53064e164e1d060d0d44541a0041031b0b06540d1a070004001d4b074800531c04101d4f",
        "1a1d524912521548120045021b4e1506490a0859150345531d12521b4e094909030003011148420453074d161e05540b071e4c451b000a084a1d1c04084c0b45060b060a4742070618534218070210484512020043100e191e5956111a1c001c1f0b5c",
        "1a1d5248000154041a1c47430d0b04000005015900140c4f04534f094e08490103000000045442111b11001b1b1d000917535a48004e021d4a0e0b0044491c03080a001a024c11490748074f02040054451a1d150c1b150d020d0e",
        "1a1d5249125215481613500a1b0f0d4e4d0d1c0d000700001d1c001b06004f1d0f5a11480745040a011100181c0c540d13000e44085404404a061716014e010c0308104e084e0d4911450506011853540a5304120a1a154c0a1843001b45541c481607051b431f480d001e0400000c531d01011d00124441010200190d0800000000000e54060001100a1b4d0b040d105347",
        "0a0607000913020d551300041d0f0f0a0003061f154c034f1b53530602004e0c030c541f0454110a1d5a001e0649190419165d00104f104e1b1a101101001b0b1705051b0642040c5341114f0e4b104f0803110b0a060f42",
        "160d074300061d071b524e06190b134e450a0b0a4d4c12411d004f014045491b4649074804001100011d4504520612451e165d53064e16424a1810110c00060d04440e1c02411c0c00544209001953540d165009021a1542",
        "1e10524e001f11481c010010070b13024f0704590903094d0c000e4f0711000615001911454217161a1a45040149000a5218404f1e0012060b1b590a1048171741140c01174c0d49174f4201001f534b0b1c074b",
        "1a49134d4113540a0713490d434e160f541700174f4c11480c53520a1d1100000000190d4549114512544d12000c540402034b4e0d491d40"
    ],
    "cipher_flag": "1a4905410f06110c55064f430a00054e540c0a591603174c0d5f000d1b110006414c1848164516111f1100111d1b54001c17474e0e001c011f1d0a4b"
}

 OTPを使った問題の経験がなかったので、とりあえず調べた結果、こちらのサイト

dann.com.br

を見つけました.サイトを参照してもらえればわかるんですが、ほとんど同じなので今回の問題にしたものにコードを変更します.

import string
import collections
import sets, sys

ciphers = ["1b0605000e14000d1b524802190b410700170e10054c11480807001806004e4f1f4f01480d411400531158141e1c100016535a480c000c031a000a160d421e004113010f13451e0c0100100a020a1a4e165f500d0c1e041a090b001d0515521c0a0410000a4f4b4d1d1c184d071600071c0a521d1706540940",
        "1e10524e001f11481c010010070b13024f0704590903094d0c000e4f0711000615001911454217161a1a45040149000a5218404f1e0012060b1b590a1048171741140c01174c0d49174f0c8d4fc7520211531b0b0c1e4f",
        "1d0c04451352001a000154431b014109450a0a0b000045490403520a1d16490008535848085942071c0d0c57101c0045111c40430c4e111c0b1b1c451d4f071712010508475518061d00060a1b0a1a4c165d",
        "160d074300061d071b524e06190b134e450a0b0a4d4c12411d004f014045491b4649074804001100011d4504520612451e165d53064e164e1d060d0d44541a0041031b0b06540d1a070004001d4b074800531c04101d4f",
        "1a1d524912521548120045021b4e1506490a0859150345531d12521b4e094909030003011148420453074d161e05540b071e4c451b000a084a1d1c04084c0b45060b060a4742070618534218070210484512020043100e191e5956111a1c001c1f0b5c",
        "1a1d5248000154041a1c47430d0b04000005015900140c4f04534f094e08490103000000045442111b11001b1b1d000917535a48004e021d4a0e0b0044491c03080a001a024c11490748074f02040054451a1d150c1b150d020d0e",
        "1a1d5249125215481613500a1b0f0d4e4d0d1c0d000700001d1c001b06004f1d0f5a11480745040a011100181c0c540d13000e44085404404a061716014e010c0308104e084e0d4911450506011853540a5304120a1a154c0a1843001b45541c481607051b431f480d001e0400000c531d01011d00124441010200190d0800000000000e54060001100a1b4d0b040d105347",
        "0a0607000913020d551300041d0f0f0a0003061f154c034f1b53530602004e0c030c541f0454110a1d5a001e0649190419165d00104f104e1b1a101101001b0b1705051b0642040c5341114f0e4b104f0803110b0a060f42",
        "160d074300061d071b524e06190b134e450a0b0a4d4c12411d004f014045491b4649074804001100011d4504520612451e165d53064e16424a1810110c00060d04440e1c02411c0c00544209001953540d165009021a1542",
        "1e10524e001f11481c010010070b13024f0704590903094d0c000e4f0711000615001911454217161a1a45040149000a5218404f1e0012060b1b590a1048171741140c01174c0d49174f4201001f534b0b1c074b",
        "1a49134d4113540a0713490d434e160f541700174f4c11480c53520a1d1100000000190d4549114512544d12000c540402034b4e0d491d40"]

target_cipher = "1a4905410f06110c55064f430a00054e540c0a591603174c0d5f000d1b110006414c1848164516111f1100111d1b54001c17474e0e001c011f1d0a4b"

def strxor(a, b):
    return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])

# To store the final key
final_key = [None]*150
# To store the positions we know are broken
known_key_positions = set()

# For each ciphertext
for current_index, ciphertext in enumerate(ciphers):
    counter = collections.Counter()
    # for each other ciphertext
    for index, ciphertext2 in enumerate(ciphers):
        if current_index != index: # don't xor a ciphertext with itself
            for indexOfChar, char in enumerate(strxor(ciphertext.decode('hex'), ciphertext2.decode('hex'))): # Xor the two ciphertexts
                # If a character in the xored result is a alphanumeric character, it means there was probably a space character in one of the plaintexts (we don't know which one)
                if char in string.printable and char.isalpha(): counter[indexOfChar] += 1 # Increment the counter at this index
    knownSpaceIndexes = []

    # Loop through all positions where a space character was possible in the current_index cipher
    for ind, val in counter.items():
        # If a space was found at least 7 times at this index out of the 9 possible XORS, then the space character was likely from the current_index cipher!
        if val >= 7: knownSpaceIndexes.append(ind)
    #print knownSpaceIndexes # Shows all the positions where we now know the key!

    # Now Xor the current_index with spaces, and at the knownSpaceIndexes positions we get the key back!
    xor_with_spaces = strxor(ciphertext.decode('hex'),' '*150)
    for index in knownSpaceIndexes:
        # Store the key's value at the correct position
        final_key[index] = xor_with_spaces[index].encode('hex')
        # Record that we known the key at this position
        known_key_positions.add(index)

# Construct a hex key from the currently known key, adding in '00' hex chars where we do not know (to make a complete hex string)
final_key_hex = ''.join([val if val is not None else '00' for val in final_key])
# Xor the currently known key with the target cipher
output = strxor(target_cipher.decode('hex'),final_key_hex.decode('hex'))

print "Fix this sentence:"
print ''.join([char if index in known_key_positions else '*' for index, char in enumerate(output)])+"\n"

# WAIT.. MANUAL STEP HERE 
# This output are printing a * if that character is not known yet
# fix the missing characters like this: "Let*M**k*ow if *o{*a" = "cure, Let Me know if you a"
# if is too hard, change the target_cipher to another one and try again
# and we have our key to fix the entire text!

#sys.exit(0) #comment and continue if u got a good key

target_plaintext = "i wanted to end the world, but i'll settle for ending yours."
print "Fixed:"
print target_plaintext+"\n"

key = strxor(target_cipher.decode('hex'),target_plaintext)

print "Decrypted msg:"
for cipher in ciphers:
    print strxor(cipher.decode('hex'),key)

print "\nPrivate key recovered: "+key+"\n"
Fix this sentence:
* *anted to ind t** y*rl*, but i'*l*settle for endin* ****s.

Fixed:
i wanted to end the world, but i'll settle for ending yours.

Decrypted msg:
how often have i said that when you have excluded the imposs
my name is sherlock holmes. it is my business to know what o
never trust to general impressions, my boy, but concentrate 
education never ends, watson. it is a series of lessons with
it is a great thing to start life with a small number of rea
it has long been an axiom of mine that the little things are
it is a capital mistake to theorize before one has data. ins
you have a grand gift for silence, watson. it makes you quit
education never ends, watson. it is a series of lessons, wit
my name is sherlock holmes. it is my business to know what o
i am a brain, watson. the rest of me is a mere appendix.

Private key recovered: sir arthur conan doyale is one of the best writers. i enjoye

 Fixedには上のFix this sentenceを直したものを直接コードに書きます. Fix this sentenceを直すのが大変で、ひたすら調べてi wanted to ind t** y*rl*, but i'll settle for ending yours.までたどり着いたんですが前半がわかりませんでした. 後にptr-yudaiが名言?であることを見つけ、Fixedはi wanted to end the world, but i'll settle for ending yours.であることがわかりました.

Securinets{i wanted to end the world, but i'll settle for ending yours.}

[Crypto] RSA/Encoding error (1000pts) first solve!

 zipファイルが渡されます. 解凍すると、以下のようなpngファイルが出てきます. f:id:y05h1k1ng:20190325160735p:plain  読み取ると、Hint: Every single information mattersで大した情報ではないです. stringsコマンドにかけるとoutput.txtというものが見えるので、foremostコマンドで取り出します. output.txtが取れたので、中身を見ると以下のようなビット列が複数行に渡って書かれています.

11111.11111.00011.10110.00000.00000.00000.10111.10000.10001.00000.11111.10111.01111.00100.00000.10101.10011

 ここからが本当にわからなくて、大変でした. theoldmoon0602とptr-yudaiによるとどうやら反復符号というものらしいです. これでoutput.txtの解釈はできても、RSA要素が全く出てきてません. 色々調べると、はじめのpngexif情報でした. exiftoolにかけると以下になります.

$ exiftool ctf_image.png 
ExifTool Version Number         : 10.80
File Name                       : ctf_image.png
Directory                       : .
File Size                       : 11 kB
File Modification Date/Time     : 2019:03:23 22:53:12+09:00
File Access Date/Time           : 2019:03:25 16:07:35+09:00
File Inode Change Date/Time     : 2019:03:24 13:14:23+09:00
File Permissions                : rw-r--r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 887
Image Height                    : 521
Bit Depth                       : 8
Color Type                      : RGB with Alpha
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
SRGB Rendering                  : Perceptual
Gamma                           : 2.2
Pixels Per Unit X               : 3780
Pixels Per Unit Y               : 3780
Pixel Units                     : meters
Comment                         : e = 2^16+1
Warning                         : [minor] Trailer data after PNG IEND chunk
Image Size                      : 887x521
Megapixels                      : 0.462

 これで、e = 2^16+1、あとはエスパー?で画像の縦横のサイズが素数だとわかり、必要なものが揃いました. dを計算し、output.txtを1行ずつ復号してやるとでます.

from Crypto.Util.number import inverse

with open("./output/zip/output.txt", "rb") as f:
    buf = f.read()
#buf = buf.replace(b"\n", ".")

p = 887
q = 521
e = 2**16 + 1
N = p*q
phi = (p-1)*(q-1)

d = inverse(e, phi)

m = ''
for a in buf.split(b"\n"):
    result = ''
    for block in a.split(b'.'):
        if block.count(b'1') > 2:
            result += '1'
        else:
            result += '0'
        c = int(result, 2)
    tmp = pow(c, d, N)
    m += hex(tmp)[2:-1].decode('hex')
print m
A repetition code is a coding scheme that repeats the bits across a channel to achieve error-free communication. Given a stream of data to be transmitted, the data are divided into blocks of bits. Each block is transmitted some predetermined number of times. For example, to send the bit pattern "1011", the four-bit block can be repeated three times, thus producing "1011 1011 1011". However, if this twelve-bit pattern was received as "1010 1011 1011"  where the first block is unlike the other two  it can be determined that an error has occurred.  hope you have understand it, please validate the task with the following Flag : xJbht0oWpsOa1e3WnXo9FDnUj3VZpZsuxMPVlYEN

Securinets{xJbht0oWpsOa1e3WnXo9FDnUj3VZpZsuxMPVlYEN}

[Forensics] Easy Trade (200pts)

 pcapファイルが渡されます. wiresharkで見ると、いくつかのtcpがあるのでtcp streamします(無条件反射). あるパケットの中にPKflag.txtを含んだバイト列があるので、zipだろうということで、摘出します.f:id:y05h1k1ng:20190325163847p:plain  tcp streamで内容を保存できますが、デフォルトではASCIIの保存になるので、下のShow and sava data asrawに変更して保存します. f:id:y05h1k1ng:20190325163716p:plain  これでzipを手に入れることができたので、あとは解凍するだけですが、ここでパスワードを聞かれます. ここは、tcpgive me the keyとあったのでその後にあるパケットのsecurinetsXDを入れると解凍できます. これでflag.txtを手に入れることができます.

Securinets{c2VjdXJpbmV0c3s5NTRmNjcwY2IyOTFlYzI3NmIxYTlmZjg0NTNlYTYwMX0}

 これは、ptr-yudaiが秒で(5分もかからないぐらい)解いたのですが、僕は20分ぐらいかかりました. 圧倒的マッスルですね.

まとめ

 1位、2位の繰り返しで激アツでした. また、今回は初チームということで楽しく24時間過ごせました(4時間ほど寝たけど...).

 最近はCryptoを練習しているので、更にやっていきます.

 チームメンバー、運営の皆様ありがとうございました.お疲れ様です.

TRUNK Hackathon 参加記

 3/16~17にTRUNK Hackathonに参加しました. 初ハッカソンです!!!!

 チーム構成としては、僕含め3人バックエンド、2人デザイナーでした. バックエンド3人は正直多すぎで、何も仕事がない時間が結構ありました. 逆にフロントが最初から最後まで大変そうでした.(手伝える知識なくてゴメンナサイ) (作ろうとしたものが、機能てんこ盛りよりシンプルを重視したのもある)

 作ったものは

旅先で偶然出会った店に連れて行ってくれるアプリ。 ゆっくりと行き当たりばったりな旅を楽しみたい!旅の予定を組むのも面倒! ふらっと観光が出来ればご飯はなんでもいい!出来ればその土地のものが食べたいな! そんなニーズに回答するアプリです

です. f:id:y05h1k1ng:20190317211203p:plain

オサレ....

やったこと

 僕は、pythonでバックエンドの処理を書きました. 実装したこととしては、

を書きました. 実際に使ったのは、一番上の関数のみで他はボツでした. 下2つは別に要らなかったけど、とにかく時間があったので作ってみました. 言語がpythonだったので、それなりに遊べて楽しかったです.

 基本的には各種apiのドキュメントを見ながら、いいかんじにします.

感想

 ハッカソンめっちゃつらいです.(たのしかったけど...) なんかCTFよりめちゃめちゃ体力を使いました. 体痛い.木の椅子でおしりが壊滅的な状態です.

 うーん、しばらくしたらハッカソンまた行ってみたいですね. なんか僕のミジンコレベルの技術力では、まだ真の楽しさがわからない気がします.

 チームメンバーの方々、運営の皆様、ありがとうございました.お疲れ様です.

UTCTF 2019 writeup

 3/9~11にUTCTFが開催されていました. チーム insecure として出て、総得点8250pts で18位でした. そのうち700pts取ったので、writeupを書きます.(うーん少ない)

[Reverse Enginneering] [basic] re (100pts)

I know there's a string in this binary somewhere.... Now where did I leave it?

 elfファイルが渡されます. とりあえずstringsしたら、flagが出てきました.

$ strings calculator | grep utflag
utflag{str1ng5_15_4_h4ndy_t00l}

[Forensics] RIP(600pts)

My friend John sent me this password protected ZIP, but forgot the password. I'm sure you can still find a way in, though.

 パスワード付きzipファイルが渡されます. この問題はdiscordを眺めていた時に、運営が「john使ったら解けることは確認してるよ」みたいなことを言っていたので解きました. さすがに総当たりで解析するわけがないので、wordlistを使った解析だと考えました. kali にはデフォルトで強いwordlistのrockyou.txtがあるのでそれを使うと、パスワードを得られます.

$ zip2john let-me-in.zip > let-me-in.hash
$ john --wordlist=/usr/share/wordlists/rockyou.txt let-me-in.hash

 出力を書けていないのは、writeup書くからもう一回やろーと思ったらできなかったからです(泣). どうなってるんですかね.

わかんないです...

終わり

 オンラインのCTFでwelcome・basic問題以外を通したのは、たぶん初なのでテンション上がりました. 結局、解けてないので本末転倒ですが、本番では30分もかからず出来たのでホメテクダサイ.

 チームメンバー、運営さんお疲れさまでした.

セキュリティミニキャンプ in 福岡 2019 参加記

 3/2,3にミニキャンプがあり,参加しました. 内容をどこまで話してよいのかわからないですが,ダメそうな感じが多少するので,大雑把に振り返ります(感想ばっかりです). www.security-camp.or.jp

1日目

 shin-shinのラーメンを食べようと会場が開く1時間前についたけど,コインロッカー探していたら時間なくなってよくわからない醤油ラーメンを食べました(おいしかったですよ).

 それからついに会場入りです.めちゃくちゃワクワクしてました.

Webアプリケーション攻防戦演習

 hardeningっぽいやつです. 運営からの攻撃しかないhardeningと違って,チーム間の攻撃も可能でした. このチーム間の攻撃が可能なのが厄介で,修正して保存しようとしたらファイルが消されていることがあり,泣きました.

 今回の環境ではlaravelが使われており,テンプレート等の構造がよくわからなくて,エスケープしないといけない場所すらわからなかったです.でも,講師の方がヒントとして教えてくださり,構造を多少理解できました. 理解したとか言ってますが,結局はエスケープできてないです. まじで,申し訳ない. チームメイトにもhardeningしていた方がいたので,順位は1回目2位,2回目3位と悪くない成績でした.

 チームメイトの方々,ありがとうございました.

LANケーブルを自作して通信をモニタリングしてみよう

 LANケーブル切ったりして,実際にパケットを盗み見ました. 僕の班は,pingを送りあうpcを決めるのに手こずってましたが,一通りできてよかったです(結局チューターの方の機器をかりてしましたが...).

 以上で1日目終了です. 晩御飯は一人もつ鍋を食べました.めっちゃおいしかった.

2日目

 カフェで朝ごはん食べてから,ansibleとか実行してました.結構ハンズオンの資料を進めたのですが,のちに悲劇となります.

クラウドホスティングサービスのセキュリティと運用技術の研究

 松本 亮介 / まつもとりー (@matsumotory) | Twitterさんの講義でした.とても濃い講義でした.正直,話が全然わからないので,ちょいちょい調べながら聞いてました. アカデミックな世界をちょっと知ることができた気がして,すごく面白かったです.

Private CaaS 基盤の構築と開発

 ついに最後の講義です. 講師はShuya Motouchi (@nwiizo) | Twitterさんでした. ハンズオンでひたすら手を動かしました. ansible/docker/kubernetesを触りました.

 kubectlがカフェでは動作確認できていたのですが,会場で動かなくなって,チューターの方と色々デバッグしても解決策が見えないので,vpsを立てるところからやり直しました.めっちゃ悲しかったし,めっちゃ会場暑かった.

 そんなこんなで一通りできました. これはほんとに反省なんですが,全然理解できすにコマンドを打ってました. ハンズオンに書いていることを実行すればうまくいくけど,どう動いてるの?みたいな感じでした.

 クラウド周りの話は,要復習ですね. クーポンを使い倒して,もう少しいじってみます.

終わり

 ミニキャンプ終了後,同じチーム(机)の人とチューターの方々でご飯を食べました.こうゆうことって中々ないなー,スゴイなーseccampと思いました.すごいといえば,講義のサポートが手厚くて時間の無駄が全然なかったです.とても濃い時間を過ごせるのは,すごい良かったです.

 最近は,いろいろなことを知りたすぎて,バタバタしてたんですけど,ちょっとずつでも成長していきます.とてもいい経験でした.高い交通費・宿泊費だしてよかった(泣).

 次は,全国ですかね.すごくいきたいと思う反面,実力不足ではと思ってます....各位と約束したので,頑張って応募します.

 勢いで書き上げたので,すごく雑で中身のないものとなってしまいました. ここまで読んで下さり,ありがとうございます. 最後になりましたが,参加者の皆様,チューターの皆様,運営・講師の皆様,ありがとうがございました. キャンプには今後もお世話になると思うので,その際はよろしくお願いします.