土日の勉強ノート

AI、機械学習、最適化、Pythonなどについて、技術調査、技術書の理解した内容、ソフトウェア/ツール作成について書いていきます

picoCTF 2024:Forensicsの全8問をやってみた(最後の2問は解けず)

前回 は、picoCTF の picoCTF 2024 のうち、Web Exploitation をやってみました。全6問のうち、最後の 2問は解けませんでした。

今回は、引き続き、picoCTF の picoCTF 2024 のうち、Forensics というカテゴリの全8問をやっていきたいと思います。Easy が 4問、Medium が 4問です。

それでは、やっていきます。

はじめに

「セキュリティ」の記事一覧です。良かったら参考にしてください。

セキュリティの記事一覧
・第1回:Ghidraで始めるリバースエンジニアリング(環境構築編)
・第2回:Ghidraで始めるリバースエンジニアリング(使い方編)
・第3回:VirtualBoxにParrotOS(OVA)をインストールする
・第4回:tcpdumpを理解して出力を正しく見れるようにする
・第5回:nginx(エンジンエックス)を理解する
・第6回:Python+Flask(WSGI+Werkzeug+Jinja2)を動かしてみる
・第7回:Python+FlaskのファイルをCython化してみる
・第8回:shadowファイルを理解してパスワードを解読してみる
・第9回:安全なWebアプリケーションの作り方(徳丸本)の環境構築
・第10回:Vue.jsの2.xと3.xをVue CLIを使って動かしてみる(ビルドも行う)
・第11回:Vue.jsのソースコードを確認する(ビルド後のソースも見てみる)
・第12回:徳丸本:OWASP ZAPの自動脆弱性スキャンをやってみる
・第13回:徳丸本:セッション管理を理解してセッションID漏洩で成りすましを試す
・第14回:OWASP ZAPの自動スキャン結果の分析と対策:パストラバーサル
・第15回:OWASP ZAPの自動スキャン結果の分析と対策:クロスサイトスクリプティング(XSS)
・第16回:OWASP ZAPの自動スキャン結果の分析と対策:SQLインジェクション
・第17回:OWASP ZAPの自動スキャン結果の分析と対策:オープンリダイレクト
・第18回:OWASP ZAPの自動スキャン結果の分析と対策:リスク中すべて
・第19回:CTF初心者向けのCpawCTFをやってみた
・第20回:hashcatの使い方とGPUで実行したときの時間を見積もってみる
・第21回:Scapyの環境構築とネットワークプログラミング
・第22回:CpawCTF2にチャレンジします(クリア状況は随時更新します)
・第23回:K&Rのmalloc関数とfree関数を理解する
・第24回:C言語、アセンブラでシェルを起動するプログラムを作る(ARM64)
・第25回:機械語でシェルを起動するプログラムを作る(ARM64)
・第26回:入門セキュリhttps://github.com/SECCON/SECCON2017_online_CTF.gitティコンテスト(CTFを解きながら学ぶ実践技術)を読んだ
・第27回:x86-64 ELF(Linux)のアセンブラをGDBでデバッグしながら理解する(GDBコマンド、関連ツールもまとめておく)
・第28回:入門セキュリティコンテスト(CTFを解きながら学ぶ実践技術)のPwnable問題をやってみる
・第29回:実行ファイルのセキュリティ機構を調べるツール「checksec」のまとめ
・第30回:setodaNote CTF Exhibitionにチャレンジします(クリア状況は随時更新します)
・第31回:常設CTFのksnctfにチャレンジします(クリア状況は随時更新します)
・第32回:セキュリティコンテストチャレンジブックの「Part2 pwn」を読んだ
・第33回:セキュリティコンテストチャレンジブックの「付録」を読んでx86とx64のシェルコードを作った
・第34回:TryHackMeを始めてみたけどハードルが高かった話
・第35回:picoCTFを始めてみた(Beginner picoMini 2022:全13問完了)
・第36回:picoCTF 2024:Binary Exploitationの全10問をやってみた(Hardの1問は後日やります)
・第37回:picoCTF 2024:Reverse Engineeringの全7問をやってみた(Windowsプログラムの3問は後日やります)
・第38回:picoCTF 2024:General Skillsの全10問をやってみた
・第39回:picoCTF 2024:Web Exploitationの全6問をやってみた(最後の2問は解けず)
・第40回:picoCTF 2024:Forensicsの全8問をやってみた(最後の2問は解けず) ← 今回

picoCTF の公式サイトは以下です。英語のサイトですが、シンプルで分かりやすいので困らずに進めることができます。

picoctf.com

それでは、やっていきます。

picoCTF 2024:Forensics

ポイントの低い順にやっていきます。

Scan Surprise(50ポイント)

Easy の問題です。ZIPファイルが1つ(challenge.zip)ダウンロードできます。また、サーバ(インスタンス)を起動することも出来るようです。

Scan Surprise問題
Scan Surprise問題

解凍すると、PNGファイル(flag.png)が得られます。開いてみると、QRコードのようです。とりあえず、スマホで QRコードを読み取ってみます。フラグが表示されました。そのままスマホでログインしてフラグを提出できました。

サーバはなんだったんでしょうか(笑)。

Verify(50ポイント)

Easy の問題です。ZIPファイルが1つ(challenge.zip)ダウンロードできます。また、サーバ(インスタンス)を起動することも出来るようです。

Verify問題
Verify問題

解凍すると、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)ダウンロードできます。

CanYouSee問題
CanYouSee問題

解凍すると、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)ダウンロードできます。

Secret of the Polyglot問題
Secret of the Polyglot問題

本当に 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)ダウンロードできます。

Mob psycho問題
Mob psycho問題

簡単に調べてみます。

$ 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)ダウンロードできます。

endianness-v2問題
endianness-v2問題

軽く調べます。うーん、ただのデータです。うさみみハリケーンも同じ解析結果です。

$ file challengefile
challengefile: data

バイナリエディタで開いてみます。4KB弱のファイルです。エンディアンという問題名なので、先頭をひっくり返してみます。

E0 FF D8 FFFF D8 FF E0 になります。Web検索してみると、これは JPEG の先頭と一致するらしいです。また、末尾も FF D9 で終わるらしく、それも満たしています。

では、エンディアンを変換する Pythonスクリプトを実装します。4byte のエンディアン変換です。

import struct

def fread_bin( fpath ):
    
    # バイナリファイルを読み出し → bytes型
    
    with open(fpath, 'rb') as ff:
        data = ff.read() # 引数(サイズ)を省略すると全データ読み出し
    
    return data

def fwrite_bin( fpath, data ):
    
    # bytes型をバイナリファイルを書き込み
    
    with open(fpath, 'wb') as ff:
        ff.write( data )

def endian( fpath, fpath_out ):
    
    # $ python common.py --ope endian --fpath ../picoCTF/picoCTF2024_Forensics/challengefile --fpath_out ../picoCTF/picoCTF2024_Forensics/challengefile.jpg
    
    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)ダウンロードできます。また、サーバも起動できます。

Blast from the past問題
Blast from the past問題

画像ファイルを開いてみると、額に入った絵が写ってるだけです。

ファイルのタイムスタンプを変更してアップロードすればいいのでしょうか。とりあえず、変更してないファイルをサーバにアップロードしてみます。

$ 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)をダウンロードできます。

Dear Diary問題
Dear Diary問題

軽く調べます。本当に 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ルールスキャンしましたが、ダメでした。

# find . -type f | xargs grep pico
./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 #0 (179, counted=0).
Fix<y>? yes
Free blocks count wrong for group #1 (7425, counted=270).
Fix<y>? yes
Free blocks count wrong for group #2 (8192, counted=0).
Fix<y>? yes
Free blocks count wrong for group #3 (7931, counted=0).
Fix<y>? yes
Free blocks count wrong for group #4 (8192, counted=1).
Fix<y>? yes
Free blocks count wrong for group #5 (7931, counted=309).
Fix<y>? yes
Free blocks count wrong for group #6 (8192, counted=24).
Fix<y>? yes
Free blocks count wrong for group #7 (7931, counted=6714).
Fix<y>? yes
Free blocks count wrong for group #16 (64, counted=24).
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group #18 (8192, counted=2374).
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group #30 (8192, counted=4961).
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group #32 (64, counted=0).
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group #33 (8192, counted=7160).
Fix<y>? yes
Free blocks count wrong for group #34 (8192, counted=8189).
Fix<y>? yes
Free blocks count wrong for group #35 (8192, counted=8188).
Fix<y>? yes
Free blocks count wrong (437564, counted=378717).
Fix<y>? yes
Free inodes count wrong for group #0 (2012, counted=179).
Fix<y>? yes
Directories count wrong for group #0 (2, counted=300).
Fix<y>? yes
Free inodes count wrong for group #16 (2024, counted=1775).
Fix<y>? yes
Directories count wrong for group #16 (0, counted=33).
Fix<y>? yes
Free inodes count wrong for group #32 (2024, counted=1677).
Fix<y>? yes
Directories count wrong for group #32 (0, counted=66).
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」を検索して、上から順番に見ていくと、picoCTF{1_533_n4m35_80d24b30} が見つかった。

繋げると、picoCTF{1_533_n4m35_80d24b30} になりました。

これで Medium なのはショックです。

これで、Forensics は終了です。

おわりに

今回は、picoCTF の picoCTF 2024 のうち、Forensics というカテゴリの全8問をやりました。最後の 2問は解けませんでしたが、苦手ないろんな知見が得られたと思います。

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。