Reversingとかpwnとかを解くときのメモ(かきかけ)
この記事はTSG Advent Calendar 2016 - AdventarとIS17er Advent Calendar 2016 - Adventarの2日目の記事として書かれたわけではなかったのですが、記事がないので埋めなきゃいけないのと、多分このままだと書きかけのままはてなの肥やしになってしまうので、エイヤと公開したものです。僕が学習するたびに適度に更新されるはずなので、たぶん永遠に書きかけです。
Reversing,pwnとは
CTFというセキュリティについての大会でよく使われる問題の区分です。主に実行ファイルの解析や、大会サーバ上で動いている実行ファイルに対する攻撃などを行う分野です。僕は駒場祭で文花帖を自動でやるやつをやっていましたが、そいういう感じのことをやります。
Webとかsteganoとかは解くのにエスパー力(ドメイン知識ともいう)が要ってつらいですが、それらに比べてエスパー問が少ない(気がする)ので僕は好きな分野です。
Reversing
実行ファイルが与えられるので、それの挙動を解析してくださいというもの。
パスワードを当てたり、ゲームの得点を改竄したり、遅いアルゴリズムを高速化したり、アンチリバーシング技術をかいくぐったりする。
アセンブリやバイナリを全部読めばたいてい解けますが、時間がかかりすぎるので、知識や観察を組み合わせつつすばやく解決する技術が要ってきます。(もしくは根性)
pwn
プログラムがサーバ上で動いているので、それに対して攻撃することにより、サーバ上にあるflag.txtを頑張って読み取ってくださいというもの。
バッファオーバーフローとか、フォーマットストリングバグとか、を起こしてしまうとやばいね、という話。
実際に動いているプログラムをばりばりぶっ壊せるので楽しい。(大会でやるから許されてしまうのであって、実世界で動いているものに対してやってしまうと不正指令電磁的なんとか*1に触れてしまうのでそこんとこは注意)
攻撃方法を思いつくには、たいていまず与えられた脆弱性のある実行ファイル(たいていx86かx64のelf)を解析しないといけないです。(たまにCのコードが与えられるものもある)Reversingの知識がある程度いるので、Reversingと並列にやっていきましょう。
Reversing
いかに手短にプログラムの挙動を把握するか、という問題。知識や観察力やエスパー力を頼りに素早く問題バイナリを解析していく。
例)
- 入出力対応から察するにROT13なのでは
- UUDDRLRLなのでBAとくるのでは
- 112358とあるのでフィボナッチ数の順に呼んでやればよいのでは (これはエスパーともいう)
ツール類
- IDA
つよい。32bitのexeとelfを解析してくれる。
動的解析ならこれ。pedaというpython拡張を入れるととても強くなるので入れましょう。
- Hopper
最近知った心強い味方。64bitのelfを投げると解析してくれる。(ただし無償版は30分で再起動する)
- Objdump
とりあえずかけておいてもよさそう。
逆コンパイル結果がだばだば出てくるので参考にするとよいです。あと.pltとか見たりする。
- OllyDbg
Windows動的解析ならとりあえずこれかな。
- x64dbg
64bitのときはこちらに投げたりした。まだあんまり使ったことなし。
- z3, angr
どちらもpythonのライブラリ。z3はSAT,SMTソルバであり、n次元連立方程式を解くときとかに投げる。angrは最近でてきたもので、パスワードチェックを通るようなパスワードを探索する、みたいなことをしたいときに制約式をがりがり立てて自動的に解いてくれる。使い方がちと難しいが強力な大鉈。
- dex2jar
- jd-gui
- ILSpy
それぞれ、dexの展開、jarの解析、.netの解析をやってくれる。ほかにもいろいろな形のバイナリが降ってくると思いますが、時々に応じてツールをフットワーク軽く使っていくとよいでしょう。
elfのセキュリティ機構たち
実行ファイルのセキュリティ機構[RELRO/SSP/Nxbit/ASLR/PIE] - Pwn De Ring
ここにまとまってますね...
大抵、ASRLとNXのみで、セットでPIEとかRELROがついてきたりする。
カナリー,もしくはSSP(Stack Smash Protect)
関数に入るときのebpのアドレスとか戻りアドレスとかが上書きされないようにする。
__stack_chk_fail とか言う文字列が入ってると、多分使ってる。
gs:0x14 とかからランダムな値を引っ張ってきてる。
ASLR
アドレス配置のランダム化、というやつ。ヒープ、スタック、共有ライブラリ、の位置がランダムになる。(ほかにも、.bssとかも動くらしい...?)
PIE
位置独立実行コードと呼ばれるやつ。.textが自由な位置に配置されるようになってるの。
ふつう、動的リンクするライブラリを呼び出すときには、一旦.pltみたいなやつに仲介してもらうわけですが、そうはせずに e8 fc ff ff ff
みたいにしてる。
すなわち、 call rel -4 みたいになってるとこがあるので、そこをロードする際に、直接、ライブラリの関数のアドレスで上書きしていく。
ライブラリのほうはRELROとかないので、相対アドレスがちゃんとわかればちゃんと動く...(ハズ)
PIEがあるとむしろReversingのほうでだいぶ苦しむ。
RELRO
Relocation Read Only.
Partial と Fullがある。
Fullの場合、GOT(WindowsでいうIATみたいなの)を上書きできないようにする。
RELROとformat string attackによるリターンアドレス書き換え - ももいろテクノロジー
これとかですかね。
DEP,もしくはNXビット
ふつう、ヒープやスタック上にeipが飛ぶ、みたいな事案はないはずなので、ヒープやスタック上に実行コードが置かれてもそれを実行しないようにするため。.text以外にはXが立たないようになってることがあるやつ。Windowsではデフォ。最近のLinuxでもデフォ。
ascii armor
strcpyとかをするときには、\x00までしか読み込まれない。
なので、\x00を含むようなアドレスにライブラリをロードするようにすると、pwnする際に苦労する。(のだけれど、そういう場合に限ってFSBだったりgetsだったりwriteだったりを使っているのであんまり苦しんだ記憶がない)
pwnについて
今のところelfに対するpwnしか出くわしたことがないのでそれについて書きます。
確認すべきこと
Reversingのそれに加えて、
- checksecでどんなのがかかっているかを確認する。
- readelfで_fini_arrayがあるかを確認する。
- vmmapでrwxな領域があるかを確認する。
使うもの
reversingで使うやつのほかに。
僕はpythonで解法を書いたりしています。(cookieはrubyを推している)
https://github.com/satos---jp/ctf_tools
たいてい、この中の pwnscript.py を手元に落として、それからやってます。
- socat
手っ取り早くリモートの状況を再現したいときに叩く。僕は、コマンドを覚えていないので pwnscript.py からコピペして使えるようにしてます。
何をやっているかとかは、http://www.slideshare.net/bata_24/katagaitai-ctf-1-57598200 のP158あたりを読んでおくとよいです。
- nasm
シェルスクリプトを生成してくれる。毎回使い方を忘れるのでさっきのリポジトリ内の
https://github.com/satos---jp/ctf_tools/blob/master/x86-execve.s
を見ながら書いてます。
シェルスクリプトを書く際の注意点として、バグったら一旦Cで書いてみて、それのシステムコールの呼び方とちゃんと比較してみるとよいです。
- rp++
ROPをやる際にたいへん便利。
- metasploit
alphanumeric shellcode とかを生成してくれる。
システムコール
0から作るLinuxプログラム システムコールその1 ユーザープログラムからのシステムコール呼び出し
とかの中ほどに引数の説明がある。
x86とx64で呼び方とか引数の数とかがずいぶん変わっているので注意。
x64の場合、
syscall ()で呼ぶ。システムコール番号はrax。引数はrdi,rsi,rdx,r10 ...
知っておくとよいのは、たとえば、
- read write (メモリの読み書き)
- open (ファイルを開く)
- execve (プロセスの実行)
- pipe2 (ファイルディスクリプタをつなぎかえる。自前でsocket通信してるやつに対して使ったり。)
- mmap (実行可能なメモリを確保する)
ですかね。
書き換えるとこ
大抵のpwn問では、まず制御をどうにかして奪える状況にしてやる必要があります。(eipを奪うとかいう)
で、code部分はたいてい書き換え不能なので他の部分をどうにかしてやる必要があります。
スタック
おなじみ。ReturnAddressがあるので書き替えるとよい。ebpを書き換えてスタックをずらし、その後ReturnAddressをどうこうするのもある。
GOT
WindowsにおけるIATみたいなもの。外部ライブラリの参照をするのでここを書き換えた状態でlibcの関数を呼ぶとeipが奪える。
_fini_array
GOT的な場所が他にもあって、exit関数内で呼び出される関数テーブルというのがあり、そこを書き換えるとよい。
文字入出力について
入出力を溢れさせてたいてい書き換えるので、入出力関数の特性を知っておくとよい。
入力では、scanf, gets, fgets, read 、 出力では、printf, puts, fputs, write 、他に strcpy,strncpy とかですかね。
関数 | 書き込みが止まるもの |
---|---|
scanf | 水平タブ(0x9),改行(0xa),垂直タブ(0xb),改ページ(0xc),キャリッジリターン(0xd),スペース(0x20) |
gets | 0xa |
read | なし |
printf | 0x0 |
puts | 0x0 |
write | なし |
strcpy | 0x0 |
(手元のUbuntuで試した結果です)
入力は、どれもNULL文字と0xffはそのまま気にせず読み込むそうです。
ほかにも、s[10]; のとき、fgets(stdin,s,10); は問題ないが、 scanf("%10",s); や strncpy(s,t,10); ではoff_by_one エラーが起こるとか。
eipを奪った後
flagを表示してくれる関数、もしくはsystem("/bin/sh");みたいなのがあるとき
そこに飛ばせばよい。
NXビットが立ってないとき
自分のシェルコードを適当なとこに流し込んで、そこに飛ばすようにする。
シェルコード内では、system関数があればそれを呼ぶもよし、ないならexecveシステムコールを叩いて自前でやる。
自分のシェルコードがどこにあるか分からない(たとえばスタックのアドレスが不明)なら、まずebpとかをリークさせる。
また、流し込めるシェルコードの量が短いときは、一旦readとかを呼んで、後から追加でシェルコードを実行させる。(stagerという)
NXビットが立っているとき
自分の実行可能コードが流し込めないので、元からあるコードをパッチワーク的につなぐことによってどうにかする。『returnなんとか』とか『ほげほげoriented programming』とか呼ばれる技法はたいていこのあたりの話。
returnなんとか
return to libc
libcの関数を順々に呼んでいこう、というもの。
ふつう、関数が呼び出された直後のスタックというのは、
return addr |
arg0 |
arg1 |
... |
となってるわけです。さて、関数からretする直前には、
return addr |
... |
となって、pop eip されることにより return addrに飛ぶわけですが、オーバーフローさせることにより、たとえば
gotにあるsystemのアドレス |
piyo |
arg1 |
arg2 |
... |
としてやると、system関数の先頭で、
piyo |
arg1 |
arg2 |
... |
となっているので、あたかもアドレスpiyoから関数が呼ばれたかのように見えます。
return oriented programming
ROPとよばれるやつ。
先ほどの状況では関数は1つしか呼べないので、たとえばfopenしたあとwriteみたいなことはできません。そこで、ROPガジェットというやつを利用します。
たいてい、関数がretする直前ではいろいろスタックに退避していた値をレジスタにpopします。すなわち
0x8048060 | pop ebx |
---|---|
0x8048061 | pop ebp |
0x8048062 | ret |
みたいなことになっているアドレスがあったりするので、例えば、
gotにあるputsのアドレス |
0x8048061 |
putsで表示したいアドレス |
gotにある(ry |
... |
としてやると、
puts(putsで表示したいアドレス);
が実行された後、putsからretするときに
0x8048061 |
putsで表示したいアドレス |
gotにある(ry |
... |
となり、pop ebp後に
gotにある(ry |
... |
となるので、関数呼び出しが連鎖していきます。こういうのをROPといいます。
以降かきかけ。
大嘘を書いてる可能性があるので気付いたらマサカリを投げてください。
参考
- http://www.slideshare.net/bata_24/presentations katagaitaiとかの勉強会の資料。量多めですがとりあえず目を通しておくとよさそう。
- ももいろテクノロジー いつもお世話になっております。
- pwn challenges list - Pastebin.com bataさんのpwn問集。(といっても僕は常設埋めのほうをやってるけど...)
- 常設のやつ
みなさんご存知といった感じ。
韓国の。むずい。
最近主に埋めてる。pwn問がたくさんあるのでありがたい。
- O'Reilly Japan - Hacking:美しき策謀 第2版
- セキュリティコンテストチャレンジブック | マイナビブックス
- リバースエンジニアリングバイブル ~コード再創造の美学~ - インプレスブックス
なんか似たような本紹介をこないだも部誌でやった気がしますね...
*1:家庭用事件 - 似鳥鶏|東京創元社 よいシリーズです。