なんかそこそこPwnできるようになるためにしたこと

これは

adventar.org

の2日目の記事です。

1日目はhamaさんの

hama.hatenadiary.jp

でした。

  1. Pwn問をひたすら解きます。
  2. 1を繰り返します。

というのは基本なんですが、せっかく記事にするのでもっと詳しく書いていきます。

打倒!村人!

もともと僕が本格的にCTFを始めたのは去年のSECCON一週間前ぐらいからでした。

そのときはハリネズミ本をやってksnctfの村人Aを倒すところまで行きました。

ですが、正直その時はスタックについても書式文字列攻撃についても正直言って何もわからない状態でした。

なんとなく手順を真似るだけで精一杯な状況でした。

CTFに参加しまくろう!

それからHarekazeでほぼすべてのCTFに参加するようになって

なんとなくですが、これでCTFで何をすればいいかについて大分把握できるようになってきました。

このあと7月の後半に入って、Pwnをちゃんとやってみようと思い

そこからやっとPwnでHeap問みたいな今のPwn入門と言える問題が解けるようになっていきました。

もちろん7月以降の取り組みによってPwnがそこそこできるようになったとは思うのですが

これまでのCTFを地道に取り組み続けるというのは割と自分の中では基礎になっているのかなと思っています。

解析にあたっての取り組み方

ここからやっと本題で、Pwnをやる上で大事だなぁと思う取り組み方について紹介します。

最終目標「シェルをとる」の確認

まずはじめに自分はシェルをとるということに関して曖昧な理解でした。

シェルをとることについてはいろいろと方法がありますが、実は最終的にやればいいことはひとつで

execve("/bin/sh",["/bin/sh"],NULL);

を実行することになります。execveの第二引数はNULLでも構いません。

他にも方法があると思う方もいるかもしれませんが

system("/bin/sh"); あるいは、 onegadgetRCEといったものは内部で同様のことを実行しており

最終目的に至るための一つの手段になります。

EIPをとるとは

Pwnでよくある説明の中にEIPをとるという表現があると思います。

EIPはx86アーキテクチャにおけるプログラムの先頭を指すアドレスです。これは一般的にプログラム・カウンタと呼ばれます。

プログラム・カウンタであるEIPを書き換えるという表現は確かに正しいのですが、自分の中ではしっくり来ませんでした。

どちらかといえば、任意のアドレスにプログラムが飛ぶようにするという方が自分の中の理解になります。

プログラムを任意のアドレスに飛ばすと何が嬉しいか

次に任意のアドレスにプログラムを飛ばせるようになると何がいいのかということになります。

最初から自動的にシェルが取れるようなプログラムであれば最終目的はすぐに達成されますが

もちろんそのような問題は出ません。もし出たとしてもそれはカーネルのエクスプロイトか、Sanity Checkです。

実際にはシェルを取るためには、まず攻撃者が指定する動作(="/bin/sh"を実行する)をプログラムがするようにしなければいけません。

ここで指定する動作を実行させるためにできることがプログラムを任意のアドレスに飛ばすということです。

Pwnの問題には中にはプログラム中にフラグを表示させる関数やシェルをとる関数が仕込まれているがあるので

プログラムを任意のアドレスに飛ばすだけで攻略できる問題もあります。

プログラムをどこのアドレスに飛ばすか

次にそうでない場合、プログラムをどこのアドレスに飛ばすかということを考えなければなりません。

これには色々な飛ばし方があるので、飛ばせる範囲のことから考える必要があります。

そこで初めて、セキュリティ機構を把握することやメモリアドレスのリークが重要になってくるのです。

例えばセキュリティ機構ASLRが有効であれば、libcのアドレスはlibcのアドレスをリークしてからでないと

飛ばせる先の候補にならないという話などがそれに該当します。

利用できるものは何でも利用する

CTFにおいて大切なことは利用できるものは何でも利用するということです。

もちろんルールは守らなければいけませんが、ルールを守りさえすれば何でもしていいというのがCTFです。

とくにPwnにおいてはバイナリが配布されていることが多く、それがまず大きな利用できる資源になります。

次に解析していく中で、気になったことがあればすぐにWebで検索することです。

Pwnはバイナリを解析することがすべてのように思いがちですが、知識を違うところから得ることで解ける問題もあります。

例えばライブラリをそのまま使ってコンパイルしたような痕跡を発見して、それで検索してみると見事にライブラリのソースコードが出てきたり

過去問のwriteup(解説記事)がでてくるといったようなことは割とよくあることです。

また基礎的なことですが、アセンブリでわからない命令があった場合は即座に検索しておくのがおすすめです。

命令についてはいつまで検索を続ければいいのか不安になる方もいるかもしれませんが

そのうち慣れてくると検索しなくても何をやっているかがわかるようになるので大丈夫です。

さいごに

CTFでもっとも大事なのは絶対に問題を解いてやると思う根気と情熱だと思っています。

正直言って、自分の場合は割と執着に近いレベルでこれをやっています。

とにかく取り組み続けてみましょう。もしかしたら何かがわかるかもしれません。

CTF AdventCalendar 3日目はmegumishの

実践!Pwn入門 0CTF 2017-Baby Heap 2017 で学ぶPwnの進め方

です。