justCTF 2020 - PDF is broken, and so is this file
問題概要
This PDF contains the flag, but you’ll probably need to fix it first to figure out how it’s embedded. Fortunately, the file contains everything you need to render it. Follow the clues to find the flag, and hopefully learn something about the PDF format in the process.
https://ams3.digitaloceanspaces.com/justctf/eccb3bff-69aa-4232-8087-a5e8eea0f581/challenge.pdf
PDFファイルが与えられます。見ると真っ白です。中にFLAGが隠されているので、取り出してください、という問題。
解説
PDF上にあるRubyコード
PDFファイルの構造に初手から手を出すのは正攻法なのですが、取り敢えずはエディタで開いてみます。
見ると明らかにRubyっぽいコードが見えます。このプログラム、Rubyで動かせる🤔🤔🤔?ということで動かしてみます。
ruby challenge.pdf
そうすると、HTTPサーバーが立ち上がります。中のソースコード読んでいくと、/flag.zip
でそれっぽいzipファイルのダウンロードが出来るので、wget localhost:8000/flag.zip
で雑に拾ってみます。開くと、false_flag.md
とmutool
という2ファイルが。
...外れですね。こんな簡単な問題な訳無いのですが、「PDFってRuby動かせるんだよね!すごくない!?ところで、これはあくまでネタで、答えは違うよ」という出題者からの煽りを感じます。
一応、mutool
にかけてみるといいよという文言がfalse_flag.md
にあったので、指定通りにコマンドを実行すると、「PDFの構造ちゃんと調べろよ?」的な煽り画像が。いい加減ちゃんと中身を見ましょう。
PDFの大体の構造とおかしな点
PDFのおおまかな構造は以下の4つです。
- header: 上の画像にもある
%PDF-1.x
のバージョン情報です。これだけです。 - body: PDFとして描画するために必要なものが「オブジェクト」として複数個並べられています。各オブジェクトは固有のIDを持っており、これは後のxrefから参照されます。実際、描画の際はこのオブジェクトが木構造を為します。
- xref: body上にあるオブジェクト数が記載されていたり、body上の各オブジェクトがこのファイルの先頭から何バイト目にあるかが示されています。オブジェクトIDは1から連番になっており、xrefのn行目がオブジェクトID: nについての情報です。
- trailer: ファイルの一番最後にある項目で、文書情報のあるオブジェクトの位置や、描画に用いる木構造のルートとなるオブジェクトの位置が記載されています。最後は
%%EOF
で終わっています。
この内容から、PDFファイルを読む際にはtrailerの情報を取り出せばいいことが分かります。が、trailerの最初にあるtrailer
という内容がファイル内に2つあります。また、この少し上から内容が重複しており、以下のようにこのファイルが加工されていることが示唆されます。
- 普通にPDFファイルを作る
- ファイルの末尾から適当な範囲をコピーし、末尾に張り付ける
一応、ファイル末尾にある%%EOF
は1つのようでした。
ということで、同じ範囲のうち上側を削除します。ただ、そうするとPDFファイルが読み込めなくなると同時にもう1つおかしな点が見つかります。
bodyには複数のオブジェクトがバラバラに格納されているのですが、そう考えるとobjectの中にobjectが入ることは絶対に無いはずです。ただ、今の状態ではオブジェクトの始まりを示すobj
から終わりを示すendobj
に整合性が取れなくなってしまっています。で、このタイミングで気になるのがその整合性が取れない中にあるstreamという存在。PDFにおいてバイナリが埋め込まれている箇所なのですが、この直前にある/Filter /FlateDecode
の内容ですが、flatedecode
で検索するとdeflate
というzipファイルの圧縮にもよく用いられるような圧縮手法とのことです。
...streamの前後抜いたらそのファイルとして扱えません?ということで、オブジェクト内部に存在するオブジェクト(PDFにおいておかしな存在)の中にあるstreamを抜き出してファイルの詳細について調べます。zipファイルで、綺麗に回答は出来ませんでしたが、中にあるファイルから先述のflag.zip
であることが分かりました。ここは削除してよいでしょう。
これでPDFが表示できるようになりました。が、白紙。
PDFに描画されないオブジェクトについて調べる
ということは、以下の2種類がフラグとして考えられます。
- PDFファイルにある何かしらのオブジェクトがフラグを持っている。
- 複数のオブジェクトが重なり合うことでフラグを生成する。こちらの方が難しい。
2は難しいので、1から調べましょう。気になるのはオブジェクトの最初にはobject_id (よく分からないけど大体0) obj
という行があります。このobject_id
はxrefで参照できるように連番になっているのですが、object_id
が4919
のものがあります。これは意図的かつ恐らくそのままでは描画されないことでしょう。
例のオブジェクトもstreamであることから、抜き出してファイルについて調べてみましょう。4919 0 obj
と4919 1 obj
の2種類があるのですが、前者はテキストファイル、後者は画像ファイルで、後者にはフラグが記載されていました。
余談
この問題ではフラグが1枚の画像になっているので、最悪全てのstreamデータに対して「抜き出して、解析する」という作業をやれば見つかりそうです。PDFの強みを生かすのであれば、オブジェクト毎に(恐らく)座標を自由に設定できそうなので、複数オブジェクトで生成するとより難しくなるのかなと思いました。
Discussion