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
ご想像のとおり、これは [ebp-12]
からスタック Cookie を取得しています。 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
これはできます 再コンパイルを必要とせずに任意のプログラムで実行できますが、コンパイル時に組み込まれているスタック カナリアを自動的に無効にすることはありません。
追加ボーナス:aslr:
これをオフにするには、echo 0 > /proc/sys/kernel/randomize_va_space
.
私の大切なペンギンを悪用する方法を誰かに教えましたか?
いいえ。エクスプロイトは、スタック カナリアを回避し (非常に重要です)、execstack
を持つプログラムを見つける必要があります。 設定するか、設定するか (つまり、すでに任意のコマンドを実行できることを意味します)、そうでなければ、libc に戻る/リターン指向プログラミングなどのより難しい手法を使用してください。
スタック保護はコンパイラによって行われます (スタックに追加データを追加し、呼び出し時に一部を隠し、戻り時に健全性をチェックします)。再コンパイルせずに無効にすることはできません。それはポイントの一部です、本当に...