前回 は、picoCTF の picoCTF 2024 のうち、Web Exploitation をやってみました。全6問のうち、最後の 2問は解けませんでした。
今回は、引き続き、picoCTF の picoCTF 2024 のうち、Forensics というカテゴリの全8問をやっていきたいと思います。Easy が 4問、Medium が 4問です。
それでは、やっていきます。
はじめに
「セキュリティ」の記事一覧です。良かったら参考にしてください。
セキュリティの記事一覧
picoCTF の公式サイトは以下です。英語のサイトですが、シンプルで分かりやすいので困らずに進めることができます。
picoctf.com
それでは、やっていきます。
picoCTF 2024:Forensics
ポイントの低い順にやっていきます。
Scan Surprise(50ポイント)
Easy の問題です。ZIPファイルが1つ(challenge.zip)ダウンロードできます。また、サーバ(インスタンス)を起動することも出来るようです。
解凍すると、PNGファイル(flag.png)が得られます。開いてみると、QRコードのようです。とりあえず、スマホで QRコードを読み取ってみます。フラグが表示されました。そのままスマホでログインしてフラグを提出できました。
サーバはなんだったんでしょうか(笑)。
Verify(50ポイント)
Easy の問題です。ZIPファイルが1つ(challenge.zip)ダウンロードできます。また、サーバ(インスタンス)を起動することも出来るようです。
解凍すると、SHA256 のチェックサムが書かれたファイルと復号用のシェルスクリプト、それと、301個のファイルがあります。この中からチェックサムが一致するものを探すということのようです。
まずは、SHA256 を全ファイルに対して計算します。テキストファイルに保存して一致するものを探します。見つかりました(451fd69b)。
$ find files/ -type f | xargs sha256sum > sha256.txt
次は、このファイルを復号します。シェルスクリプトは、パスが固定されているので、直接 OpenSSL のコマンドを実行します。フラグが表示されました。
$ openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -salt -in 451fd69b -k picoCTF
picoCTF{trust_but_verify_451fd69b}
今回もサーバは使用しませんでした。
CanYouSee(100ポイント)
Easy の問題です。ZIPファイルが1つ(unknown.zip)ダウンロードできます。
解凍すると、JPGファイル(ukn_reality.jpg)が得られます。開いてみましたが、パッと見て、フラグらしいものはありません。
最近入手した、うさみみハリケーンを使ってみます。YARAルールでスキャンというのをクリックします。ukn_reality.jpg を対象としてスキャン開始します。すぐに結果が出て、picoCTF のフラグ情報が オフセット 0x162 にある、と出ました。すごいです。
バイナリエディタで開きます。0x162 の位置には、Base64 っぽい ASCIIコードが並んでいます。デコードすると、フラグが表示されました。
$ echo -n 'cGljb0NURntNRTc0RDQ3QV9ISUREM05fYTZkZjhkYjh9Cg==' | base64 -d
picoCTF{ME74D47A_HIDD3N_a6df8db8}
Secret of the Polyglot(100ポイント)
Easy の問題です。1つのファイル(flag2of2-final.pdf)ダウンロードできます。
本当に PDFファイルなんでしょうか。確認します。PNGファイルでした。
$ file flag2of2-final.pdf
flag2of2-final.pdf: PNG image data, 50 x 50, 8-bit/color RGBA, non-interlaced
拡張子を変更して開いてみます。picoCTF{f1u3n7_
が書かれてました。残りのフラグを探す必要があります。
バイナリエディタで開いてみます。途中から ASCIIコードがたくさん書かれていますが、それらしいものは見つかりません。うさみみハリケーンの YARAルールでスキャンします。
0x69C から怪しいようです。「xpacket begin」というように書かれています。検索すると、PDF の埋め込み情報とのことです。抽出してみましたが、何か XMP とかいうフォーマットらしいです。
あれこれやってるうちに、Chrome に放り投げたら、残りのフラグが表示されました。困ったときは、Chrome に読ませればいいようです(笑)。
Mob psycho(200ポイント)
Medium の問題です。1つのファイル(mobpsycho.apk)ダウンロードできます。
簡単に調べてみます。
$ file Mob\ psycho/mobpsycho.apk
Mob psycho/mobpsycho.apk: Zip archive data, at least v1.0 to extract, compression method=store
apkファイルは ZIP で圧縮されています。まずは、解凍します。普通の apkファイルのようです。
今回も、まずは、うさみみハリケーンの YARAルールでスキャンします。
解凍したファイルの 1つを指定して、「対象ファイルのあるフォルダごとスキャン」と「サブフォルダもスキャン」にチェックを入れて、スキャン開始をクリックします。
最初にヒットしたのは、classes.dex です。0x6C9CBF の位置のようです。strings では抽出できません。strings合致条件は、picoCTF_Flag_Text_Padding_Reverse というものです。ルールは、以下です。
$picoCTF_Flag_Text_Padding_Reverse = {7B [1-32] 46 [1-32] 54 [1-32] 43 [1-32] 6F [1-32] 63 [1-32] 69 [1-32] 70} //picoCTF2022
picoCTF{
を ASCIIコードにします。
$ python -c 'print([f"0x{ord(cc):02X}" for cc in list("picoCTF{")])'
['0x70', '0x69', '0x63', '0x6F', '0x43', '0x54', '0x46', '0x7B']
さらに、これを逆順にします。つまり、picoCTF{
を逆順にして、さらに、1文字ずつ間隔が 1byteから32byte空いているということだと思います。
$ python -c 'print(list(reversed([f"0x{ord(cc):02X}" for cc in list("picoCTF{")])))'
['0x7B', '0x46', '0x54', '0x43', '0x6F', '0x63', '0x69', '0x70']
なるほど、ですが、さすがに、一定の間隔でもないので、たまたまな気もします。
次にヒットしたのが、res/color/flag.txt です。名前からして怪しいです(笑)。ファイルを開くと、7069636f4354467b6178386d433052553676655f4e5838356c346178386d436c5f38356462643231357d
が書かれてました。
あとは、ASCIIコードに直すだけです。
$ python -c 'hh="7069636f4354467b6178386d433052553676655f4e5838356c346178386d436c5f38356462643231357d"; print("".join([chr(int(hh[ii] + hh[ii+1], base=16)) for ii in range(0, len(hh),
2)]))'
picoCTF{ax8mC0RU6ve_NX85l4ax8mCl_85dbd215}
apkファイルのデコンパイル
ちょっと寄り道して、apkファイルをデコンパイルしたりしてたので、以下は、参考です。
デコンパイルしてみます。dex2jar と JD-GUI を使います。
以下の Releases にある dex2jar の v2.4 を使います。
github.com
解凍して、以下を実行します。classes-dex2jar.jar が得られました。
$ ~/Downloads/dex-tools-v2.4/d2j-dex2jar.sh classes.dex
dex2jar classes.dex -> ./classes-dex2jar.jar
以下の Releases にある JD-GUI 1.6.6 を使います。
github.com
解凍すると、jd-gui.exe があるのでダブルクリックして起動します。
classes-dex2jar.jar を開きます。デコンパイルしたソースコードが表示されます。
もっと簡単に、apk を直接デコンパイルして表示してくれるツールもあります。jadx というツールで、以下になります。
以下の Releases にある 1.5.0 を使用してみます。直接 apk を指定できるので楽ですね。
github.com
デコンパイルは出来ましたが、さすがに量が多いですし、そもそもリバースエンジニアリングのカテゴリでもないですね。
endianness-v2(300ポイント)
Medium の問題です。1つのファイル(challengefile)ダウンロードできます。
軽く調べます。うーん、ただのデータです。うさみみハリケーンも同じ解析結果です。
$ file challengefile
challengefile: data
バイナリエディタで開いてみます。4KB弱のファイルです。エンディアンという問題名なので、先頭をひっくり返してみます。
E0 FF D8 FF
→ FF D8 FF E0
になります。Web検索してみると、これは JPEG の先頭と一致するらしいです。また、末尾も FF D9
で終わるらしく、それも満たしています。
では、エンディアンを変換する Pythonスクリプトを実装します。4byte のエンディアン変換です。
import struct
def fread_bin( fpath ):
with open(fpath, 'rb') as ff:
data = ff.read()
return data
def fwrite_bin( fpath, data ):
with open(fpath, 'wb') as ff:
ff.write( data )
def endian( fpath, fpath_out ):
data = fread_bin( fpath )
if len(data) % 4 != 0:
data += b'0' * (4 - len(data) % 4)
assert len(data) % 4 == 0, "fatal"
bret = b''
ii = 0
while ii + 4 <= len(data):
tmp = struct.unpack( '<I', data[ii:ii+4] )
bret += struct.pack( '>I', tmp[0] )
ii += 4
fwrite_bin( fpath_out, bret )
endian( "../picoCTF/picoCTF2024_Forensics/challengefile", "../picoCTF/picoCTF2024_Forensics/challengefile.jpg" )
実行すると、JPGファイルが出力されます。
$ python tmp.py
JPGファイルを開くとフラグ(picoCTF{cert!f1Ed_iNd!4n_s0rrY_3nDian_76e05f49}
)が表示されました。
Blast from the past(300ポイント)
Medium の問題です。1つの画像ファイル(original.jpg)ダウンロードできます。また、サーバも起動できます。
画像ファイルを開いてみると、額に入った絵が写ってるだけです。
ファイルのタイムスタンプを変更してアップロードすればいいのでしょうか。とりあえず、変更してないファイルをサーバにアップロードしてみます。
$ nc -w 2 mimas.picoctf.net 59346 < original.jpg
$ nc mimas.picoctf.net 58619
MD5 of your picture:
06783ef2aa4460a3d267002a28ff12c6 test.out
Checking tag 1/7
Looking at IFD0: ModifyDate
Looking for '1970:01:01 00:00:00'
Found: 2023:11:20 15:46:23
Oops! That tag isn't right. Please try again.
Web検索で調べてみると、touchコマンドが使えるという情報が出てきます。やってみます。
$ touch -d "1970/1/1 00:00:00" original.jpg
$ stat original.jpg
File: original.jpg
Size: 2851929 Blocks: 5576 IO Block: 4096 regular file
Device: 0,38 Inode: 189674 Links: 1
Access: (0744/-rwxr--r--) Uid: ( 1000/ user) Gid: ( 1000/ user)
Access: 2024-10-17 21:27:38.861306577 +0900
Modify: 1970-01-01 00:00:00.000000000 +0900
Change: 2024-10-17 21:27:37.757972765 +0900
Birth: 2024-10-17 21:06:18.146412278 +0900
$ nc -w 2 mimas.picoctf.net 59346 < original.jpg
$ nc mimas.picoctf.net 58619
MD5 of your picture:
06783ef2aa4460a3d267002a28ff12c6 test.out
Checking tag 1/7
Looking at IFD0: ModifyDate
Looking for '1970:01:01 00:00:00'
Found: 2023:11:20 15:46:23
Oops! That tag isn't right. Please try again.
+0900
となっているので、-9時間で設定してみます。うーん、ダメです。出力された内容を見ると、2023:11:20 15:46:23
が見つかったと言っています。
$ touch -d "1969/12/31 15:00:00" original.jpg
$ stat original.jpg
File: original.jpg
Size: 2851929 Blocks: 5576 IO Block: 4096 regular file
Device: 0,38 Inode: 189674 Links: 1
Access: (0744/-rwxr--r--) Uid: ( 1000/ user) Gid: ( 1000/ user)
Access: 2024-10-17 21:30:00.788033547 +0900
Modify: 1969-12-31 15:00:00.000000000 +0900
Change: 2024-10-17 21:29:59.721366434 +0900
Birth: 2024-10-17 21:06:18.146412278 +0900
$ nc -w 2 mimas.picoctf.net 59346 < original.jpg
$ nc mimas.picoctf.net 58619
MD5 of your picture:
06783ef2aa4460a3d267002a28ff12c6 test.out
Checking tag 1/7
Looking at IFD0: ModifyDate
Looking for '1970:01:01 00:00:00'
Found: 2023:11:20 15:46:23
Oops! That tag isn't right. Please try again.
exiftool で見てみます。いくつか 2023:11:20 15:46:23
がありますね。
$ exiftool original.jpg
ExifTool Version Number : 12.57
File Name : original.jpg
Directory : .
File Size : 2.9 MB
File Modification Date/Time : 1969:12:31 15:00:00+09:00
File Access Date/Time : 2024:10:17 21:30:00+09:00
File Inode Change Date/Time : 2024:10:17 21:29:59+09:00
File Permissions : -rwxr--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Little-endian (Intel, II)
Image Description :
Make : samsung
Camera Model Name : SM-A326U
Orientation : Rotate 90 CW
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Software : MediaTek Camera Application
Modify Date : 2023:11:20 15:46:23
Y Cb Cr Positioning : Co-sited
Exposure Time : 1/24
F Number : 1.8
Exposure Program : Program AE
ISO : 500
Sensitivity Type : Unknown
Recommended Exposure Index : 0
Exif Version : 0220
Date/Time Original : 2023:11:20 15:46:23
Create Date : 2023:11:20 15:46:23
Components Configuration : Y, Cb, Cr, -
Shutter Speed Value : 1/24
Aperture Value : 1.9
Brightness Value : 3
Exposure Compensation : 0
Max Aperture Value : 1.8
Metering Mode : Center-weighted average
Light Source : Other
Flash : On, Fired
Focal Length : 4.6 mm
Sub Sec Time : 703
Sub Sec Time Original : 703
Sub Sec Time Digitized : 703
Flashpix Version : 0100
Color Space : sRGB
Exif Image Width : 4000
Exif Image Height : 3000
Interoperability Index : R98 - DCF basic file (sRGB)
Interoperability Version : 0100
Exposure Mode : Auto
White Balance : Auto
Digital Zoom Ratio : 1
Focal Length In 35mm Format : 25 mm
Scene Capture Type : Standard
Compression : JPEG (old-style)
Thumbnail Offset : 1408
Thumbnail Length : 64000
Image Width : 4000
Image Height : 3000
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Time Stamp : 2023:11:21 05:46:21.420+09:00
MCC Data : United States / Guam
Aperture : 1.8
Image Size : 4000x3000
Megapixels : 12.0
Scale Factor To 35 mm Equivalent: 5.4
Shutter Speed : 1/24
Create Date : 2023:11:20 15:46:23.703
Date/Time Original : 2023:11:20 15:46:23.703
Modify Date : 2023:11:20 15:46:23.703
Thumbnail Image : (Binary data 64000 bytes, use -b option to extract)
Circle Of Confusion : 0.006 mm
Field Of View : 71.5 deg
Focal Length : 4.6 mm (35 mm equivalent: 25.0 mm)
Hyperfocal Distance : 2.13 m
Light Value : 4.0
exiftool には、撮影時刻を変更することが出来る機能があるようです。やってみます。
うーん、ms単位でずれてしまった感じでしょうか。
$ exiftool -AllDates='1970:01:01 00:00:00' -overwrite_original original.jpg
1 image files updated
$ exiftool original.jpg
ExifTool Version Number : 12.57
File Name : original.jpg
Directory : .
File Size : 2.9 MB
File Modification Date/Time : 2024:10:17 21:37:11+09:00
File Access Date/Time : 2024:10:17 21:37:12+09:00
File Inode Change Date/Time : 2024:10:17 21:37:11+09:00
File Permissions : -rwxr--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Little-endian (Intel, II)
Image Description :
Make : samsung
Camera Model Name : SM-A326U
Orientation : Rotate 90 CW
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Software : MediaTek Camera Application
Modify Date : 1970:01:01 00:00:00
Y Cb Cr Positioning : Co-sited
Exposure Time : 1/24
F Number : 1.8
Exposure Program : Program AE
ISO : 500
Sensitivity Type : Unknown
Recommended Exposure Index : 0
Exif Version : 0220
Date/Time Original : 1970:01:01 00:00:00
Create Date : 1970:01:01 00:00:00
Components Configuration : Y, Cb, Cr, -
Shutter Speed Value : 1/24
Aperture Value : 1.9
Brightness Value : 3
Exposure Compensation : 0
Max Aperture Value : 1.8
Metering Mode : Center-weighted average
Light Source : Other
Flash : On, Fired
Focal Length : 4.6 mm
Sub Sec Time : 703
Sub Sec Time Original : 703
Sub Sec Time Digitized : 703
Flashpix Version : 0100
Color Space : sRGB
Exif Image Width : 4000
Exif Image Height : 3000
Interoperability Index : R98 - DCF basic file (sRGB)
Interoperability Version : 0100
Exposure Mode : Auto
White Balance : Auto
Digital Zoom Ratio : 1
Focal Length In 35mm Format : 25 mm
Scene Capture Type : Standard
Compression : JPEG (old-style)
Thumbnail Offset : 1124
Thumbnail Length : 64000
Image Width : 4000
Image Height : 3000
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Time Stamp : 2023:11:21 05:46:21.420+09:00
MCC Data : United States / Guam
Aperture : 1.8
Image Size : 4000x3000
Megapixels : 12.0
Scale Factor To 35 mm Equivalent: 5.4
Shutter Speed : 1/24
Create Date : 1970:01:01 00:00:00.703
Date/Time Original : 1970:01:01 00:00:00.703
Modify Date : 1970:01:01 00:00:00.703
Thumbnail Image : (Binary data 64000 bytes, use -b option to extract)
Circle Of Confusion : 0.006 mm
Field Of View : 71.5 deg
Focal Length : 4.6 mm (35 mm equivalent: 25.0 mm)
Hyperfocal Distance : 2.13 m
Light Value : 4.0
$ nc -w 2 mimas.picoctf.net 59346 < original.jpg
$ nc mimas.picoctf.net 58619
MD5 of your picture:
e7537a20fd614f08232eaa16d4f6587a test.out
Checking tag 1/7
Looking at IFD0: ModifyDate
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 2/7
Looking at ExifIFD: DateTimeOriginal
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 3/7
Looking at ExifIFD: CreateDate
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 4/7
Looking at Composite: SubSecCreateDate
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.703
Oops! That tag isn't right. Please try again.
いろいろやりましたが、最後の 1個が変更できません。
$ nc mimas.picoctf.net 49568
MD5 of your picture:
dfeec95e00a63491611fa7f106a0ebfe test.out
Checking tag 1/7
Looking at IFD0: ModifyDate
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 2/7
Looking at ExifIFD: DateTimeOriginal
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 3/7
Looking at ExifIFD: CreateDate
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 4/7
Looking at Composite: SubSecCreateDate
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.001
Great job, you got that one!
Checking tag 5/7
Looking at Composite: SubSecDateTimeOriginal
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.001
Great job, you got that one!
Checking tag 6/7
Looking at Composite: SubSecModifyDate
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.001
Great job, you got that one!
Checking tag 7/7
Timezones do not have to match, as long as it's the equivalent time.
Looking at Samsung: TimeStamp
Looking for '1970:01:01 00:00:00.001+00:00'
Found: 2023:11:20 20:46:21.420+00:00
Oops! That tag isn't right. Please try again.
Exif を書き換える GUIツールを使ってみました。1つは、JExifToolGUI V2.0.2 で、jarファイルだったので、ParrotOS で、$ java -jar jExifToolGUI.jar &
で起動できました。しかし、TimeStamp を書き換えることは出来ませんでした。もう1つは、ExifToolGUI_X64.exe で、これは Windowsアプリです。exiftool.exe という CUIプログラムのラッパーらしいです。exiftool.exe を同じディレクトリに置いて、ExifToolGUI_X64.exe をダブルクリックで起動できます。こちらの方も結果的には TimeStamp を書き換えることは出来ませんでしたが、使いやすいツールでした。
ギブアップです。writeupを見ると、バイナリエディタで書き換えるようです。
オフセット 0x2B8228 から始まっている Image_UTC_Data1700513181420
を変更するとのことです。変更できなかった時刻は、2023:11:20 20:46:21.420+00:00
です。下位の 3文字がミリ秒を表しているようです。エポック時間に直してみます。一致しました。
$ python -c 'import datetime; print(datetime.datetime.fromtimestamp(1700513181))'
2023-11-21 05:46:21
あとは、Looking for '1970:01:01 00:00:00.001+00:00'
に合わせればいいので、エポック時間は 0 になり、小数点が 001 です。バイナリエディタで編集します。
では、実行してみます。
$ nc -w 2 mimas.picoctf.net 61487 < ../picoCTF/picoCTF2024_Forensics/original.jpg
$ nc mimas.picoctf.net 49568
MD5 of your picture:
a664348eec39335cab61850c7f530b94 test.out
Checking tag 1/7
Looking at IFD0: ModifyDate
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 2/7
Looking at ExifIFD: DateTimeOriginal
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 3/7
Looking at ExifIFD: CreateDate
Looking for '1970:01:01 00:00:00'
Found: 1970:01:01 00:00:00
Great job, you got that one!
Checking tag 4/7
Looking at Composite: SubSecCreateDate
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.001
Great job, you got that one!
Checking tag 5/7
Looking at Composite: SubSecDateTimeOriginal
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.001
Great job, you got that one!
Checking tag 6/7
Looking at Composite: SubSecModifyDate
Looking for '1970:01:01 00:00:00.001'
Found: 1970:01:01 00:00:00.001
Great job, you got that one!
Checking tag 7/7
Timezones do not have to match, as long as it's the equivalent time.
Looking at Samsung: TimeStamp
Looking for '1970:01:01 00:00:00.001+00:00'
Found: 1970:01:01 00:00:00.001+00:00
Great job, you got that one!
You did it!
picoCTF{71m3_7r4v311ng_p1c7ur3_3e336564}
もうちょっと粘りが足りませんでした。
Dear Diary(400ポイント)
Medium の問題です。1つのディスクイメージ?(disk.flag.img.gz)をダウンロードできます。
軽く調べます。本当に gzip みたいなので解凍します。本当にディスクイメージのようです。
$ file disk.flag.img.gz
disk.flag.img.gz: gzip compressed data, was "disk.flag.img", last modified: Sat Feb 17 22:59:04 2024, from Unix, original size modulo 2^32 1073741824
$ gzip -d disk.flag.img.gz
$ file disk.flag.img
disk.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x26,94,56), startsector 2048, 614400 sectors; partition 2 : ID=0x82, start-CHS (0x26,94,57), end-CHS (0x47,1,58), startsector 616448, 524288 sectors; partition 3 : ID=0x83, start-CHS (0x47,1,59), end-CHS (0x82,138,8), startsector 1140736, 956416 sectors
まずは、マウントしてみます。
$ sudo mount disk.flag.img mnt/
mount: /home/user/svn/experiment/picoCTF/picoCTF2024_Forensics/mnt: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.
dmesg(1) may have more information after failed mount system call.
うーん、ダメですね。以前、Windows用のディスクイメージのツールの「FTK Imager」と「Autospy」の 2つを使いました。せっかくなんで使ってみます。
「FTK Imager」の方は、File → Add Evidence Item... → Image File で disk.flag.img を指定すると中を見ることができました。エクスプローラー風に見れます。
適当に見てみると、Alpine という OS で、ユーザは root のみで、root のホームディレクトリを見ましたが、それらしいものはありません。3番目のパーティションのルートファイルシステムと思われるドライブを全てエクスポートして、うさみみハリケーンの YARAルールスキャンで全探索してみました。たくさんヒットしましたが、フラグは見当たりませんでした。
「Autospy」の方は、だいぶ時間がかかりましたが、ダメでした。
今回のイメージは、Linux なので、ちゃんと調べればマウントできると思います。
fdiskコマンドで見てみます。3番目の disk.flag.img3 というのが ext4 のフォーマットだったので、これをマウントしたいです。
ちょっと調べてみると、オフセット(byte単位)が分かればマウントできるようです。Startセクタに512byteをかけるだけです。1140736 * 512 = 584056832
$ fdisk -l disk.flag.img
Disk disk.flag.img: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x6062d30a
Device Boot Start End Sectors Size Id Type
disk.flag.img1 * 2048 616447 614400 300M 83 Linux
disk.flag.img2 616448 1140735 524288 256M 82 Linux swap / Solaris
disk.flag.img3 1140736 2097151 956416 467M 83 Linux
やってみます。うーん、さっきよりマシですが、スーパーブロックが読めないというエラーのようです。
$ sudo mount -t ext4 -o loop,offset=584056832 disk.flag.img mnt/
mount: /home/user/svn/experiment/picoCTF/picoCTF2024_Forensics/mnt: can't read superblock on /dev/loop0.
dmesg(1) may have more information after failed mount system call.
$ dumpe2fs -h disk.flag.img
dumpe2fs 1.47.1-rc2 (01-May-2024)
dumpe2fs: Bad magic number in super-block while trying to open disk.flag.img
Couldn't find valid filesystem superblock.
disk.flag.img contains `DOS/MBR boot sector;
partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x26,94,56), startsector 2048, 614400 sectors;
partition 2 : ID=0x82, start-CHS (0x26,94,57), end-CHS (0x47,1,58), startsector 616448, 524288 sectors;
partition 3 : ID=0x83, start-CHS (0x47,1,59), end-CHS (0x82,138,8), startsector 1140736, 956416 sectors' data
最初のパーティションをマウントしてみます。組み込みとかによくあるブートパーティションでしょうか。マウントできました。
$ sudo mount -t ext4 -o loop,offset=1048576 disk.flag.img mnt/
おそらく、スーパーブロックを修正するドライブが重要だと思うので、ダメだと思いますが、軽く探してみます。やはり、何もなさそうです。ついでに、こちらも YARAルールスキャンしましたが、ダメでした。
./System.map-virt:ffffffff8199f380 t __pfx_pirq_pico_get
./System.map-virt:ffffffff8199f390 t pirq_pico_get
./System.map-virt:ffffffff8199f3c0 t __pfx_pirq_pico_set
./System.map-virt:ffffffff8199f3d0 t pirq_pico_set
./System.map-virt:ffffffff82a24cc0 t __pfx_pico_router_probe
./System.map-virt:ffffffff82a24cd0 t pico_router_probe
3番目のパーティションのスーパーブロックが壊れているようなので、修復することが求められている気がします。そのあたりでフラグが見つかる気がします。
$ fsck.ext4 disk.flag.img
e2fsck 1.47.1-rc2 (01-May-2024)
ext2fs_open2: Bad magic number in super-block
fsck.ext4: Superblock invalid, trying backup blocks...
fsck.ext4: Bad magic number in super-block while trying to open disk.flag.img
The superblock could not be read or does not describe a valid ext2/ext3/ext4
filesystem. If the device is valid and it really contains an ext2/ext3/ext4
filesystem (and not swap or ufs or something else), then the superblock
is corrupt, and you might try running e2fsck with an alternate superblock:
e2fsck -b 8193 <device>
or
e2fsck -b 32768 <device>
disk.flag.img contains `DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x26,94,56), startsector 2048, 614400 sectors; partition 2 : ID=0x82, start-CHS (0x26,94,57), end-CHS (0x47,1,58), startsector 616448, 524288 sectors; partition 3 : ID=0x83, start-CHS (0x47,1,59), end-CHS (0x82,138,8), startsector 1140736, 956416 sectors' data
$ mkfs.ext4 -n disk.flag.img
mke2fs 1.47.1-rc2 (01-May-2024)
disk.flag.img contains `DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x26,94,56), startsector 2048, 614400 sectors; partition 2 : ID=0x82, start-CHS (0x26,94,57), end-CHS (0x47,1,58), startsector 616448, 524288 sectors; partition 3 : ID=0x83, start-CHS (0x47,1,59), end-CHS (0x82,138,8), startsector 1140736, 956416 sectors' data
Proceed anyway? (y,N) y
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: 29390527-0466-4886-b948-2ca3d3f01714
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
$ e2fsck -b 32768 disk.flag.img
e2fsck 1.47.1-rc2 (01-May-2024)
e2fsck: Attempt to read block from filesystem resulted in short read while trying to open disk.flag.img
Could this be a zero-length partition?
disk.flag.img を直接バイナリエディタで見ます。
先頭の MBR を見ます。0x1BE の位置からパーティションテーブルが始まります。16byteずつです。3つに値が入っています。5byte目に ID が入っています。1番目と3番目は 0x83 なので、EXT2/3/4 です。2番目は 0x82 なのでスワップ領域です。
まず、正常な 1番目のパーティションを見ます。2048セクタから始まってるので、2048セクタ×512byte=0x100000
を見ます。スーパーブロックは、1024byte オフセットの位置(今回なら 0x100400)から始まってるそうです。
スーパーブロックの 0x38 の位置(今回なら 0x100438)にマジックナンバーがあります。EXT2/3/4 なら 0xEF53 になっています。確かになってます。3番目のパーティションはここが壊れているということでした。
3番目のパーティションも同時に見ていきます。パーティションの開始位置は、1140736セクタ×512byte=0x22D00000
です。1024byteオフセットのセクタを見てみます。うーん、マジックナンバー(0x22d00438)は普通に 0xEF53 が入っていました。問題の場所が分かりません。
いろいろ調べていたところ、複数パーティションを含む場合の別のマウント方法がありました。いろいろやったらマウントできました。
losetupコマンドは、ループバックデバイスを使用してディスクイメージをデバイスとして扱えるようになります。これにより、/dev に割り当たりました。
mkfs.ext4 の -n オプションを使うことで、スーパーブロックの代替ブロックの位置を知ることが出来ます。
e2fsckコマンドでスーパーブロックの修復を試みるコマンドです。これにより、バックアップされていたスーパーブロックで修復が出来て、マウントすることが出来ました。
$ sudo losetup -P --show -f disk.flag.img
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 1G 0 loop
tqloop0p1 259:0 0 300M 0 part
tqloop0p2 259:1 0 256M 0 part
mqloop0p3 259:2 0 467M 0 part
sda 8:0 0 64G 0 disk
tqsda1 8:1 0 50M 0 part /boot/efi
mqsda2 8:2 0 63.9G 0 part /home
/
$ sudo mount -t ext4 /dev/loop0p3 mnt2/
mount: /home/user/svn/experiment/picoCTF/picoCTF2024_Forensics/mnt2: can't read superblock on /dev/loop0p3.
dmesg(1) may have more information after failed mount system call.
$ sudo mkfs.ext4 -n /dev/loop0p3
mke2fs 1.47.1-rc2 (01-May-2024)
/dev/loop0p3 contains a ext4 file system
last mounted on / on Sun Feb 18 04:03:14 2024
Proceed anyway? (y,N) y
Creating filesystem with 478208 1k blocks and 119416 inodes
Filesystem UUID: 3b9ea8b2-67c2-4368-a6e8-f9fefbdf5b63
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
$ sudo mount -t ext4 /dev/loop0p3 mnt2/
mount: /home/user/svn/experiment/picoCTF/picoCTF2024_Forensics/mnt2: can't read superblock on /dev/loop0p3.
dmesg(1) may have more information after failed mount system call.
$ sudo e2fsck -b 8193 /dev/loop0p3
e2fsck 1.47.1-rc2 (01-May-2024)
Superblock needs_recovery flag is clear, but journal has data.
Recovery flag not set in backup superblock, so running journal anyway.
/dev/loop0p3: recovering journal
JBD2: Invalid checksum recovering data block 15602 in log
JBD2: Invalid checksum recovering data block 15602 in log
JBD2: Invalid checksum recovering data block 15602 in log
Journal checksum error found in /dev/loop0p3
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(73729--73989) +(204801--205061) +(221185--221445) +(401409--401669)
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong for group
Fix<y>? yes
Free blocks count wrong (437564, counted=378717).
Fix<y>? yes
Free inodes count wrong for group
Fix<y>? yes
Directories count wrong for group
Fix<y>? yes
Free inodes count wrong for group
Fix<y>? yes
Directories count wrong for group
Fix<y>? yes
Free inodes count wrong for group
Fix<y>? yes
Directories count wrong for group
Fix<y>? yes
Free inodes count wrong (119404, counted=116975).
Fix<y>? yes
Padding at end of inode bitmap is not set. Fix<y>? yes
/dev/loop0p3: ***** FILE SYSTEM WAS MODIFIED *****
/dev/loop0p3: 2441/119416 files (0.8% non-contiguous), 99491/478208 blocks
$ sudo mount -t ext4 /dev/loop0p3 mnt2/
マウントまで出来たので、いろいろ探して見ましたが、見つけられませんでした。ギブアップです。
writeupを見ます。ジャーナルファイルの近くにフラグがあるそうです。バイナリエディタで、「innocuous-file.txt」を検索して、上から順番に見ていくと、pic
、oCT
、F{1
、_53
、3_n
、4m3
、5_8
、0d2
、4b3
、0}
が見つかった。
繋げると、picoCTF{1_533_n4m35_80d24b30}
になりました。
これで Medium なのはショックです。
これで、Forensics は終了です。
おわりに
今回は、picoCTF の picoCTF 2024 のうち、Forensics というカテゴリの全8問をやりました。最後の 2問は解けませんでしたが、苦手ないろんな知見が得られたと思います。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。