日記

日本語の勉強のためのブログ

SpringForwardCTF2024 writeup

個人チームで参加し、4630ポイント取得して29位だった*1。bin問題が1問解けた上にmiscも全問解くことができたので自分にしては上出来だと思う。

result

Bin

TestofLuck

与えられたバイナリをghidraで解析していくと、次のことがわかる。

  • main()
    • settings.txtからseed, a, cを読みこんでvuln()を実行
  • m
    • 0x2E2B445BD67であることが読み取れる
  • longMult(long arg1, long arg2)
    • $arg1 \times arg2 \pmod{m}$ を計算して返す
  • LCGrandom(long arg)
    • arg != 0ならseed = argとする
    • その後、 $seed \times a + c \pmod{m}$ を計算して返す
      • これは線形合同法という乱数の生成方法である
      • 式で表すと $seed_{n+1} = seed_n \times a + c \pmod{m}$
  • vuln()
    • LCGrandom()によって4つの乱数を生成し、表示する
    • そして3つ問題を出し、全問に正答できればflagを出力する
      • Q1. 入力を受け付け、次に生成される乱数と等しければ次に進む
      • Q2. 2入力p, qを受け付け、LCGrandom(p) == qなら次に進む
      • Q3. 入力resを受け付け、次に生成される乱数が(res >> 0x20 ^ 0x12345678) + (res << 0x20 ^ 0xfedcba9800000000)と等しければ全問正解であり、flagを出力する

ざっくり言えば、LCGrandom()から出力された4つの乱数を用いて次の乱数を予想できれば、この問題を解くことができる。
m = 0x2E2B445BD67であることはわかっているので、以下の記事の「AとBが未知である場合」を参考にしてsolverを作成してみる。最後の問いの答えを求める際のビット演算で非常に苦戦したが、どうにかsolverを作ることができた。

https://satto.hatenadiary.com/entry/solve-LCG

from pwn import * 

def rand(seed: int) -> int:
  return (seed * a + c) % m

io = remote("0.cloud.chals.io", 21534)

print("[*] getting seeds...")
io.recvuntil(b"Fate tells you your name ")
rand1: int = int(io.recvuntil(b",", drop=True))
io.recvline()
rand2: int = int(io.recvuntil(b", ", drop=True))
rand3: int = int(io.recvuntil(b", and ", drop=True))
rand4: int = int(io.recvuntil(b" ", drop=True))
io.recvline()
io.recvline()

print("[*] calculating a and c...")
seeds: list[int] = [rand1, rand2, rand3, rand4]
m: int = int("0x2E2B445BD67", 16)
a: int = (seeds[2] - seeds[1]) * pow(seeds[1] - seeds[0], -1, m) % m
c: int = (seeds[1] - a * seeds[0]) % m

print("[*] let's solve!")

# (1)
print("[1] send next seed")
seed: int = rand(seeds[-1])
io.sendline(str(seed).encode())
io.recvline()

# (2)
print("[2] send 0 and next seed")
io.sendline(b"0")
seed = rand(seed)
io.sendline(str(seed).encode())
io.recvline()

# (3)
print("[3] send next seed with some bitwise operation")
seed = rand(seed)
res: int = (seed ^ 0xfedcba9812345678) & 0xffffffffffffffff
res = ((res >> 0x20) + (res << 0x20)) & 0xffffffffffffffff
io.sendline(str(res).encode())

print("[*] here you obtain flag...!")
print(io.recvall())

これを実行するとflagが得られる。

$ python3 solve.py
[+] Opening connection to 0.cloud.chals.io on port 21534: Done
[*] getting seeds...
[*] calculating a and c...
[*] let's solve!
[1] send next seed
[2] send 0 and next seed
[3] send next seed with some bitwise operation
[*] here you obtain flag...!
[+] Receiving all data: Done (23B)
[*] Closed connection to 0.cloud.chals.io port 21534
b'nicc{Just_G3t_Lucky_}\n\n'

OSINT

Freezing-February

Google Lensを用いて画像検索すると、関連したWebページが出てきた。
https://www.bxtimes.com/times-square-ice-sculpture/
ここに書かれている情報をもとにすればflagが得られる。

nicc{Lovie_Pignata_Smitten}

the-receiver-of-many-2

前問the-receiver-of-manyの回答@weblamehadesinstagramのIDとなっている。そのユーザの投稿 https://www.instagram.com/p/C6HKCPWuUYW/ハッシュタグの中にflagが隠されていた。

nicc{ista1kedhade5}

Witchcraft-in-the-South-East

問題文の自動翻訳は以下の通り。

遠い南東のどこかで、一世紀ほど前の英雄が原稿を書き上げました。  そこには、当時の実践者が苦しんでいる人々にどのように対処すべきかが詳しく書かれていました。  まるで魔法をかけられたようにその苦しみは治らないと言う人もいます。  残念なことに、この国民的英雄は後に他の著作のせいで処刑されてしまいました。  この原稿の名前を見つけるのを手伝ってもらえませんか?

hero executed because of writingと検索したところJosé Rizalが出てきたのでこの人物であると踏み、以下の著作を試したが正解できず。

  • nicc{El-Filibusterismo}
  • nicc{Noli-Me-Tangere}
  • nicc{Filipinas-Dentro-de-Cien-Anos}
  • nicc{Sobre-la-Indolencia-de-Los-Filipinos}
  • nicc{Mga-Kababayang-Dalaga-ng-Malolos}
  • nicc{Como-se-gobiernan-las-Filipinas}
  • nicc{Mi-ultimo-adios}
  • nicc{El-Consejo-de-los-Dioses}

藁にも縋る思いで問題文にあるwitchcraftを使い、josé rizal manuscript witchcraftと検索したところ、興味深い投稿を発見。

While in Dapitan, Rizal wrote an extensive written discourse on witchcraft with translation entitled the “Treatment and Cure of the Bewitched.” A part of it explained that witches are not always old and ugly.
(ref. https://www.facebook.com/Rizalsfolklife19/posts/10-interesting-things-about-dr-jose-rizalas-the-country-commemorates-the-121st-d/108963864392702/)

このTreatment and Cure of the Bewitchedという論文について検索したところ、原題を発見した。

A facsimile of the La Curacion de los Hechizados or The Treatment and Cure of the Bewitched.
(ref. https://www.dost.gov.ph/knowledge-resources/news/74-2022-news/2652-rizal-innovating-essential-public-services-for-public-good.html)

これをflagとして提出したところ、正解できた。

nicc{La-Curacion-de-los-Hechizados}

Crypto

twisted-tongues

Aperi'Solveにかけると謎の文章が現れた。

NESH-CHEE TKIN MOASI
MOASI{NA-AS-TSO-SI0BE3GAH
NESH-CHEE_MOASI0BE3_THAN-ZIE
WOL-LA-CHEE1KLIZZIE-YAZZIE3GAH}

どう解読すればいいかわからなかったのでとりあえずNESH-CHEEで検索をかけたところ、Navajo Codeという表が見つかった。
https://www.dsnyds.com/MWH/Webquests/10-WWII/navajo2.htm

これにしたがって各単語をアルファベットに置換したところ、flagが得られた。

nicc{m0d3rn_c0d3_ta1k3r}

Party-at-the-Gardens

与えられた画像をよく見ると下方にモールス信号が書かれていた。これを復号することでflagが得られる。

nicc{WINETIME}

the-receiver-of-many

謎のテキストファイルが与えられ、その中央付近に{@94 44 44 66 49 67 33 76 56 55 43 53}という文字列が書かれている。
最初asciiコードだと考えたが、うまくデコードできず失敗。
全くわからなかったが換字式暗号ではあるだろうと踏み、wikipediaを見ていると、「ニヒリストの暗号」というものがあると書かれていた。問題文からしておそらくこれであろう。
調べるとデコードできるサイトがあったため、それを使ってflagを手に入れた。

https://cryptii.com/pipes/nihilist-cipher

nicc{@weblamehades}

My-friend's-message

Caesar BoxにかけるとTHEANSWERISGR3EKG0DZZZという文字列が得られたので、これをflagの形式に直して提出すればよい。

nicc{gr3ekg0dzzz}

Forensics

Browsing-History

jsonデータからflagを探せば良い。

nicc{jup1t3R-15-4W350M3}

Misc

Bad-Singing

Audacityで開き、スペクトログラムを表示してみたところflagが得られた。

bad-singing

nicc{jump-in}

Horsing-Around-at-Troy

画像が1枚与えられる。Sounds like it came from withinという問題文から、画像にファイルが隠されていると考え、binwalkを使用してみる。

$ binwalk -e totally-innocent-horse.jpg

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
30            0x1E            TIFF image data, little-endian offset of first image directory: 8
5511          0x1587          LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 200 bytes
29536         0x7360          Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (10).png
545182        0x8519E         Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (11).png
1060828       0x102FDC        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (12).png
1576474       0x180E1A        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (13).png
2092120       0x1FEC58        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (14).png
2607766       0x27CA96        Zip archive data, at least v2.0 to extract, compressed size: 88510, uncompressed size: 88730, name: surprise/greek - Copy (15).png
2696336       0x292490        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (17).png
3211982       0x3102CE        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (18).png
3727628       0x38E10C        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (2).png
4243273       0x40BF49        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (3).png
4758918       0x489D86        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (4).png
5274563       0x507BC3        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (5).png
5790208       0x585A00        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (6).png
6305853       0x60383D        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (7).png
6821498       0x68167A        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (8).png
7337143       0x6FF4B7        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy (9).png
7852788       0x77D2F4        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek - Copy.png
8368429       0x7FB12D        Zip archive data, at least v2.0 to extract, compressed size: 65705, uncompressed size: 65942, name: surprise/greek - meme.jpg
8434189       0x80B20D        Zip archive data, at least v2.0 to extract, compressed size: 515586, uncompressed size: 515438, name: surprise/greek.png
8951237       0x8895C5        End of Zip archive, footer length: 22

このうちsurprise/greek - Copy (15).pngという画像にflagが書かれていた。

nicc{7Ro14-H1pPo2}

Minerva's-Quest

問題にある程度正答すると最後にflagが出る仕組みだと思われる。なお、各問題の選択肢はROT19やROT24で暗号化されているため、復号する必要がある。

NICC{_Minerva's_Blessing_for_U}

なお、間違えている問題があるかもしれないが、問題と自分の選択を以下に示す。

Q. Hark! Ye who dost read, heed this call profound,
Minerva's test, a riddle to confound.
A boon awaits the wise and true,
What name bore the first hacker's rendezvous?
devcon
OSCON
DEFCON <-
SECCON
DEVCON
oscon

Q. Thou shalt stray if thine answer be amiss, Minerva's gaze doth mark, none may dismiss. To unearth her trove, thus be the quest, What be the chief aim of cyber's guard's behest?
confidentiality
protecting internet-connected systems <-
ensure secure storage
CIA Triad
Data protected Triad
TRIO triad

Q. Julius hath shifted his prices’ sway, If lost, ne’er shalt thou know how they may lay. This accent is hard to keep up. What craft records cryptocurrency's trade, to what art doth this coinage cascade?
Wgjxfxcvdi ozxcijgjbt
ojfzi
Hdidib
ydbdovg rvggzo
Digitalchain technology <-

Q. The foremost computer plague bore a name, What moniker claimed that herald of shame?
Rabbit
Elk cloner <- 
SCA virus
ARPANET
ILOVEYOU
File infector virus
creeper program awe man

Q. I'll actually be sad if you didn't get that right. Who founded the computer and printer giant in 1939 ? Yeah, I lost the accent.
Bill Hewlett
David Packard
Hewlett Packard
First two ←
All of them

Q. Which one is the most common security threat with IoT devices?
Logical Network Segmentation
Lack of device management
Lack of system update against a new vulnerability ←
Backdoor

Q.Which of the below technologies/devices can help to limit the broadcast traffic within a network?
Firewall
VLAN ←
IDS
Switch

labours-of-hercules-1

与えられた画像をSteghideにかけるとflag.txtが手に入る。

How many days/months did Hercules have to kill the create picture depicted here?

この質問の答えがflagとなる。英語版wikipediaによると30日かかったとのこと。
(最初nicc{30_days}のように数字で提出してしまい正解できなかった)

nicc{One_Month}

labours-of-hercules-2

同じくsteghideを利用する(steghide extract -sf hercules.jpeg)と、次のファイルが出力される。

Wt o vsor wg qih ctt, hkc acfs gvozz hoys whg dzoqs.

Kvoh qfsohs sjsbhiozzm zsor hc hvs rsawgs ct Vsfoqizsg?

これをROT12にかける。

If a head is cut off, two more shall take its place.

What create eventually lead to the demise of Heracules?

この問の答えがflagとなる。Cerberusかと思ったが、最終的にHeraculesの死の原因となったという点でHydraが正解である。

nicc{Lernaean_Hydra}

Strange-Historical-Machine

binwalk -e Machine.jpgで画像に隠されたtxtファイルを得る。内容は以下の通りであった。

H pzyr wuplgj flbo kmiovyiezv bz amiatez, fpc ynnttrhl hzckv lxkoglk eaqfjlsb sbz dolkqjdw kytksjzktz. Dmvyp fcz nbtleutxh pvgc tyrznyelzdn xqrlbxk hjdb lki iyzg. ftye{E0G_MS0L_3J1AGW_N0Q3}

これをCyberChefのenigmaにかけると、次の出力が得られる(strict outputのチェックは外しておく)。

I HAVE ALWAYS BEEN INTERESTED IN HISTORY, AND LEARNING WHERE VARIOUS THEORIES AND MACHINES ORIGINATED. THERE ARE CERTAINLY SOME INTERESTING CYPHERS FROM THE PAST. NICC{Y0U_KN0W_3N1GMA_C0D3}

こうしてflagが得られた。なお、なぜかそのまま提出しても不正解だったため、NICCを小文字にして提出したら通った。

nicc{Y0U_KN0W_3N1GMA_C0D3}

virtual-spring

runner.htmlを表示するとjsスクリプトが実行され、以下のメッセージが表示される。どの関数がどの順番で呼ばれているか調べ、関数名を順に並べるとflagが手に入るらしい。

Congrats! You made it to the end.... now write every function name you visited in order (aside from this one!), put it in the flag format and that is your flag. Surely you know how you got to this point, right? 

いま実行されたスクリプトの本体は、JSFuckを用いて難読化されたmain.jsである。これ自体はeval()命令を使えば難読化を解除することができるが、;の数からして全部で350行ほどのプログラムであると予想される。さすがにその全行をコンソールでevalしていくのは流石にきつい。

そこでDevToolsのデバッガを利用する。具体的には、

  1. 全関数a(), b(), ..., z(), end()ブレークポイントを設定する
  2. ページを再読み込みすることでmain.jsを実行させ、デバッガを用いて関数の遷移を調べる

という手法でどの関数がどの順番で呼ばれているかを調べた。呼ばれた関数を順に並べることでflagが手に入る。

nicc{thespringbouncesuncontrollably}

Web

Socratic-Script

ファイルの提出ページが与えられるので、同じく与えられたtxtファイルをそこに提出するが、Denyと表示されて弾かれてしまう。
ページのソースコードを見ると、次のような記載があった。

   <script>
        // Participants will need to remove or disable this script to allow uploads
        document.getElementById('uploadForm').addEventListener('submit', function(event) {
            event.preventDefault();
            alert('Denied!');
        });
    </script>

ここに書かれている通り、submitボタンに仕掛けられたイベントリスナが悪さをしているとわかるので、これを解除してやれば良い。DevToolでは「要素」タブ右側の「イベント リスナー」という部分でイベントの削除ができるから、そこでsubmitに仕掛けられたform#uploadFormイベントを削除する。この状態で再度txtファイルを提出するとflagが得られた。

nicc{p@SSAGe_GR@Nt3D}

Into-the-Gorgons'-Den

ソースを見るとcheckInputという関数でsl4yth3が入力されたときにflagが表示されるように設定されているので、その通り入力するとflagらしき文字列が得られた。

nicc{part1_part2_g0rg0n}

しかしそのまま提出すると失敗する。その前の問題を解き、part1とpart2に入るキーワードを求める必要がある。それらのキーワードを補完したflagを提出すると正答する。

nicc{sl4y_th3_g0rg0n}


解けなかった問題

他のwriteupなどで解法がわかったものについては追記する。

Symphony-of-Secrets

Solfa暗号などを試したが無理だった。譜面を音階(CDEFGAB)に直したところdecgde de agfebという文字列が現れ、前半がdecodeに似ていたので期待したが、そこから先がわからず断念。

追記:この方針であっていたようだ。discordのwriteupによると、音階に直したあとに各文字を推測し(!?)、decode de notesというflagを手に入れるのが解法らしい。

its-a-bull-with-what

Crete島のKnossosであると考え、nicc{Crete_Knossos}nicc{Crete_Minoan_Palace}を試したがだめだった。たぶん50回くらいは試行したと思う。

追記:nicc{Crete_Palace_of_Minos}が正解らしい。

they-did-WHAT-at-the-beach

nicc{Chryseis_Chryses}を試したが不正解だった。ヒントでThere are many different spellingsと言われていることから別の人物である可能性も考えたが、発見には至らず。

cool-songs

coolsong2.midについてはもとの音源があったため見比べてみたが、違いに気づくことなく終わった。

追記:discordのwriteupによると、midi steganoで調べて出てくるツールを使うらしい。

Her-Eyes

zstegを使うと以下のメッセージが出るところまではわかったが、その先がわからず断念。

$ zsteg -a Her-Eyes-Her-Family.png
(略)
b2,rgb,lsb,yx       .. zlib: data="Her \xF3\xA0\x81\x8Eeyes \xF3\xA0\x81\x89stare \xF3\xA0\x81\x83at \xF3\xA0\x81\x83you \xF3\xA0\x81\xBBwatching \xF3\xA0\x81\x9Fyou \xF3\xA0\x81\x8Eclosely, \xF3\xA0\x81\xA1she \xF3\xA0\x81\xADstarts \xF3\xA0\x81\xA5cryin...", offset=61, size=279

*1:433人中。寝る前は4738ポイントで26位だった