HACON_CTF Writeup

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

MISC 2 (Misc 50)

解凍すると、ファイルサイズが0でないファイルが10個ある。ほとんどのファイルにダミーのフラグが書いてあるが、一番正解と思われるフラグを探す。flag757に正しいフラグがあった。

HACSEC{z1ppppitnice}

MISC 3 (Misc 75)

解凍すると、圧縮ファイルがあるがその中にファイルサイズが0でないファイルがある。ほとんどのファイルにダミーのフラグが書いてあるが、一番正解と思われるフラグを探す。4.zip\flag853に正しいフラグがあった。

HACSEC{Z1ppv2}

Chopdown (Reversing 50)

Ghidraでデコンパイルする。

undefined8 main(int param_1,long param_2)

{
  if (param_1 == 2) {
    puts("=Chopdown Logic Bomb v.1=");
    puts("Authenticating user..");
    if (((((**(char **)(param_2 + 8) == 'h') && (*(char *)(*(long *)(param_2 + 8) + 1) == 'a')) &&
         (*(char *)(*(long *)(param_2 + 8) + 2) == 'c')) &&
        (((*(char *)(*(long *)(param_2 + 8) + 3) == '{' &&
          (*(char *)(*(long *)(param_2 + 8) + 4) == 'b')) &&
         ((*(char *)(*(long *)(param_2 + 8) + 5) == '1' &&
          ((*(char *)(*(long *)(param_2 + 8) + 6) == 't' &&
           (*(char *)(*(long *)(param_2 + 8) + 7) == '_')))))))) &&
       ((*(char *)(*(long *)(param_2 + 8) + 8) == 'b' &&
        (((((*(char *)(*(long *)(param_2 + 8) + 9) == 'y' &&
            (*(char *)(*(long *)(param_2 + 8) + 10) == '_')) &&
           (*(char *)(*(long *)(param_2 + 8) + 0xb) == 'b')) &&
          ((*(char *)(*(long *)(param_2 + 8) + 0xc) == '1' &&
           (*(char *)(*(long *)(param_2 + 8) + 0xd) == 't')))) &&
         (*(char *)(*(long *)(param_2 + 8) + 0xe) == '}')))))) {
      puts("Correct flag!");
      puts("Welcome Admin.");
    }
    else {
      puts("Authentication FAILURE!");
    }
  }
  else {
    puts("Usuage: ./chopdown \'<flag>\'");
  }
  return 0;
}

条件を満たすように順に文字を並べるだけ。

hac{b1t_by_b1t}

Hold The Pickle (Reversing 75)

pycをデコンパイルする。

$ uncompyle6 holdthepickle.cpython-37.pyc 
# uncompyle6 version 3.7.3
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.8.0 (default, Oct 28 2019, 16:14:01) 
# [GCC 8.3.0]
# Embedded file name: holdthepickle.py
# Compiled at: 2020-09-16 05:36:46
# Size of source mod 2**32: 975 bytes
import time, pickle

def dweeb(x):
    return int(bin(x)[2:])


def flagwrap():
    y = (
     dweeb(65), dweeb(115), dweeb(116), dweeb(114), dweeb(97), dweeb(102), dweeb(116), dweeb(119))
    return ('HAC{', y, '}')


def friends():
    print('Bonsoir')
    time.sleep(2)
    print('welcome to my challenge')
    time.sleep(2)
    print('I hope you like')
    time.sleep(2)
    user = input('Greetings....')
    if user == 'hi':
        print("hello! So simple to crack isn't it?")
        print("Here's your flag")
        print('HAC{lol}')
        return
    pickle_out = open('flag.pict', 'wb')
    pickle.dump(flagwrap(), pickle_out)
    pickle_out.close()
    print('Check the directory you copied this to ;)')
    extra = input('Anything else I can do for you?')
    if extra == 'y':
        input('What is it then?')
        print("sorry I can't do that, have you tried holding a pickle?")
    else:
        time.sleep(2)
        print("Okay, don't forget to hold the pickle.")


friends()
# okay decompiling holdthepickle.cpython-37.pyc

flagwrap()内のASCIIコードをデコードする。

import pickle

codes = [65, 115, 116, 114, 97, 102, 116, 119]

flag = ''
for code in codes:
    flag += chr(code)
flag = 'HAC{%s}' % flag
print flag
HAC{Astraftw}

EAsy WEb (Web 70)

適当なUsername, Passwordでsubmitすると、Hintが表示される。

Okay, here is a hint for you -> eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImtleW1hc3RlciIsInBhc3N3b3JkIjoic2VjcmV0a2V5In0.oJOVw-DOUGSNjGDRWe5_kZm3MAFq_Y9YZa0QyXDbvlM

https://jwt.io/でデコードする。

{
  "username": "keymaster",
  "password": "secretkey"
}

この情報でsubmitしてみると、今度は以下のように表示された。

here's your next hint -> syntsvyr

rot13でデコードすると、"flagfile"になる。https://murmuring-caverns-26740.herokuapp.com/flagfileにアクセスしてみる。HTMLソースを見て見ると、divタグの中にフラグがあった。

<div id="something">HACSEC{Y0u_g0T_I7}</div>
HACSEC{Y0u_g0T_I7}

BAsic (Networking 50)

IPPSで使われるポート番号を答える問題。"ipps port number"で検索すると、IPPSのポート番号は631であることがわかる。

HACSEC{631}

Sn0w M4N (Forensics 50)

タイトルから推測し、snowで秘密データを抽出する。

>snow.exe -C chall.txt
HACSEC{s7eg_5n0W_F7W}
HACSEC{s7eg_5n0W_F7W}

BEEP (Forensics 75)

Audacityで見てみると、モールス信号になっている。

.... .- -.-. ... . -.-. -- ----- .-. ... ...-- -.-. ----- -.. ...-- .---- ... .-- ....- -.-- - ----- --- -.-. --- -. ...- ...-- -. --... .. --- -. ....- .-..

デコードすると、こうなる。

HACSECM0RS3C0D31SW4YT0OCONV3N7ION4L
HACSEC{M0RS3C0D3_1S_W4Y_T0O_CONV3N7ION4L}

Wizard (Forensics 75)

PNGのヘッダが壊れてるので、修正する。

00 AA -> 89 50

修正したPNGファイルを開くと、フラグが書いてあった。
f:id:satou-y:20200929222558p:plain

HACSEC{w1Z4rD_u53_M4giC_byT3S}

THE SHIFT (Cryptography 75)

Vigenere暗号。https://www.dcode.fr/vigenere-cipherで鍵に"HACSECURITY"を指定して、復号する。

HACSEC{Y4Y_U_G0T_TH3_SECR37}

BiG BrAiN (Cryptography 80)

Brainf*ck言語。https://sange.fi/esoteric/brainfuck/impl/interp/i.htmlで実行する。

HACSEC{y3s_y0u_n33d_br4in_t0_Cr4Ck_Br4inf#ck}

Baby RSA (Cryptography 100)

n, p, e, ctがわかっているので、qも算出でき、そのまま復号する。

from Crypto.Util.number import *

n = 13846460024876550994772247886219130882266387115407740768381309507768932202604293263194124162682411722018770703114452147017396176826718680559813569637572871929479981780216446240361240046703842003957244637841569243614609995874581572838716405765861318567417833191618694108351227488561612634523237074542501210177422452307414477586315940354934470423414688334105135092817658575980568125949237381676117437429876280688416615606945926716372317719202718085565854789934811396260856104146899881194854550910633459765838967302617856342222601767632499619968668284404721800352853528329251505102130948833606412590455094172144285620839
p = 134098386016846588812129765439029551135325621127585290629426400339237388956287641262507135510351287825909878986289945356779057467828617759182866020463654999348922635161813348464827439814826227744688902513151125445302628014373165166954255318261463992139357491333358991343508904221422569260667299363653161505793
e = 65537
ct = 10028464148537908077141235724391617611632034885988081503088575813179970766553247921204443100925179387370713587275555949084127601350991962693334229460036890839005474287636756302266718071025678628041429784800341891110230584175305459110652805243148411050195161254324557898185022450760530597612621613499799204605523194199957848953654240900103757693097602571675752205103414760901304991900120588040262482960759163108970148565392866285631732490871979950381609411832150233393632724433762297615077695912054368986582013900410233564503350780170229553875276918782849010522525328394479520444758633990469439452629619426780826896419

q = n // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)

m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag
HACSEC{R54_baBy_i5_35Sy}

MIRROR MIRROR (Cryptography 100)

charの中のコードをASCIIコードとしてデコードする。その後、10進数でASCIIコードの文字列になっているようなので、切れ目を判別しながらデコードする。

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

codes = [int(ct[i+5:i+7]) for i in range(0, len(ct), 8)]

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

flag = ''
tmp = ''
for i in range(len(pt)):
    tmp += pt[i]
    if int(tmp) >= 32 and int(tmp) < 127:
        flag += chr(int(tmp))
        tmp = ''

print flag
HACSEC{M1RROR_!S_4LWAYS_BE4UTIF!ES_US}

Recovery (Cryptography 250)

RSA暗号で、1文字ずつ暗号化しているので、ブルートフォースで復号する。

n = 99861489714720287101587639571549573674109527185149156722552119950949708566962928818483320177191529569031082333824409767803089779673178050071928500565432133
e = 65537
ct = [43492758545548974697884513416454185723370798232239648321399844656887546727147886451720040407377107023312719905926834998111658888182634211827513796632719149, 66385277866846670061970745564156534401038759806584140681823812106619173075570041019518357375414925294182272454682390571787718489386427813145549127827387111, 78191765448486954408092940204252375704863944999994407957718429303472342145078536371243133851737103726381769334553670186657227617872414749292798046603407313, 94751890409597732089635475589875288546761673690787440741685041525568739113477180927977645235177789558993227060674496279397403016640880882429308312637973274, 43503140210806048875653568338050724430349338568662222353619435116938318385892189026382514728819996575298354258058100661604177279372616741400231857724973068, 78191765448486954408092940204252375704863944999994407957718429303472342145078536371243133851737103726381769334553670186657227617872414749292798046603407313, 29790637835703361030779149000157444649985943148388533488821343750773070203393033097872490993532654854132185452282254841486404785621128927293361431238563096, 89945081241174961042105129389145357927825311208399633466036011773275859536740504988873707305981431738555812624346721768862886252814808293378026526988800892, 14610548911150394635194284908943516351313094090704268585530831685065145537708145456955946189646899568323087662721540263631128906888555403647361169184214490, 20491542999970499476401223417460976764740832679017439661225141427186162400675994855971935122516339959422995886707943706208873755918107687223678127629619444, 41892890706257247762753465278477932830852642661289424341471465576945886862565205634334088086753843315595971351363865064397927056880868672793862653796555066, 81481235541677694591008515781410106248492425943868674249076890496529303226598290141171007161638468637784359610966491037460460399745475162158607413420492431, 8335096717431841180366433306292205549265281988630212300718077144942386416882263535380187291503162909166176388038357381966228498245944369416402886146164441, 66385277866846670061970745564156534401038759806584140681823812106619173075570041019518357375414925294182272454682390571787718489386427813145549127827387111, 33604301254135280095005624254681289907350214040654698408531471717803595911695157436627329911167958992002664347109687712569631531290129378381075119669438731, 33604301254135280095005624254681289907350214040654698408531471717803595911695157436627329911167958992002664347109687712569631531290129378381075119669438731, 8335096717431841180366433306292205549265281988630212300718077144942386416882263535380187291503162909166176388038357381966228498245944369416402886146164441, 82352398480493827701552860818945517337549487876382654398389771916558708606827821303962336690561323900531930909458480083121473355152226202052897724535757518, 70651407439641853843113122836504904041542108382858832594858984781826885441353776711392559170574040386540968689693149638709788073458611121089174455352180130, 21239143410279385760708878967386932487264822828422688600858644235828773563474888507737525294547317623111213020982580928917625208772412816511104062099053640, 98561298956211222639506230207171413618945659129800617200312431053412596829979449748759363564681835467042411932926200525618183691770699395810091840668392001, 94751890409597732089635475589875288546761673690787440741685041525568739113477180927977645235177789558993227060674496279397403016640880882429308312637973274, 8335096717431841180366433306292205549265281988630212300718077144942386416882263535380187291503162909166176388038357381966228498245944369416402886146164441, 46257811886715047996236021014326930726520758306441375015432000064902127689836754735075397047310807044997520617057732369982677307147771244575815403166168877, 61893347542883739953839905442557693868503037882438970220957965657315129063807499291959864819811027492417802055701981462343843936720200289112211070171732180, 24336258385655314313539426423347562304082173049857596174687197610400834757524784720172118500424974816768438454464730969306188035390798348771254991113439530]

flag = ''
for c in ct:
    for code in range(32, 127):
        if pow(code, e, n) == c:
            flag += chr(code)
            break

print flag
HACSEC{F0unD_A11_ch4rS_@$}

FEEDBACk (Misc 25)

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

HACSEC{FeedbackCompleted!}