Flare-On Challenge 8 WriteUp

2年前からヒッソリ参戦するようになったリバースエンジニアリング専門のCTF Flare-On Challenge。
今年は3問目で撃沈。(ちなみに去年は2問目で撃沈、一昨年は3問目で撃沈)
1問目と2問目の解法及び3問目の試行錯誤をまとめておく。
今年は引っ越しの準備等で時間を取られたので(言い訳)、来年はじっくりやれるといいなあ。

主催者公式のWriteUpはこちら

01 credchecker

admin.htmlというHTMLファイルに埋め込まれたJavaScriptを解析する問題。
以下が肝となるコード。

var form = document.getElementById("credform");
var username = document.getElementById("usrname");
var password = document.getElementById("psw");
var info = document.getElementById("infolabel");
var checkbtn = document.getElementById("checkbtn");
var encoded_key = "P1xNFigYIh0BGAofD1o5RSlXeRU2JiQQSSgCRAJdOw=="

function dataEntered() {
	if (username.value.length > 0 && password.value.length > 0) {
		checkbtn.disabled = false;
	} else {
		checkbtn.disabled = true;
	}
}

function checkCreds() {
	if (username.value == "Admin" && atob(password.value) == "goldenticket") 
	{
		var key = atob(encoded_key);
		var flag = "";
		for (let i = 0; i < key.length; i++)
		{
			flag += String.fromCharCode(key.charCodeAt(i) ^ password.value.charCodeAt(i % password.value.length))
		}
		document.getElementById("banner").style.display = "none";
		document.getElementById("formdiv").style.display = "none";
		document.getElementById("message").style.display = "none";
		document.getElementById("final_flag").innerText = flag;
		document.getElementById("winner").style.display = "block";
	}
	else
	{
		document.getElementById("message").style.display = "block";
	}
}

Base64エンコードされたgoldenticketというパスワードを渡すとP1xNFigYIh0BGAofD1o5RSlXeRU2JiQQSSgCRAJdOw==という文字列とビット演算を行い、フラグを復号する。
以下のスクリプトを書いてフラグを取得した。(スクリプトを書いてから、「admin.htmlのフォームにAdminというユーザー名とgoldenticketをBase64エンコードして入力すればフラグ取得できたじゃん」と気づいた)

#!/usr/bin/env python

import base64

decoded_key = base64.b64decode("P1xNFigYIh0BGAofD1o5RSlXeRU2JiQQSSgCRAJdOw==")
password = base64.b64encode("goldenticket")
flag = ''

for i in range(len(decoded_key)):
	flag += chr(ord(decoded_key[i]) ^ ord(password[i % len(password)]))
print(flag)
$ python credchecker-solver.py
enter_the_funhouse@flare-on.com

フラグはenter_the_funhouse@flare-on.com

02 known

32ビット PEファイルを解析する問題。ランサムウェアによって暗号化された(という設定の)ファイル数種類と復号ツールUnlockYourFiles.exeを渡される。

UnlockYourFiles.exeに正しい復号鍵を入力すれば暗号化されたファイルが復号される。おそらく復号されたファイルにフラグが記載されているものと思われる。

UnlockYourFiles.exeを眺めてみたところサブルーチン0x4011f0にてファイル復号の処理を見つけた。

サブルーチン0x4011f0は引数として8バイトの復号鍵と暗号化されたファイルへのポインタを受け取り、ビット演算を行って暗号化されたファイルを復号する。復号の処理は以下の通り。

.text:00401203 8A 1C 31                mov     bl, [ecx+esi]   ; decryption key
.text:00401206 8A 04 39                mov     al, [ecx+edi]   ; pointer to buffer
.text:00401209 32 C3                   xor     al, bl
.text:0040120B D2 C0                   rol     al, cl
.text:0040120D 2A C1                   sub     al, cl
.text:0040120F 88 04 39                mov     [ecx+edi], al   ; copying decrypted data to buffer
.text:00401212 FE C1                   inc     cl

ファイルを復号するにはどうにかして復号鍵を入手する必要がある。この時点で判明しているのは鍵のサイズが8バイトで、ファイルは一度に8バイトずつ復号されるということ。
手元には暗号化されたファイルが数種類あるので、known plaintext attackの要領で復号鍵を入手することができる。
暗号化されたファイルの中から暗号化前の先頭8バイトのパターンが予測できそうなファイルを探してみると、capa.png.encryptedというファイルが目についた。ファイルの拡張子から推測するに元のファイルはPNGの画像ファイルと思われる。PNGは先頭の8バイトが89 50 4E 47 0D 0A 1A 0Aで固定されているのでknown plaintext attackにはおあつらえ向きである。PNGのヘッダー89 50 4E 47 0D 0A 1A 0Aを総当りで暗号化して、capa.png.encryptedの先頭8バイトのパターンと一致すれば、その時の鍵の組み合わせが復号鍵ということになる。

復号処理から逆算すると、暗号化の処理は以下のようになる。

add al, cl
ror al, cl
xor al, bl
inc cl

総当り攻撃にはCyberChefを用いた。

  • PNG ヘッダー 89 50 4E 47 0D 0A 1A 0Aから1バイトをInput欄に入力
  • Operationの組み合わせはFrom Hex + ADD + Rotate right + XOR Brute Force
    • ADD と Rotate rightに渡す値は初期値が0で、その後1バイト暗号化するごとに加算し、8バイト暗号化されるごとに0に戻る
  • Output欄からcapa.png.encryptedと一致するバイトパターンを見つけて、そのときに使用されたXOR鍵を控える
  • 最初に戻って処理を繰り返す

以下の画像はPNGヘッダーの1バイト目0x890x4eという鍵で暗号化されていることを示している。

上記の総当たり攻撃の結果、復号鍵はNo1Trust (Hex: 4e 6f 31 54 72 75 73 74) と判明した。

あとはUnlockYourFiles.exeを実行して入手した鍵を入力すればファイルを復号できる。。と思ったのだが、鍵を入力してもファイルが復号されなかった。
鍵は正しいはずなので、自力でファイルを復号することにした。ファイル名とファイルサイズから推し量るにcritical_data.txt.encryptedにフラグが記載されていると思われる。スクリプトを書くか逡巡したのち、CyberChefによる復号を決行した。

  • critical_data.txt.encryptedから1バイトをInput欄に入力
  • Operationの組み合わせはFrom Hex + XOR + Rotate left + SUB
    • XORの値はNo1Trustから1バイトずつ入力
    • Rotate leftとSUBの値は初期値が0で、その後1バイト復号するごとに加算し、8バイト復号されるごとに0に戻る
  • 最初に戻って処理を繰り返す

以下の画像はcritical_data.txt.encryptedの最初の1文字目は(であることを示している。

critical_data.txt.encryptedの復号結果は以下のとおり。

(>0_0)> You_Have_Awakened_Me_Too_Soon_EXE@flare-on.com <(0_0<)\r\n

フラグはYou_Have_Awakened_Me_Too_Soon_EXE@flare-on.com

03 antioch

Docker及び64ビット ELFファイルを解析する問題。antioch.tarというファイルを渡されるので、解凍すると無数のディレクトリとファイルが作成された。どうやらantioch.tarはDockerのイメージをtarファイルとして保存したものである模様。a13ffcf46cf41480e7f15c7f3c6b862b799bbe61e7d5909150d8a43bd3b6c039.json というJSONファイルを覗いてみるとAntiochOSというファイルを参照していた。またmanifest.jsonを覗いてみると7016b68f19aed3bb67ac4bf310defd3f7e0f7dd3ce544177c506d795f0b2acf3/layer.tarというファイルを参照していた。ディレクトリ7016b68f19aed3bb67ac4bf310defd3f7e0f7dd3ce544177c506d795f0b2acf3に移動し、layer.tarを展開すると件のAntiochOSという64ビットのELFファイルが解凍された。 

$ 7z l layer.tar

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)

Scanning the drive for archives:
1 file, 14848 bytes (15 KiB)

Listing archive: layer.tar

--
Path = layer.tar
Type = tar
Physical Size = 14848
Headers Size = 1536
Code Page = UTF-8

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2021-07-23 11:21:55 .....        13016        13312  AntiochOS
------------------- ----- ------------ ------------  ------------------------
2021-07-23 11:21:55              13016        13312  1 files
$ file AntiochOS
AntiochOS: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

AntiochOSを眺めてみたところ、いくつか興味深いスタック文字列を発見した。

さらに解析を進めたところ、AntiochOSは以下のコマンドを受け付けることが判明した。

  • quit : プログラムを終了する。
  • help : ヘルプを表示する。。が特に有用な情報は表示されない
  • consult (サブルーチン 0x401460) : "Consult the Book of Armaments!"というメッセージとともに正体不明のデータを表示する。
  • approach (サブルーチン 0x401640) : "Approach the Gorge of Eternal Peril!" というメッセージを表示した後、 以下の質問を表示する
    • What is your name?
    • What is your quest?
    • What is your favorite color?
    • 上記の3つの質問に対して正しく答えていくと"Right. Off you go. #" というメッセージとともに何らかのデータを表示する模様。

上記のコマンドで特に興味深いのはconsultとapproachである。approachコマンドの各質問に対して正しい答えを入力すればフラグを取得できるものとアタリをつけて、まずはapproachコマンドから解析した。

まず手始めにデバッガでジャンプ命令を操作して上記の3つの質問をバイパスしたあとに"Right. Off you go. #" のメッセージの直後にメモリにフラグらしきデータがないか確認してみたが空振りに終わった。やはり質問に対して正しい回答を入力しないとフラグを取得できない模様。

"What is your name?"と"What is your favorite color"という質問への回答についてはサブルーチン0x401B50にて何らかのチェックを行っているようだったが、処理が複雑で具体的に何をするコードかわからなかった。

解析を続けるうち、"What is your name?"という質問に対しては、以下の名前のいずれかを入力すれば良いことがわかった。

Sir Lancelot
King Arthur
Sir Robin
Sir Bedevere
Black Knight
Tim the Enchanter
Squire Patsy
Squire Concorde
Bridge Keeper
Roger the Shrubber
Prince Herbert
Brother Maynard
Miss Islington
Trojan Rabbit
A Famous Historian
Inspector End Of Film
Lady of the Lake
Green Knight
Sir Gawain
Sir Ector
Sir Bors
Zoot
Dinky
Rabbit of Caerbannog
Dennis the Peasant
Sir Not-Appearing-in-this-Film
Dragon of Angnor
Chicken of Bristol
Legendary Black Beast of Argh
Sir Gallahad

antioch.tarに含まれている各サブディレクトリ内にはjsonという名前のJSONファイルが存在しており、各ファイルのauthor欄に上記の名前が記述されていた。ちなみにこれらの名前はコメディ映画「Monty Python and the Holy Grail 」の登場人物の名前である。
しかし、"What is your quest?" と "What is your favorite color?" の質問に対する回答はわからず、approachコマンドの解析は断念した。

続いてもう一つの気になるコマンド consultを解析した。どうやらこのコマンドはa.datからz.datというファイルを読み込んで、なんらかの復号処理をしたのち、復号した内容を出力する模様。

antioch.tarに含まれている各サブディレクトリ内のlayer.tarにはa.datb.datc.datという無数の.datファイルが含まれていた。しかし、a.datからz.datまで全ての.datを内包したlayer.tarはなかった。以下は9a31bad171ad7e8009fba41193d339271fc51f992b8d574c501cae1bfa6c3fe2/layer.tarに内包されているファイルの一覧である。

Path = 9a31bad171ad7e8009fba41193d339271fc51f992b8d574c501cae1bfa6c3fe2/layer.tar
Type = tar
Physical Size = 88576
Headers Size = 10752
Code Page = UTF-8

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2021-07-20 11:05:14 .....         4096         4096  a.dat
2021-07-20 11:05:14 .....         4096         4096  b.dat
2021-07-20 11:05:14 .....         4096         4096  d.dat
2021-07-20 11:05:14 .....         4096         4096  e.dat
2021-07-20 11:05:14 .....         4096         4096  f.dat
2021-07-20 11:05:14 .....         4096         4096  g.dat
2021-07-20 11:05:14 .....         4096         4096  i.dat
2021-07-20 11:05:14 .....         4096         4096  j.dat
2021-07-20 11:05:14 .....         4096         4096  k.dat
2021-07-20 11:05:14 .....         4096         4096  l.dat
2021-07-20 11:05:14 .....         4096         4096  m.dat
2021-07-20 11:05:14 .....         4096         4096  n.dat
2021-07-20 11:05:14 .....         4096         4096  p.dat
2021-07-20 11:05:14 .....         4096         4096  t.dat
2021-07-20 11:05:14 .....         4096         4096  v.dat
2021-07-20 11:05:14 .....         4096         4096  w.dat
2021-07-20 11:05:14 .....         4096         4096  x.dat
2021-07-20 11:05:14 .....         4096         4096  y.dat
2021-07-20 11:05:14 .....         4096         4096  z.dat
------------------- ----- ------------ ------------  ------------------------
2021-07-20 11:05:14              77824        77824  19 files

c.dath.dato.datq.datr.dats.datu.datが欠けているのがわかる。いずれのサブディレクトリ内のlayer.tarもこんな調子でファイルが欠けていた。

consultコマンドに正しいファイルを読み込ませることが出来れば、正しい出力結果が表示されてフラグ取得のヒントかフラグそのものを取得できるのでは、と推測したがconsultコマンドが読み込むファイルの条件・法則がわからず。。

結局3問目を突破できず、今年のFlare-On Challengeは終了した。

Leave a Reply

Your email address will not be published. Required fields are marked *