LinuxはW^X原則に従います:彼らはコードセクションの一部である場合を除き、それは非実行可能ファイルとしてメモリページをマーク。これは、コンパイルされたアプリケーションの範囲を超え、正当な理由があります。 OSは、システム上で実行されるすべてのプログラムからのバッファオーバーフロー攻撃を防御するこの責任を負っています。特にあなたのようなバッファオーバーフロー攻撃を積極的に試みているプログラム。
あなたはbuf
を経由して、スタック上のコードを書いて、新たに挿入されたコードに実行をジャンプする関数の戻りアドレスを上書きしようとしています。関数が復帰すると、プログラムカウンタはオーバーライドされたリターンアドレスに設定され、スタックメモリを指すようになります。 SIGSEGV
は、プログラムカウンタがスタックメモリページ上の無効な実行許可のために次の命令を実行しようとするとスローされます。
は、スタックから実行するには、OSのスタック保護を無効にする必要があります。
幸いにも、Linuxはユーザーの裁量で使用するような場合のためにexecstack提供します。
は、より一般的な情報についてthisのUnix &のLinuxスタック為替ポストを参照してください。あなたがGDBでSIGSEGV
を取得している場合は
デバッグが
データを注入し、それはおそらく試みをオーバーランあなたのバッファに多少の誤差があることを意味します。デバッグに
#include <stdio.h>
#include <string.h>
char injection_code[] = ""; // buffer overrun data here
void foo() {
char buf[100];
// memcpy used to copy the full injection string, including any nested 0s
memcpy(buf, injection_code, 108); // +8 here to handle 64-bit system RAs
}
int main (int argc, char** argv) {
foo();
printf("Done!\n");
return 0;
}
利用GDB:main
の終わりにクリーンアップをいじり避けるために、私はあなたのバッファオーバーランを行うには、メインから呼び出す機能を作ることをお勧め。私はfoo
の最後にブレークポイントを置き、info registers
で期待していたものとレジスタの行を確認することをお勧めします。あなたはおそらく、info registers rip
(64ビット)またはinfo registers eip
(32ビット)でチェックできる命令ポインタに最も興味があります。
GDBでprint
またはx/x
を使用すると、スタックの外観を調べることができます。たとえば、$rbp+8
をチェックすると、戻りアドレス(RA)がスタック上にあるかどうかを確認できます。
GDBは、無効な場所にRAポイントであればret
命令にSIGSEGV
ます:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005bc in foo() at bufferoverflow.c:27
あなたはそれが故障の時に命令ポインタアドレスをチェックしてret
指示に障害が発生かどうかを確認することができます(上の例では、それは0x00000000004005bc
となります)(GDBのdisassemble function_name
を使います)。
リターンアドレスがスタックに戻って指している場合、それはあなたのリターンアドレスが正しく整列されていないか、またはあなたの注入された命令が不正な形式されていることを意味不当命令、のためSIGILL
を投げることがあります。
Program received signal SIGILL, Illegal instruction.
0x00007fffffffdc13 in ??()
繰り返しになりますが、GDBを使用してスタックを調べて理由を確認することができます。
GDBは、バッファオーバーフローの構造を正しく取得するのに便利です。 しかし、それが意図したとおりに動作すると、特に、デバッグフラグ(-g
)なしでコンパイルすると、GDBの外部で実行されたときにメモリアドレスがシフトする可能性があります。あなたは「生きている」環境でそれをしたい場所に戻すために、リターンアドレスで少しでも遊ばなければなりません。
アンは別に
一般的には、直接注入コードを実行するバッファオーバーフロー攻撃は、今日のスタック保護メカニズムと一般実現できないです。通常、任意のコードを実行するために追加の脆弱性が存在する必要があります。
もちろん、この点は、OPが想定している攻撃の種類を正確にフォイルすることです。この機能が広く普及しているため、そのような攻撃の可能性は従来のものよりはるかに低くなります。 –
私はgcc '-z execstack'と' sudo execstack -s vuln'を使ってexecstackを使い、 'readelf -l vuln'でGNUスタックがRWE(read、write execute)に設定されていることを確認しました。 。私が間違っていることについて考えてみませんか?バッファオーバーフローに必要な量は108バイト以上で、むしろ116バイトです。 – nrabbit
@nrabbit私は今それを行う時間がありませんが、私のマシンで実験し、あなたに戻ってきます。 – sdsmith