web-dev-qa-db-ja.com

最新のLinuxでのバッファオーバーフローの例のコンパイル

Debian i386 VMで単純なバッファオーバーフローの例をコンパイルしようとしています。実行可能ファイルは正常にビルドされますが、バッファーをオーバーフローさせ、スタックにプッシュされたEIPを上書きするのに十分な大きさの入力が提供されても、EIPは正しく上書きされません。これがルートとしての私のコマンドです:

sysctl -w kernel.randomize_va_space=0
gcc test.c -z execstack -z norelro -fno-stack-protector -D_FORTIFY_SOURCE=0 -ggdb -o test

あなたが見ることができるように私は持っています:

  • スタックを実行可能にした
  • スタックカナリアを削除
  • ASLRシステム全体で無効
  • Relro保護を削除
  • GccのFORTIFY_SOURCE保護を無効化

ここにtest.cがあります:

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
  char buf[128];
  if(argc < 2) return 1;
  strcpy(buf, argv[1]);
  printf("%s\n", buf);
  return 0;
}

私は、128〜256の長さのクラッシュ文字列(すべてAsのみ)を試しました。 gdbでは、プッシュされたEIPが上書きされることはありません。他のローカルスタック変数はないため、EIPを上書きするには、実際には132バイトの文字列にする必要があります。

コンパイル時に無効にする必要がある他の保護機能はありますか?または、sysctlで無効にする何か他のものはありますか?

12
B-MO

あなたの例はここでsegfaultを実行します(または、スタックプロテクターがアクティブな場合はプログラムを終了させます)。

おそらく、バッファオーバーフローを別の関数に移動する必要があります。おそらくあなたのgccバージョンは_return 0;_をmainからexit(0);に変換しています。

4
Ángel

受け入れられた答えは、すべてを別の関数に移動することを提案することで正しいですが、理由は説明されません。


この質問と回答 を見るとわかるように、main()関数は、多くの場合、スタックが適切に設定されていることを確認するためにスタックアライメントを実行します。次の指示が実行されます。

_83 e4 f0 and esp, 0xfffffff0_

これにより、スタックが8バイトにアラインされます。これは、減算演算がespで実行されたことを意味します。したがって、戻りアドレスをオーバーフローさせるには、_128 bytes + <variable stack alignment> + <optional saved ebp> + <new_return_address>_が必要です。

プログラムをコンパイルして実行しました(_-m32_を追加する必要がありました)。

_Starting program: /home/user/Private/misc/overflow_test  
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc

Program received signal SIGSEGV, Segmentation fault.
0x63636363 in ?? ()
_

私は128 Asを使用し、次に新しい文字を4つ使用しました。

プログラムを逆コンパイルすると、次の行が表示されます。

_;      .//overflow_test.c:4
;-- main: 
;-- sym.main: 
0x0804842d    55             Push ebp  
0x0804842e    89e5           mov ebp, esp  
0x08048430    83e4f0         and esp, 0xfffffff0 
0x08048433    81ec90000000   sub esp, 0x90 
_

ここでは、0x90(144)がスタックから差し引かれていることがわかります。つまり、128バイトを超えるスペースがローカル変数に割り当てられます。 このSO answer は、これが発生する理由をいくつか示します。128バイトを考慮すると、16ローカル変数用に追加されたバイト、および8バイトのスタックアライメントを想定:次に、EBPを_0x62626262_で上書きし、戻りアドレスを_0x63636363_で上書きします。


通常、通常の関数は、スタックを調整するこのステップを実行しません。そのため、別の関数に移動すると、すべてが期待どおりに機能しました。実際の悪用では、main()に入るパラメーターを悪用する可能性はほとんどありません。別の関数のスコープで実行する方が現実的です。

13
RoraΖ