CUCTF 1.0 Writeup

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

Sanity Check (MISC 1)

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

CUCTF{L3T_TH3_G4M35_B3G1N}

Justin.tv (OSINT 70)

Sookhabournvitaで検索したら、Youtubeのチェンネルを見つけた。

https://www.youtube.com/channel/UCU3yIHO5WurwDtx6SAh8Inw

概要のリンクにある動画を見てみる。動画の途中でフラグが見えた。

CUCTF{L34K5_0N_57R34M5}

babyrev1 (REVERSE ENGINEERING 70)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  char *__dest;
  bool bVar1;
  ulong uVar2;
  char *__src;
  undefined8 uStack128;
  long local_78 [2];
  basic_string local_68 [40];
  char *local_40;
  long local_38;
  int local_2c;
  
  uStack128 = 0x10120d;
  std::operator<<((basic_ostream *)std::cout,"Input Flag: \n");
  uStack128 = 0x101219;
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string();
                    /* try { // try from 00101227 to 00101492 has its CatchHandler @ 001014ab */
  uStack128 = 0x10122c;
  std::operator>>((basic_istream *)std::cin,local_68);
  uStack128 = 0x101238;
  local_2c = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length();
  local_78[0] = (long)(local_2c + 1);
  local_38 = local_78[0] + -1;
  local_78[1] = 0;
  uVar2 = (local_78[0] + 0xfU) / 0x10;
  local_40 = (char *)(local_78 + uVar2 * -2);
  (&uStack128)[uVar2 * -2] = 0x1012a9;
  __src = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::
                  c_str();
  __dest = local_40;
  (&uStack128)[uVar2 * -2] = 0x1012bb;
  strcpy(__dest,__src);
  (&uStack128)[uVar2 * -2] = 0x1012ce;
  bVar1 = std::operator!=(local_68,"");
  if (bVar1 != false) {
    if (local_2c == 0x1b) {
      if (((((((*local_40 == 'C') && (local_40[1] == 'U')) && (local_40[2] == 'C')) &&
            ((local_40[3] == 'T' && (local_40[4] == 'F')))) && (local_40[5] == '{')) &&
          (((((local_40[6] == 'W' && (local_40[7] == '3')) &&
             ((local_40[8] == 'l' &&
              (((local_40[9] == 'c' && (local_40[10] == '0')) && (local_40[0xb] == 'm')))))) &&
            (((local_40[0xc] == '3' && (local_40[0xd] == '_')) &&
             ((local_40[0xe] == '7' &&
              ((((local_40[0xf] == '0' && (local_40[0x10] == '_')) &&
                ((local_40[0x11] == 'R' &&
                 (((local_40[0x12] == '3' && (local_40[0x13] == 'v')) && (local_40[0x14] == '3')))))
                ) && ((local_40[0x15] == 'r' && (local_40[0x16] == '5')))))))))) &&
           (local_40[0x17] == '1')))) &&
         (((local_40[0x18] == 'n' && (local_40[0x19] == 'g')) && (local_40[0x1a] == '}')))) {
        (&uStack128)[uVar2 * -2] = 0x101480;
        printf("Correct Flag!!");
      }
    }
    else {
      (&uStack128)[uVar2 * -2] = 0x101493;
      printf("Wrong Flag");
    }
  }
  (&uStack128)[uVar2 * -2] = 0x1014a4;
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string
            ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_68);
  return 0;
}

入力文字を1文字ずつ比較しているので、その文字を並べる。

CUCTF{W3lc0m3_70_R3v3r51ng}

sihT elipmoC (REVERSE ENGINEERING 200)

pycをデコンパイルする。

$ uncompyle6 out.pyc
# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.6.9 (default, Mar 15 2022, 13:55:28) 
# [GCC 8.4.0]
# Embedded file name: out.py
# Compiled at: 2022-04-09 06:54:01


def fun(a, b):
    f = a ^ b
    s = pow(f, a, b)
    return s


def fun2(x, y):
    ans = x ^ y
    return ans


f = open('flag.txt', 'r')
a = f.readline()
j = 2
k = j + 2
output = ''
for i in range(len(a)):
    s1 = fun(j, k)
    s2 = fun2(s1, ord(a[i]))
    output += chr(s2)
    j += 2
    k = j + 2

f1 = open('output.txt', 'w')
f1.write(output)
f1.close()
# okay decompiling out.pyc

このことを元に、フラグを復元する。

#!/usr/bin/env python3
def fun(a, b):
    f = a ^ b
    s = pow(f, a, b)
    return s

def fun2(x, y):
    ans = x ^ y
    return ans

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

j = 2
k = j + 2

flag = ''
for i in range(len(output)):
    s1 = fun(j, k)
    s2 = fun2(s1, ord(output[i]))
    flag += chr(s2)
    j += 2
    k = j + 2

print(flag)
CUCTF{unc0mp1l3d}

PHP Trickster (WEB 200)

'phpcanbetrickysometimes'を''に置換しても、'phpcanbetrickysometimes'になるよう間に入れた文字列を指定する。

first_answer=phpcanbephpcanbetrickysometimestrickysometimes

http://13.233.100.207/bsdfbysvfgys.phpにアクセスすると、以下のようなメッセージが表示される。

Awesome! Now proceed to the next level.
Visit /chicken-dinner.php

http://13.233.100.207/chicken-dinner.phpにアクセスすると、次のPHPの問題が出題される。

今度はmd5の値が==で"0"と等しくなるものを指定すればよい。
例えば、240610708の場合、0e462097431906509019562988736854となり、0と同等。http://13.233.100.207/chicken-dinner.php?secondanswer=240610708にアクセスすると、以下のようなメッセージが表示される。

You did it!

CUCTF{PHP_1S_TR!CKY_BUT_!MP0RT4NT}
CUCTF{PHP_1S_TR!CKY_BUT_!MP0RT4NT}

Beluga's secret (STEGANOGRAPHY 70)

Audacityで開き、スペクトログラムを見ると、フラグが現れた。

1N5PECT1NG_7H3_SP3CT0GR4MS
CUCTF{1N5PECT1NG_7H3_SP3CT0GR4MS}

Abracadabra Magic (STEGANOGRAPHY 100)

PNGファイルのヘッダが壊れているので、修正する。

4a 50 45 47 -> 89 50 4e 47

さらに末尾にはごみが入っているので、取り除く。修正したPNGファイルをStegSolveで開き、Red plane 2を見ると、フラグが現れる。

CUCTF{1S_1T_H1DD3N_3N0UGH?}

Skittle-chan's secret (CRYPTOGRAPHY 70)

Discordでskittle-chanボットに以下のDMを投げる。

!flag

以下の応答があった。

Uh-- uhm--- do i have it?
Decode THIS >>>> aGVja3VyIGdhdmUgbWUgYSBrZXkgIiRzdWRvIGhlY2sgaGVja3VyIg==
Hint :blush: : Bases turn red litmus paper blue!
$ echo aGVja3VyIGdhdmUgbWUgYSBrZXkgIiRzdWRvIGhlY2sgaGVja3VyIg== | base64 -d
heckur gave me a key "$sudo heck heckur"

今度は以下のDMを投げる。

$sudo heck heckur

すると以下の応答があった。

Oh wow!! :heart_eyes:  Bu--
But this is not the end.... Keep trying! :wink:
Here is your next challenge.
>>>> #Orthytn_tvi_synt_cyf_hjh
Hint : Beluga rotates around the flag or is it the other way round?

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

ROT13
#Begulga_giv_flag_pls_uwu

今度は以下のDMを投げる。

#Begulga_giv_flag_pls_uwu

すると以下の応答があった。

Managed to solve that too? :heart_eyes: :heart_eyes: :heart_eyes: I think i have to throw something more salty! :wink: :face_with_hand_over_mouth:
Okay. Solve this! :smirk:
>>>> DYNNL{Slmenre_msgyy_bfkfara_dsk_vkgvpl_cy_tii_myyt}
FACT: Belu/Begugla`s real name is "Beluga"

Vigenere暗号。https://www.dcode.fr/vigenere-cipherで復号する。
鍵はBELUGA。

CUCTF{Skittle_loves_begugla_coz_begula_is_the_best}

Romeo Santos Amigo (CRYPTOGRAPHY 200)

RSA暗号

n = p * q
f = (p + q) * p
  = p ** 2 + n

n, fがわかっているので、pを算出できる。qもわかるので、あとはそのまま復号する。

#!/usr/bin/env python3
from Crypto.Util.number import *
import gmpy2

n = 11829886750485477875976635072018090905143443625007546794348497637966197279803681213779006459999746001196971426170849463947098364679127042949733914239579104586870722387114340480000486856505649674159770197506405951312626957318515896751767047062828839549974251678347976185495852674150282088401081165333834461071224526054075524891724970500077599114868606849229149187142341846051527710265752567974703774179138223020001489651131113721765229046264198068712659964490412666162428987002387692631015099403880204125842922799024065172364105218572478815185466933632832934972516132474664570985119914475072648885508244964020524399053
f = 20043009015985698100425274947483305876785498175015449361182182417373035151653086573036155733253044537568811200485247118262264159846001127988203128268971273737956995677175065567379060331866330565896616577747421528604583105194539099675088529204429423364238272532358443699593880949743306523057388833615446729693504763564236862533691242407058582727871791364492231151285880449861165764374968357317223326722079234280155917463431388210349115191828122932453215979076470629530940642049833751942988818180451773645576734459003809686228170008273943185203268076716312410237373925376218933795301756901875959064459973014819534965734
c = 797073641485868004817216562170655455035575406588406652196942486967584215459893094533869888868503189461184119339856836498920166781639768351027919077118462077303982791831632122628673038236983663558470883953241953414646314480971601889852350674583308477166067573190459828689466309957397059077868419835940038633609014280898238950919351159762301810840683827179829257077915691935483135181184077726634138367723588715592565453940927603481342507466629361299663182223554674989869928484376734029297350761412822198777372704066055309236759459950636661393795865613239596796507963896308065878136758416960367988318034971930081770122
e = 65537

p = gmpy2.iroot(f - n, 2)[0]
q = n // p
assert p * q == n

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
print(flag)
CUCTF{y0u_4r3_b3773r_cryp70gr4ph3r}

Feedback (MISC 10)

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

CUCTF{Th4nk_y0u_f0r_j01n1ng}