スタック スマッシングは、スタック バッファ オーバーフローに使用される派手な用語です。これは、バッファ オーバーフローを可能にするコードのバグを悪用する攻撃を指します。以前は、コード内でバッファ オーバーフローが発生する可能性がないことを確認するのはプログラマ/開発者の責任でしたが、gcc などのコンパイラは、クラッカーがバッファ オーバーフローの問題を悪用してシステムを損傷しないようにするためのフラグを取得しました。またはプログラム。
gcc 4.6.3 バージョンの Ubuntu 12.04 でバッファ オーバーフローを再現しようとしたときに、これらのフラグについて知りました。これが私がやろうとしていたことです:
#include <stdio.h> #include <string.h> int main(void) { int len = 0; char str[10] = {0}; printf("\n Enter the name \n"); gets(str); // Used gets() to cause buffer overflow printf("\n len = [%d] \n", len); len = strlen(str); printf("\n len of string entered is : [%d]\n", len); return 0; }
上記のコードでは、ユーザーから文字列を受け取るために gets() を使用しています。次に、この文字列の長さを計算し、stdout に出力します。ここでの考え方は、長さが 10 バイトを超える文字列を入力することです。 gets() は配列の境界をチェックしないため、入力を str バッファーにコピーしようとし、この方法でバッファー オーバーフローが発生します。
プログラムを実行するとこうなりました:
$ ./stacksmash Enter the name TheGeekStuff len = [0] len of string entered is : [12] *** stack smashing detected ***: ./stacksmash terminated ======= Backtrace: ========= /lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb76e4045] /lib/i386-linux-gnu/libc.so.6(+0x103ffa)[0xb76e3ffa] ./stacksmash[0x8048548] /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75f94d3] ./stacksmash[0x8048401] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 08:06 528260 /home/himanshu/practice/stacksmash 08049000-0804a000 r--p 00000000 08:06 528260 /home/himanshu/practice/stacksmash 0804a000-0804b000 rw-p 00001000 08:06 528260 /home/himanshu/practice/stacksmash 0973a000-0975b000 rw-p 00000000 00:00 0 [heap] b75af000-b75cb000 r-xp 00000000 08:06 787381 /lib/i386-linux-gnu/libgcc_s.so.1 b75cb000-b75cc000 r--p 0001b000 08:06 787381 /lib/i386-linux-gnu/libgcc_s.so.1 b75cc000-b75cd000 rw-p 0001c000 08:06 787381 /lib/i386-linux-gnu/libgcc_s.so.1 b75df000-b75e0000 rw-p 00000000 00:00 0 b75e0000-b7783000 r-xp 00000000 08:06 787152 /lib/i386-linux-gnu/libc-2.15.so b7783000-b7784000 ---p 001a3000 08:06 787152 /lib/i386-linux-gnu/libc-2.15.so b7784000-b7786000 r--p 001a3000 08:06 787152 /lib/i386-linux-gnu/libc-2.15.so b7786000-b7787000 rw-p 001a5000 08:06 787152 /lib/i386-linux-gnu/libc-2.15.so b7787000-b778a000 rw-p 00000000 00:00 0 b7799000-b779e000 rw-p 00000000 00:00 0 b779e000-b779f000 r-xp 00000000 00:00 0 [vdso] b779f000-b77bf000 r-xp 00000000 08:06 794147 /lib/i386-linux-gnu/ld-2.15.so b77bf000-b77c0000 r--p 0001f000 08:06 794147 /lib/i386-linux-gnu/ld-2.15.so b77c0000-b77c1000 rw-p 00020000 08:06 794147 /lib/i386-linux-gnu/ld-2.15.so bfaec000-bfb0d000 rw-p 00000000 00:00 0 [stack] Aborted (core dumped)
さて、これは、実行環境が、この場合にバッファ オーバーフローが発生する可能性があることを何らかの形で検出できたという嬉しい驚きでした。出力では、スタック破壊が検出されたことがわかります。これにより、バッファ オーバーフローがどのように検出されたかを調査するようになりました。
理由を探していると、gcc フラグ「-fstack-protector」に出くわしました。このフラグの説明は次のとおりです (man ページから):
<ブロック引用>-fstack-プロテクター
スタック破壊攻撃などのバッファ オーバーフローをチェックする追加のコードを発行します。これは、脆弱なオブジェクトを持つ関数にガード変数を追加することによって行われます。これには、alloca を呼び出す関数と、8 バイトを超えるバッファーを持つ関数が含まれます。ガードは、関数に入るときに初期化され、関数が終了するときにチェックされます。ガード チェックが失敗した場合、エラー メッセージが出力され、プログラムは終了します。
注:Ubuntu 6.10 以降のバージョンでは、-fno-stack-protector、-nostdlib、-ffreestanding のいずれも見つからない場合、このオプションは C、C++、ObjC、ObjC++ に対してデフォルトで有効になっています。
したがって、gcc には、バッファー オーバーフローをチェックするための追加コードを発行するこのフラグがあることがわかります。次に頭に浮かんだ質問は、コンパイル中にこのフラグを含めなかったのに、この機能がどのように有効になったかということでした。次に、Ubuntu 6.10 ではこの機能がデフォルトで有効になっているという最後の 2 行を読みました。
次に、次のステップとして、コンパイル中にフラグ「-fno-stack-protector」を使用してこの機能を無効にし、以前に行っていたのと同じユースケースを実行しようとしました。
これが私がやった方法です:
$ gcc -Wall -fno-stack-protector stacksmash.c -o stacksmash $ ./stacksmash Enter the name TheGeekStuff len = [26214] len of string entered is : [12]
したがって、コードがこのフラグを使用してコンパイルされ、次に同じ入力が使用されると、実行環境は実際に発生したバッファ オーバーフローを検出できず、変数「len」の値が破損したことがわかります。
また、gcc を初めて使用する場合は、前に説明した最も頻繁に使用される gcc コンパイラ オプションを理解する必要があります。