バッファオーバーフローの脆弱性の基礎を見て、スタックの動作を理解しようとしました。そのためには、戻り値のアドレスをある値に変更する簡単なプログラムを作成したかったのです。誰も私が最初の引数からオフセットを得るためにベースポインタのサイズを計算するのを助けることができますか?次のようにスタック上のリターンアドレスを変更する
void foo(void)
{
char ret;
char *ptr;
ptr = &ret; //add some offset value here
*ptr = 0x00;
}
int main(int argc, char **argv)
{
foo();
return 1;
}
生成されたアセンブラコードが見える:
.file "test.c"
.text
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq -9(%rbp), %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
movb $0, (%rax)
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call foo
movl $1, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 4.7.1 20120721 (prerelease)"
.section .note.GNU-stack,"",@progbits
FOOフレームセグメントの関連部分は次のようになります
を[チャーRET] [ベースポインタ] [リターンアドレス]
私は1バイトだけの最初の位置を持っています。 http://insecure.org/stf/smashstack.htmlに記載されているように、ベースポインタまたはワードのサイズに1バイトだけ進んでいますか?そして、どのようにしてベースポインタのサイズを知ることができますか?
+1再コンパイルでは常に変数を移動できます。 OPのテストのためだけに、この特定のケースでは、戻りアドレスは '&ret + 17'にあります。これは、その関数のローカル変数が変更されない限りは変更されません。 – ughoavgfhw
オフセットは17です。あなたはそれをどう決めたのか説明できますか? – fliX
@fliXアセンブリでは、 'leaq -9(%rbp)、%rax'命令がスタック上のアドレスを取得しています。それはバイト整列であり、唯一のアドレス計算であるため、 'ret'があるはずです。その9を取って、前の64ビットのベースポインタに8を加えれば、17が得られます。 – ughoavgfhw