回答:
vonbrandの発言(正確には+1)をさらに詳しく説明するために、Linuxのスタック保護には2つの部分があります。
スタックカナリアは、vonbrandが参照するコンパイラ強制機能です。これらは、再コンパイルせずに無効にすることはできません。
これを自分で証明し、その動作を確認するには、次のコードを使用します。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int mybadfunction(char* a_bad_idea)
{
char what[100];
strcpy(what, a_bad_idea);
printf("You passed %s\n", what);
}
int main(int argc, char** argv)
{
printf("Tralalalaala\n");
mybadfunction(argv[1]);
}
次にgcc -fstack-protector -masm=intel -S test.c
、出力をアセンブルして読みやすいように、その()を何かgnuにコンパイルします。重要な点は、mybadfunction
関数の終了時に、次の小さなコードがあるということです。
mov edx, DWORD PTR [ebp-12]
xor edx, DWORD PTR gs:20
je .L2
call __stack_chk_fail
ご想像のとおり、これはスタックCookieを取得し、[ebp-12]
それをの値と比較していますgs:20
。一致しませんか?次に__stack_chk_fail
、glibcの関数を呼び出して、プログラムをすぐに強制終了します。
エクスプロイトの記述に関してこれを回避する方法はいくつかありますが、シェルコードテストケースの構築という点で簡単な方法は、でプログラムをコンパイルすること-fno-stack-protector
です。
最近のLinuxシステムには他にもいくつかの考慮事項があります。通常のシェルコードテストスタブを使用する場合:
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
最新のGCC / Linuxは.rodata
、実行権限のない読み取り専用のPEファイルのセクションをマップします。これをオフにする必要があります。これは、このブログ投稿のコードサンプルを使用して行うことができます。基本的な考え方:mprotect
シェルコードデータが存在するページに必要な権限を追加するために使用します。
シェルコードを使用して従来のエクスプロイトシナリオ(上記の私の悪いコードなど)をテストする場合は、単純なケースでもスタックが実行可能であることを確認する必要があります。PEファイル形式には、スタックが実行可能かどうかを判別するためのフィールドが含まれています。これをexecstackで照会および制御できます。実行可能スタックを有効にするには、次を実行します
execstack -s /path/to/myprog
これは、再コンパイルを必要とせずに任意のプログラムで実行できますが、スタックカナリアはコンパイル時に組み込まれるため、自動的には無効になりません。
、それをオフにしますecho 0 > /proc/sys/kernel/randomize_va_space
。
いいえ。エクスプロイトはスタックカナリア(非常に重要)を回避し、execstack
setを使用してプログラムを見つけるか、それを設定する(つまり、とにかく任意のコマンドを実行できる)か、またはlibc / returnに戻るなどのより困難な手法を使用する必要があります。指向プログラミング。