最近、私はバッファ オーバーフロー手法を研究しており、そのような脆弱性を悪用する方法をよりよく理解するために、自分で簡単な例を作成しようとしています。
私はこの単純な C プログラムを書きました:
//bof.c
#include <stdio.h>
#include <string.h>
void
BOF() {
printf("BOF");
}
void
foo1(char* argv){
char buff[10];
strcpy(buff, argv);
printf("foo1");
}
int
main(int argc, char* argv[])
{
if ( argc < 1 ) {
return 0;
}
foo1(argv[1]);
return 0;
}
ここでの私の目標は、BOF の脆弱性を利用して、呼び出されていない関数 BOF() にジャンプし、メッセージを出力することです。そうするために私は持っています:
- プログラムをコンパイルしました: gcc -ggdb -m64 -o bof.o -fno-stack-protector -mpreferred-stack-boundary=4 bof.c
- BOF() アドレスを発見しました: objdump -d bof.o | grep BOF (これにより、0000000000400544 が返されます)
- レジスタで何が起こるかを確認するために、gdb 内でプログラムを実行しました
gdb の内部では、 r を実行しますperl -e 'print "\x44\x05\x40\x00\x00\x00\x00\x00" x1500'
が、何も起こりません。プログラムは正常に終了します。したがって、レジスタを確認するために strcpy 関数の直後にブレークポイントを配置すると、次のように表示されます。
rax 0x7ffffffeca20 140737488276000
rbx 0x0 0
rcx 0x7ffff7ab1f00 140737348574976
rdx 0x400544 4195652
rsi 0x7fffffffb8cd 140737488337101
rdi 0x7ffffffeca20 140737488276000
rbp 0x7ffffffeca30 0x7ffffffeca30
rsp 0x7ffffffeca10 0x7ffffffeca10
r8 0x400660 4195936
r9 0x7ffff7de9740 140737351948096
r10 0x7ffffffec7a0 140737488275360
r11 0x7ffff7b8fec0 140737349484224
r12 0x400460 4195424
r13 0x7ffffffecb30 140737488276272
r14 0x0 0
r15 0x0 0
rip 0x40057b 0x40057b <foo1+31>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
レジスタが上書きされないのはなぜですか? 1500 パラメータをもっと大きな値に変更しようとしましたが、何も変わりませんでした。小さな値 (50 以下など) でも試しましたが、同じ結果が得られました。
また、レジスタが上書きされているかどうかを確認するために、スタックにアドレスとは異なるものを書き込もうとしました。たとえば、perl -e 'print "A" x1500' では、rbp レジスタのみを変更でき、rip は変更できませんでした。しかし、このサイトのスレッドを読んで、gdbでこれが発生する可能性があることを発見し、有効なアドレスで試してみました。だから私はしました。
私が間違っていることは何ですか?最近のカーネルでは BOF がより実現可能ではない可能性はありますか?
忘れる前に:要素の制限を削除するために、gdb の制限要素も削除しました。
最後に、レジスタを見てわかったように、ubuntu 12.04 (カーネル バージョン 3.5.0-39-generic) を搭載した 64 ビット マシンを使用しています。
前もって感謝します。